Tuscany Web Application based Integration with Geronimo
Introduction
Apache Tuscany provides a java implementation of the emerging SCA specifications for SOA. Apache Geronimo is a fully certified Java EE 5 application server runtime. The ability to deploy and run SCA composite applications with Geronimo will bring great value to both projects and communities. In this whitepaper, we will describe a simple web application based integration between Tuscany and Geronimo and walk through how to develop a web application using Apache Tuscany and deploy it to Apache Geronimo.
WAR Packaging Scheme
In this scheme, we simply package the application artifcts together with the required tuscany jars and dependencies into standard web application archive (WAR). The WAR can be deployed to the most popular web containers such as Geronimo, Tomcat, Jetty and WebSphere. Some container-specific deployment descriptor files may be added.
As illustrated in Figure 1, there are a few important files or folders in the WAR:
- META-INF/sca-contribution.xml: Defines the deployable composites for a given contribution
- WEB-INF/web.xml: Configures the web application with a tuscany servlet filter
- WEB-INF/geronimo-web.xml: Configures the web application to provide geronimo-specific deployment options
- WEB-INF/lib: Contains all the required tuscany jars and their dependencies
Figure 1. WAR packaging scheme
web.xml
In the web.xml, a tuscany provided servlet filter is configured to startup/shutdown the Tuscany runtime when the web application is started or stopped. The tuscany filter is also responsible to dispatch HTTP requests to HTTP-based bindings such as Web Services, JSONRPC and Atom/RSS Feed.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <display-name>Apache Tuscany Calculator Web Service Sample</display-name> <filter> <filter-name>tuscany</filter-name> <filter-class>org.apache.tuscany.sca.host.webapp.TuscanyServletFilter</filter-class> </filter> <filter-mapping> <filter-name>tuscany</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
geronimo-web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-2.0" xmlns:d="http://geronimo.apache.org/xml/ns/deployment-1.2"> <d:environment> <d:moduleId> <d:groupId>org.apache.tuscany.sca</d:groupId> <d:artifactId>sample-calculator-ws-webapp</d:artifactId> <d:version>1.2-incubating-SNAPSHOT</d:version> <d:type>war</d:type> </d:moduleId> <d:inverse-classloading /> </d:environment> </web-app>
sca-contribution.xml
<?xml version="1.0" encoding="UTF-8"?> <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="http://sample" xmlns:sample="http://sample" name="Calculator"> <component name="CalculatorServiceComponent"> <implementation.java class="calculator.CalculatorServiceImpl"/> <reference name="addService" > <interface.java interface="calculator.AddService" /> <binding.ws uri="http://localhost:8080/sample-calculator-ws-webapp/AddServiceComponent"/> </reference> <reference name="subtractService" target="SubtractServiceComponent"></reference> <reference name="multiplyService" target="MultiplyServiceComponent"></reference> <reference name="divideService" target="DivideServiceComponent"></reference> </component> <component name="AddServiceComponent"> <implementation.java class="calculator.AddServiceImpl"/> <service name="AddService"> <interface.java interface="calculator.AddService" /> <binding.ws/> </service> </component> <component name="SubtractServiceComponent"> <implementation.java class="calculator.SubtractServiceImpl"/> </component> <component name="MultiplyServiceComponent"> <implementation.java class="calculator.MultiplyServiceImpl"/> </component> <component name="DivideServiceComponent"> <implementation.java class="calculator.DivideServiceImpl"/> </component> </composite>
<?xml version="1.0" encoding="UTF-8"?> <contribution xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="http://sample" xmlns:sample="http://sample"> <deployable composite="sample:Calculator"/> </contribution>
Devloping a Tuscany web application for Geronimo using Maven and Eclipse
Test automation with maven
<!-- This profile handles generation of jar/war artifacts to be used in executing tests in a web-container --> <profile> <id>webapp</id> <activation> <activeByDefault>false</activeByDefault> </activation> <dependencies> <dependency> <groupId>org.apache.tuscany.sca</groupId> <artifactId>tuscany-host-webapp</artifactId> <version>1.2-incubating-SNAPSHOT</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.apache.tuscany.sca</groupId> <artifactId>tuscany-host-webapp-junit</artifactId> <version>1.2-incubating-SNAPSHOT</version> <scope>runtime</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.3</version> <scope>provided</scope> </dependency> </dependencies> <build> <pluginManagement> <plugins> <!-- Skip local junit test cases --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.3.1</version> <configuration> <skip>true</skip> </configuration> </plugin> </plugins> </pluginManagement> <plugins> <!-- Generate web-xml --> <plugin> <groupId>org.apache.tuscany.sca</groupId> <artifactId>tuscany-maven-web-junit</artifactId> <version>1.2-incubating-SNAPSHOT</version> <executions> <execution> <id>generate-web-xml</id> <phase>process-resources</phase> <goals> <goal>generate</goal> </goals> </execution> </executions> </plugin> <!-- Create war and include jUnit test classes --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.0.2</version> <configuration> <primaryArtifact>false</primaryArtifact> <!-- Exclude a few jars to avoid conflicts --> <warSourceExcludes>WEB-INF/lib/tuscany-host-tomcat-*.jar,WEB-INF/lib/tuscany-host-jetty-*.jar,servlet-api-*.jar, WEB-INF/classes/META-INF/sca-contribution*.xml</warSourceExcludes> <webResources> <resource> <directory>${project.build.directory}/test-classes</directory> <targetPath>WEB-INF/classes</targetPath> </resource> <resource> <directory>${project.build.directory}/classes/META-INF</directory> <includes> <include>sca-contribution*.xml</include> </includes> <targetPath>META-INF</targetPath> </resource> <!-- Add the junit --> <resource> <directory>${settings.localRepository}/junit/junit/4.2</directory> <includes> <include>junit-4.2.jar</include> </includes> <targetPath>WEB-INF/lib</targetPath> </resource> </webResources> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>war</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </profile> <profile> <id>geronimo</id> <activation> <activeByDefault>false</activeByDefault> </activation> <properties> <http.port>8080</http.port> <http.base>http://127.0.0.1:${http.port}</http.base> <geronimo.home>${env.GERONIMO_HOME}</geronimo.home> </properties> <build> <plugins> <!-- Generate web-xml and geronimo deployment descriptor --> <plugin> <groupId>org.apache.tuscany.sca</groupId> <artifactId>tuscany-maven-web-junit</artifactId> <version>1.2-incubating-SNAPSHOT</version> <executions> <execution> <id>generate-web-xml</id> <configuration> <geronimo>true</geronimo> </configuration> <phase>process-resources</phase> <goals> <goal>generate</goal> </goals> </execution> <execution> <id>web-junit-test</id> <configuration> <url>${http.base}/${project.build.finalName}/junit?op=runAll</url> </configuration> <phase>integration-test</phase> <goals> <goal>test</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.geronimo.plugins</groupId> <artifactId>geronimo-maven-plugin</artifactId> <version>2.0.2</version> <configuration> <geronimoHome>${geronimo.home}</geronimoHome> </configuration> <executions> <execution> <id>start-container</id> <phase>pre-integration-test</phase> <goals> <goal>start</goal> </goals> <configuration> <background>true</background> </configuration> </execution> <execution> <id>deploy-war</id> <phase>pre-integration-test</phase> <goals> <goal>deploy</goal> </goals> <configuration> <moduleArchive>${project.build.directory}/${project.build.finalName}.war</moduleArchive> </configuration> </execution> <execution> <id>undeploy-war</id> <phase>post-integration-test</phase> <goals> <goal>undeploy</goal> </goals> <configuration> <moduleId>${groupId}/${artifactId}/${version}/war</moduleId> </configuration> </execution> <execution> <id>stop-container</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> <configuration> <username>system</username> <password>manager</password> </configuration> </execution> </executions> </plugin> </plugins> </build> </profile>