Monday, November 22, 2010

Using Eclipse with multi level Maven project structure

Yesterday I've been struggling with setting up Eclipse to work with some project having multi level Maven project structure. Eclipse uses its own flat project layout and isn't able to handle this properly. I've tried multiple approaches to achieve this project working, being built and debug in Eclipse. Finally I've found some workaround.

By multi level Maven project I mean following layout:

|- project
   |- pom.xml    <-- parent pom.xml
   |- project1   <-- subproject 1
      |- src
      |- pom.xml <-- subproject pom.xml using parent pom.xml
   |- project2   <-- subproject 2
      |- src
      |- pom.xml <-- subproject pom.xml using parent pom.xml

In such layout we cannot simply import subprojects into workspace separately and use maven 2 eclipse plugin, because they use upper level pom.xml. On the other hand - we cannot have subproject in Eclipse project subfolder. It seems to be no easy way to have it working.

There are also some other problems, for example I wanted to have everything in single subversion node to be transparently checked in and updated. My subprojects used some resources and other code from main project, and from each other. The additional fun was the requirement to have all projects run in single Tomcat instance working in IDE in debug mode. But after longer time I've found a soultion.

To do the job you need M2eclipse only. First start with checking out the repo into a single project. After this, you have the project in workspace with no sources, not even Java project. And this won't be your really used project, but will be useful to operate on svn.

Now you have to download somewhere appropriate maven version and setup in Window | Preferences | Maven | User Settings path to maven conf/settings.xml file. I don't know if it is really necessary because I haven't played without it.

We will use standard Dynamic Web Project with linked sources from our main project to configure whole env in following steps:
  1. Create Dynamic Web Project.
  2. Uncheck Use default location and select project1 dir from workspace in field below. Here I've had some NullPointerException with setting Dynamic Web Module facet on this project. If you have that too, after creation you need to enable Dynamic Web Module facet manually in project properties, Project Facets section. After these steps you should have Dynamic Web Project with Maven layout, linked to project1 dir. You probably have there single source folder.
  3. Click on project and select Maven | Enable dependency management from context menu. Maven should correct source paths and configure libs - you should have now few source dirs there. Now the Maven is enabled and after cleaning and building project you should have the project properly built. You can experience only some "missing artifact" problems with pom, but they're harmless. If your project is not built properly, check Java Build Path entries in project properties and fix the problems. Previously I run command line maven compilation to download all necessary libraries into repository, so if Eclipse can't found libs maybe you have to do it.
  4. When you can build project properly, the last thing is to setup server deployment policy. You can do it in Deployment Assembly section of project properties. On the beginning it's completely invalid and configured to work with standard eclipse Dynamic Web Project. Remove everything there, and add:
    • /src/config/YOURCONFIG deployment to /WEB-INF/classes (using Add | Folder)
    • /src/main/java -> /WEB-INF/classes
    • /src/main/resources -> /WEB-INF/classes
    • /src/main/webapp -> /
    • Maven Dependencies -> /WEB-INF/lib (using Add | Java build path entries)
  5. You can now remove unnecessary build and WebContent directories from your project.
Now, add your project as Server Runtime Module and try to rebuild everything, publish and run in the server. You should now be able to work with code from eclipse with the maven layout. You can now create other projects in workspace, linked with different subprojects in your super-project, and configure them as web modules too, to be working together. The last problem I encountered has been a fact, that Eclipse deploys all Maven Dependencies into /WEB-INF/lib directory, event those marked for "provided" scope. This can results with problems, when these libs conflict with those from server runtime. These problems can appear in various ways (I've had some JSP exception, since the jsp-api.jar has been overridden). Unfortunately there is no simple solution neither in Eclipse nor M2eclipse to exclude these files (at least I haven't been able to find something working). I've overcome this problem with another workaround - I've built the project manually using package maven goal, and the I joined libs from generated webapp to Deployment Assembly in project properties, instead of whole Maven Dependencies.

No comments:

Post a Comment