Wednesday, September 4, 2013

JRebel and maven overlays

It was a while ago when I have posted on issues related to using JRebel with Intellij and maven. Today I would like to say few words about web applications.
Actually, I have configured JRebel for the first time because of web apps :). Well, because we couldn't use exploded wars. Can you imagine redeploying heavy war file only to check fix for something as complicated as spelling error ? Well, I couldn't. For this basic scenario default JRebel configuration for web comes in handy. What do we have here ? The classpath space of a war is mapped to target directory whereas web content to source directory. Perfect. Now, every time I save a jsp file the change is reflected on the server. Obviously, JRebel is better than that. For example spring web-mvc is supported thus you can add new mappings to the controller on the fly.

Overlays

The maven-war-plugin comes with the overlaying feature. Overlays (when over-used) are pure evil ;), but sometimes you cannot do much about it. I will try to picture the idea with very simple example. In the figure you have two projects: web1 and web2. You can download the code from Github - last update contains the changes from current post.
I have configure the overlays to merge web2 module into web1. This can be achieved with configuration listed below. The empty overlay block is this handle so points to web1 project. As a result the resources from web2 will overlay web1's resources in case there is no exclusion specified. In the figure exclusion is marked with grey spot. As you can see the resulting war contains some resources from web1 (blue spots) and web2 (red spots). The resources from web1 are these excluded in configuration or not included in web2 module. The content of target war (only jsp's for simplification) is shown in the figure on the right. There are two files from web2 module and one from the web1 module. Ugly. In fact we have hello.jsp file in both modules.You can check the content of the web page after build & deploy procedure. When you point your browser to the action that results in hello.jsp you will see the content of the file from the web2 module.
Let's try it now with JRebel. For this experiment I will use configuration from the listing above. To run the server with JRebel you need to modify the run script or provide environment property. To enable JRebel for JBoss I have modified standalone.conf.bat adding set "JAVA_OPTS=%JAVA_OPTS% -javaagent:E:\path_to_rebel\jrebel.jar" to the configuration. After server restart you will see different content under the same location. It happened because the web folder from war is mapped to source folder in web1 module.

Modifying JRebel configuration

Lets try to achieve expected behaviour. JRebel configuration allows to add multiple directories, which is presented in the listing below. Using this configuration you should see following log messages in server log: So does it work as expected ? Nope. The content of hello.jsp from web1 module is rendered. You can try to reorder dirs in rebel.xml which helps from time to time. Actually, I was not able to reproduce this problem. I though I can pinpoint the problem playing with bigger project at work but here it works in 80% of cases. Anyway, situation is better than before. Now we are able to edit page3.jsp from the second module.
Fortunately, we can be better than that and provide a configuration that is compatible (and stable) with our overlays. When we define two link blocks the ordering from xml is preserved. So in this case web block looks like that: In case, this doesn't work for some specific version of JRebel there is only one thing you can do before bursting into tears. You can use include exclude blocks to shape the final JRebel mapping.

Final note

Web overlay mechanism is evil. You need know how does it work. You need to know locations of the files and the relations (especially overwrites) between them. When it comes to JRebel ... I wish directory definition is stable and better documented.

What comes next

In case you use the source project, you've probably got some problems with the configuration. There are full paths defined which work in my configuration and not necessary in yours. Next, time when talking about JRebel + maven I will share my opinion on how to survive sharing such a project within a team.

Thursday, August 22, 2013

JRebel, Intellij, and maven placeholders - lessons learned

In my last post I have mentioned that there are some scenarios where using JRebel is not so straightforward. But it does not mean it's complicated. There are three steps needed: think, configure, and run. For those of you who need some sandbox for experimentation there is trivial project deployed to GitHub. There are several revisions that will illustrate the problems and solutions I am discussing.

Think

The rule of thumb (in my opinion) is to work with the smallest deltas possible. Unfortunately, there are different conditions for capturing changes for different types of resources. Fortunately, we can handle most (if not all) of them.
The rebel configuration generated by the IDE plugin maps jar/war/ear config to default location. In case of jars, it is the build (target) folder. I am working with Intellij but my project's layout is defined by maven. Thus incremental changes to java classes are handled easily in the default configuration. Resource (like xml or property files) changes are captured by JRebel only if we update them in the build folder which (to my best knowledge) must be handled by maven. The situation of Eclipse users with m2e plugin on board is a way better as they can configure resource processing triggers.
Alternatively we can adjust rebel.xml configuration. In this way changes are captured as soon as files are saved. But ... This mode is not applicable when we have any preprocessing in resource files.
Finally, we can map several physical locations to a virtual one. There filtering mechanisms allow us to find the most optimal configuration for our needs.

Configure

JRebel can be configured in several different ways. First, the rebel.xml file might be generated by Eclipse/Intellij plugin (from what I've seen plugin for Eclipse is more powerful). Second you may configure maven plugin to generate rebel.xml file for you. Finally, you can just write it by yourself.
In the listing below a simple JRebel configuration for single module is provided: In this configuration the classpath of mod2.jar will be replaced with the content of build directory.
If we want to have to see immediate effect of the resource changes we can use the following configuration: In the above listening we combine the class path from two locations. The resources are monitored in source folder so every change triggers reconfiguration. Classes and other types of resources are collected from build directory. Thus, classes are updated on-the-fly after the recompilation.
Please note that in the previous scenario there will be an exception thrown in case there are maven placeholders in resource files. In this case we need to slightly modify our example. This way we capture instant changes to resource files, and changes to the property file triggered by maven resource processing.

Run

This is it we have chosen and configured our application (maybe in a separate maven profile) to be run with JRebel. Run it from within your IDE, or as agent in standalone mode.
In my next post I will try to describe my observations on using JRebel for maven web modules.

JRebel is great but what to do when you application is not a "typical" one.

I find JRebel a great tool. It may save you some/a lot of time depending on your scenario. There are plugins that allows for on-the-fly reconfiguration of multiple aspects of your application. You can perform a complete makeover to you Java classes, JSP resource, IoC configuration, aspects - to name only few.
I have capture a screencast  for a very simple example. There are few beans that are dynamically reconfigured - as well as the logging configuration.

But what to do with more complex scenarios ? In the following posts (or post) I will try to share my observations on using  JRebel in a project that:

  • is developed by multiple developers (using varying tools while maven is common denominator)
  • has multi-modular structure and quite few lines of code,
  • has several builds modes (e.g. production, development, and testing artifacts with varying configurations are possible)
  • uses nasty maven tricks including resources filtering, profiles, conditional configuration, overlaying and many more,
  • allows for building different products from partially common code-base
For the moment I will tell you one thing: default configuration is not sufficient here. 

Monday, August 19, 2013

Hibernate filtering behavior with cache.

As you may know there is a possibility in hibernate to handle objects visibility with filtering rules.
There are few issues worth remembering when filtering is combined with cache mechanism:

  • the filtering is not enabled by default (so if you want to use it for a session you need to enable filters)
  • the filtering bypasses second level cache. 
  • the filtering is not applied for Session.get or Session.load methods.