Chapter 5. Develop and deploy Spring-MVC (OSGi-fied) project


Our Spring-DM Target Platform contains enough bundles to define itself as Spring-MVC/web-enabled platform. So, in this chapter we will go through the steps on how to develop web Spring-MVC based project and deploy it inside of our Target Platform.

We are going through the following steps:

  • Create Web Project as Eclipse Plug-in project

  • Define configurations required to deploy it inside of Spring-DM

  • Deploy Spring-MVC project into Spring-DM Target Platform

We are only going to go through essential steps. The full source for this project is available here.

 

The Use Case foe this project is to provide the UI to interact with the Reverser service we’ve created earlier. So we’ll define a simple Form where we will be able to enter the String value and submit it. In return we should get our String back in reversed order.


Prerequisite:  Create Tomcat Configurations

To create a new We Project as Eclipse plug-in project follow identical procedure we went through in chapter 3.1 Create Spring-DM Servoce Project.

No you need to make sure that our Tomcat is properly configured. Since this tutorial was updated to use Tomcat 6 distribution available via Spring Source Enterprise Bundle Repository you need to provide some extra Catalina configuration. To accomplish this you will attach two Fragment bundles to the com.springsource.org.apache.catalina bundle. To develop and attach the Fragment you would follow the same steps you did when you were creating Log4J Fragment Bundle. But to save time these Fragment bundles are already provided as part of this distribution, so export them as Projects into your Eclipse or STS workspace and make sure they are selected in the Workspace part of your Target Platform launch configuration. 

The Fragment bundles you'll be working with are:
- catalina.config - provides default conf/web.xml configuration to the Catalina bundle. (nothing exciting)
- server.config - provides server configuration parameters in conf/server.xml (e.g., port etc...). Use this fragment to manage ports and other Tomcat configurations.

This is pretty much it.
Start your Target Platform and make sure you see Server output (port etc. . .) in your console.

====================================================================================
. . . . . .
1436 [SpringOsgiExtenderThread-2] INFO  org.springframework.beans.factory.support.DefaultListableBeanFactory  - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@ecb654: defining beans [stringReverserOsgi,stringReverser]; root of factory hierarchy
1452 [Tomcat Catalina Start Thread] INFO  org.apache.coyote.http11.Http11Protocol  - Starting Coyote HTTP/1.1 on http-8888
1463 [Tomcat Catalina Start Thread] INFO  org.springframework.osgi.web.tomcat.internal.Activator  - Succesfully started Apache Tomcat/6.0.18 @ Catalina:8888
1485 [Tomcat Catalina Start Thread] INFO  org.springframework.osgi.web.tomcat.internal.Activator  - Published Apache Tomcat/6.0.18 as an OSGi service
. . . . . . 
====================================================================================

5.1. Create Web Project as Eclipse Plug-in project

To create a new We Project as Eclipse plug-in project follow identical procedure we went through in chapter 3.1 Create Spring-DM Servoce Project


The only difference we must name our project so in ends in .war 

Withe release of Spring-DM 1.1 .0 Web Extender component of Spring-DM no longer recognizes web bundles based on existance of WEB-INF/web.xml at the root of the bundle. Instead it only looks at the name of the bundle (packaged or exploded). And if file/directory doe not end with WAR it wil not be treated as web bundle.

So we are going to name our project simpleweb.war


To save time, instead of creating project from scratch, import it from the resources provided


Once done, our project will have the following structure:



Obviously it is not a standard OSGi bundle structure, thus when packaging we will not be able to use Export Plug-in functionality we used earlier. But since any bundle is just a JAR file we can use JAR command or JAR utility provided by Eclipse and package it that way. There are also maven-jar-plugin  and maven-war-plugin which could be utilized very nicely to package web applications as OSGi bundles.

But for now since it is just another plug-in project we wouldn't need to package it. Instead it will be deployed automaticly into our target platform as Workspace resource by Eclipse PDE.


Our Context Root for this application will be the obvious, which is the name of the WAR file. It means once deployed our application would be available at http://[yourhost:port/simpleweb


[Tip]Tip:
You can also read section 8.4 Configuring Web Extender section of Spring-DM reference manual to see that there is another way of specifying Context Root, by supplying Web-ContextPath header in your MANIFEST file (e.g. Web-ContextPath: springmvc where springmvc would become Context Root of your application)

5.2. Define OSGi specific deployment configurations

Some extra details of Spring-MVC specifics overall web integration with Spring-DM environment are provided in section 8. Web-support of Spring-DM reference manual.

Even though our project is a very basic Spring-MVC implementation, there are few things that are worth mentioning:

 

In order to be properly used inside of OSGified web platform we need to define special Web Application Context implementation which is “. . .dedicated, OSGi-aware. . .” Web Application Context to bootstrap our web configuration in Spring-DM environment. This class called OsgiBundleXmlWebApplicationContext

Below is a fragment of web.xml. There you’ll see how we define this Application Context using init-param contextClass. We do it for both Web Application Context (Dispatcher Servlet), as well as Root Application Context (Context Loader)

==================================================================================== 
. . . . . . . . . .
<context-param>
 <param-name>contextClass</param-name>
 <param-value>
 org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
 </param-value>
</context-param>
<listener>
 <listener-class>
 org.springframework.web.context.ContextLoaderListener
 </listener-class>
</listener>

<servlet>
 <servlet-name>osgiwebmvc</servlet-name>
 <servlet-class>
 org.springframework.web.servlet.DispatcherServlet
 </servlet-class>
 <init-param>
 <param-name>contextClass</param-name>
 <param-value>
org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
 </param-value>
 </init-param>
 <load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
 <servlet-name>osgiwebmvc</servlet-name>
 <url-pattern>/osgi/*</url-pattern>
</servlet-mapping>
. . . . . . . . . .
====================================================================================


The biggest difference from Standard Web project vs. OSGified Web project is its ability to integrate with class loading mechanism defined by OSGi™. This means that although this is a basic web project it is still an OSGi™ bundle, thus requiring proper import entries in MANIFEST file.

The current MANIFEST for this project looks like this:

====================================================================================
Manifest-Version: 1.0
Bundle-Version: 1.0
Bundle-SymbolicName: simpleweb.war
Bundle-Name: Simple Web MVC Bundle
Bundle-Vendor: Spring Framework
Bundle-ManifestVersion: 2
Bundle-ClassPath: WEB-INF/classes/
Import-Package: javax.servlet.http;version="2.5.0",
javax.servlet.jsp;version="2.0.0",
javax.servlet.jsp.jstl.core;version="1.1.2",
javax.servlet.jsp.jstl.fmt;version="1.1.2",
javax.servlet.jsp.jstl.tlv;version="1.1.2",
org.apache.taglibs.standard.resources;version="1.1.2",
org.apache.taglibs.standard.tag.rt.core;version="1.1.2",
org.apache.taglibs.standard.tei;version="1.1.2",
org.apache.taglibs.standard.tlv;version="1.1.2",
org.springframework.osgi.sample.service,
org.springframework.osgi.web.context.support;version="1.1.0",
org.springframework.stereotype;version="2.5.5",
org.springframework.web.bind.annotation;version="2.5.5",
org.springframework.web.context;version="2.5.5",
org.springframework.web.servlet;version="2.5.5",
org.springframework.web.servlet.view;version="2.5.5"
Require-Bundle: org.springframework.osgi.servlet-api.osgi
====================================================================================

The two important entries here are: 

 

Bundle-Classpath: - which points to the location of all our class files

Import-Package: - Which imports all the packages required by this bundle to work.

 

The only thing left is to package our project and deploy it. As far as packaging, WAR file is a valid OSGi™ bundle, so jarring it into WAR and dropping it into your Target Platform will work.

However, in the next step we will look how to deploy it without packaging (exploded), which could be very useful when developing a new project and changes are frequent. 

 

One other interesting point worth mentioning is how we interact with Simple Service (our string reverser)


Our applicationContext.xml uses osgi name space to specify reference to OSGi service we exported from Simple Service bundle we created earlier (Chapter 3). It also specifies the interface we want this service to be referenced by. Obviously this service had to be published under this interface to begin with.

==================================================================================== 
. . . . . . . . . .
<osgi:reference id="stringReverser">
 <osgi:interfaces>
<value>org.springframework.osgi.sample.service.StringReverser</value>
 </osgi:interfaces>
</osgi:reference>
. . . . . . . . . .
====================================================================================
There are no more deviations from standard Spring-MVC patterns.
 

5.3. Deploy Spring-MVC project into Spring-DM Target Platform

Deploying Spring-MVC project into Spring-DM Target platform is identical to the way we deployed our Simple Service project. Just start Target Platform and if you didn't miss the Log4J cnfiguration step earlier you should see simmilar  message at eth bottom of yoru console

====================================================================================
. . . . . .
3024 [Timer-2] INFO org.springframework.osgi.web.deployer.tomcat.TomcatWarDeployer 
 - Successfully deployed bundle [Simple Web MVC Bundle (simpleweb.war)] at
 [/simpleweb] on server org.apache.catalina.core.StandardService/1.0
. . . . . . 
====================================================================================

Your bundle was successfully started and deployed to Tomcat.

Hit this link http://localhost:8080/webmvc-osgi/ and you should see the front page of our Spring-MVC application. 

 

 

That's all there is to it.