Arun Gupta, Miles to go ...

Arun Gupta is a technology enthusiast, a passionate runner, and a community guy who works for Sun Microsystems.
Main | Next page »

http://blogs.sun.com/arungupta/date/20070829 Wednesday August 29, 2007

Excel using WSIT - Metro and .NET interoperability sample

If you attended JavaOne 2007 or any other conference afterwards where Metro (JAX-WS + WSIT/Tango) team presented, then you've probably seen this demo. The demo shows an Excel 2007 spreadsheet invoking a Secure and Reliable endpoint deployed on GlassFish. Today, I'm announcing the availability of the WSIT endpoint and Excel client code with full instructions to build, deploy and run the sample.

Metro Release Candidate 1 was announced recently and is integrated in GlassFish RC4. You can learn more about .NET interoperability aspects of Metro by watching this deep dive interview or reading this 26-page article.

The source code for this sample is available in "wsit/wsit/samples/excelclient" directory. It can be checked out using the command:

cvs -d :pserver:yourid@cvs.dev.java.net:/cvs co wsit/wsit/samples/excelclient

A compressed bundle of the sample is available here.

Running the demo involves an extensive setup for .NET client. Please make sure to review the software requirements before proceeding with the installation.

Try it and send us feedback at users@metro or Metro Forum.

Technorati: webservices metro glassfish dotnet .net interoperability netbeans wcf

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20070802 Thursday August 02, 2007

wsHttpDualBinding - a non-interoperable binding

Based upon a user request, I'll explain why wsDualHttpBinding (a system-provided binding in WCF) is not an interoperable binding. This blog entry will explain the service endpoint code, client code, generated WSDL and the SOAP messages exchanged based upon the DualHttp Binding Sample that is bundled with the Windows SDK samples. This is also an update to an earlier attempt to explain wsDualHttpBinding.

In the sample, I replaced the default wsDualHttpBinding with an equivalent custom binding (after removing the security) as:

<bindings>
  <customBinding>
    <binding name="Binding1">
      <reliableSession />
      <compositeDuplex />
      <oneWay />
      <textMessageEncoding
                     messageVersion="Soap12WSAddressing10" 
                     writeEncoding="utf-8" />
      <httpTransport authenticationScheme="Anonymous"
                     bypassProxyOnLocal="false"
                     hostNameComparisonMode="StrongWildcard"
                     proxyAuthenticationScheme="Anonymous"
                     realm=""
                     useDefaultWebProxy="true" />
    </binding>
  </customBinding>
</bindings>

The wsDualHttpBinding, also known as Composite Duplex or Full Duplex Binding, provides a bi-directional communication between Client and Endpoint. In a single direction communication, the client can invoke a set of operations on a service and this interface is referred as primary interface in Duplex binding. The set of operations that a service can invoke on the client is called as callback interface.

The sample in Windows SDK is a trivial calculator service where primitive Math operations are performed in a running session on the "primary" interface and results are returned on the "callback" interface.

Service Endpoint Code

Let's understand the service endpoint code first. The "primary" service endpoint interface looks like:

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", 
                 SessionMode=SessionMode.Required,
                 CallbackContract=typeof(ICalculatorDuplexCallback))]
public interface ICalculatorDuplex
{
  [OperationContract(IsOneWay=true)]
  void Clear();
  [OperationContract(IsOneWay = true)]
  void AddTo(double n);

  ...
}

Three points to note in this code:

  • A duplex contract requires a session, because a context must be established to correlate the set of messages being sent between client and service. Even though this is specified using SessionMode=SessionMode.Required attribute but the default value of SessionMode=SessionMode.Allowed (equivalent of not specifying) will be sufficient as well. This is because all Duplex bindings in .NET maintain a transport session.

  • Callback interface is specified using CallbackContract attribute.

  • All the methods are declared as One-way operations otherwise the response can be returned on the transport back channel itself. The documentation on this particular binding is limited.

The "callback" interface is defined as:

public interface ICalculatorDuplexCallback
{
  [OperationContract(IsOneWay = true)]
  void Result(double result);

  ...
}

In order for a service endpoint to establish a connection with the "callback" interface on client, a CallbackChannel is obtained from the OperationContext in the implementation of the "primary" interface as:

public class CalculatorService : ICalculatorDuplex
{
  double result;
  ICalculatorDuplexCallback callback = null;

  public CalculatorService()
  {
    result = 0.0D;
    callback = OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();
  }

Another variable is initialized to return the running result. The implementation of each method in the "primary" interface then invokes a method on the "callback" interface to return the running result as:

public void AddTo(double n)
{
  result += n;
  callback.Result(result);
}

Generated WSDL

Now let's look at the generated WSDL fragments. The policy assertion elements are:

<wsp:All>
  <wsrm:RMAssertion xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm/policy">
    <wsrm:InactivityTimeout Milliseconds="600000" /> 
    <wsrm:AcknowledgementInterval Milliseconds="200" /> 
  </wsrm:RMAssertion>
  <cdp:CompositeDuplex xmlns:cdp="http://schemas.microsoft.com/net/2006/06/duplex" /> 
  <ow:OneWay xmlns:ow="http://schemas.microsoft.com/ws/2005/05/routing/policy" /> 
  <wsaw:UsingAddressing /> 
</wsp:All>

The wsrm:RMAssertion and wsaw:UsingAddressing elements are bound to a known namespace and their behavior is clearly documented. However the specification of cdp:CompositeDuplex and ow:OneWay elements are unclear at this time. This does not allow any WSDL-based interoperability whenever these elements are included.

All methods from the "primary" and the "callback" interface are generated in one wsdl:portType. The methods from the "primary" interface are generated as One-way operations. But methods from the "callback" interface are generated as Notification operation. For example, one of the methods from "callback" interface looks like:

<wsdl:operation msc:isInitiating="true" msc:isTerminating="false" name="Result">
  <wsdl:output
      wsaw:Action="http://Microsoft.ServiceModel.Samples/ICalculatorDuplex/Result"
      message="tns:ICalculatorDuplex_Result_OutputCallbackMessage"/>
</wsdl:operation>

JAX-WS, the core of Metro, supports only Request-Response and One-way operations. This is the second place where WSDL-based interoperability will not work with any JAX-WS-based WSDL import tool, such as wsimport. Moreover, the WSDL-to-Java mapping defined by the JAX-WS specification requires each wsdl:portType map to a single Java interface. This WSDL design pattern requires two interfaces to be generated from a single wsdl:portType.

There are some other elements in namespace prefix bound to "http://schemas.microsoft.com/ws/2005/12/wsdl/contract" and their purpose is also unclear. Rest of the WSDL is pretty straight-forward.

Client side code

On the client side, svcutil (WSDL importing tool for .NET 3.0) generates the "primary" and "callback" interface from the WSDL. The "callback" is implemented as:

public class CallbackHandler : ICalculatorDuplexCallback
{
  public void Result(double result)
  {
    Console.WriteLine("Result({0})", result);
  }

  public void Equation(string eqn)
  {
    Console.WriteLine("Equation({0})", eqn);
  }
}

This client instance is initialized with the callback implementation as:

class Client
{
  static void Main()
  {
    // Construct InstanceContext to handle messages on callback interface
    InstanceContext instanceContext = new InstanceContext(new CallbackHandler());

    // Create a client with given client endpoint configuration
    CalculatorDuplexClient client = new CalculatorDuplexClient(instanceContext);

And then the client invokes the service endpoint normally as shown below:

// Call the AddTo service operation.
double value = 100.00D;
client.AddTo(value);

...

SOAP messages

Lets look at the SOAP messages exchanged between client and endpoint now. The first call from the client to an endpoint triggers a protocol handshake for establishing a session. The CreateSequence protocol message looks like:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence</a:Action>
    <a:ReplyTo>
      <a:Address>http://iamfine.sfbay.sun.com/Temporary_Listen_Addresses/bfd8c103-b0f9-4c65-9cb6-fbebb7d1517b/4e0cdb31-2451-4fb6-84b8-dc286e5f26c8</a:Address>
    </a:ReplyTo>
    <a:MessageID>urn:uuid:51918652-9a78-4ba3-82f5-e68ecd664d42</a:MessageID>
    <a:To s:mustUnderstand="1">http://localhost:8888/</a:To>
  </s:Header>
  <s:Body>
    <CreateSequence xmlns="http://schemas.xmlsoap.org/ws/2005/02/rm">
      <AcksTo>
        <a:Address>http://iamfine.sfbay.sun.com/Temporary_Listen_Addresses/bfd8c103-b0f9-4c65-9cb6-fbebb7d1517b/4e0cdb31-2451-4fb6-84b8-dc286e5f26c8</a:Address>
      </AcksTo>
      <Offer>
        <Identifier>urn:uuid:b1116e69-f1dd-45b0-8495-129645038160</Identifier>
      </Offer>
    </CreateSequence>
  </s:Body>
</s:Envelope>

The WCF runtime uses the Windows HTTP.SYS library to host an endpoint at the address specified in a:ReplyTo. This address is used for all subsequent messages sent on the callback channel. This message is used to create a session for the "primary" interface. The message also carries an offer, in the SOAP Body, to create a "callback" interface session.

The CreateSequenceResponse protocol message returns "primary" interface session identifier and also accepts the offered "callback" session. The message looks like:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequenceResponse</a:Action>
    <a:RelatesTo>urn:uuid:51918652-9a78-4ba3-82f5-e68ecd664d42</a:RelatesTo>
    <a:To s:mustUnderstand="1">http://iamfine.sfbay.sun.com/Temporary_Listen_Addresses/bfd8c103-b0f9-4c65-9cb6-fbebb7d1517b/4e0cdb31-2451-4fb6-84b8-dc286e5f26c8</a:To>
  </s:Header>
  <s:Body>
    <CreateSequenceResponse xmlns="http://schemas.xmlsoap.org/ws/2005/02/rm">
      <Identifier>urn:uuid:d483898c-4bd3-4077-ba04-07a9010ab27f</Identifier>
      <Accept>
        <AcksTo>
          <a:Address>http://localhost:8888/</a:Address>
        </AcksTo>
      </Accept>
    </CreateSequenceResponse>
  </s:Body>
</s:Envelope>

Now, because of the way each method is implemented (invoking callback.Result(result) method at the end of each "primary" operation), a response to a request received by an endpoint is returned over the callback channel. This happens under-the-cover even though all messages in the "primary" interface are defined as One-way operations.

The behavior is quite analogous to a Request-Response operation primitive. I wonder what are the usecases of wsDualHttpBinding ?

Summary

Finally, I summarize the reasons that makes wsDualHttpBinding a non-interoperable binding:

  1. The specifications of cdp:CompositeDuplex and ow:OneWay are not available and these elements will thus be ignored by the Metro WSDL importing tool.

  2. The operations from "callback" interface are mapped as Notification operation in the WSDL. This operation primitive is not supported by Metro.

  3. On the service endpoint, all the operations from "primary" and "callback" interface are mapped to a single wsdl:portType. On the client side, wsdl:portType is mapped to separate "primary" and "callback" interfaces. The Java-to-WSDL mapping defined by the JAX-WS specification allows one-to-one mapping between Java interface and wsdl:portType.

Technorati: webservices interoperability wcf metro jax-ws wsit

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20070801 Wednesday August 01, 2007

SOAP Message Logging in Metro and WCF

Metro provides Secure, Reliable, Transactional and .NET 3.0 interoperable Web services stack in GlassFish. This entry explains how to enable SOAP message logging in Metro and .NET 3.0.

The SOAP message logging in Metro is explained here.

In WCF (the Web services stack in .NET), the Configuration Editor Tool is the preferred way to enable SOAP message logging. But sometimes you may want to directly edit your configuration file, for example, if you do not want to re-generate the file again. In such cases you can include the XML fragments from the template configuration file given below into your application specific configuration and this will enable only SOAP message logging:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel.MessageLogging" switchValue="Warning, ActivityTracing">
        <listeners>
          <add type="System.Diagnostics.DefaultTraceListener" name="Default">
            <filter type="" />
          </add>
          <add name="ServiceModelMessageLoggingListener">
            <filter type="" />
          </add>
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add initializeData="LOG_DIRECTORY\messages.svclog"
           type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
           name="ServiceModelMessageLoggingListener" traceOutputOptions="Timestamp">
        <filter type="" />
      </add>
    </sharedListeners>
  </system.diagnostics>
  <system.serviceModel>
    <diagnostics>
      <messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtTransportLevel="true" />
    </diagnostics>
  </system.serviceModel>
</configuration>

After the client application is invoked, all SOAP messages will be logged to LOG_DIRECTORY\messages.svclog file. The message log can be viewed using svctraceviewer.

Technorati: wcf webservices wsit metro glassfish

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20070710 Tuesday July 10, 2007

GlassFish V2 Beta3 and Vista - Interoperable out-of-the-box

GlassFish V2 beta3 is now available. I take this opportune moment for a follow up entry showing how a Reliable WSIT endpoint can be invoked from WCF client and vice versa. WSIT is already integrated in GlassFish V2.

The first part where a WSIT endpoint is invoked by a WCF client is now already available in this entry by Jesus Rodriguez. Couple of points in the entry:

  • The Web Service configuration (a.k.a. WSIT configuration file) is not hand edited. Instead it is conveniently generated by NetBeans IDE as shown in screencast #ws3. The user experience really is to just check mark a box and all the relevant XML fragments are generated by NetBeans.
  • Even though entry requires to rely on SOAP 1.1 (mistyped as WS-Addressing 1.1) , it workes with SOAP 1.2 very well. In fact, I've used SOAP 1.2 in the code below.

This entry provides the code to deploy a Reliable WCF endpoint and invoke it using a WSIT client.

  1. Create a service endpoint service.svc as:

    <%@ServiceHost language=c# Debug="true" Service="WCFReliableEndpoint.Hello" %>

    using System.ServiceModel;

    namespace WCFReliableEndpoint
    {
      [ServiceContract]
       public interface IHello
       {
         [OperationContract]
         string sayHello(string name);
       }

       public class Hello : IHello
       {
         public string sayHello(string name)
         {
           return "Hello " + name;
         }
       }
    }
  2. In the same directory, create Web.config as:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <system.serviceModel>
        <services>
          <service name="WCFReliableEndpoint.Hello" behaviorConfiguration="MetadataBehavior">
            <endpoint address=""
                      binding="customBinding"
                      bindingConfiguration="Binding1"
                      contract="WCFReliableEndpoint.IHello" />
          </service>
        </services>

        <bindings>
          <customBinding>
            <binding name="Binding1">
              <reliableSession />
                <textMessageEncoding messageVersion="Soap12WSAddressing10" writeEncoding="utf-8" />
                <httpTransport authenticationScheme="Anonymous" bypassProxyOnLocal="false"
                  hostNameComparisonMode="StrongWildcard"
                  proxyAuthenticationScheme="Anonymous" realm=""
                  useDefaultWebProxy="true" />
            </binding>
          </customBinding>
        </bindings>

        <behaviors>
          <serviceBehaviors>
            <behavior name="MetadataBehavior">
              <serviceMetadata httpGetEnabled="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>

      </system.serviceModel>
    </configuration>
  3. If IIS was installed after Vista installation was complete, then you'll have to explicitly register WCF components with IIS following these instructions and as shown below:

  4. Create a virtual directory, say wsit-reliable, in IIS mapping to the directory where service.svc and Web.config are present. You should now see the default WCF/IIS page as below:



    The service endpoint is now hosted at http://localhost/wsit-reliable/service.svc and the WSDL of the endpoint looks like:

  5. Create a WSIT client, using NetBeans IDE, following the instructions in screencast #ws2. Enable WSIT message logging by adding the following property to domains/domain1/config/domain.xml:

    <jvm-options>-Dcom.sun.xml.ws.assembler.client=true</jvm-options>
  6. The SOAP messages exchanged between the WSIT client and the WCF endpoint are given below:

    ====[com.sun.xml.ws.assembler.client:request]====
    <?xml version="1.0" ?>
    <S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
      <S:Header>
        <To xmlns="http://www.w3.org/2005/08/addressing">http://iamfine/wsit-reliable/service.svc</To>
        <Action xmlns="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence</Action>
        <ReplyTo xmlns="http://www.w3.org/2005/08/addressing">
          <Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
        </ReplyTo>
        <MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:fcaef2ab-bccf-4a08-a1d1-b10f7819f7ea</MessageID>
      </S:Header>
      <S:Body>
        <ns2:CreateSequence
            xmlns:ns6="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
            xmlns:ns5="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
            xmlns:ns4="http://www.w3.org/2005/08/addressing" xmlns:ns3="http://schemas.microsoft.com/ws/2006/05/rm"
            xmlns:ns2="http://schemas.xmlsoap.org/ws/2005/02/rm">
          <ns2:AcksTo>
            <ns4:Address>http://www.w3.org/2005/08/addressing/anonymous</ns4:Address>
          </ns2:AcksTo>
          <ns2:Offer>
            <ns2:Identifier>uuid:4953079f-3726-40b5-b6b4-255eb46c0fda</ns2:Identifier>
          </ns2:Offer>
        </ns2:CreateSequence>
      </S:Body>
    </S:Envelope>
    ============
    ====[com.sun.xml.ws.assembler.client:response]====
    <?xml version="1.0" ?>
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
      <s:Header>
        <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequenceResponse</a:Action>
        <a:RelatesTo>uuid:fcaef2ab-bccf-4a08-a1d1-b10f7819f7ea</a:RelatesTo>
      </s:Header>
      <s:Body>
        <CreateSequenceResponse xmlns="http://schemas.xmlsoap.org/ws/2005/02/rm">
          <Identifier>urn:uuid:8ebe44c6-494c-4a43-8ade-dab90800d7f5</Identifier>
          <Accept>
            <AcksTo>
              <a:Address>http://iamfine/wsit-reliable/service.svc</a:Address>
            </AcksTo>
          </Accept>
        </CreateSequenceResponse>
      </s:Body>
    </s:Envelope>
    ============
    ====[com.sun.xml.ws.assembler.client:request]====
    <?xml version="1.0" ?>
    <S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
      <S:Header>
        <To xmlns="http://www.w3.org/2005/08/addressing">http://iamfine/wsit-reliable/service.svc</To>
        <Action xmlns="http://www.w3.org/2005/08/addressing">http://tempuri.org/IHello/sayHello</Action>
        <ReplyTo xmlns="http://www.w3.org/2005/08/addressing">
          <Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
        </ReplyTo>
        <MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:5ac7c151-8049-444e-8dd0-1e053b26895d</MessageID>
        <ns2:Sequence
          xmlns:ns4="http://www.w3.org/2005/08/addressing"
          xmlns:ns3="http://schemas.microsoft.com/ws/2006/05/rm"
          xmlns:ns2="http://schemas.xmlsoap.org/ws/2005/02/rm">
          <ns2:Identifier>urn:uuid:8ebe44c6-494c-4a43-8ade-dab90800d7f5</ns2:Identifier>
          <ns2:MessageNumber>1</ns2:MessageNumber>
        </ns2:Sequence>
        <ns2:AckRequested
          xmlns:ns4="http://www.w3.org/2005/08/addressing"
          xmlns:ns3="http://schemas.microsoft.com/ws/2006/05/rm"
          xmlns:ns2="http://schemas.xmlsoap.org/ws/2005/02/rm">
          <ns2:Identifier>urn:uuid:8ebe44c6-494c-4a43-8ade-dab90800d7f5</ns2:Identifier>
        </ns2:AckRequested>
      </S:Header>
      <S:Body>
        <sayHello xmlns:ns2="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://tempuri.org/">
          <name>Duke</name>
        </sayHello>
      </S:Body>
    </S:Envelope>
    ============
    ====[com.sun.xml.ws.assembler.client:response]====
    <?xml version="1.0" ?>
    <s:Envelope
        xmlns:s="http://www.w3.org/2003/05/soap-envelope"
        xmlns:r="http://schemas.xmlsoap.org/ws/2005/02/rm"
        xmlns:a="http://www.w3.org/2005/08/addressing">
      <s:Header>
        <r:Sequence s:mustUnderstand="1">
          <r:Identifier>uuid:4953079f-3726-40b5-b6b4-255eb46c0fda</r:Identifier>
          <r:MessageNumber>1</r:MessageNumber>
        </r:Sequence>
        <r:SequenceAcknowledgement>
        <r:Identifier>urn:uuid:8ebe44c6-494c-4a43-8ade-dab90800d7f5</r:Identifier>
        <r:AcknowledgementRange Lower="1" Upper="1"></r:AcknowledgementRange>
          <netrm:BufferRemaining xmlns:netrm="http://schemas.microsoft.com/ws/2006/05/rm">8</netrm:BufferRemaining>
        </r:SequenceAcknowledgement>
        <a:Action s:mustUnderstand="1">http://tempuri.org/IHello/sayHelloResponse</a:Action>
        <a:RelatesTo>uuid:5ac7c151-8049-444e-8dd0-1e053b26895d</a:RelatesTo>
      </s:Header>
      <s:Body>
        <sayHelloResponse xmlns="http://tempuri.org/">
          <sayHelloResult>Hello Duke</sayHelloResult>
        </sayHelloResponse>
      </s:Body>
    </s:Envelope>
    ============

There were no custom settings or configurations required to make the WSIT client This shows, once again, that GlassFish V2 and .NET 3.0 (pre-bundled in Vista) are interoperable out of the box.

Technorati: webservices wsit glassfish reliablemessaging wcf interoperability

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20070508 Tuesday May 08, 2007

Screencast #WS5: Excel using WSIT! JavaOne 2007 Demo

Web Services Interoperability Technology (WSIT, aka Project Tango) enables first-class interoperability between Sun's Web services stack and Microsoft .NET 3.0 framework. First-class means truly out-of-the-box which does not require any configuration of parameters on either side. To demonstrate that, in JavaOne 2007, we are showing how an Excel 2007 spreadsheet on Windows Vista can invoke a secure and reliable WSIT endpoint hosted on GlassFish V2.

If you are attending JavaOne, session TS-4865 (Wed 4:10pm and repeat on Fri 1:30pm) and booth #966 in the Pavilion shows this sample in detail. But if you are not able to attend, then you can enjoy the screen cast.

Enjoy it here!

Here are the key points highlighted in this demo:

  1. Proven real-world interoperability with .NET 3.0. It's not just confined to "Hello World" or some arcane test case.
  2. Technologies transparent to applications
    1. No new APIs (use existing JAX-WS or EJBs)
    2. Excellent support in NetBeans IDE.
  3. Integrated with GlassFish V2, an open source, production-quality and Java EE 5 compatible application server.

Leave a comment on the blog if you have a similar scenario in your organization and would like to know more details.

Technorati: wsit webservices glassfish javaone screencast wcf

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20070426 Thursday April 26, 2007

How to invoke a WSIT endpoint from a WCF client ?

You've developed a reliable, secure transactional and interoperable Web service using Web Services Interoperability Technology (WSIT, aka Project Tango) plug-in in NetBeans 5.5.1 and deployed on GlassFish v2. NetBeans IDE provide a very seamless experience to build such a Web service. The primary goal of WSIT is to provide first-class interoperability with Windows Communication Foundation (WCF), the Web services component of .NET 3.0 framework. Once the Web service is deployed, you'd like to invoke this Web service by writing a client using Visual Studio. It's not straight forward to do so today and this entry highlights the steps required to do that.

  1. If not already done, create a reliable WSIT endpoint and deploy on GlassFish v2 following the screencast #ws3.
  2. For creating a WCF client, install the following software
    1. If not using Vista, then install .NET 3.0 Framework runtime.
    2. Microsoft Visual Studio 2005 Professional Edition (available via MSDN) - There are additional requirements for Express editions (free lightweight versions of Visual Studio)
    3. Microsoft Visual Studio 2005 Professional Edition SP1
    4. Microsoft Visual Studio 2005 Professional Edition SP1 Update
    5. Visual Studio 2005 Extensions for .NET 3.0 Framework (WCF & WPF), Nov 2006 CTP - For Express editions, Windows Vista SDK is required as well for WCF scenarios.
  3. Start Visual Studio
  4. Create a new Visual C#, Windows, Console Application. Program.cs is shown in the main Visual Studio window.
  5. In Solution Explorer, right-click on the project name and select "Add Service Reference ...". This is the big difference. If you select "Add Web Reference ...", then this creates a proxy and app.config for .NET 2.0 framework. But WSIT is about interoperability with .NET 3.0 framework.
  6. Specify the location of the WSIT endpoint, in our case (http://localhost:8080/WebApplication1/NewWebServiceService?wsdl).
  7. In the Main function of Program.cs, add the logic to invoke the generated proxy. The code looks like:
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using ConsoleApplication1.localhost;
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                NewWebServiceClient client = new NewWebServiceClient();
                Console.WriteLine(client.sayHello("Duke"));
            }
        }
    }
  8. Build the solution by selecting "Build", "Build Solution" (default shortcut Ctrl+Shift+B).
  9. Run ConsoleApplication1\bin\Debug\ConsoleApplication1.exe. This will make a request to WSIT endpoint and get a response back.

The generated app.config file looks like:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="NewWebServicePortBinding">
          <reliableSession acknowledgementInterval="00:00:00.2000000" flowControlEnabled="true"
              inactivityTimeout="00:10:00" maxPendingChannels="4" maxRetryCount="8"
              maxTransferWindowSize="8" ordered="true" />
          <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16" 
              messageVersion="Soap11WSAddressing10" writeEncoding="utf-8">
              <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
                  maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          </textMessageEncoding>
          <httpTransport manualAddressing="false" maxBufferPoolSize="524288"
              maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous"
              bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
              keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Anonymous"
              realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
              useDefaultWebProxy="true" />
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:8080/WebApplication1/NewWebServiceService"
          binding="customBinding" bindingConfiguration="NewWebServicePortBinding"
          contract="ConsoleApplication1.localhost.NewWebService" name="NewWebServicePort" />
    </client>
  </system.serviceModel>
</configuration>

Here are the SOAP messages that get exchanged over the wire:

====[com.sun.xml.ws.assembler.server:request]====
<?xml version="1.0" ?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence</a:Action>
    <a:MessageID>urn:uuid:3429a390-96df-4f26-bd8c-fc85bd8f1858</a:MessageID>
    <a:To s:mustUnderstand="1">http://localhost:8080/WebApplication1/NewWebServiceService</a:To>
  </s:Header>
  <s:Body>
    <CreateSequence xmlns="http://schemas.xmlsoap.org/ws/2005/02/rm">
      <AcksTo>
        <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
      </AcksTo>
      <Offer>
        <Identifier>urn:uuid:402432c9-b191-4912-a04a-69bbdbd1b2d3</Identifier>
      </Offer>
    </CreateSequence>
  </s:Body>
</s:Envelope>
============
====[com.sun.xml.ws.assembler.server:response]====
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
  <S:Header>
  <To xmlns="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/anonymous</To>
    <Action xmlns="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequenceResponse</Action>
    <MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:b51f92ee-9ab9-4a90-a61e-d5dd3a77a0f9</MessageID>
    <RelatesTo xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:3429a390-96df-4f26-bd8c-fc85bd8f1858</RelatesTo>
  </S:Header>
  <S:Body>
    <ns2:CreateSequenceResponse xmlns:ns6="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ns5="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:ns4="http://www.w3.org/2005/08/addressing" xmlns:ns3="http://schemas.microsoft.com/ws/2006/05/rm" xmlns:ns2="http://schemas.xmlsoap.org/ws/2005/02/rm">
      <ns2:Identifier>uuid:d01cff2f-9192-4672-942b-2ec284a93802</ns2:Identifier>
      <ns2:Accept>
        <ns2:AcksTo>
          <ns4:Address>http://localhost:8080/WebApplication1/NewWebServiceService</ns4:Address>
        </ns2:AcksTo>
      </ns2:Accept>
    </ns2:CreateSequenceResponse>
  </S:Body>
</S:Envelope>
============
====[com.sun.xml.ws.assembler.server:request]====
<?xml version="1.0" ?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:r="http://schemas.xmlsoap.org/ws/2005/02/rm" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <r:Sequence s:mustUnderstand="1">
      <r:Identifier>uuid:d01cff2f-9192-4672-942b-2ec284a93802</r:Identifier>
      <r:MessageNumber>1</r:MessageNumber>
    </r:Sequence>
    <a:Action s:mustUnderstand="1">sayHello</a:Action>
    <a:MessageID>urn:uuid:d9c8b864-f236-40ad-a4c0-72c42565855f</a:MessageID>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <a:To s:mustUnderstand="1">http://localhost:8080/WebApplication1/NewWebServiceService</a:To>
  </s:Header>
  <s:Body>
    <sayHello xmlns="http://test/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <name xmlns="">Duke</name>
    </sayHello>
  </s:Body>
</s:Envelope>
============
====[com.sun.xml.ws.assembler.server:response]====
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
  <S:Header>
    <To xmlns="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/anonymous</To>
    <Action xmlns="http://www.w3.org/2005/08/addressing">http://test/NewWebService/sayHelloResponse</Action>
    <MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:9091661c-c817-4411-b8aa-7f4f937162da</MessageID>
    <RelatesTo xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:d9c8b864-f236-40ad-a4c0-72c42565855f</RelatesTo>
    <ns2:Sequence xmlns:ns4="http://www.w3.org/2005/08/addressing" xmlns:ns3="http://schemas.microsoft.com/ws/2006/05/rm" xmlns:ns2="http://schemas.xmlsoap.org/ws/2005/02/rm">
      <ns2:Identifier>urn:uuid:402432c9-b191-4912-a04a-69bbdbd1b2d3</ns2:Identifier>
      <ns2:MessageNumber>1</ns2:MessageNumber>
    </ns2:Sequence>
    <ns2:AckRequested xmlns:ns4="http://www.w3.org/2005/08/addressing" xmlns:ns3="http://schemas.microsoft.com/ws/2006/05/rm" xmlns:ns2="http://schemas.xmlsoap.org/ws/2005/02/rm">
      <ns2:Identifier>urn:uuid:402432c9-b191-4912-a04a-69bbdbd1b2d3</ns2:Identifier>
    </ns2:AckRequested>
    <ns2:SequenceAcknowledgement xmlns:ns4="http://www.w3.org/2005/08/addressing" xmlns:ns3="http://schemas.microsoft.com/ws/2006/05/rm" xmlns:ns2="http://schemas.xmlsoap.org/ws/2005/02/rm">
    <ns2:Identifier>uuid:d01cff2f-9192-4672-942b-2ec284a93802</ns2:Identifier>
    <ns2:AcknowledgementRange Upper="1" Lower="1"></ns2:AcknowledgementRange>
    </ns2:SequenceAcknowledgement>
  </S:Header>
  <S:Body>
    <ns2:sayHelloResponse xmlns:ns2="http://test/">
      <return>Hello Duke</return>
    </ns2:sayHelloResponse>
  </S:Body>
</S:Envelope>
============ 

The same programming model will work for creating a WCF client if you add security or transactions support on the WSIT endpoint.

Technorati: wsit glassfish webservices vista wcf visualstudio

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20061224 Sunday December 24, 2006

http://blogs.sun.com/arungupta/date/20061019 Thursday October 19, 2006

Interop Plugfest: Behind the curtains

Read Jorgen's interview on The Server Side about how the Interop plugfests at Microsoft are arranged. There is full section talking about WSIT and WCF interoperability towards the end of the interview. As mentioned in my previous plugfest reports (1, 2, 3), we have incrementally achieved a very good level of interoperability with Microsoft. And this is also evident (Green and Yellow is good) in the slide used at Microsoft tracking WS-* adoption in the industry.

WSIT technologies are available in GlassFish.

Technorati: WSIT WCF

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20061004 Wednesday October 04, 2006

WSIT and WCF Plugfest

"I" in WSIT stands for Interoperability. To ensure WSIT is interoperable with .NET 3.0, WSIT engineers made a third visit to Microsoft headquarters in less than a year. Microsoft hosted the third plugfest at their campus and Sun Microsystems showed up to test WSIT and GlassFish interoperability with their upcoming .NET 3.0 stack.

Harold, Mike, Jiandong, Joe, Ken and myself (all from Sun) "wsited" Microsoft last week. We were just representations of the bigger team and effort scattered all over the globe (Santa Clara, Burlington, Salt Lake City, Portland, Prague, Germany, France, Bangalore). And then there were some engineers doing remote testing as well.

As mentioned earlier, WS-Addressing functionality in JAX-WSA is cleaned up and now an integral part of  JAX-WS 2.1 RI. That has been my focus for the past few weeks. So in this plug-fest, I took our JAX-WS 2.1 RI for interop on WS-Addressing test cases. Microsoft has caused a few interop problems with WS-Addressing in the past (Member Submission policy assertion namespace change, incorrect Action from WCF client, WS-Addressing WSDL namespace change). But this time everything worked, it just worked. And that's what is out-of-the-box interoperability.

Other than that, we had a good success rate doing interop on WS-Atomic Transactions, WS-Reliable Messaging, WS-Secure Conversation, WSS 1.0 and 1.1, WS-Trust. We achieved interop on composite scenarios like Secure Reliable Messaging and Secure MTOM. And this interop is two-way meaning that WCF client invoke WSIT endpoint and WSIT client invoke WCF endpoint.

We care about "I", the most, in WSIT. GlassFish v2 now integrates WSIT bits on a regular basis. When GlassFish v2 goes final, be assured it will be interoperable with .NET 3.0 framework shipping in Windows Vista and other platforms.

Read about our success stories from first and second plugfests.

Technorati: WSIT Interoperability Indigo WCF Dotnet

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20061003 Tuesday October 03, 2006

WS-Addressing Member Submission Policy Assertion Namespace Change in WCF

WCF RC1 (probably in Jul CTP as well) changed the policy assertion namespace URI to declare the usage of Member Submission WS-Addressing. The namespace was changed from:

http://schemas.xmlsoap.org/ws/2004/09/policy/addressing

to

http://schemas.xmlsoap.org/ws/2004/08/addressing/policy

Thus any WSDL published by a WCF-based service endpoint using Member Submission WS-Addressing cannot be imported by WSIT clients directly. We will provide a fix in the days to come.

But in order to fix the problem, in the meanwhile, when importing such a WSDL using wsimport, you need to localize the WCF-generated WSDL, change the namespace to the original namespace (ending in 2004/09/policy/addressing) and then import it using wsimport.

Similarly, any WSDL published by a WSIT-based endpoint cannot be imported by svcutil directly. The temporary fix involves localizing the WSIT-generated WSDL, changing the namespace as it is recognized by their tools (ending in 2004/08/addressing/policy) and then importing it using their tool.

Technorati: WSIT Web-services  WCF Interoperability WSIT

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20060921 Thursday September 21, 2006

WS-Addressing and WSIT M2

Other than performance improvements and minor bugfixes, the biggest change in WS-Addressing from WSIT M1 to M2 is enabling interoperability with a publicly available release of .NET 3.0 runtime (a.k.a. WCF or Indigo). The problem was identified few weeks ago and fixed right away but this is the first milestone build to incorporate the fix.

As mentioned earlier, WS-Addressing functionality is getting subsumed in JAX-WS 2.1. If everything goes well, a subsequent release of WSIT will use WS-Addressing functionality from JAX-WS 2.1 instead of JAX-WSA. As a developer, this change will not be visible to you except that it will be a faster and better performing implementation. Read Vivek's blog for more details on JAX-WS 2.1 roadmap. I'll provide more details on WS-Addressing implementation in a later entry.

Other than that, there is not much activity on JAX-WSA. Hope you are enjoying WSITing.

Technorati: WSIT Web-services JAX-WSA WCF

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20060918 Monday September 18, 2006

Upcoming WCF Plugfest

Microsoft is hosting a Windows Communication Foundation (a.k.a. Indigo) interop plug-fest in Seattle from Sep 26-28. Sun Microsystems will participate in this plug-fest as we did during the previous two (Mar 2006, Nov 2005). We will be taking WSIT and GlassFish for all the interop testing.

I'll post another blog entry, with our interop report, after the plug-fest.

Technorati: Interoperability WSIT WCF Indigo

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20060817 Thursday August 17, 2006

WSIT Milestone 1

WSIT Milestone 1 release has been available for few days now.

Follow 4 simple steps to download the binary release or build from the source and build a secure, reliable and interoperable Web service using the comprehensive tutorial. The samples range from simply adding the two numbers to a price quote service using secure, reliable and brokered trust pattern. All the samples can be installed on GlassFish or Tomcat.

Although the milestone binary does not interoperate with a publicly-available Windows Communication Foundation the current version of the sources does interoperate with the July CTP (runtime and SDK). A WSIT binary release that does interoperate with WCF will be available soon.

Your feedback is very appreciated.

Technorati: WSIT Web-services WCF Indigo GlassFish

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20060807 Monday August 07, 2006

JavaOne 2006 Keynote WSIT Demo

A new sample is added to WSIT samples that shows an enterprise Web service enabling integration both within and across boundaries. This sample demonstrates a price quotation service that provides list price to clients based on the product identifiers. The client makes a request to a Retail Quote Service (RQS)  which then communicates with multiple Wholesale Quote Service (WQS) to get the best price and returns that to the client. In the first version of this sample, the client and all the service endpoints (RQS + 2 WQS) are built and deployed using WSIT. A later version of the sample will replace one of the WQS to be built and deployed using Windows Communication Foundation (WCF) and also have a WCF client, in addition to WSIT client, invoking the RQS.

The sample demonstrates secure reliable communication between RQS and two WQS. It also demonstrates secure MTOM between the client and RQS. A picture is worth a thousand pictures and so this graphical representation should help visualize.

This sample was demonstrated in JavaOne 2006 keynote and used as the basis of my JavaOne 2006 technical session (TS-5540). In case, you need more technical details, the StarOffice version of slide has speaker notes and animation.

Instructions to check out the sample

This sample can be checked out using the instructions given here. These instructions will retrieve WSIT sources along with the sample sources as both are required to build, run and deploy the sample. The sample exists in wsit/wsit/samples/pricequote directory. Once checked out, follow the instructions in readme.html in the pricequote directory to build and deploy the sample on GlassFish.

Technorati: Javaone Indigo WCF Web-services Interoperability presos

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20060804 Friday August 04, 2006

WCF Interop: Workaround for Incorrect Action values from WCF client

In my last blog entry, I described how WS-Addressing Action header value is calculated. A WSIT-enabled client/endpoint generates/expects the correct values per W3C Candidate Recommendation.  However Microsoft's WCF (Windows Communication Foundation) client does not generate the correct value of Action header in all cases. This blog describes the issue and workaround. 

As described in the previous blog, in the first case, where wsaw:Action is explicitly associated with wsdl:input message, WCF client generates the correct Action header value. In the second case where a non-empty soapAction is specified on wsdl:binding/wsdl:operation, WCF client generates the correct Action header value. In the third case where either soapAction is not specified or defined with an empty string as it's value, WCF client generates empty string as Action header instead of the default action. This causes an interoperability issue between WSIT and WCF starting Jun CTP. Lets understand this issue and see how it can be worked around.

If the WSDL has either of the following binding sections:  

<binding name="..." type="tns:wsaTestPortType">
  ...
  <operation name="echo">
    <soap:operation soapAction="">
    ...
  </operation>
</binding>

where soapAction's value is an empty string, or

<binding name="..." type="tns:wsaTestPortType">
    ...
  <operation name="echo">
    <soap:operation>
    ...
  </operation>
</binding>

where soapAction is not specified, then WCF client sends empty string as Action header value.

This is incorrect as W3C WS-Addressing WSDL Binding requires a default action to be generated/expected in this case. But because WSIT-based endpoint expects the correct value according to W3C Candidate Recommendation, there is a conflict and thus WSIT and WCF do not interoperate. Without getting into why there are different interpretations of the spec (probably another blog later), lets see how we can work around this.

WSIT Java-first endpoint, WCF client

If you build your Web service endpoint starting from Java (as opposed to starting from WSDL), then wsimport tool will generate a WSDL with soapAction="" in the SOAP binding. The reason it does that is because JSR 181 (Web Services Metadata for the JavaTM Platform) says all methods in a SEI (service endpoint interface) are mapped to WSDL operations. A @WebMethod annotation may be used to customize the mapping, but in it's absence a default @WebMethod is assumed on each method. The @WebMethod annotation has a member with name "action" that determines the value of soapAction for SOAP bindings. This member has a default value of "" (empty string). And thus, in this case, any WSDL generated by WSIT, either at runtime or using wsimport tool, where SEI does not have @WebMethod.action set to any non-empty-string value, has soapAction="" in the SOAP binding section.

So if your SEI looks like:

@WebService
public class AddNumbersImpl {

  public int addNumbers(int number1, int number2) {
    ...
  }
}

The generated SOAP binding will look like:

<operation name="addNumbers">
  <soap:operation soapAction="" />
  ...
</operation>

As explained above, WSIT and WCF do not interoperate for such a WSDL. The default value (empty string) of soapAction can easily be overridden by adding a @WebMethod annotation on your method as shown below. So if your SEI looks like:

@WebService
public class AddNumbersImpl {

  @WebMethod(action="addNumbers";)
  public int addNumbers(int number1, int number2) {
    ...
  }
}

The generated SOAP binding in this case looks like:

<operation name="addNumbers">
  <soap:operation soapAction="addNumbers" />
  ...
</operation>

WCF client will generate "addNumbers" as the Action header and WSIT endpoint will accept it as a valid value.

WSIT WSDL-first endpoint, WCF client

If you are starting from WSDL, then you can either explicitly specify wsaw:Action attribute on the input message, as shown below:

<portType name="AddNumbersImpl">
  <operation name="addNumbers">
    <input message="tns:addNumbers" wsaw:Action="http://example.org/action/echoIn"/>
    <output message="tns:addNumbersResponse"/>
  </operation>
</portType>

Note, this is only required to be changed for input messages as WSIT endpoint generates the correct action on fault and output messages going back to WCF client.

Alternatively you can change, or add if missing, soapAction in the binding section, as shown below:

<operation name="addNumbers">
  <soap:operation soapAction="addNumbers" />
  ...
</operation>

As a convenience, you can use the operation name as the value of either wsaw:Action or soapAction since that is guaranteed to be unique.

WCF Endpoint, WSIT client

A WCF endpoint always generates explicit wsaw:Action for each message in the portType and exactly same value of soapAction. WSIT client is interoperable with WCF endpoints out of the box in this case.

Hopefully WCF will be fixed in the upcoming CTP and behave as per W3C standards. Then this workaround will not be required and life will be simpler again :)

Technorati:   WSIT WCF Indigo Web-services Interoperability

del.icio.us | furl | simpy | slashdot | technorati | digg |
|
Main | Next page »

Valid HTML! Valid CSS!

This is a personal weblog, I do not speak for my employer.