CXF & Spring web service implementation on JBoss 7
nward1 Dec 14, 2011 9:13 PMI can't seem to get a web service implementation class that is configured using Spring Framework to work on JBoss 7. I tried using the standard JAX-WS web.xml servlet setup as well as the standard Spring web.xml setup and having my web service implementation extend SpringBeanAutowiringSupport to autowire a field. However, the field never gets set. The web service did work on JBoss 5 with the JBoss Native ws stack. So, I think the CXF JBoss ws stack doesn't work with SpringBeanAutowiringSupport. I also tried configuring Spring support in JBoss per the JBossWS-CXF installation instructions and using jboss-cxf.xml to configure the web service implementation class via Spring. However, I'm getting an error waying that org.jboss.wsf.stack.cxf.InvokerJSE is not found (i.e. ClassNotFoundException).
Here's the details of my JBoss and web application setup. Any ideas what I'm missing or where I can find a good example similar to this situation?
I'm using JBoss 7.0.2 in standalone mode. I renamed standalone-preview.xml to standalone.xml to enable JAX-WS support on JBoss 7, which by default using CXF. I also installed the Spring jboss module per the JBossWS-CXF installation instructions (using JBossWS-CXF 4.0.0.CR1).
Here's the relevant web service related code and configuration files...
{toc}
web.xml
{code}
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Medication Risk Web Service</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:META-INF/spring/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>medicationRiskWebService</servlet-name>
<servlet-class>com.seg.medicationrisk.webservice.MedicationRiskWebServiceImpl</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>medicationRiskWebService</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
{code}
WEB-INF/jboss-cxf.xml
{code}
<beans xmlns='http://www.springframework.org/schema/beans' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:beans='http://www.springframework.org/schema/beans'
xmlns:jaxws='http://cxf.apache.org/jaxws'
xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.w3.org/2006/07/ws-policy http://www.w3.org/2006/07/ws-policy.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd'>
<bean name="medicationRiskService" class="com.seg.medicationrisk.service.MedicationRiskServiceImpl" />
<bean id ="medicationRiskWebService" class="com.seg.medicationrisk.webservice.MedicationRiskWebServiceImpl">
<property name="medicationRiskService" ref="medicationRiskService"/>
</bean>
<!-- implementor specifies a bean id per the leading "#" character.
See: http://cxf.apache.org/docs/jax-ws-configuration.html for details.
-->
<jaxws:endpoint
id="medicationRiskWebServiceEndPoint"
implementor="#medicationRiskWebService"
address="http://localhost:8080/MedicationRiskService-1.0.0-SNAPSHOT">
<jaxws:invoker>
<bean class="org.jboss.wsf.stack.cxf.InvokerJSE" />
</jaxws:invoker>
</jaxws:endpoint>
</beans>
{code}
src/main/resources/META-INF/spring/applicationContext.xml
{code}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:property-placeholder location="classpath*:META-INF/spring/*.properties" />
<context:spring-configured />
<context:component-scan base-package="com.seg">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
type="annotation" />
</context:component-scan>
<bean name="medicationRiskService" class="com.seg.medicationrisk.service.MedicationRiskServiceImpl" />
</beans>
{code}
Web Service Implementation Class
Note that this class delegates to the medicationRiskService POJO class that is Autowired, but medicationRiskService is currently null at run-time.
{code}
/**
*
*/
package com.seg.medicationrisk.webservice;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import com.seg.medicationrisk.MedicationRiskService;
import com.seg.medicationrisk.service.IMedicationRiskService;
@WebService(
serviceName = "MedicationRiskService",
targetNamespace = "http://medicationrisk.seg.com/",
endpointInterface = "com.seg.medicationrisk.MedicationRiskService",
wsdlLocation = "WEB-INF/wsdl/MedicationRiskService.wsdl",
portName="MedicationRiskServiceSOAP")
public final class MedicationRiskWebServiceImpl extends SpringBeanAutowiringSupport implements
MedicationRiskService {
@Autowired
private IMedicationRiskService medicationRiskService;
public IMedicationRiskService getMedicationRiskService() {
return medicationRiskService;
}
public void setMedicationRiskService(
IMedicationRiskService medicationRiskService) {
this.medicationRiskService = medicationRiskService;
}
/* (non-Javadoc)
* @see com.seg.medicationrisk.MedicationRiskService#determineToxicLevel(java.util.List)
*/
@WebMethod
public String determineToxicLevel(List<String> medication) {
return medicationRiskService.calculateToxicLevel(medication);
}
}
{code}
pom.xml
{code}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.seg</groupId>
<artifactId>MedicationRiskService</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>MedicationRiskService</name>
<description>MedicationRiskService</description>
<properties>
<cxf.version>2.4.4</cxf.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jetty.version>6.1.4</jetty.version>
<spring.version>3.0.5.RELEASE</spring.version>
<slf4j.version>1.5.10</slf4j.version>
<java.version>1.6</java.version>
<junit.version>4.8.2</junit.version>
<aspectj.version>1.6.12</aspectj.version>
</properties>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!-- Spring Dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/webapp/WEB-INF/wsdl/MedicationRiskService.wsdl</wsdl>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<packagingExcludes>WEB-INF/web.xml</packagingExcludes>
</configuration>
</plugin>
<!-- Facilitates downloading source and javadoc in Eclipse -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.8</version>
<configuration>
<wtpversion>2.0</wtpversion>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<!-- Plugin to run and test through maven -->
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.25</version>
<configuration>
<scanIntervalSeconds>3</scanIntervalSeconds>
</configuration>
</plugin>
<!-- Ensures we are compiling at 1.6 level -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<!-- Tomcat plugin for embedded tomcat -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
<version>1.1</version>
<configuration>
<path>/${project.build.finalName}</path>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.cxf
</groupId>
<artifactId>
cxf-codegen-plugin
</artifactId>
<versionRange>
[2.4.3,)
</versionRange>
<goals>
<goal>wsdl2java</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
{code}
WEB-INF/wsdl/MedicationRiskService.wsdl
{code}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://medicationrisk.seg.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="MedicationRiskService" targetNamespace="http://medicationrisk.seg.com/">
<wsdl:types>
<xsd:schema targetNamespace="http://medicationrisk.seg.com/">
<xsd:element name="determineToxicLevel">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="medication" type="xsd:string" maxOccurs="unbounded" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="determineToxicLevelResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="toxicLevel" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="determineToxicLevelRequest">
<wsdl:part element="tns:determineToxicLevel" name="parameters"/>
</wsdl:message>
<wsdl:message name="determineToxicLevelResponse">
<wsdl:part element="tns:determineToxicLevelResponse" name="parameters"/>
</wsdl:message>
<wsdl:portType name="MedicationRiskService">
<wsdl:operation name="determineToxicLevel">
<wsdl:input message="tns:determineToxicLevelRequest"/>
<wsdl:output message="tns:determineToxicLevelResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="MedicationRiskServiceSOAP" type="tns:MedicationRiskService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="determineToxicLevel">
<soap:operation soapAction="http://www.com/MedicationRiskService/determineToxicLevel"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="MedicationRiskService">
<wsdl:port binding="tns:MedicationRiskServiceSOAP" name="MedicationRiskServiceSOAP">
<soap:address location="http://localhost:8080/MedicationRiskService-1.0.0-SNAPSHOT"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
{code}