Thursday, October 11, 2007

Getting Maven and Eclipse to work together to filter resources

I don't really care for any of the Eclipse plugins currently available for Maven (m2eclipse or Q4E), however I do like the Maven plugin for eclipse (it seems to be the only one that works). At Overstock.com everyone uses Eclipse, so as we are moving to Maven it is important that Maven work well in the IDE. Most folks checkout their code, develop and then check there code back into svn via Eclipse, never hitting the command line. Obviously, the Maven Eclipse plugin won't be good for them, so currently we are using m2eclipse for Eclipse/Maven integration. One of the problems I've been running into is filtering resources, I believe if you are using m2eclipse and you choose (from the popup menu) Maven -> Update Source Folders all your resources will be filtered (if you have filtering turned on in your pom.xm). I don't want to do that and folks will forget to do it, furthermore, since I do use the Maven Eclipse plugin (requiring the command line) and I don't use m2eclipse, this won't work for me. So how do you get Maven and Eclipse to work together? This feature request for m2eclipse provides some pointers. Eugene suggests using a Maven build(er), but I cannot do that (because I'm not using m2ecilpse and I couldn't get it to work correctly when I tried), so I'll use a Program builder instead. In the Package Explorer, right click on your project and select properties, this brings up the Properties for xxx dialog box. In the list on the left, choose Builders, as shown in the image below (click on any of the images below for a larger version): Next, click the New... button and choose the Program builder: In the Properties for New_Builder (1) dialog box, use the Browse File System... button to locate your copy of the mvn executable. For the Working Directory section, click the Browse Workspace... button and select your project. For the Arguments section add the following:
resources:resources resources:testResources
Here is how the dialog should look like so far: To finish things off, select the Build Options tab at the top of the Properties for New_Build (1) dialog box and make sure the During auto builds check box is selected (actually you want all check boxes under Run the builder to be checked except for During a "Clean"). Next select the Specify working set of relevant resources check box and then click Specify Resources.... In the dialog box that pops up, navigate to your src/main/resources and src/test/resources folders and click the check box to the left so these folders are included in your working set, click Finish. Here is what the Build Options tab should look like: That's it, now when you refresh your workspace, try to run a unit test, etc. all your resources are filtered just as if you were doing it from the command line. If you have a way to do this correctly with m2eclipse or Q4E please let me know. Update: you may want to add the -o command line switch for Maven so that it doesn't try to look for JARs to download. You will want to add -o to the resources:resources... code above. Update 2: If you are using the m2eclipse plugin, check out Eugene Kuleshov's response to this post. Also, if you decide to keep using an external builder, you'll want to make sure the "Refresh resources upon completion." check box is selected on the Refresh tab of the builder dialog box. Update 3/12/08: In the "Build Options" section above you'll need to select all options under "Run the builder", so that it runs both during and after a clean. Also, I no longer use the m2eclipse builder, I only use a Program Builder.

13 comments:

Eugene Kuleshov said...

We certainly do know how to configure this with m2eclipse. :-)

Chris Maki said...

Hi Eugene

Thanks for the follow-up post. I just tried it out and it works like a champ. I'll start using that when I use m2eclipse :-) BTW, is this something you could add to m2eclipse so folks don't have to manually do this for every project?

Chris

Eugene Kuleshov said...

Actually I have an idea how to make it work without adding this external builder. Stay tuned. :-)

Chris Maki said...

I'm looking forward to hearing more about what you have in mind. I'm switched to using the m2 builder for filtering but now every time I save a file, the builder kicks in and it's starting to really bug me :-)

Felix Röthenbacher said...

Is it possible to use m2eclipse plugin to copy filtered resources to a server (i.e. publish)
with WTP?

mmue said...

Great HowTo. Its really the solution to all my resources problems .... I thought. I realised that the Eclipse "just copy the resources" function is still in place and starts after I triggered the maven process resources.
The only two solutions I found are:
1. Exclude all files from the resources folder in the BuildPath configuration
or
2. Remove the resources folder completely as source folder

Both work but are not configurable from the maven-eclipse-plugin and therefore have to be configured manually for each project (in a larger project not acceptable).

I wonder what you found for a solution for this problem?

Chris Maki said...

Hi felix röthenbacher

I'm not sure if m2eclipse can do this but you might want to ask eugene kuleshov, he created the m2eclipse plugin.

Chris

Chris Maki said...

Hi mmue

The filter process I outlined in the post works for me, however, I've made a few changes to the way I use it at work. Specifically, I now use a Program Builder and not an m2eclipse builder (I only use Q4E now btw). I'll update the post in a second, but the you'll need to check all the options available on the Build Options tab, under "Run the builder:", this means the builder runs during and after a clean, that seems to make it all work correctly. Let me know if that fixes things for you.

Chris

wow power leveling said...
This comment has been removed by a blog administrator.
daveyjones said...
This comment has been removed by the author.
Anonymous said...

As pointed out on another blog it is a manual process to configure the builder in eclipse, every developer in a team must do that themselves and then whenever you run mvn eclipse:eclipse the eclipse settings are lost.

However you can configure the eclipse plugin in the pom.xml to generate the necessary eclipse build configuration as follows:

<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<additionalBuildcommands>
<buildCommand>
<name>org.ui.externaltools.ExternalToolBuilder</name>
<triggers>auto,full,incremental,</triggers>
<arguments>
<LaunchConfigHandle>&lt;project&gt;/.mavenResources.launch</LaunchConfigHandle>
</arguments>
</buildCommand>
</additionalBuildcommands>
<additionalConfig>
<file>
<name>.mavenResources.launch</name>
<content>
<![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${maven.home}/bin/mvn.bat"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="resources:resources resources:testResources"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="$${workspace_loc:/profitmaker-webapp}"/>
</launchConfiguration>
]]>
</content>
</file>
</additionalConfig>
</configuration>
</plugin>
...
</plugins>

Carlo LF said...

A really great tip! The process-ressources goal was indeed the only reason for me to install m2eclipse. But because it didn't work well with WST I had a lot of problems.
So please, don't you ever delete this blog entry, because I made a link to it in our developper FAQ.

RustamAbd said...

The previous post by Anonymous is good, but there is still some dependency on project name. Here's a plugin config that is really independent of project name and can be copied to other POM's as-is:


<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<additionalBuildcommands>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>auto,full,incremental,</triggers>
<arguments>
<LaunchConfigHandle>&lt;project&gt;/.externalToolBuilders/mvn-resources.launch</LaunchConfigHandle>
</arguments>
</buildCommand>
</additionalBuildcommands>
<additionalConfig>
<file>
<name>.externalToolBuilders/mvn-resources.launch</name>
<content>
<![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="true"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="&#36;{working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;launchConfigurationWorkingSet editPageId=&quot;org.eclipse.ui.resourceWorkingSetPage&quot; factoryID=&quot;org.eclipse.ui.internal.WorkingSetFactory&quot; label=&quot;workingSet&quot; name=&quot;workingSet&quot;&gt;&#13;&#10;&lt;item factoryID=&quot;org.eclipse.ui.internal.model.ResourceFactory&quot; path=&quot;/${project.artifactId}/src/main/resources&quot; type=&quot;2&quot;/&gt;&#13;&#10;&lt;/launchConfigurationWorkingSet&gt;}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="$${system_path:mvn.bat}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="resources:resources"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="&#36;{workspace_loc:/${artifactId}}"/>
</launchConfiguration>]]>
</content>
</file>
</additionalConfig>
</configuration>
</plugin>