File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Ant, Maven and Other Build Tools and the fly likes Getting used to Maven Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Engineering » Ant, Maven and Other Build Tools
Bookmark "Getting used to Maven" Watch "Getting used to Maven" New topic
Author

Getting used to Maven

Eric Nielsen
Ranch Hand

Joined: Dec 14, 2004
Posts: 194
I started exploring Maven2 over the weekend and while I've gotten close to having both a working build system and a productive development environment, its still not quite right. The application(well skeleton of an application) worked prior to the Maven-ization.

First, it seems like I'm missing something about using the "provided" scope. I don't have the dependency graph in front of me, but at least one of the libraries brought in servlet.api and then Maven pushes it into the war. Of course the container complains when it unpacks the war. I added an explicit dependency block for servlet.api with the "provided" scope, but Maven is still copying the jar into the WEB-INF/lib folder. Is there some other place I need to look to configure this?

Second, I'm using Struts2 and Spring2 and the struts2-spring-plugin. However, I always get the error that the ObjectFactory can not be found for "spring". I know I've seen a few lines in the log before this about the application loading the Spring Context, but I'm not seeing all the INFO messages about beans being loaded that I think I saw in the non-Maven version. I've confirmed that the paths to all the XML files match examples from other Maven-enabled applications (like the quickstart app from the struts 2 tutorial on integrating Struts2/Spring2/Hibernate3), but it would seem like the application context file is likely not being picked up? Any other gotchas you can think of to help steer me towards useful debugging?

Third, I found this blog on integrating Maven, Eclipse, and Tomcat. I was wondering if anyone else is using a similar system, having to change your eclipse build settings everytime you do a release (since the version number is hard-coded in this system), seems a little awkward.

Thank you.
Nathan Pruett
Bartender

Joined: Oct 18, 2000
Posts: 4121

First issue, if you want to override the scope (or version) of a transitive dependency, you'll need to add a <dependencyManagement> section to your POM. (See Maven's Introduction to the Dependency Mechanism - the part right before System Dependencies.)

Second issue, how are you handling the application context files? Is your project a WAR archetype and you're putting the app context files in the src/main/webapp/WEB-INF directory? Or do you have them in a resources directory? or are you using a more specialized archetype? Or enabling filtering?

Third issue, sorry - no suggestions here...


-Nate
Write once, run anywhere, because there's nowhere to hide! - /. A.C.
Eric Nielsen
Ranch Hand

Joined: Dec 14, 2004
Posts: 194
Thank you for the response.

On my first issue: I've tried adding the dependencyManagement section, did a mvn clean, mvn install but the servlet-api.jar is still getting added to the WAR file. I searched over the dependency tree and can't find servlet-api.jar anywhere on the list. Just in case it was an artifact of some previous tests, I removed all mention of if in the POM did another mvn clean,mvn install. Still no luck. The emitted log message from Tomcat doesn't seem like its causing problems, but I know its not correct...

On the second issue.... I used just the basic "create"/default archetype. I have modified the POM to say that the packaging is "war". In src/main/webapp/ I have my jsps, WEB-INF/web.xml. In src/main/resources/ I have applicationContext.xml, structs.xml, and META-INF/persistence.xml
Nathan Pruett
Bartender

Joined: Oct 18, 2000
Posts: 4121

Hmmm... not sure what's going on with that first issue... can you post your POM?

As for the second, try moving the files from src/main/resources to /src/main/webapp/WEB-INF - if they're in resources, Maven assumes they get sent the same place as classes do, so they're probably going into WEB-INF/classes.
Eric Nielsen
Ranch Hand

Joined: Dec 14, 2004
Posts: 194
On the first issue, I changed back to the explicit dependency and dependencyManagement and it seems to work now. The only other change I made was re-applying the settings in Properties > Tomcat. (didn't change anything just hit Apply again). I did that because it didn't seem like Tomcat was actually looking in the correct directory anymore, why it had the correct path listed, and why the behavoir change with by hitting apply I'm not sure, but that seemed to fix it. Experimenting a little bit more, it looks like after a mvn clean, the Tomcat settings seem to be out of sync with some level of reality and I need to re-apply the already correct settings.

After trying your suggestion, it wasn't finding the applicationContext.xml file. I reverted that change. Did another clean/install/re-apply cycle and now everything seems to work.

Can you offer any insight into how Maven is interacting with the Tomcat settings?
Nathan Pruett
Bartender

Joined: Oct 18, 2000
Posts: 4121

When you say you re-applied settings in Properties > Tomcat - this is through your IDE, right? Are you pointing Tomcat at the WAR that gets produced in the "target" folder of your Maven project? If this is the case, settings might get confused because every time you do a "clean" Maven deletes the entire "target" directory - so Tomcat might think the path no longer exists. If you are pointing Tomcat at the file, a better approach might be to look into a Tomcat deployer plugin, or use Cargo to actually configure and launch a brand new container for your app.
Eric Nielsen
Ranch Hand

Joined: Dec 14, 2004
Posts: 194
Thanks that explains it. (Yes it was using the Properties > Tomcat pane within Eclipe.)

So at present, I have Tomcat pointing at the directory produced by maven (ie target/app-version/) and so yes the mvn clean process will wipe that out, causing the problem I'm seeing.

I also have the built-in Eclipse compiler set to put its files in the correct place with that path, so incremental compiles/etc don't require a redeploy/mvn build. However I'm doing TDD, so I'm not hitting the deployed app too often so I guess going through a mvn build/deploy with the Tomcat (or Jetty) plugin wouldn't really be a problem for my looking around the app. I'm currently trying to get in-process acceptence tests running with Jetty, so I could even run my acceptence tests without needing to deploy.

I guess I'm convincing myself that I don't really need the sysdeo tomcat plugin in eclipse and just to relaunch with maven after changes won't be a problem. Is that basically what you were getting at?
Nathan Pruett
Bartender

Joined: Oct 18, 2000
Posts: 4121

Yes - that's what I was getting at And in reality, doing a deploy isn't really that different from what you were doing - when you point Tomcat at a directory it just sees a file change and redeploys the app.
Eric Nielsen
Ranch Hand

Joined: Dec 14, 2004
Posts: 194
OK, I'm still not quite in a working state. While the current problem isn't exactly a build problem, I'm not sure it makes sense to separate it from the current thread's context....

Summary after current changes:
src/main/resources
-- applicationContext.xml
-- struts.xml
-- META-INF/persistence.xml

src/main/webapp/WEB-INF/web.xml

mvn jetty:run (or tomcat eploy) both work suitable. Launching tomcat from the IDE can work if the following conditions are met 1) mvn install after any mvn clean and 2) the whole tomcat properties re-application as discussed above. (Both steps are needed to make sure that the resources/webapp files are copied to the correct place in the classpath/web context as appropriate.)

At this point I'm trying to setup a sample integration test. From the Better Builds with Maven book, it says the only way to add integration tests is to introduce a seperate maven module. Thus switching my project from currently a single module project to a multi-module one and I'm a little confused by how to wrap a higher level project around an existing project, without completely messing up eclips. I'm also a little uncomfortable introducing a seperate module jsut for integration tests, but if its an easy process, please let me know and I'll give it a go.


I've also tried creating acceptance tests as unit tests by using an embedded Jetty within the test case, allowing a self contained test environment. (Would need to then use includes/excludes to separate unit/integration tests into the test and integration-test phases... and probably a little bit of tweak to the pre-integration test phase to copy a few resource files around.) However this approach, is throwing an exception when starting Jetty (while Jetty works as standalone)

Here's the exception:
2007-09-13 22:51:53.148::WARN: Failed startup of context org.mortbay.jetty.webapp.WebAppContext@9ead8{,src/main/webapp}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.NoSuchMethodError: org.springframework.util.ClassUtils.getMostSpecificMethod(Ljava/lang/reflect/Method;Ljava/lang/Class Ljava/lang/reflect/Method;
Caused by: java.lang.NoSuchMethodError: org.springframework.util.ClassUtils.getMostSpecificMethod(Ljava/lang/reflect/Method;Ljava/lang/Class Ljava/lang/reflect/Method;

Can you offer any advice for getting integration tests working under either appraoch?
Nathan Pruett
Bartender

Joined: Oct 18, 2000
Posts: 4121

Unfortunately, integration tests are one of the areas that Maven just doesn't have a good approach to. It doesn't really fit into the Maven "model" of a project build cycle - it's really a test, so if it doesn't pass, this overall build cycle should fail. But for you to run the test, you have to do a build, install, and be able to run/deploy your application.

Basically, the only approach I've heard to this is what you said - to make another project for acceptance tests. The main drawback of this approach of acceptance testing is that passing/failing the acceptance tests don't automatically pass/fail the build, especially an issue with continuous integration tools. However, it's pretty much all you can do (for now, and as far as I know...). But, this doesn't necessarily require a multi-module project in your IDE.

You can make a *completely* brand new separate project that includes your original project as a dependency. Or you can make a "super"-project and have your your main project and your acceptance tests both be sub-projects (in the Maven sense). In either of these, you can make these both separate projects in your IDE. Just use the directory that contains the lowest level POM as the "base" directory of that project in Eclipse.
Eric Nielsen
Ranch Hand

Joined: Dec 14, 2004
Posts: 194
Actually, I meant to post a follow-up late last night.... While battling my way through the example in Better Builds with Maven, I found the two archetypes that the Cargo plugin provides. One sets up the appropriate multi-module project (webapp and functional tests), one manages to do it all within a single project (through using the includes/excludes approach to partition the test source tree).

Neither builds successfully out of the box, since the generated code in the archetypes sample tests/implementation classes don't use the correct packages, but once the packages are corrected both can reach the integration-test goal successfully. The integration tests are conducted in Cargo and run before the install or deploy (and terminate the build if they fail) so this should play nice with CI.

Now I haven't moved my code into either of these projects, so I haven't confirmed that the archetype's setup will play nice with Spring 2 and Struts 2, but I'm hopeful that between my earlier explorations and these archetype setups that I'll have a working solution soon.

(The next thing for me to play with, but by no means worth spending a lot of time on, is using the same system for running the integration/acceptance tests on the local machine, to running them on a staging/clone of production machine -- possibly by co-opting the verify goal. This wouldn't be on the default build path for developers, but probably would be on the CI's build and developers could kick it off if needed.)

I think I'll stick with the single project archetype as that's simpler and if the only reason they seem to prefer the two project approach is to avoid having the "include/exclude" extra configuration, I think that the extra configuration is actually a more understandable approach than setting up the extra module... I will need to look a little at seeing how the surefire report, cobertura coverage etc differ between the two approaches... It would be nice to get a two sets of each of those reports, which might be easier under the two module project... but I'm unclear if cobertura works cross module...
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Getting used to Maven
 
Similar Threads
Maven web project dependencies
Maven + Tiles + Struts2
Spring Major version '3' expected
java.util.MissingResourceException: Can't find bundle for base name in JSF Spring Maven project
Richfaces + Spring + Maven Setup help