Friday, November 28, 2008

Tutorial-like spring application with excel support. Step 1 - hello world

Recently our marketing decided that they urgently  need an application which will retrieve certain statistics from our database and return them as excel files. As long as our main application historicly does not really use any web framework (thus evolving into a framework on its own), I've decided that it is a really good time to continue introduction of Spring framework to our codebase. Spring framework is quite clean and useful dependency injection framework which also has a lot of stuff (like JdbcTemplate class and whole data access package) which really make a life of a developer easier. Dependency injection here basicly means that we can write special configuration file which allow us to create instances of classes we need with all the necessary parameters set via set methodsor constructor parameters - really simple and cool. 

So the two main things which made this application not absolutely trivial were 1) the application should be integrated with JNDI DataSource deployed in the JBoss application server 2)  it should return statistics as excel file. But before starting doing that we need to create a trivial Spring application which will be a base for further development. To start working with Spring in a web application we should add necessary spring libraries (in our case they are - spring-core.jar, spring-web.jar, spring-webmvc.jar and spring.jar) and add the following code to the web.xml configuration file:

<listener>
   <listener-class>
  org.springframework.web.context.ContextLoaderListener
</listener-class>
 </listener>
 
 <servlet>
   <servlet-name>dispatch</servlet-name>
   <servlet-class>
  org.springframework.web.servlet.DispatcherServlet
</servlet-class>
   <load-on-startup>1</load-on-startup>
 </servlet>
 
 <servlet-mapping>
   <servlet-name>dispatch</servlet-name>
   <url-pattern>/get/*</url-pattern>
 </servlet-mapping>
The whole concept behind that is quite trivial: we added a listener class which is being called when application is initialized, loads bean configuration from  configuration file (applicationContext.xml by default) and loads the [servletname]-servlet.xml configuration files for the servlets with [servletname] defined in web.xml. To make it work properly we also need to create an aplicationContext.xml file (which we will leave empty) and dispatch-servlet.xml file which configures the main servlet of the application:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="viewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
  <property name="prefix" value="/WEB-INF/jsp/"/>
  <property name="suffix" value=".jsp"/>
</bean>
<bean id="urlMapping"
    class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
  <property name="mappings">
    <props>
      <prop key="/*">dispatchController</prop>
    </props>
  </property>
</bean>
<bean id="dispatchController"
   class="com.goaiss.internal.stats.web.DispatchController">
 </bean>
</beans>

And again nothing really magical happens here, we define a view resolver - a class which responsible for locating a resulting view for a request - in the most simple case it is a jsp file. Than we tell application that all the urls coming to this servlet will be handled by a controller named dispatchController which we define in the last bean declaration. After doing that we just need to create a simple jsp file e.g. test.jsp, DispatchController class (yeah, that's true you need to occasionally write java code while dealing with Spring) which will be super tiny:

public class DispatchController extends MultiActionController {
   public ModelAndView actionTest(HttpServletRequest request,
                                   HttpServletResponse response)
                       throws Exception {
        return new ModelAndView("test");
   }
}

and now we are ready to put a link to index.jsp file e.g. <a href="get/actionTest">Hello world!</a> and say "Hello world" in the most simple Spring application :) 

Eclipse project for the this application can be found here

Wednesday, November 12, 2008

setting up javarebel with eclipse and jboss

I like simple things and things which do not bother me and do not try to tell me how to do the things, that's why I'm using Linux and program in Java with Eclipse IDE. And also I happen to be boring enough to like server side development. Sometimes it is a bit embarrasing to answer a question about my hobby, after I already told that I do java serverside for living. But anyway, there is a thing which annoys me that much, that I even thought about using script languages (argh!) sometimes (unfortunately - they annoy me even more). Luckily there is a nice project called JavaRebel (used for on-the-fly class reloading) which together with JSP Weaver another project of the same company (which tries to do the same thing for JSP) makes the situation better. And as long as I tend to forget how to set the things up after I do it once - I will describe the whole process in a small tutorial.

First I've created an empty workbench for eclipse, added jboss server to the servers view and added a petclinic project from Spring samples, so that default ant task will build an application, pack it to the war file and deploy it to my local JBoss (that's how I usually configure the applications I work with), all in all - it looks like that:

So now the initeresting part of story - JavaRebel is the jvm agent which means that it is loaded with a JVM, receives its events and controls it magicly reloading changed classes on the fly. So after downloading it from zeroturnaround site you need to set up JBoss so that the virtual machine it is running on has this agent. For doing that you need to select JBoss server in Eclipse servers view (nobody likes running servers from a command line right? :)), double click on it, select "open launch configuration" and add JavaRebel arguments to the VM arguments:

-noverify -javaagent:/path/to/javarebel/lib/javarebel.jar -Drebel.dirs=/paths/to/class/folders/bin

/path/to/javarebel/lib/ - path to a folder where you unzipped javarebel library

/path/to/class/folders/bin -  path where the compiled .class files bein placed (by default eclipse puts it to bin folder of your project)

It should look something like:

After that, make sure that the automatic publishing is switched on (the same screen where the "open launch configuration" link was).  And you can launch JBoss. The first message in the server console should show that JavaRebel is successfully launched - e.g.

It will be a bit different if you do not have a license though :)  The easiest way now to check if the voodoo has worked (for petclinic of course) is to comment out some validation from org.springframework.samples.petclinic.validation.OwnerValidator than go to http://localhost:8080/petclinic/addOwner.do and try to add an empty one - the commented out validation will not be triggered and you'll see the following message in the server console:

INFO [STDOUT] JavaRebel: Reloading class 'org.springframework.samples.petclinic.validation.OwnerValidator'.

That's really cool, JavaRebel's hot redeploy works in 95% of real life situations in my experience  (yeah it does have limitations) but it does not really bug me.

The sad part of this story is JSP Weaver which is still unable to handle most of real life scriptlets (sometimes even the simple ones like &lt;jsp:setproperty name="ad" property="language" value="&lt;%= lang %>" /> are showstoppers for it). Scriptlets are evil, I know, sometimes though they are lesser evil and I really hope it will be fixed in the near future so I could change "make the situation better" to "solve the problem" and add a JSP Weaver installation chapter to this tutorial.