Tuesday, September 1, 2009

Spring DM , OSGI and WAR deployment

I spent some time trying to figure out how to run Tomcat web app under Spring DM and Apache Felix OSGI container.
First let`s look at ./conf/config.properties , here is list of modules to load:

1) Felix core and felix shell:
file:bundle/org.apache.felix.shell-1.2.0.jar \
file:bundle/org.apache.felix.shell.tui-1.2.0.jar \
file:bundle/org.apache.felix.bundlerepository-1.4.0.jar \
2) Spring DM jars:
file:bundle/com.springsource.net.sf.cglib-2.1.3.jar \
file:bundle/com.springsource.org.aopalliance-1.0.0.jar \
file:bundle/com.springsource.slf4j.api-1.5.0.jar \
file:bundle/com.springsource.slf4j.log4j-1.5.0.jar \
file:bundle/com.springsource.slf4j.org.apache.commons.logging-1.5.0.jar \
file:bundle/log4j.osgi-1.2.15-SNAPSHOT.jar \
file:bundle/org.springframework.aop-2.5.6.A.jar \
file:bundle/org.springframework.beans-2.5.6.A.jar \
file:bundle/org.springframework.context-2.5.6.A.jar \
file:bundle/org.springframework.core-2.5.6.A.jar \
file:bundle/org.springframework.web-2.5.6.A.jar \
file:bundle/spring-osgi-core-1.2.0.jar \
file:bundle/spring-osgi-extender-1.2.0.jar \
file:bundle/spring-osgi-io-1.2.0.jar \
3) Servlet API jar
file:bundle/com.springsource.javax.servlet-2.4.0.jar \
4) Tomcat Catalina and Tomcat starter jars:
file:bundle/catalina.osgi-5.5.23-SNAPSHOT.jar \
file:bundle/catalina.start.osgi-1.0.0.jar \
5) Spring DM Tomcat integration jars
file:bundle/spring-osgi-web-1.2.0.jar \
6) Spring DM web extender , it listens when war bundle gets deployed and hooks it up with tomcat
file:bundle/spring-osgi-web-extender-1.2.0.jar \
7) and finally war file itself
file:bundle/ui.war

to make war file work is OSGI environment I added some properties /META-INF/MANIFEST.MF file, here is ant script code that does it:

<target name="war" depends="build" description="Create a war file">
<pathconvert property="jar.classpath" pathsep=", ">
<mapper>
<chainedmapper>
<flattenmapper/>
<globmapper from="*" to="WEB-INF/lib/*"/>
</chainedmapper>
</mapper>
<path>
<fileset dir="./war/WEB-INF/lib"/>
</path>
</pathconvert>

<mkdir dir="build/jars"/>
<jar destfile="build/jars/ui.war"
basedir="war">
<manifest>
<attribute name="Bundle-Version" value="1.0"/>
<attribute name="Bundle-ManifestVersion" value="2"/>
<attribute name="Web-ContextPath" value="ui"/>
<attribute name="Bundle-SymbolicName" value="com.ddao.ui"/>
<attribute name="Bundle-Name" value="My UI"/>
<attribute name="Export-Package" value="com.ddao.ui"/>
<attribute name="Import-Package"
value="javax.servlet,javax.servlet.http,javax.servlet.resources,org.springframework.osgi.web.context.support,org.osgi.framework,org.springframework.web.context,org.springframework.web.context.support,org.springframework.beans.factory.config"/>
<attribute name="Bundle-Classpath" value="WEB-INF/classes, ${jar.classpath}"/>
</manifest>
</jar>
</target>


I added next lines to web.xml to make sure Spring is using right application context type:


<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>



Spring configuration is expected to be in /WEB-ING/applicationContext, here is example:

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

<osgi:reference id="osgiSerivceExample" interface="com.ddao.services.OsgiExampleService" cardinality="0..1"/>

<bean id="myDataServlet" class="com.ddao.ui.server.MyDataServlet">
<property name="osgiService" ref="osgiSerivceExample"/>
</bean>
</beans>


To inject OSGI services into servlet I used autowire factory:

@Override
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
final WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
applicationContext.getAutowireCapableBeanFactory().configureBean(this, "myDataServlet");
}



hope this will help you to save time.

No comments:

Post a Comment

Followers