• SEARCH BOX

Combine Jetty and Spring Application Context

Spring's Logo The goal of this post is to use one xml configuration file which is Spring's applicationContext.xml and load it only once for the duration of the application running in an embedded jetty server. Read more...

Tutorial on Android Layout

A thumbnail of adroid. Android is an open source platform for mobile devices. Not a hardware. It is a software stack as defined by Google. Encase your not familiar with the term, software stack is compose of an Operating System(OS), middle-ware and the key applications. Read more...

Hi, my name's Paul Labis.

I'm a developer in Makati City, Philippines. Focused on building online Java/J2EE based applications. I'm interested in freelance or part-time work from home.

Saturday, May 29, 2010

Combine Jetty and Spring Application Context XML Configuration

The goal is to use one xml configuration file which is Spring's applicationContext.xml and load it only once for the duration of the application. Using Embedded jetty as my lightweight server to run my Spring MVC application, I must tell my dispatcher servlets to use spring applicationContext.xml which already been loaded as its parent context. That way, dispatcher servlet will be able to  referenced bean configured on springs application context.

To do that, create a class that extends org.mortbay.jetty.Server and implement org.springframework.context.ApplicationContextAware. This is pretty straight forward, we extend jetty server so we can configure its parent context. We implemented spring application context aware so whenever spring successfully loaded applicatContext.xml bean configuration, it gets the current application context. We then configure it as parent context of servlets.

Code on ServerConfigurer.java:
package com.sample.config;

import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.ServletHandler;
import org.mortbay.jetty.webapp.WebAppContext;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.GenericWebApplicationContext;

public class ServerConfigurer
    extends Server
    implements ApplicationContextAware
{
    private String _webAppDir = null;
    private String _contextPath = null;
    private ServletHandler _servletHandler = null;
    private static ApplicationContext _applicationContext = null;

    public String getContextPath() {
        return _contextPath;
    }
    public ServletHandler getServletHandler() {
        return _servletHandler;
    }
    public String getWebAppDir() {
        return _webAppDir;
    }
    /**
     * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException
    {
        _applicationContext = applicationContext;
    }
    public void setContextPath(String contextPath) {
        _contextPath = contextPath;
    }
    public void setServletHandler(ServletHandler servletHandler) {
        _servletHandler = servletHandler;
    }
    public void setWebAppDir(String webAppDir) {
        _webAppDir = webAppDir;
    }

    @Override
    protected void doStart()
        throws Exception
    {
        final WebAppContext webAppContext = new WebAppContext(getServer(), _webAppDir, _contextPath);
        final GenericWebApplicationContext webApplicationContext = new GenericWebApplicationContext();
        webApplicationContext.setServletContext(webAppContext.getServletContext());
        webApplicationContext.setParent(_applicationContext);
 
webAppContext.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, webApplicationContext);
        webApplicationContext.refresh();
        webAppContext.setServletHandler(_servletHandler);
        addHandler(webAppContext);
        super.doStart();

    }
}

Text on bold note: Those are the pieces of code that basically are the most important in the server configurer. The setApplicationContext() method is the one that configures that gets the application context loaded by spring. The method doStart() is the one that does the story telling to web app that a current context has been loaded and it is the context should be used. 

Code on applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" >


    <!-- more beans configured -->
    <bean name="webServer" class="point to your server configurer java file" init-method="start">   
        <property name="connectors">
            <list>
                <bean class="org.mortbay.jetty.nio.SelectChannelConnector">
                    <property name="host" value="${jetty.host}"/>
                    <property name="port" value="${jetty.port}"/>
                </bean>
            </list>
        </property>

        <property name="webAppDir" value="${jetty.webApp.dir}"/>
        <property name="contextPath" value="${jetty.context.Path}"/>
       
        <property name="servletHandler">
            <bean class="org.mortbay.jetty.servlet.ServletHandler">
                <property name="servlets">
                    <list>
                        <bean class="org.mortbay.jetty.servlet.ServletHolder">
                            <property name="name" value="dispatcher" />
                            <property name="servlet">
                                <bean class="org.springframework.web.servlet.DispatcherServlet" />
                            </property>
                        </bean>
                    </list>
                </property>
                <property name="servletMappings">
                    <list>
                        <bean class="org.mortbay.jetty.servlet.ServletMapping">
                            <property name="servletName" value="dispatcher" />
                            <property name="pathSpec" value="*.htm" />
                        </bean>
                    </list>
                </property>
            </bean>
        </property>

        <property name="handlers">
            <list>
                <!-- 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="${http.log.dir}/access.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>
               
</beans>

That xml file comprise server configuration of your jetty server pointing dispatcher servlet use  Spring's application context. Your next step is run your application the way you want.
 example:
        _applicationContext = new ClassPathXmlApplicationContext(_resourceLocations);
        _applicationContext.start();


I also did another article related to Spring MVC/IOC-DI and Embedded Jetty utilizing applicationContext .xml of Spring. You might be interested running and configuring jetty through java code and not from applicationContext.xml.

Hope this helps! For suggestion, please feel free to leave your comments.

5 comments :

andersmartinsen said...

Which version of Spring are you using?

andersmartinsen said...

Nice article, but I get an compilation error on
_applicationContext.start();

Paul Labis said...

Hi andersmartinsen,

I have no clue why you get a compilation error. My guess is that you might have done something wrong on the class that extends jetty server.

I'm using spring version 2.5.5...

Regards,
Paul

msshapira said...

very nice + simple (relatively) clean implementation.

If you don't mind. please help with two issues:
a) if all my beans are in this "applicationContext.xml", what else should be in the "dispatcher-servlet.xml" (the compilation requires it...)

b) do you have any idea how, using this example, I could map an additional servlet: com.sun.jersey.spi.spring.container.servlet.SpringServlet so that I can use jersey and make the app RESTfull?

Regards.
Menachem

Paul Labis said...

Hi Menachem,

Thanks for your complement.

a. The spring controllers are placed on dispatcher-servlet.xml. This is an implementation where dispatcher servlet bean are able to re-use/reference one time loaded beans on application context. And oh, this is a solution for a spring MVC app..

b. Yes, there is a way though you have to figure it out to make it work with restfull.. To be able to add another servlet, you should be adding it in the list for servlet and servlet mapping on xml.

Hope you find this helpful.

Regards,
Paul

Post a Comment

 

Author

Followers

Techie Projects

Open Source