Continuing from part 1, this part will cover the following porting steps in

1.3 Porting Steps

  • 1.3.1 Naming conventions
  • 1.3.2 Generate stubs
  • 1.3.3 Ant target to generate stubs
  • 1.3.4 Test Webservices client
  • 1.3.5 Configure Logging SOAP packet (incoming and outgoing)
  • 1.3.6 Instructions for setting up SOAP packet logging on client side
  • 1.3.7 Test client code snippet

1.3.1 Porting Steps

To port JBoss Webservices stack from JBoss 4.0.4 to 4.2 >= without breaking interoperability from JAX-RPC style webservices to JAX-WS style web services few steps are required.
  • WSDL (which act as a contract) generated previously has to be modified to work with JAX-WS compliant JbossWS.
  • Some naming conventions has to be followed while generating new WSDL so that stubs are generated with ease.
  • Generate Stubs
  • Logging SOAP Packet Logging
1.3.1.1 Diffrences between WSDL's

Here is an old generated WSDL using JAX-RPC Stack on JBoss
<?xml version="1.0" encoding="UTF-8"?>

<wsdl:definitions name="matt_HelloWorld3" targetNamespace="http://www.vishal.com.au/matt.HelloWorld3"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.vishal.com.au/matt.HelloWorld3">


<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://localhost/matt/HelloWorld3/HelloWorld" xmlns:tns="http://localhost/matt/HelloWorld3/HelloWorld" xmlns:edm="http://www.vishal.com.au/matt.HelloWorld3">

<xsd:import namespace="http://www.vishal.com.au/matt.HelloWorld3"/>

<xsd:complexType name="HelloWorldRequest">
<xsd:sequence>

<xsd:element name="id" nillable="true" type="xsd:string"/>

</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="HelloWorldRespons">
<xsd:sequence>
<xsd:element name="result" nillable="true" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.vishal.com.au/matt.HelloWorld3"
xmlns:edm="http://www.vishal.com.au/matt.HelloWorld3"
xmlns:tns="http://localhost/matt/HelloWorld3/HelloWorld">

<xsd:import namespace="http://localhost/matt/HelloWorld3/HelloWorld"/>

<xsd:element
name="HelloWorld" type="tns:HelloWorldRequest"/>


<xsd:element name="HelloWorldRespons" type="tns:HelloWorldRespons"/>

</xsd:schema>

</wsdl:types>

<wsdl:message name="HelloWorld">
<wsdl:part name="HelloWorld" element="tns:HelloWorld"/>
</wsdl:message>
<wsdl:message name="HelloWorldOutput">
<wsdl:part name="HelloWorldRespons" element="tns:HelloWorldRespons"/>
</wsdl:message>
<wsdl:portType name="matt_HelloWorld3PortType">
<wsdl:operation name="HelloWorld">
<wsdl:input message="tns:HelloWorld"/>
<wsdl:output message="tns:HelloWorldOutput"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="matt_HelloWorld3Binding" type="tns:matt_HelloWorld3PortType">

<soap:binding
style="document" transport="http://schemas.xmlsoap.org/soap/http"/>

<wsdl:operation name="HelloWorld">
<soap:operation soapAction=""/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="matt_HelloWorld3Service">
<wsdl:port name="matt_HelloWorld3Port0" binding="tns:matt_HelloWorld3Binding">
<soap:address location="http://spthd01:5565/soap/DocLiteral"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>


Modified WSDL for JAX-WS stack in JBoss
<?xml version="1.0" encoding="UTF-8"?>

<wsdl:definitions
name="matt_HelloWorld3"
targetNamespace="http://www.vishal.com.au/matt.HelloWorld3"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.vishal.com.au/matt.HelloWorld3">



<wsdl:types>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.vishal.com.au/matt.HelloWorld3"
xmlns:edm="http://www.vishal.com.au/matt.HelloWorld3">



<xsd:element name="HelloWorld"
type
="edm:HelloWorldRequest"/>


<xsd:element
name="HelloWorldRespons" type="edm:HelloWorldRespons"/>

<xsd:complexType name="HelloWorldRequest">
<xsd:sequence>
<xsd:element name="id" nillable="true" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>

<xsd:complexType
name="HelloWorldRespons">

<xsd:sequence>
<xsd:element name="result" nillable="true" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

</wsdl:types>

<wsdl:message
name="HelloWorld">

<wsdl:part name="HelloWorld" element="tns:HelloWorld"/>
</wsdl:message>
<wsdl:message name="HelloWorldOutput">
<wsdl:part name="HelloWorldRespons" element="tns:HelloWorldRespons"/>
</wsdl:message>
<wsdl:portType name="matt_HelloWorld3PortType">
<wsdl:operation name="HelloWorld">
<wsdl:input message="tns:HelloWorld"/>
<wsdl:output message="tns:HelloWorldOutput"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="matt_HelloWorld3Binding" type="tns:matt_HelloWorld3PortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="HelloWorld">
<soap:operation soapAction=""/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="matt_HelloWorld3Service">
<wsdl:port name="matt_HelloWorld3Port0" binding="tns:matt_HelloWorld3Binding">
<soap:address location="http://spthd01:5565/soap/DocLiteral"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>



Difference between original WSDL and modified WSDL
  • No import statement required here
  • HelloWorld is not a complex type but just an element, if it is complex type it adds another layer in SOAP Packet
  • Similarly HelloWorldRespons is not a complex type but just an element

1.3.1 Naming conventions

For naming conventions lets look at code snippet from original wsdl

JAX-WS specification is pedantic about method name and
input argument name.
It says method name has to same as arguement name, otherwise
it will not work_. Here elemnet="tns:HelloWorld" is the
input argument and name="HelloWorld" is just a local name.

<wsdl:message
name="HelloWorld">

<wsdl:part
name="HelloWorld" element="tns:HelloWorld" />

</wsdl:message>


JAX-WS specification also _recommends_ to name return type,
suffix with word _Response_.

In this case its not used, it is using word _Respons_ with missing _e_.
Here elemnet="tns:HelloWorldRespons" is the output arguement
and name="HelloWorldRepons" is just a local name.

<wsdl:message name="HelloWorldOutput"> <wsdl:part
name
="HelloWorldRespons" element="tns:HelloWorldRespons" />

</wsdl:message>


Here method/function/behavior prototype is declared.
Method name is _HelloWorld_ (operation name="HelloWorld")
same as input arguement (element="tns:HelloWorld" defined
under message name="HelloWorld".
This has to be same, otherwise it will not work/generate
right stubs.

<wsdl:portType
name="matt_HelloWorld3PortType">

<wsdl:operation
name="HelloWorld">

<wsdl:input
message="tns:HelloWorld" />

<wsdl:output
message="tns:HelloWorldOutput" />

</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="matt_HelloWorld3Binding"
type
="tns:matt_HelloWorld3PortType">

Web services Style is document/literal and Wrapped. Wrapped
word is not mentioned, but it is the type of
arguements/paratmeters used in method/operation which
identfies it whether it is a Wrapped or non Wrappped service.
If an operation parameter uses element in declartion then
it is wrapped. In our case it is this

<wsdl:part
name="HelloWorld" element="tns:HelloWorld" />

which makes it warpped.

For non warpped it will be

<wsdl:part name="HelloWorld" type="xsd:string" />
<soap:binding style="document"
transport
="http://schemas.xmlsoap.org/soap/http" />

Document type

<wsdl:operation
name="HelloWorld">

<soap:operation
soapAction="" />
<wsdl:input>
<soap:body
use="literal" />

Literal Type

</wsdl:input>
<wsdl:output>
<soap:body
use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>



1.3.2 Generate Stubs

To generate stubs new tools sets are usd in JBoss 4.2 >= series.
Previuously it used to use wstools bundled with JBoss 4.0.4, now it uses
wsconsume and wsprovide.

Wsconsume is used for top down approach - i:e; to generate stubs from WSDL

Wsprovide is used for bottom up approach
For both of them their are ant targets as well.

For this exercise I have used command line tools.

Command to generate stubs from WSDL.


vsm@jm000606:client11$ ~/javadev/jboss/bin/wsconsume.sh -k -p au.com.hello.client11.test.orig HelloWorldOrig.wsdl
JBossWS-Native stack deployed
parsing WSDL...

generating code...
au.com.hello.client11.test.orig.HelloWorldRequest.java
au.com.hello.client11.test.orig.HelloWorldRespons.java
au.com.hello.client11.test.orig.MattHelloWorld3PortType.java
au.com.hello.client11.test.orig.MattHelloWorld3Service.java
au.com.hello.client11.test.orig.ObjectFactory.java
au.com.hello\client11.test.orig.package-info.java
vsm@jm000606:client11$

I'm using unix based tools but you can use wsconsume.bat on windows.~~


1.3.3 Ant target to generate stubs

<path id="web.services.classpath">

<fileset

dir
="C:/Program Files/Java/jdk1.5.0_06/lib/"
includes
="*.jar" />

<fileset dir="D:/javadev/jboss-4.2.1.GA/lib/endorsed/"
includes
="*.jar" />

<fileset

dir
="D:/javadev/jboss-4.2.1.GA/lib/" includes="*.jar" />


<!-- Please dont put jaxws-tools.jar and jaxws-rt.jar on
Eclipse's classpath at all, its fine within ant. Its
to do with JAXB API bundled in Eclispe and Jboss -->

<fileset dir="D:/javadev/jboss-4.2.1.GA/client/">
<include
name="activation.jar"/>

<include
name="getopt.jar"/>

<include
name="wstx.jar"/>

<include
name="jbossall-client.jar"/>

<include
name="log4j.jar"/>

<include
name="mail.jar"/>

<include
name="jbossws-spi.jar"/>


<include name="stax-api.jar"/>
<include
name="jaxb-api.jar"/>

<include
name="jaxb-impl.jar"/>

<include
name="jaxb-xjc.jar"/>

<include
name="streambuffer.jar"/>

<include name="stax-ex.jar"/>

<include name="javassist.jar"/>
<include
name="jboss-xml-binding.jar"/>

<include
name="jbossws-client.jar"/>

<include name="jboss-jaxws.jar"/>
<include
name="jboss-jaxrpc.jar"/>

<include
name="jboss-saaj.jar"/>


<include name="jboss-srp-client.jar"/>
<include
name="jbossws-common.jar"/>


<!-- Be careful with these two jars in Eclipse,
dont put it on classpath -->


<include
name="jaxws-tools.jar"/>

<include
name ="jaxws-rt.jar"/>

</fileset>

</path>



<!-- Ant task for wsconsume -->


<target name="gen_stubs">
<taskdef
name="wsconsume"
classname
="org.jboss.wsf.spi.tools.ant.WSConsumeTask">

<classpath>
<path refid="web.services.classpath" />
</classpath>

</taskdef>



<wsconsume
fork
="true"
verbose="true"
sourcedestdir="${basedir}"
package
="au.com.hello.integrate.anttask.stubs"
keep
="true"
wsdl
="GetMemberTest.wsdl" />

<!--destdir="${basedir}"-->


</target>

<!-- Ant task for wsprovide -->
<target name="test-wsproivde" >

<taskdef name="WSProvideTask"
classname="org.jboss.wsf.spi.tools.ant.WSProvideTask">
<classpath refid="web.services.classpath"/>
</taskdef>

<WSProvideTask
fork="false"
keep="true"
destdir="out"
resourcedestdir="out-resource"
sourcedestdir="out-source"
genwsdl="true"
verbose="true">

</WSProvideTask>

</target>








1.3.3.1 More on wsconsume options:
If -keep option is set, the generated java files will be removed. -keep option is automatically set by WSConsume tool if you'll specify sourcedestdir attribute in your apache ant task.

Thus if you will specify sourcedestdir, the generated java files will not be deleted after the compilation phase.

So sourcedestdir points to the directory, where WsimportTool will generate java files
While destdirpoints to a directory where these java files will be compiled to class files.

1.3.4 Test Webservices Client

Now only remaining bit is to write a Test Client and invoke the service.
Code snippet from test client.

public class TestWSClient {

static Logger log = Logger.getLogger(TestWSClient.class);

public static void main(String[] args)
{
// TODO Auto-generated method stub

PropertyConfigurator.configure(
"D:/javadev/eclipse_workspace/TestWs/src/au/com/hello/client2/log4j.properties");

Logger log = Logger.getLogger(TestWSClient.class);
log.info("Got My logger going -1 ");

MattHelloWorld3Service service = new MattHelloWorld3Service();
MattHelloWorld3PortType port = service.getPort(MattHelloWorld3PortType.class) ;

BindingProvider bp = (BindingProvider) port;
bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "test");
bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "test");

log.info ("Got My logger going -2");

HelloWorldReq memreq = new HelloWorldReq();

String response = port.helloWorld("Hi Vishal");
System.out.println (" Returned messages is " + response);
}
}

1.3.5 Logging SOAP Packet

First configure your JBoss Server side.
Go to jboss-log4j.xml under conf directory.
Uncomment this section
<!-- Enable JBossWS message tracing
<category name="jbossws.SOAPMessage">
<priority value="TRACE"/>
</category>
-->

1.3.6 Instructions for setting up SOAP packet logging on client side
Create a log4j.properties file with these options


# Set root logger level to ALL and its only appender to A1.
log4j.rootLogger=ALL, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# Other appenders can be used here and can bee added to root

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

Now inside your test client add this line which configures this logging.

PropertyConfigurator.configure("D:/javadev/eclipse_workspace/TestWs/src/au/com/hello/client2/log4j.properties");

Now when you will run your server it will log outgoing and incoming soap packets

Outgoing SOAP packet is
<env:Envelope
xmlns:env
='http://schemas.xmlsoap.org/soap/envelope/'>

<env:Header/>
<env:Body>
<ns1:HelloWorld xmlns:ns1='http://www.vishal.com.au/matt.HelloWorld3'>
<id>Hi Vishal</id>
</ns1:HelloWorld>
</env:Body>
</env:Envelope>


Incoming SOAP packet is


<edm:HelloWorldRespons
xmlns:edm="http://www.vishal.com.au/matt.HelloWorld3">

<result>Hello Hi Vishal</result>
</edm:HelloWorldRespons></SOAP-ENV:Body>
</SOAP-ENV:Envelope>


1.3.7 Test client code snippet


public static void main(String[] args) {

PropertyConfigurator.configure("D:/javadev/eclipse_workspace/TestWs/src/au/com/hello/client2/log4j.properties");

log.info("Got My logger going -1 ");

MattHelloWorld2Service service = new MattHelloWorld2Service();
MattHelloWorld2PortType port = service.getPort(MattHelloWorld2PortType.class) ;

BindingProvider bp = (BindingProvider) port;
bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "test");
bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "test");

log.info ("Got My logger going -2");

HelloWorld2 memReq = new HelloWorld2();
memReq.setId("Hellow Mathew");

HelloWorld2Respons resp = port.getMessage(memReq);

System.out.println (" Returned messages is " );

}


Part - 3 of tutorial is continued here

Other useful tips on J2EE
Del.icio.us Digg! My StumbleUpon Page