Posts Tagged ‘spring’

Spring and Jetty Integration

Wednesday, December 10th, 2008

Jetty is a pretty darn awesome J2EE web container. With amazing features like non-blocking IO, continuations and immediate integration with Cometd – I feel that it is a solid, production ready container.

I hate war files, I hate web.xml files – there’s just way too much black magic that needs to be done to get things up and running. It is nice once someone has done the dirty work, and got the initial web.xml constructed, but I wouldn’t want to be that person who starts it all off.

Oh – another thing – I absolutely LOVE dependency injection. Using the web.xml approach, you’ll almost always have to start off a servlet of some sort to initialise various services that you’ll need – moreover the easiest way to access these services on other servlets is to use singletons, and we all know why singletons are bad!

So, I end up using Jetty in an embedded setup, and used to write various wrappers around the configuration so that I can do most of the common things with minimal code. A good example will be to setup a bunch of contexts and a DefaultServlet for regular file serving. However, the way Jetty is written makes it really easy to be used in Spring – everything is a simple bean with a bunch of setters.

To start off, lets write down the bean. Notice I’ve added an init-method attribute to start(). If you don’t want Spring to kick off your server, then just grab hold of the bean and call start() on it explicitly.

<bean name="WebServer" class="org.mortbay.jetty.Server" init-method="start">
</bean>

Then, lets add some connectors to it:

<property name="connectors">
  <list>
  <bean name="LocalSocket" class="org.mortbay.jetty.nio.SelectChannelConnector">
      <property name="host" value="localhost"/>
      <property name="port" value="8080"/>
  </bean>
  </list>
</property>

You will need some handlers (one of them will be a context handler to serve your servlets). I’ve added a logging handler so that the server logs requests in the same format as apache’s combined log.

<property name="handlers">
  <list>
    <bean class="org.mortbay.jetty.servlet.Context">
      <property name="contextPath" value="/"/>
      <property name="sessionHandler">
        <bean class="org.mortbay.jetty.servlet.SessionHandler"/>
      </property>
      <property name="resourceBase" value="/var/www"/>
      <property name="servletHandler">
        <bean class="org.mortbay.jetty.servlet.ServletHandler">
          <property name="servlets"> <!-- servlet definition -->
            <list>
            <!-- default servlet -->
            <bean class="org.mortbay.jetty.servlet.ServletHolder">
              <property name="name" value="DefaultServlet"/>
              <property name="servlet">
                <bean class="org.mortbay.jetty.servlet.DefaultServlet"/>
              </property>
              <property name="initParameters">
                <map>
                  <entry key="resourceBase" value="/var/www"/>
                </map>
              </property>
            </bean>
            </list>
          </property>
          <property name="servletMappings">
            <list><!-- servlet mapping -->
            <bean class="org.mortbay.jetty.servlet.ServletMapping">
              <property name="pathSpecs">
                <list><value>/</value></list>
              </property>
              <property name="servletName" value="DefaultServlet"/>
            </bean>
            </list>
          </property>
        </bean>
      </property>
    </bean>
    <!-- log handler -->
    <bean class="org.mortbay.jetty.handler.RequestLogHandler">
      <property name="requestLog">
        <bean class="org.mortbay.jetty.NCSARequestLog">
          <property name="append" value="true"/>
          <property name="filename" value="/var/log/jetty/request.log.yyyy_mm_dd"/>
          <property name="extended" value="true"/>
          <property name="retainDays" value="999"/>
          <property name="filenameDateFormat" value="yyyy-MM-dd"/>
        </bean>
      </property>
    </bean>
  </list>
</property>

And thats about it. If you need to add more servlets, then all you have to do is add an entry to ServletHandler’s properties for servlets and servletMappings.

Now, image if I had to get a reference to a DAO, or some other service in my servlet – it’s just going to be a matter of adding a member, exposing it via a setter and whacking in the dependency on the servlet Spring config above. All done in nice dependency injected way. No more overriding init() on the servlet and picking up some context attribute via some magic string. The best part of this

Here’s the whole Spring config – hack away to your needs!

<bean name="WebServer" class="org.mortbay.jetty.Server" init-method="start">
<property name="connectors">
  <list>
  <bean name="LocalSocket" class="org.mortbay.jetty.nio.SelectChannelConnector">
    <property name="host" value="localhost"/>
    <property name="port" value="8080"/>
  </bean>
  </list>
</property>
<property name="handlers">
  <list>
    <bean class="org.mortbay.jetty.servlet.Context">
      <property name="contextPath" value="/"/>
      <property name="sessionHandler">
        <bean class="org.mortbay.jetty.servlet.SessionHandler"/>
      </property>
      <property name="resourceBase" value="/var/www"/>
      <property name="servletHandler">
        <bean class="org.mortbay.jetty.servlet.ServletHandler">
          <property name="servlets"> <!-- servlet definition -->
            <list>
            <!-- default servlet -->
            <bean class="org.mortbay.jetty.servlet.ServletHolder">
              <property name="name" value="DefaultServlet"/>
              <property name="servlet">
                <bean class="org.mortbay.jetty.servlet.DefaultServlet"/>
              </property>
              <property name="initParameters">
                <map>
                  <entry key="resourceBase" value="/var/www"/>
                </map>
              </property>
            </bean>
            </list>
          </property>
          <property name="servletMappings">
            <list><!-- servlet mapping -->
            <bean class="org.mortbay.jetty.servlet.ServletMapping">
              <property name="pathSpecs">
                <list><value>/</value></list>
              </property>
              <property name="servletName" value="DefaultServlet"/>
            </bean>
            </list>
          </property>
        </bean>
      </property>
    </bean>
    <!-- log handler -->
    <bean class="org.mortbay.jetty.handler.RequestLogHandler">
      <property name="requestLog">
        <bean class="org.mortbay.jetty.NCSARequestLog">
          <property name="append" value="true"/>
          <property name="filename" value="/var/log/jetty/request.log.yyyy_mm_dd"/>
          <property name="extended" value="true"/>
          <property name="retainDays" value="999"/>
          <property name="filenameDateFormat" value="yyyy-MM-dd"/>
        </bean>
      </property>
    </bean>
  </list>
</property>
</bean>

Follow up on XP-Dev.com release

Thursday, November 20th, 2008

A quick follow up post on the recent release of XP-Dev.com. There were some bugs that needed to be resolved. Some pretty critical ones, while others were just minor annoyances. However, the dust should have settled now. I’m not saying that there aren’t any bugs left, but most have been fixed. Of course, if you do notice anything odd, please raise a support ticket and we’ll resolve it asap.

I decided to take it easy the past couple of days, as I’ve been working on XP-Dev.com like a maniac for the past 4 weeks. Just to give this some context – I began rewriting the whole of XP-Dev.com from 16th October 2008 and released it on 17th November 2008, which is about a months worth of work. I current site has 13k lines of Java (not including unit tests) and 2k lines of HTML/Velocity templates. There’s about 1k lines of XML, but most of that is just Spring configuration (NOT their web framework – I’m only using Spring for IOC), and I had a day job to take care of. There was plenty of refactoring done during this time, and these numbers are only the final figures. All in all – a crazy month, but well worth it!

It is a complete re-write with a whole new custom MVC framework and object relational mapper (ORM) layer. I’m seriously considering releasing the MVC framwork as open source (the ORM needs some work!), which I think is pretty darn good – writing new dynamic pages and forms is a breeze! Now, I’m sure a lot of you might be wondering why I embarked on such an ambitious journey ? Well, stay tuned as I will be posting a series of blog posts on how I re-engineered and re-architected XP-Dev.com, and the reasons behind those decisions.

The new XP-Dev.com has only been released for 3 days and I did get quite a few mails from users who expressed their gratitude. I can’t begin to thank all of you for those kind emails and support tickets – it is really good to know that there are plenty of you out there who are happy users, and that the past month has been well worth it! I’ve got many more ideas to put into XP-Dev.com, so, think of the recent release as the beginning of something new :)