Friday, March 20, 2009

JBoss Seam Hot Deploy with Maven - Update

I just published an updated version of the Seam Hotdeploy Maven Plugin (see my previous post here). For a detailed description on how to use it, have a look at the Google Code Wiki. I also updated the sample Maven POM featuring JBoss Seam 2.1.1.GA.

The new version should be easier to configure and play nicer with e.g. the Eclipse Maven plugin (I'm not using NetBeans/IntelliJ too often, but I hope this works also fine there). The new Eclipse builder configuration looks like shown in the image below:



Note: The Eclipse Maven plugin using its embedded Maven had somehow problems with the extended lifecycle of the Hotdeploy Plugin. Using an external Maven installation (2.0.10) felt not only faster but was also not having problems with it.

30 comments:

Anonymous said...

This is great but I do have an issue in that the Eclipse builder runs every 2 seconds. Is is possible to trigger the build only when the code or resources change or when I manually want to build?

Unknown said...

I've seen this behavior when the build did some sort of resource refresh (which probably included the Maven target folder), triggering itself all the time. Anything like that you might have active in your build settings?

Anonymous said...

It happens whenever the workspace gets refreshed.

What do you mean by "some sort of resource refresh"? I copied your pom.xml file and turned off the java builder as I don't think it is needed. Right?

Anonymous said...

I also see this in the Console:
[INFO] [build-helper:add-source {execution: add-source}]
[INFO] Source directory: C:\dev\SeamM2Test\src\main\hot added.

Why does the hot directory get added? It is already there?

Can you also explain:
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!

Is there a way to fix this?

Unknown said...

For the source directory: Maven supports by default only one source folder (src/main/java). "Add" in this context means that the src/main/hot directory will be added to the list of folders getting compiled by the Maven compiler plugin.

For the platform encoding warning, see the discussion here.

Getting back to your initial problem: Is your Maven builder configured to refresh your workspace (builder refresh tab)? If so, this will most probably cause the builder to fire in a loop.

For the builder setup, I have the Java builder on, the newer version of the Maven Eclipse plugin works much better with it. It might help to:
- Create a new project with the Maven Eclipse wizard and the WAR-archetype and look at the project settings
- Let the Maven plugin sync your project settings with right-clicking your project and select Maven -> Update Project Configuration.

Hope that helps...

Miloslav Vlach said...

Hi, I have problem with task compiler:compile. The build-helper:add-source plugin adds files to this plugin and I can't deploy the application to the JBoss.
When I remove the plugin build-helper:add-source netbeans reports error on classes in hot folder.
Know somebody where make I error ?

Thanks Mila

Unknown said...

Hi Mila

Do you get a duplicate class error when deploying to JBoss? In case you used the linked sample POM, I just realized that the version number of the hot deploy plugin is not up to date there (should be 0.3.1). The plugin compares both output folders for compile:compile and hotdeploy:compile and skips classes present in both locations while packaging the WEB-INF/classes folder. Creating the filter patterns had a bug in a previous version.

Just update, run a clean, make sure the application is deleted from JBoss and try again.

BTW the sample POM will be deprecated in the near future. Instead, have a look at the Seam Archetype (ICEFaces support described here).

Lucian Ochian said...

Hey Thomas,

Your plug-in is really cool. Can you tell me how it can be configured for a production environment? What I am asking is how it can be configured so that the final war file doesn't have the WEB-INF/dev directory(eliminate the hot deployment).

Thanks,
Lucian

Unknown said...

Hi Lucian

I assume you refer to the seam-war packaging. Embarrassingly this is not in the plugin yet. Should be a simple flag where you can switch hot packaging.

...Expect a new plugin version this week. ;-)

Lucian Ochian said...

Thomas,

Thank you for the follow-up. Another problem is when the maven2> hot is executed, I get exceptions because the app server tries to deploy the app before the copy process is finished. It would be nice if the application is copied somewhere in a temporary location on the server and then moved to the deploy directory.

Thank you,

Lucian

Unknown said...

Hi Lucian
Thanks for your feedback! I have created two issues on Google code for your suggestions.

Anonymous said...

I used the new jbsarch type and successfully built my project with mvn archetype:generate -DarchetypeCatalog=http://tinyurl.com/jbsarch and mvn package using maven 2.2.0. I now wanted to import the project into Eclipse 3.5 m2 0.98 JDK 1.6.0_15 but first of all get an error: com.ctp.seam.maven:maven-hotdeploy-plugin' does not exist or no valid version could be found. Then when I use your settings for the maven builder I get: Required goal not found: hotdeploy:explode in com.ctp.seam.maven:maven-hotdeploy-plugin:0.3.1. What am I missing? Please help.

Anonymous said...

I think I fixed the issue by upgrading to cli 0.6.6 and explicitly adding version 0.3.1 version to the maven-hotdeploy-plugin in the webapp pom.xml

Anonymous said...

I am back where Eclipse rebuilds every two seconds when automatic build is turned on. This is rather frustrating and I have no idea how to turn this off. Please help

Anonymous said...

I think clear instructions on how to combine this great plug-in with Eclipse and an automatic build for hot deployment would be fantastic (Galileo 3.5, M2 0.9.9.200906081351, Apache Maven 2.2.0).

Your help is appreciated.

Unknown said...

@Lucian: New version out, see the release news.

@Bernhard: Will have to look at it. Using a Maven builder in Eclipse can be rather annoying (I got annoyed by the popups when editing XHTML files) so I also use the CLI plugin in the Seam archetype. For incremental deployments I'm usually down to less than 1 sec, which is really cool.

Has anyone played around with the Maven integration in JBoss Tools? I guess once this is final, that's more the way to go in Eclipse.

Miloslav Vlach said...

I have set the hotdeploy plugin version 0.3.1, but the classes directory still contains all classes. I think this is because of this:
[WARNING] Duplicate class filtering is active but this requires hot deployable classes to be compiled first [directory /home/mvlach/skoleni/vyreseno/seamtest1/target/classes-hotdeploy does not exist].

But seamtest1 contains the main pom and the compiled classes are in directory
.../seamtest1/seamtest1-webapp/target/classes-hotdeploy

I compile this by using mvn hotdeploy:exploded in the main directory. So the mvn -Pclean clean don't wokrs too.

The project is created by mvn archetype:generate -DarchetypeCatalog=http://tinyurl.com/jbsarch

Unknown said...

Hi Miloslav
The most up-to-date documentation of the archetype creation can be found on the Google code wiki:

http://code.google.com/p/ctpjava/wiki/JBossSeamMavenArchetype

It is correct that the hotdeploy:exploded goal (as well as the special clean) works only when run in the WAR module directory - imagine you have a utility JAR module which gets this goal called on (which happens when you run it in the parent POM location) - what should it do with it? So you have to run 'package' on the main module or the hotdeploy stuff in your WAR module.

I you want really fast build cycles, I'd also recomment to use the cli plugin in the WAR module: mvn cli:execute-phase and then simply 'hot' on the maven console. Runs the incremental build in usually < 1 sec.

Miloslav Vlach said...

Hello, thanks you for the answer. But I'm not succesfully. I follow the steps on the URL you have write, but the classes are not copied corretly.

I have create a blog entry, so please, read the entry - here I can't post pictures :(.

http://www.bpsolutions.cz/blog/-/blogs/jboss-seam-and-hotdeploy

Thanks Mila

Unknown said...

Hmm, weird. Can you confirm
- you have this result on a plain command line run without having it imported into NetBeans (Eclipse WTP compiled for some cases into src/main/webapp/WEB-INF/classes, which screws up hot deployment)
- and WEB-INF/dev exists in the target output and contains the Authenticator.class?

What the plugin does is to compare the regular compiler output (target/classes) and the hot deploy output (target/classes-hotdeploy) and creating Ant patterns to exclude classes from the regular compiler output when they are present in the hot deploy output.

Can you run maven with the -X switch? Should print the exclude pattern somewhere towards the end:

[DEBUG] Source exclude patterns: [...]

Miloslav Vlach said...

Hello, can you send mail email address, the log file are very long. mvlach--at--bpsolutions--dot--cz

Unknown said...

That line will do it:
mvn hotdeploy:exploded -X | grep 'exclude patterns'

Miloslav Vlach said...

Hi,

I have updated the source code like this:

protected void performClassPackaging(final SeamWarPackagingContext context) throws MojoExecutionException {
String[] excludes = context.isDuplicateClassExclusion() ? prepareExcludes(context) : null;

for (String file : excludes) {
System.out.println("File to exclude: " + file);
}

final PathSet main = getFilesToIncludes(context.getClassesDirectory(), null, excludes);

Iterator it = main.iterator();
while (it.hasNext()) {
Object o = it.next();
System.out.println("Item: " + o);
}


try {
copyFiles(Overlay.currentProjectInstance().getId(), context, context.getClassesDirectory(),
main, CLASSES_PATH, false);
} catch (IOException e) {
throw new MojoExecutionException(
"Could not copy webapp classes[" + context.getClassesDirectory().getAbsolutePath() + "]", e);
}
}

and this is log output...

getHotdeployOutputDirectory: /home/mvlach/etrader/etrader-www/etrader-www-webapp/target/classes-hotdeploy
File to exclude: /cz/bpsolutions/etraderwww/Dummy.class
Item: seam.properties
Item: messages_bg.properties
Item: components.properties
Item: cz/bpsolutions/etraderwww/Authenticator.class
Item: cz/bpsolutions/etraderwww/Dummy.class
Item: messages_it.properties
Item: messages_de.properties
Item: security.drl
Item: messages_tr.properties
Item: META-INF/persistence.xml
Item: META-INF/orm.xml
Item: messages_fr.properties
Item: messages_en.properties
[INFO] Webapp assembled in [165 msecs]
[INFO] [hotdeploy:exploded]

I don't know why, but the method getFilesToIncludes don't exclude the file from the pathset.

Mila

Miloslav Vlach said...

This implementation works for me:


protected void performClassPackaging(final SeamWarPackagingContext context) throws MojoExecutionException {
String[] excludes = context.isDuplicateClassExclusion() ? prepareExcludes(context) : null;
String[] excludes2 = new String[excludes.length];
int i = 0;
for (String file : excludes) {
if (context.getLog().isDebugEnabled()) {
context.getLog().debug("File to exclude: " + file);
}
if (file.startsWith("/")) {
excludes2[i] = file.substring(1, file.length());
} else {
excludes2[i] = file;
}
System.out.println("new fileName: " + excludes2[i]);
i++;
}

final PathSet main = getFilesToIncludes(context.getClassesDirectory(), null, excludes2);

try {
copyFiles(Overlay.currentProjectInstance().getId(), context, context.getClassesDirectory(),
main, CLASSES_PATH, false);
} catch (IOException e) {
throw new MojoExecutionException(
"Could not copy webapp classes[" + context.getClassesDirectory().getAbsolutePath() + "]", e);
}
}

Unknown said...

Can you file this as an issue on Google code? Thanks! Will have to check why the excludes behave differently...

BTW: String[] excludes might be null in the code above, which will result in a NullPointerException in the for loop resp. when accessing the length property.

Miloslav Vlach said...

Hi,

bug created.

Thanks you for the NPE, I know, but I want only find the problem. I will use this plugin (in my situation were in all class folders classes, so the NPE will not be thrown).

I think there is problem in linux environment.

Mila

Unknown said...

Unfortunately not:
- EJB 3 components are not hot deployable
- I'm still looking for a possibility to create an EAR archetype without copying the whole WAR archetype :-) Suggestions are very welcome...

For a regular EAR/EJB3 Seam archetype you might also check this Seam forum page.

Conor MacMahon said...

Hi Thomas,
Many thanks for your plugin, I have successfully used it to create a dummy webapp, and hot deployed a change to the Authenticator class.
However, anytime I do perform a 'hot' deploy via the maven console, I notice that the jboss does a full reload of the war to get that change in. Is that to be expected?
I ask, as I'm trying to configure seam and jboss, so that seam gui class changes can be hot deployed to jboss, but DO NOT require a full reload of the war. If you can think of a way to do that, I'd be very grateful for your comments and advice Thomas.
Agains thanks for the plugin,
Regards,
Conor

Unknown said...

Hi Conor
You're most likely using JBoss 5 then - I remember I got rid of the behavior with a hint somewhere in the Seam forum.
I'll check if I can dig this out again and put it into the Wiki.

Unknown said...

Hi Conor
Wiki is updated. Hope that helps.