X
  • Sun
    October 26, 2007

Testing Interoperability Between Metro and .NET

Guest Author

By Harold Carr

The March 2007 Tech Tip, Securing Web Services Using WSIT introduced Web Services Interoperability Technology (WSIT), an implementation of open web services technologies that enables interoperability between Java EE and .NET. WSIT along with Java API for XML-Based Services (JAX-WS) comprise the stack of web services technologies in GlassFish v2. The web services stack in GlassFish v2 is called Project Metro or Metro for short. Metro is built into Sun Java System Application Server 9.1. Metro also runs in other containers such as Tomcat.

WSIT, also called Project Tango, includes features that enable
advanced web service interoperability with the .NET Windows
Communication Foundation (WCF), a set of technologies for
building and running connected systems. WSIT also addresses key
aspects of web services interoperability such as reliable
messaging, transaction handling, and security. What this means
is that any combination of Metro-based and WCF-based clients and
services can interoperate with support for reliable messaging,
transaction handling, and security.

To ensure that the stack of WCF and Metro technologies
interoperate properly and provide the proper support, Microsoft
and Sun engineers run comprehensive interoperability tests
called "plug-fests". You can find out more about the plug-fests,
including the scenarios that are tested, by viewing the Web
Services Interoperability Plug-Fest
Home Page. All tests pass in the
current levels of .NET and Metro: .NET 3.0 and
Metro 1.0.

In this tip, you'll build and run an interoperability test in
which a Metro-based client communicates with a WCF-based
service. A package that contains the code for the
interoperability test
accompanies the tip. The code examples in the tip are taken from
the source code of the sample (which is included in the
package).

A Reliable One-Way Interoperability Test

The interoperability test you'll build and run in this tip is
a "reliable one-way test." This type of test is described in
"Scenario #1.1. One-Way Anonymous Client" in the document WCF
(Indigo) Introperability Lab: Reliable Messaging
. This
is a typical enterprise use case where a client sends data to
a service for processing but does not wait for a response --
that's why it's called "One-Way". However, the client wants
assurances that the messages are received by the service.

The message flow in this test is as follows:








Reliable Messaging Operation
Reliable Messaging Operation



 

  • The client initiates the establishment of a reliable
    communication channel by sending a CreateSequence protocol
    message.



  • The service creates a sequence identifier to uniquely identify
    the reliable channel. The service returns this identifier in
    a CreateSequenceResponse protocol message.



  • The client sends three application messages. Each of these
    messages is accompanied with header information containing the
    sequence identifier for the channel and a message number
    identifying the message.



  • For each application message received, the service responds
    with a SequenceAcknowledgement identifying what messages have
    been received. The service does this without having to wait
    for the business logic to complete processing.



  • If the client sees that some of the messages it sent have not
    been received, it retransmits those messages. (This situation
    is not tested in this tip.)



  • The client closes the channel when the channel is no longer
    needed. This causes a LastMessage protocol messages to be sent.



  • The service responds with a SequenceAcknowledgement protocol
    message indicating which messages have been received.



  • Again, if the client sees that some of the messages it sent
    have not been received, it resends those messages. This is
    followed by another LastMessage. The LastMessage-resend
    sequence repeats until all messages have been received by the
    service. (That is not exercised in this tip.)



  • The client sends a TerminateSequence protocol message.



  • The service responds with an HTTP 202 response indicating that
    the request has been accepted for processing.


Metro-Based Client

Let's start by creating the Metro-based client. You can view the
source code for the client in the file ReliableOneWay.java. Here
is a snippet of the source code in that file:


   package reliableoneway.client;

   

   import org.tempuri.IPing;

   import org.tempuri.PingService;

   

   public class ReliableOneWay {

   

       public ReliableOneWay() {}

       

       public static void main(final String[] args) 

       {

        try {

        

            PingService service = new PingService();

            IPing port = service.getCustomBindingIPing();

            

            msg(null, "BEFORE FIRST MESSAGE");

            

            msg(port, "FIRST MESSAGE");

            msg(port, "SECOND MESSAGE");

            msg(port, "THIRD MESSAGE");

            

            msg(null, "TERMINATE");

            

            ((com.sun.xml.ws.Closeable)port).close(); 

Using a reliable messaging (RM)-based web service is no
different than using any SOAP-based web service. First you
create a proxy to the service (see the section Running
wsimport
). Here, the service is PingService, which is
defined in the WSDL (see the section WSDL). Then you
obtain a port defined in that service, in this case,
CustomBindingIPing. Then you can send application messages to
that service by calling the ping method on the port. Here the
method msg calls port.ping(String) when port is not null. In
this example, three messages are sent.

These steps are the same steps you would take to use any
SOAP-based web service. The one additional step is calling close
on the port. This signals Metro to terminate the RM channel if
the service is using RM. In general, it's a good idea to close
ports when they are no longer needed. This enables Metro to
reclaim any resources used by that port.


WSDL

You generate the PingService proxy from the Web Service
Definition Language (WSDL) file for the service. You can find
the WSDL for the service by going to the
Web Services
Interoperability Plug-Fest
Home Page. Click on the "RM
Endpoints (WS-Addressing 1.0)" link. Then click on the "OneWay.svc"
link. The address of the WSDL is http://131.107.72.15/ReliableMessaging_Service_WSAddressing10_Indigo/OneWay.svc?wsdl.

The WSDL file is quite large because it is used for other test
scenarios besides scenario 1.1, that is, scenarios that involve
security. The port that this tip uses is named
CustomBinding_IPing. It references the following policy binding:


   <wsp:Policy wsu:Id="CustomBinding_IPing_policy">

     <wsp:ExactlyOne>

       <wsp:All>

         <wsrm:RMAssertion>

           <wsrm:InactivityTimeout Milliseconds="600000"/>

           <wsrm:AcknowledgementInterval Milliseconds="200"/>

         </wsrm:RMAssertion>

         <wsaw:UsingAddressing/>

       </wsp:All>

     </wsp:ExactlyOne>

   </wsp:Policy>  

The RMASssertion in the policy binding specifies an RM policy
assertion for the service. Within the assertion, the
InactivityTimeout parameter sets then interval of time that the
service remains inactive before closing. The
AcknowledgementInterval parameter sets the interval of time that
a destination waits before sending an acknowledgment to the
message source on reliable channels. You can find out more about
RM policy assertions in the WS-ReliableMessaging Policy specification. The
main point here is that including the RMAssertion in the WSDL
and then referencing it in the CustomBinding_IPing binding that
is used in the CustomBinding_IPing port causes operations on
that port to use reliable messaging.

The Structure of the Test

In this tip, you'll use ant to create the proxy, compile the
code, and run the client test. You can also use NetBeans -- for
more details, see the WSIT Tutorial.

If you haven't already done so, download and install GlassFish v2.
Then download the sample application for the tip and extract its contents. You should now see the newly extracted
directory as <sample_install_dir>/interop, where
<sample_install_dir> is the directory where you installed the
sample application. For example, if you extracted the contents
to C:\\ on a Windows machine, then your newly created directory
should be at C:\\interop.

Although this tip demonstrates only one scenario, the directory
structure below the interop directory is set up such that
common artifacts are factored out to be used with other tests.
The directory structure is as follows:


  common.xml

  rm     

       build.xml

       netbeans

           ReliableOneWayService

               ...

       src

           reliableoneway

               build.props

               build.xml

               client

                   ReliableOneWay.java

                   ...

               server

                   etc

                       EchoServiceRMCustomOnly.wsdl

                       ReliableOneWay.xsd

At the top level of the directory structure, the build.xml file
imports common.xml, where the real action takes place, and
defines one target: run-reliableoneway. The run-reliableoneway
file cleans the build directory. It then:

  • Runs wsimport
  • Compiles the generated code and the ReliableOneWay.java code
  • Runs the test

Running wsimport

Here is the snippet of code in the build.xml file that runs wsimport:


   <target name="run-reliableoneway">

        

        <ant target="run-wsimport" 

             antfile="src/reliableoneway/build.xml" 

             inheritall="false"/>

Notice that it uses the build.xml file in the
rm/src/reliableoneway directory. That file, in turn, uses the
build.props file in the rm/src/reliableoneway directory. Here is
the contents of build.props:


   test.wsdl=

    http://131.107.72.15/ReliableMessaging_Service_ ...

    

   client.dir=client

   className=reliableoneway.client.ReliableOneWay

The build.props file is a property file that defines test.wsdl
to be the location of the WSDL file of the service. It also sets
two other parameters used by common.xml so it can be used for
other tests that are not covered in this tip.

The build.xml file in the rm/src/reliableoneway directory then
uses the run-wsimport target from the common.xml file.

The wsimport task fetches the WSDL file specified in parameter
test.wsdl. It then generates the proxy code into the
rm/build/classes/org/tempuri directory, and the data schema
class into the
rm/build/classes/com/microsoft/schemas/_2003/_10/serialization
directory. This class is large because it is a superset of all
data used by all the interoperability test scenarios.

Compiling the Code and Running the Test

The final two steps in the run-reliableoneway target are:


   <ant target="compile" 

        antfile="src/reliableoneway/build.xml" 

        inheritall="false"/>

   <ant target="run-tests" 

        antfile="src/reliableoneway/build.xml" 

        inheritall="false"/>

The compile step runs the Java Programming Language compiler,
javac, on the developer-written code, ReliableOneWay.java. The
run-tests step executes the main test class as specified in the
className parameter set in build.props file. In this case,
className is set to reliableoneway.client.ReliableOneWay.

Note that sysproperty is set in the run-tests target of the common.xml file.


   <sysproperty 

   key="com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump" 

   value="true"/>

This enables the client to send and receive messages.

Setting Environment Variables

Four ant parameters are set from environment variables (here shown in bash syntax):


   export PROXY_HOST=-DproxyHost=my.proxy.example.com

   export PROXY_PORT=-DproxyPort=8765

   export METRO_HOME=/glassfish/b58g

   export TEST_HOME=~/metro-wcf-interop-tests/rm

If you are not behind a firewall then explicitly set PROXY_* to nothing:


   export PROXY_HOST=

   export PROXY_PORT=

Set METRO_HOME to the top-level installation direction of
GlassFish. That setting is used to locate Metro JAR files such
as webservices-rt.jar and webservices-tools.jar in
$METRO_HOME/lib. (If you are using Tomcat or another web
container you need to update common.xml to correctly reference the
location of the Metro JAR files.)

Executing the Test

If you haven't already done so, start GlassFish by entering the following command:


   $METRO_HOME/bin/asadmin start-domain domain1

Then change to the $TEST_HOME directory and enter the following
command on the command line:


   ant  

Note: This test is designed to run with JDK 5. If you want to
run the test with JDK6, you need to use the Java Endorsed Standards Override Mechanism.

Test Results

The output of the test should look similar to the content in the example-output-wcf-endpoint.txt file in the
rm/src/reliableoneway/client directory.

You can ignore all the WARNING messages at the beginning of the
test run, such as the following:


    [java] WARNING: WSP0075: Policy assertion 

    "{http://docs.oasis-open.org/ws-rx/wsrmp/200702}RMAssertion" 

    was evaluated as "UNKNOWN".

These warnings are from the numerous policies for bindings in
the WSDL that are not used in this test. Similarly, you can
ignore the non-standard SOAP 1.2 binding warning messages in
the run-wsimport step.

In the output, search for BEFORE FIRST MESSAGE. This is printed
to the console just before the first invocation of port.ping.
When port.ping is called, the RM infrastructure holds the
application message back -- it first establishes a reliable
channel by sending a CreateSequence protocol message.


   Content-Type: application/soap+xml;charset="utf-8";

   action="http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence"

The CreateSequenceResponse protocol message returned from the
service contains an Identifier that will be used to identify the
reliable channel.

After the reliable channel is established, the application
message is sent containing <Text>FIRST MESSAGE</Text> in the
Body element. The header contains a Sequence element that
contains the reliable channel Identifier along with
a MessageNumber, in this case the number 1.


   <S:Envelope xmlns:..."><S:Header>...

   <ns2:MessageNumber>1</ns2:MessageNumber>...

   </S:Header>...<Text>FIRST MESSAGE</Text>...

   </S:Envelope>

Because this is a oneway message, the response to this message
contains an empty Body. The header contains
a SequenceAcknowledgement element that contains the Identifier
and an AcknowledgementRange with attributes Lower and Upper,
in this case the numbers 1 and 1 respectively.


   <s:Envelope xmlns:...><s:Header>...

   <r:SequenceAcknowledgement>

   <r:Identifier>urn:...</r:Identifier>

   <r:AcknowledgementRange Lower="1" Upper="1"/>...

   </r:SequenceAcknowledgement>...

   </r:SequenceAcknowledgement>

This means the lowest message number received by the service was
1 and the highest message number was 1. When there are gaps in
the acknowledgement range the client RM infrastructure resends
lost messages. It releases message copies (for garbage
collection) after those messages have been acknowledged.

Two more application messages are sent with MessageNumbers 2 and
3 respectively.


   <S:Envelope xmlns:...><S:Header>...

   <ns2:MessageNumber>2</ns2:MessageNumber>...

   </S:Header>...><Text>SECOND MESSAGE</Text>...

   </S:Envelope>

   

   <S:Envelope xmlns:...><S:Header>...

   <ns2:MessageNumber>3</ns2:MessageNumber>...

   </S:Header>...<Text>THIRD MESSAGE</Text>...

   </S:Envelope>

The responses contain AcknowledgementRanges with Lower/Upper
attributes 1/2 and 1/3 respectively.

TERMINATE is printed to the console then the port.close() is
called. This causes the RM infrastructure to send a message with
an empty Body. The header of this message contains a Sequence
element with the Identifier and a MessageNumber of 4. The header
also contains an Action element specifying LastMessage to
let the service know the reliable channel is going to be closed.


   <S:Envelope xmlns:...><S:Header>...

   <ns2:MessageNumber>4</ns2:MessageNumber>

   <ns2:LastMessage/>...   </ns2:Sequence>...

   <Action xmlns=...">

   http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage

   </Action>...

The service responds with a SequenceAcknowledgement containing
AcknowledgementRange 1/4 indicating all messages have been
received.


   <s:Envelope xmlns:...><s:Header>

   <r:SequenceAcknowledgement>...>

   <r:AcknowledgementRange Lower="1" Upper="4"/>...

   </r:SequenceAcknowledgement>...

   </s:Envelope>

If messages are missing the client resends them.

After the client RM infrastructure sends LastMessage and
receives a SequenceAcknowledgement response indicating that all
messages have been received, it sends a message with an Action
header element containing TerminateSequence.


    Content-Type: application/soap+xml;charset="utf-8";

    action=

   "http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence"

This lets the service know that it can release all resources
associated with the reliable channel identified by the Identifier
element. The service responds with an HTTP 202 response.


      null: HTTP/1.1 202 Accepted

Summary

This tip showed you how to build and run a reliable messaging
test in which a Metro-based client communicates with a WCF-based
service, in other words, a public WCF endpoint.

Of course, you can also run the same interoperability test or
other interoperability tests using a WCF-based client or
a Metro-based service. Running the tests with different
combinations of Metro-based and WSF-based clients and servers
should enable you to verify interoperability between Metro and
.NET. It will also enable you to become a contributor to the
open source Metro project and test
the interoperability of the code you contribute.


About the Author

Harold Carr is the engineering lead for enterprise web
services interoperability at Sun Microsystems. Previous to this
role, Harold was responsible for RMI-IIOP load-balancing and
fail-over in the Sun Java System Application Server. He designed
the core architecture used in Sun's CORBA ORB and in the
JAX-RPC 2.0 reference implementation and the scalable socket
communications architecture used in SJSAS HTTP and IIOP
remoting. Harold helped write the OMG Portable Object Adapter
specification and was chairperson of the OMG Portable
Interceptor specification. Previous to Sun, he did distributed
computing research at Hewlett-Packard Research Laboratories and
Schlumberger Research Laboratories, was Chief Architect of
Visual Lisp technology at Autodesk, and was a logic simulation
consultant for Cirrus Logic. He holds a Ph.D., in Computer
Science from the University of Utah.

Join the discussion

Comments ( 1 )
  • Valery Thursday, September 30, 2010

    please fix html references to images locations


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.