JBossWS-Native comes with support for both WS-RM 1.0 and WS-RM 1.1. In this sample we will show how to create client and endpoint communicating each other using WS-RM 1.1 The sample uses WS-Policy specification to configure WS-RM.
Creating the WS-RM based service and client is very simple. User needs to create regular JAX-WS service and client first. The last step is to configure WSRM.
The service
We will start with the following endpoint implementation (bottom-up approach):
package org.jboss.test.ws.jaxws.samples.wsrm.service; import javax.jws.Oneway; import javax.jws.WebMethod; import javax.jws.WebService; @WebService ( name = "SimpleService", serviceName = "SimpleService", wsdlLocation = "WEB-INF/wsdl/SimpleService.wsdl" targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wsrm" ) public class SimpleServiceImpl { @Oneway @WebMethod public void ping() { System.out.println("ping()"); } @WebMethod public String echo(String s) { System.out.println("echo(" + s + ")"); return s; } }
Let's say that compiled endpoint class is in directory /home/username/wsrm/native/classes. Our next step is to generate JAX-WS artifacts and WSDL.
Generating WSDL and JAX-WS Endpoint Artifacts
We will use wsprovide commandline tool to generate WSDL and JAX-WS artifacts. Here's the command:
cd $JBOSS_HOME/bin ./wsprovide.sh --keep --wsdl \ --classpath=/home/username/wsrm/native/classes \ --output=/home/username/wsrm/native/wsprovide/generated/classes \ --resource=/home/username/wsrm/native/wsprovide/generated/wsdl \ --source=/home/username/wsrm/native/wsprovide/generated/src \ org.jboss.test.ws.jaxws.samples.wsrm.service.SimpleServiceImpl
The above command generates the following artifacts:
# compiled classes ls /home/username/wsrm/native/wsprovide/generated/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/ Echo.class EchoResponse.class Ping.class # java sources ls /home/username/wsrm/native/wsprovide/generated/src/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/ Echo.java EchoResponse.java Ping.java # contract artifacts ls /home/username/wsrm/native/wsprovide/generated/wsdl/ SimpleService.wsdl
All aforementioned generated artifacts will be part of endpoint archive. The endpoint archive consists of the following files:
jar -tvf jaxws-samples-wsrm.war 0 Tue Apr 15 19:06:14 CEST 2008 META-INF/ 106 Tue Apr 15 19:06:12 CEST 2008 META-INF/MANIFEST.MF 0 Tue Apr 15 19:06:14 CEST 2008 WEB-INF/ 591 Tue Apr 15 19:05:42 CEST 2008 WEB-INF/web.xml 0 Tue Apr 15 19:06:14 CEST 2008 WEB-INF/classes/ 0 Tue Apr 15 19:04:50 CEST 2008 WEB-INF/classes/org/ 0 Tue Apr 15 19:04:50 CEST 2008 WEB-INF/classes/org/jboss/ 0 Tue Apr 15 19:04:50 CEST 2008 WEB-INF/classes/org/jboss/test/ 0 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/ 0 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/ 0 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/ 0 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/ 0 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/ 0 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/ 1385 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/SimpleServiceImpl.class 995 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/Echo.class 1043 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/EchoResponse.class 679 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/Ping.class 0 Tue Apr 15 19:06:14 CEST 2008 WEB-INF/wsdl/ 2934 Tue Apr 15 19:05:36 CEST 2008 WEB-INF/wsdl/SimpleService.wsdl
The content of web.xml file is:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>SimpleService</servlet-name> <servlet-class>org.jboss.test.ws.jaxws.samples.wsrm.service.SimpleServiceImpl</servlet-class> </servlet> <servlet-mapping> <servlet-name>SimpleService</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
Generating JAX-WS Client Artifacts
Before we will write regular JAX-WS client we need to generate client artifacts from WSDL. Here's the command to achieve that:
cd $JBOSS_HOME ./wsconsume.sh --keep \ --package=org.jboss.test.ws.jaxws.samples.wsrm.generated \ --output=/home/username/wsrm/native/wsconsume/generated/classes \ --source=/home/username/wsrm/native/wsconsume/generated/src \ /home/username/wsrm/native/wsprovide/generated/wsdl/SimpleService.wsdl
The above command generates the following artifacts:
# compiled classes ls /home/username/wsrm/native/wsconsume/generated/classes/org/jboss/test/ws/jaxws/samples/wsrm/generated/ Echo.class EchoResponse.class ObjectFactory.class package-info.class Ping.class SimpleService.class SimpleService_Service.class # java sources ls /home/username/wsrm/native/wsconsume/generated/src/org/jboss/test/ws/jaxws/samples/wsrm/generated/ Echo.java EchoResponse.java ObjectFactory.java package-info.java Ping.java SimpleService.java SimpleService_Service.java
Now the last step is to write the regular JAX-WS client using generated artifacts.
Writing Regular JAX-WS Client
The following is the regular JAX-WS client using generated artifacts:
package org.jboss.test.ws.jaxws.samples.wsrm.client; import java.net.URL; import javax.xml.namespace.QName; import javax.xml.ws.Service; import org.jboss.test.ws.jaxws.samples.wsrm.generated.SimpleService; public final class SimpleServiceTestCase { private static final String serviceURL = "http://localhost:8080/jaxws-samples-wsrm/SimpleService"; public static void main(String[] args) throws Exception { QName serviceName = new QName("http://www.jboss.org/jbossws/ws-extensions/wsrm", "SimpleService"); URL wsdlURL = new URL(serviceURL + "?wsdl"); Service service = Service.create(wsdlURL, serviceName); SimpleService proxy = (SimpleService)service.getPort(SimpleService.class); proxy.ping(); // one way call proxy.echo("Hello World!"); // request responce call } }
Now we have both endpoint and client implementation but without WSRM in place. Our next goal is to turn on WS-RM feature.
Turning on WS-RM 1.1
In order to turn on WS-RM in JBossWS-Native four steps are necessary:
- extend WSDL with WS-Policy containing both WSRM and WS-Addressing policy
- provide both endpoint and client jaxws configuration files
- update endpoint implementation to use endpoint jaxws file
- update client to use client jaxws file and close the sequence
Extending WSDL Using WS-Policy
To activate WSRM we need to extend WSDL with WSRM and addressing policy. Here is how it looks like:
<?xml version="1.0" encoding="UTF-8"?> <definitions name='SimpleService' targetNamespace='http://www.jboss.org/jbossws/ws-extensions/wsrm' xmlns='http://schemas.xmlsoap.org/wsdl/' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:tns='http://www.jboss.org/jbossws/ws-extensions/wsrm' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <!-- - - - - - - - - - - - - - - - - - - - - - - - - - --> <!-- Created WS-Policy with WSRM addressing assertions --> <!-- - - - - - - - - - - - - - - - - - - - - - - - - - --> <wsp:UsingPolicy/> <wsp:Policy wsu:Id="wsrm11policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <wsp:All> <wsp:ExactlyOne> <wsp:All> <ns1:RMAssertion xmlns:ns1="http://docs.oasis-open.org/ws-rx/wsrmp/200702"/> <ns2:UsingAddressing xmlns:ns2="http://www.w3.org/2006/05/addressing/wsdl"/> </wsp:All> </wsp:ExactlyOne> </wsp:All> </wsp:Policy> <types> <xs:schema targetNamespace='http://www.jboss.org/jbossws/ws-extensions/wsrm' version='1.0' xmlns:tns='http://www.jboss.org/jbossws/ws-extensions/wsrm' xmlns:xs='http://www.w3.org/2001/XMLSchema'> <xs:element name='echo' type='tns:echo'/> <xs:element name='echoResponse' type='tns:echoResponse'/> <xs:element name='ping' type='tns:ping'/> <xs:complexType name='ping'> <xs:sequence/> </xs:complexType> <xs:complexType name='echo'> <xs:sequence> <xs:element minOccurs='0' name='arg0' type='xs:string'/> </xs:sequence> </xs:complexType> <xs:complexType name='echoResponse'> <xs:sequence> <xs:element minOccurs='0' name='return' type='xs:string'/> </xs:sequence> </xs:complexType> </xs:schema> </types> <message name='SimpleService_echo'> <part element='tns:echo' name='echo'/> </message> <message name='SimpleService_echoResponse'> <part element='tns:echoResponse' name='echoResponse'/> </message> <message name='SimpleService_ping'> <part element='tns:ping' name='ping'/> </message> <portType name='SimpleService'> <operation name='echo' parameterOrder='echo'> <input message='tns:SimpleService_echo'/> <output message='tns:SimpleService_echoResponse'/> </operation> <operation name='ping'> <input message='tns:SimpleService_ping'/> </operation> </portType> <binding name='SimpleServiceBinding' type='tns:SimpleService'> <!-- - - - - - - - - - - - - - - - - - - - --> <!-- Associated WS-Policy with the binding --> <!-- - - - - - - - - - - - - - - - - - - - --> <wsp:PolicyReference URI="#wsrm11policy"/> <soap:binding style='document' transport='http://schemas.xmlsoap.org/soap/http'/> <operation name='echo'> <soap:operation soapAction=''/> <input> <soap:body use='literal'/> </input> <output> <soap:body use='literal'/> </output> </operation> <operation name='ping'> <soap:operation soapAction=''/> <input> <soap:body use='literal'/> </input> </operation> </binding> <service name='SimpleService'> <port binding='tns:SimpleServiceBinding' name='SimpleServicePort'> <soap:address location='REPLACE_WITH_ACTUAL_URL'/> </port> </service> </definitions>
We added wsp:UsingPolicy, wsp:Policy and wsp:PolicyReference elements to WSDL.
Providing Endpoint and Client JAX-WS Configuration Files
In order to activate WSRM in JBossWS-Native integration user have to provide both endpoint and client jaxws configuration files containing both addressing and WSRM handlers in the processing chain.
The endpoint jaxws configuration file, in our case we will call it wsrm-jaxws-endpoint-config.xml has the following content:
<?xml version="1.0" encoding="UTF-8"?> <jaxws-config xmlns="urn:jboss:jaxws-config:2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:javaee="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="urn:jboss:jaxws-config:2.0 jaxws-config_2_0.xsd"> <endpoint-config> <config-name>Standard WSRM Endpoint</config-name> <post-handler-chains> <javaee:handler-chain> <javaee:protocol-bindings>##SOAP11_HTTP</javaee:protocol-bindings> <javaee:handler> <javaee:handler-name>WSAddressing Handler</javaee:handler-name> <javaee:handler-class>org.jboss.ws.extensions.addressing.jaxws.WSAddressingServerHandler</javaee:handler-class> </javaee:handler> <javaee:handler> <javaee:handler-name>WSRM Handler</javaee:handler-name> <javaee:handler-class>org.jboss.ws.extensions.wsrm.jaxws.RMServerHandler</javaee:handler-class> </javaee:handler> </javaee:handler-chain> </post-handler-chains> </endpoint-config> </jaxws-config>
The client jaxws configuration file, in our case we will call it wsrm-jaxws-client-config.xml has the following content:
<?xml version="1.0" encoding="UTF-8"?> <jaxws-config xmlns="urn:jboss:jaxws-config:2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:javaee="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="urn:jboss:jaxws-config:2.0 jaxws-config_2_0.xsd"> <client-config> <config-name>Standard Anonymous WSRM Client</config-name> <reliable-messaging> <message-retransmission attempts="50" interval="10" timeout="10"/> </reliable-messaging> <post-handler-chains> <javaee:handler-chain> <javaee:protocol-bindings>##SOAP11_HTTP</javaee:protocol-bindings> <javaee:handler> <javaee:handler-name>WSAddressing Handler</javaee:handler-name> <javaee:handler-class>org.jboss.ws.extensions.addressing.jaxws.WSAddressingClientHandler</javaee:handler-class> </javaee:handler> <javaee:handler> <javaee:handler-name>WSRM Handler</javaee:handler-name> <javaee:handler-class>org.jboss.ws.extensions.wsrm.jaxws.RMClientHandler</javaee:handler-class> </javaee:handler> </javaee:handler-chain> </post-handler-chains> </client-config> </jaxws-config>
Note
Both client and endpoint jaxws configuration files are available in native WSRM tests. Users can copy them from there.
The next step is to include jaxws endpoint configuration file in META-INF directory of the endpoint archive.
jar -tvf jaxws-samples-wsrm.war 0 Tue Apr 15 19:06:14 CEST 2008 META-INF/ 106 Tue Apr 15 19:06:12 CEST 2008 META-INF/MANIFEST.MF 0 Tue Apr 15 19:06:14 CEST 2008 WEB-INF/ 591 Tue Apr 15 19:05:42 CEST 2008 WEB-INF/web.xml 0 Tue Apr 15 19:06:14 CEST 2008 WEB-INF/classes/ 0 Tue Apr 15 19:04:50 CEST 2008 WEB-INF/classes/org/ 0 Tue Apr 15 19:04:50 CEST 2008 WEB-INF/classes/org/jboss/ 0 Tue Apr 15 19:04:50 CEST 2008 WEB-INF/classes/org/jboss/test/ 0 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/ 0 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/ 0 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/ 0 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/ 0 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/ 0 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/ 1385 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/SimpleServiceImpl.class 995 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/Echo.class 1043 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/EchoResponse.class 679 Tue Apr 15 19:05:10 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/Ping.class 0 Tue Apr 15 19:06:14 CEST 2008 WEB-INF/wsdl/ 2934 Tue Apr 15 19:05:36 CEST 2008 WEB-INF/wsdl/SimpleService.wsdl 2033 Tue Apr 15 19:05:52 CEST 2008 META-INF/wsrm-jaxws-endpoint-config.xml
What about client side, the client jaxws configuration file must be available on the client classpath, in our case it will be available as META-INF/wsrm-jaxws-client-config.xml resource.
Updating Endpoint Code to Reference Custom JAX-WS Config File
Now we need to update endpoint implementation to reference custom JAX-WS configuration file. Here's the updated endpoint code:
package org.jboss.test.ws.jaxws.samples.wsrm.service; import javax.jws.Oneway; import javax.jws.WebMethod; import javax.jws.WebService; import org.jboss.ws.annotation.EndpointConfig; @WebService ( name = "SimpleService", serviceName = "SimpleService", wsdlLocation = "WEB-INF/wsdl/SimpleService.wsdl", targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wsrm" ) @EndpointConfig ( configFile = "META-INF/wsrm-jaxws-endpoint-config.xml", configName = "Standard WSRM Endpoint" ) public class SimpleServiceImpl { @Oneway @WebMethod public void ping() { System.out.println("ping()"); } @WebMethod public String echo(String s) { System.out.println("echo(" + s + ")"); return s; } }
As users can see we added JBossWS proprietary EndpointConfig annotation to reference the endpoint config.
Updating Client Code to Reference Custom JAX-WS Config File and Close the Sequence
Now we need to update client implementation as well to reference custom JAX-WS configuration file. We will also add the call to close the created sequence there. Here's the updated client code:
package org.jboss.test.ws.jaxws.samples.wsrm.client; import java.net.URL; import javax.xml.namespace.QName; import javax.xml.ws.Service; import org.jboss.ws.core.StubExt; import org.jboss.ws.extensions.wsrm.api.RMProvider; import org.jboss.test.ws.jaxws.samples.wsrm.generated.SimpleService; public final class SimpleServiceTestCase { private static final String serviceURL = "http://localhost:8080/jaxws-samples-wsrm/SimpleService"; public static void main(String[] args) throws Exception { QName serviceName = new QName("http://www.jboss.org/jbossws/ws-extensions/wsrm", "SimpleService"); URL wsdlURL = new URL(serviceURL + "?wsdl"); Service service = Service.create(wsdlURL, serviceName); SimpleService proxy = (SimpleService)service.getPort(SimpleService.class); ((StubExt)proxy).setConfigName("Standard Anonymous WSRM Client", "META-INF/wsrm-jaxws-client-config.xml"); proxy.ping(); // one way call proxy.echo("Hello World!"); // request responce call ((RMProvider)proxy).closeSequence(); } }
And that's all. Now user have both endpoint and client using WS-RM 1.1 when communicating each other.
Sample Sources
All sources from this tutorial are part of JBossWS-Native distribution.
Comments