2011-09-21

When Vaadin Seems to Ignore Your Modifications

They first thing you’ll notice when trying the Vaadin 6 tutorial is how little code is needed for an interactive web app. The second thing you’ll notice is that when you modify the source code, nothing happens.

You might add a label to the form, for example, but at runtime the label fails to appear.

This is maddening when the joy of a new app turns into utter frustration. You might even quit Eclipse, restart, run your app, and still find your changes ignored. What’s going on? Well multiple bugs and features are biting.

Restart App

While developing and testing you may need to restart your Vaadin app. Do this by appending the app's URL in your web browser's address bar with:
?restartApplication
Another way is to append:
?debug
That approach displays a JavaScript window on top of your app’s window with buttons for restarting the app, as well as debugging your window's layout, and other features.

Session Persistance

First, if you are using Tomcat as your web server, you’ve discovered Tomcat's default feature where it persists a session object automatically when quitting. In a conventional app, the session has just a few simple values, probably just small pieces of text. So it makes sense to save those to disk, and restore those values to memory when the session is recreated at runtime. With Vaadin, the session object holds your entire Vaadin app including all the windows and their current state. Upon restarting the session, Tomcat restores your Vaadin app as it was running previously, like magic. Unfortunately, your Vaadin app's "init"  method is not run again. So your changes do not take effect. Makes sense, as the definition of the "init" method is to run when the app first begins, and in this case of Tomcat restoring your session, the app is already running so no need to call "init".

The solution is simple: Turn off the Tomcat feature of session persistence. Doing seems simple: Find and edit Tomcat’s "context.xml" file to uncomment the line:
<Manager pathname="" />
The trick is which "context.xml" to edit. No need to edit the one your Tomcat installation, which would affect all web apps. Instead, copy the "context.xml" from the tomcat/conf folder. Place that copy nested inside your project folder, and edit there:
/workspace/your_project/WebContent/WEB-INF/context.xml
Now you'll only be affecting this webapp, and not others.

I suggest doing turning off session persistence for every Vaadin app you create. Session persistence and restoration of a Vaadin app is a big deal. You should think through ramifications such as how to handle database connections. Admittedly it would be nice if users found their app in the same configuration as their last work session, but you need to develop and test appropriately.

Missing Pieces

When you run a Vaadin app in Eclipse, you are using the WTP (Web Tools Project) plugins set which handles getting your Eclipse session to find, configure, and run a web server with your web app. Unfortunately, WTP seems to have “issues”, as we say when speaking politely, when running your web app.

What actually happens is that WTP deploys a copy of your webapp to a hidden folder, and then invokes Tomcat. That works fine the first time. But upon successive times, WTP seems to get confused about what to copy over.

A workaround is to clear your web app from the hidden folder. Look for the hidden folder ".metadata" in your Eclipse workspace folder. Then ".plugins" > "org.eclipse.wst.server.core" > "tmp0" > "wtpwebapps". There you'll find your webapp's folder. You may delete it. But you must also delete this file to avoid confusing Eclipse: workspace/.metadata/.plugins/org.eclipse.wst.server.core/publish/publish0.dat

That workaround is tedious to do repeatedly. Another workaround is to avoid WTP altogether. Some folks on the Vaadin forums talk about running Jetty directly within your project, while avoiding WTP entirely. Jetty is built to be embeddable, so this is supposedly pretty easy. But I already know and use Tomcat, and want to be using it for development. And I did not want to learn yet another development arrangement. So I chose not to go that route, though it may a wise one.

Another workaround is JRebel. Some references to this product on the Vaadin forums led me to this remarkable product. JRebel pulls a few tricks to make development easier, especially web app development. It does seem to solve this problem of missing pieces while running within the IDE. I'm not clear on how JRebel accomplishes this, but it seems to be working well for me.

Hot Swapping Classes

Another frustration of web app development is making changes to classes and then having to shutdown and restart the web server all over again. The Java platform has built-in features for hot-swapping classes while still running the app. But for various reasons, those features do not work well with web-servers.

You can shutdown the web server by clicking in Eclipse's Servers panel, select your web server, and click the red square icon to perform a shutdown. But this gets tedious. And I often found myself with problems that seemed to require quitting and restarting Eclipse as well. Not fun.

Solution: JRebel, again. Swapping fresh classes while running is JRebel's raison d'être. I’ve only begun to work with JRebel for a few days, but it seems to be doing this hot-swap trick very well.

I Save File → Eclipse Re-compiles → JRebel Re-deploys

In fact, it works so well, I did not understand how to use it after installation. I made a change to a class, and then went back to the docs to see how to tell JRebel to compile and deploy it. I could not find any such doc. Frustrated, I switched back to Eclipse. There I noticed a fresh line in the console pane, something about SuchAndSuch class has been deployed. While not believing it, I did a restart of my app using the URL trick mentioned above, and voilà, my changed classes too effect. Apparently all I need is to save the .java file! Saving triggers Eclipse to automatically re-compile. The re-compile triggers JRebel to re-deploy of the changed class to Tomcat running via WTP within Eclipse. My fresh class was installed while Tomcat continued executing. Amazing. JRebel has a plugin for Eclipse that provides for this integration.

While not absolutely mandatory for Vaadin work, JRebel certainly makes life easier. They have a free-of-cost “Social” edition for non-commercial purposes while connected on the Internets, so give JRebel a try.

JRebel does not affect deploying your app to production. However, if you want to hot-swap parts of your app in production, LiveRebel is a sibling product designed for that purpose. JRebel is for development, while LiveRebel is for deployment.

Be sure to make the correct settings for JRebel, both when you install JRebel and each time you create a Vaadin project. For JRebel in Eclipse, read sections 2.2, 3.2, and 4.2 of the JRebel Reference Manual. Really quite easy.

2 comments:

  1. JRebel doesn't recompile the class for you, Eclipse does (when you press Ctrl+S). JRebel only detects that the class was recompiled and does its job.

    ReplyDelete