Sunday, January 4, 2009

Task 3 - Rapid turnaround in Tapestry 5

The goal of this task is to learn how Tapestry can boost your productivity by allowing you to modify (some) files and see the changes immediately. This does not mean we will be learning how to configure the servlet container of your choice to reload the context when some files were changed. Oh no, I will be talking and demonstrating live class reloading.

I will continue to work on a web application from Task 1. Seeing is believing, so click on a play button of the screencast below to witness live class reloading in action.



Alternate location to view this screencast.

If you have already read the documentation at the official site, you probably know that you cannot change just any class and expect to be reloaded by the framework. A change to any loaded class inside the controlled package is noticed by the framework and acted appropriately upon. In case of our demo application the controlled packages are:

  • org.driving.school.pages
  • org.driving.school.components
  • org.driving.school.mixins
  • org.driving.school.base
We will be experimenting and exploring live class & template reloading in tasks to come.

As I “promised” in previous post I will tell you how to prepare your development environment to pick up changes in any CSS files your application will have. How can I be writing about something so basic after you have just watched a state of the art framework capability to pick up changes in class files? Well, if you are developing in Windows and using Jetty as your servlet container, then you will probably spend some time googling for a solution. I was.

But first let’s show the problem. In Eclipse (on Windows) open our school project. Add a css folder under src/main/webapp and create a new file school.css inside.
body {
color: red;
}

Then, modify Index.tml to include a reference to this CSS file. The head section should look like
<head>
<title>school Start Page</title>
<link rel="stylesheet" type="text/css" href="${asset:context:css/school.css}" />
</head>

Now start the web app if it was not already started. You should see


That is ok, red color as expected. Now change the color to black for instance in school.css in Eclipse while the web app is still running and save the changes. You will get


Now go googling. Just kidding, read on.

Stop web app by clicking on a red square in the Console view.

You have to get a copy of webdefault.xml file. Where? The safest way is to extract it from the jetty jar you are running your application with. If you look at the pom.xml file of the school application you will see a maven-jetty-plugin
<!-- Run the application using "mvn jetty:run" -->
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.9</version>
<configuration>
<!-- Log to the console. -->
<requestLog implementation="org.mortbay.jetty.NCSARequestLog">
<!-- This doesn't do anything for Jetty, but is a workaround for a Maven bug
that prevents the requestLog from being set. -->
<append>true</append>
</requestLog>
</configuration>
</plugin>

Notice the version 6.1.9. Navigate to %HOMEPATH%/.m2/repository/org/mortbay/jetty/jetty/6.1.9. Open jetty-6.1.9.jar and extract webdefault.xml file to src/main/resources/org/mortbay/jetty/webapp/ of the school project. Open this file in Eclipse and locate the section
<init-param>
<param-name>useFileMappedBuffer</param-name>
<param-value>true</param-value>
</init-param>

Change the value to false.
Modify pom.xml to look like
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.9</version>
<configuration>
<webAppConfig>
<defaultsDescriptor>src/main/resources/org/mortbay/jetty/webapp/webdefault.xml</defaultsDescriptor>
</webAppConfig>
<requestLog implementation="org.mortbay.jetty.NCSARequestLog">
<filename>target/yyyy_mm_dd.request.log</filename>
<append>true</append>
</requestLog>
</configuration>
</plugin>

The important part is which tells Jetty where to locate our modified webdefault.xml file. The need for this change we have made is described at http://docs.codehaus.org/display/JETTY/Files+locked+on+Windows.

Start the school web app. You will most likely get an error:

[INFO] Starting jetty 6.1.9 ...
2009-01-05 00:40:28.779::INFO: jetty-6.1.9
2009-01-05 00:40:28.789::WARN: failed ContextHandlerCollection@1e903d5
java.lang.IllegalArgumentException: Illegal context spec:null

WTF?

Change the version of the plugin to
<version>6.1.14</version>

Start the school web app again. Jetty started! If not, write a dirty comment on this blog.

What a detour. Do you still remember what we are trying to do? Type http://localhost:8080/school in the browser. Do you see the text in the color you have specified in the CSS file? Now change the color, save the school.css (you should not get an error dialog this time) and refresh the browser. Finally.







Reblog this post [with Zemanta]

6 comments:

  1. dobar članak ...

    Pozdrav Borut ... ja sam Marko iz Rijeke (Hrvaška) i do tvog bloga sam došao preko "tapestry central" bloga ... drago mi je da sam napokon shvatio da se netko, relativno blizu mene :-) bavi aktivno tim najboljim java web framework-om na svijetu ...

    Poslao sam vam pozivnicu na linked in, u istoj smo Apache Tapestry grupi.

    Velki pozdrav.

    ReplyDelete
  2. Hi, thanks for your article it is very interesting.

    Do you know why when I change the file out of eclipse the live class reloading doesn't work ?

    What is the diference between save the file inside eclipse and save it in an external editor ?

    Thanks in advance

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. ja sam Marko iz Rijeke (Hrvaška) i do tvog bloga sam došao preko "tapestry sikiş hikayelercentral" bloga ... drago mi je da sam napokon shvatio da se netko, relativno blizu mene :-) bavi aktivno tim najboljim java web framework-om na svijetu ...

    ReplyDelete
  5. This comment has been removed by a blog administrator.

    ReplyDelete