How do you configure your machine in order to have save-and-refresh for Java web projects? When you ask this question to developers, the answer starts with “oh, well…”, and continues with a description of something that sort-of works. And everyone has his own way.
First – why do you need this? Because doing copying and restarting the server is a productivity killer – wastes a lot of your time. Without the productivity boost of syncing your project with the container, even for simple fixes, you may need a full build-and-deploy cycle before you can test it. And that may take a lot of time, depending on the size of the project.
I’ll write down a few, to complement my StackOverflow answer:
- IDE integration – IDEs have an option to add a local server and deploy projects to it. That requires additional plugins, configuring what workspace files go where in the servlet container, and doesn’t always work. And when there is Maven in the picture, it either doesn’t work, or requires yet another plugin (as described in this answer of mine)
- You use some tools for synchronizing directory structures. In Eclipse there’s the FileSync plugin, which let’s you configure which workspace files go where in the servlet container. Other tools may exist for doing the same thing (e.g. unison) , or you may have written some script or plugin to do it.
- Running the servlet container from maven (if using maven) – either the tomcat plugin or the jetty plugin let you do that. The downside is that in order to run in debug mode, you need to attach external debugger (rather than using the built-in IDE-server integration for that). And it requires the plugin configuration. Also, have in mind that if using jetty (the faster option) for development, there might be difference in behaviour if your production container is tomcat. Not much of a hassle, but still something to have in mind.
- Manually copying the project files – this doesn’t sound that terrible in the beginning, but then it starts bothering you – after all, it’s a task asking to be automated.
- Regular HotSwap – simply run the servlet container in debug mode. You get the bodies of your methods swapped whenever you change the class file. However, changing the method or class signatures requires restart. I’ve always used this option, and it hasn’t been that painful – after all method signature redefinition and refactoring don’t happen too often, and even when they do, it’s ok to restart the server, because you are not focused on getting some particular feature to work.
- DCEVM – a VM enhancement that allows complete reloading of classes. I haven’t used it, but if it works properly, it should address the signature redefinition problem mentioned above.
- JRebel – a commercial alternative. I’ve never used it, I’ve heard it’s good, and I know there are a lot of extras, that let you use it with various frameworks, so that reconfiguring the spring context, for example, doesn’t need a restart. I don’t think these things happen that often, and so I’ve never recommended JRebel (being commercial), but it’s an important option that you should consider.
- Restarting the server on every change. If the project is small, this takes very little time and might be an option. But I wouldn’t recommend it even for small projects, as at least HotSwap is very easy to configure (and you need debug mode anyway)
So many options – so typical for the Java world. And they work more or less fine. However, I decided to add one more option, that has almost zero-configuration – aardWARk.
It works by putting the aardwark.war file in your tomcat, renaming it, so that the name includes the path to your project directory, and it handles the syncrhonization. Note that this is an option added to the first list above. For hotswapping you’d still need one of the three options in the second list. There is a more detailed setup guide on the project page, but there are a few things to emphasize:
- it works only with maven projects. In order to have zero-configuration, the convention-over-configuration of maven needs to be used
- it is IDE-independent and servlet-container-independent.
- it does what I think no other solution above can do (apart from JRebel, probably) – it will synchronize the maven dependent projects as well. Normally, you have a multi-module project, where some projects are packaged as jars, and other (web) projects depend on them. But you need to be able to change a class in, say, the “core” module, and to immediately see the changes in the webapp. This would mean repackaging and reloading the jar. AardWARk simply parses the pom, finds the dependent projects and copies their classes to the classpath, which overrides the existing definitions
- multiple projects are supported, and also configuration via a properties file (if you don’t want or can’t name the war file to contain the path to the project)
- syncing jars files does not happen on changing the pom – you need to rebuild and restart. A bit of a workaround to embedding maven and running the dependency goal, but you need to restart anyway, if new jars are added.
- it’s called aardWARk for a simple reason – it would be best if this war file is loaded before the ones of your project. Not necessarily, as it is needed only for syncing the jar files, but preferably. Servlet containers do not guarantee the loading order of webapps, but it is likely that they are picked alphabetically – hence aardwark (war instead of var, for obvious reasons).
I hope it is a useful tool, and I’ll be glad if people start using it and give their feedback.