Monday, January 24, 2011

JAX-WS and json attachment

In this post I am going to explain how create simple soap/http-json codec attachment call.

Assumption:  target user aware of wsimport, wsdl , soap and json.
1)   Create wsdl  with attachment messages

<wsdl:definitions name="Attachment" 
targetNamespace="http://jsonwebservice.googlecode.com/attachment"
  xmlns:tns="http://jsonwebservice.googlecode.com/attachment" 
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:json="http://schemas.jsonsoap.org/wsdl/json/"
  xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
  xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">

<wsdl:types>
    <xsd:schema elementFormDefault="qualified" targetNamespace="http://jsonwebservice.googlecode.com/attachment">
1.1)   Dummy input object for testing.


<xsd:complexType name="TestInput">
  <xsd:sequence>
     <xsd:element name="input" type="xsd:string"/>
   </xsd:sequence>  
 </xsd:complexType>
1.2) Response type definition "html" element is a attachment.  JAX-WS generate DataSource, Source or Image java type based on xmime contnet type.

<xsd:complexType name="HtmlStreamOutput">
   <xsd:sequence>
     <xsd:element name="outputFormates" type="xsd:string"/>
     <xsd:element name="html" type="xsd:base64Binary" xmime:expectedContentTypes="application/html"/>
   </xsd:sequence>
 </xsd:complexType>

 </xsd:schema>
  </wsdl:types>

1.3) Here is mime type with java type mapping.


public static final String JPEG_IMAGE_MIME_TYPE = "image/jpeg"; java Image
    //public static final String PNG_IMAGE_MIME_TYPE = "image/png";java Image
    public static final String GIF_IMAGE_MIME_TYPE = "image/gif";java Image
    public static final String TEXT_XML_MIME_TYPE = "text/xml"; Source
    public static final String TEXT_HTML_MIME_TYPE = "text/html"; DataHandler
    public static final String TEXT_PLAIN_MIME_TYPE = "text/plain"; String
    public static final String APPLICATION_XML_MIME_TYPE = "application/xml"; Source
    public static final String MULTIPART_MIME_TYPE = "multipart/*"; DataHandler
 

1.4) Then define all fancy wsdl message port and binding declarations.


<wsdl:message name="TestInputRequest">
    <wsdl:part name="testInput" type="tns:TestInput"/>
  </wsdl:message>
  <wsdl:message name="GetHtmlResponse">
    <wsdl:part name="getChartOutput" type="tns:HtmlStreamOutput"/>
  </wsdl:message>
<wsdl:portType name="ChartPort">

<wsdl:operation name="getHTMLStream">
      <wsdl:input message="tns:TestInputRequest"/>
      <wsdl:output message="tns:GetHtmlResponse"/>
    </wsdl:operation>

  </wsdl:portType>
<wsdl:binding name="SOAPChartBinding" type="tns:ChartPort">

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

<wsdl:operation name="getHTMLStream">
<soap:operation soapAction="http://jsonwebservice.googlecode.com/attachment/getHTMLStream"
style="rpc" />
<wsdl:input><soap:body use="literal" namespace="http://jsonwebservice.googlecode.com/attachment"/></wsdl:input>
 <wsdl:output>
  <mime:multipartRelated>
<mime:part>
<soap:body use="literal" namespace="http://jsonwebservice.googlecode.com/attachment"/>
</mime:part>
<mime:part>
<mime:content part="html" type="image/jpeg"/>
</mime:part>
</mime:multipartRelated>
 </wsdl:output>
</wsdl:operation>

  </wsdl:binding>
<wsdl:binding name="ChartBinding" type="tns:ChartPort">
<json:binding transport="http://jsonplugin.googlecode.com/json/" style="rpc"/><wsdl:operation name="getHTMLStream">





<json:operation soapAction="http://jsonwebservice.googlecode.com/attachment/getHTMLStream"
style="rpc" />
<wsdl:input><json:body use="literal" namespace="http://code.google.com/json"/></wsdl:input>
<wsdl:output>
  <mime:multipartRelated>
<mime:part>
<json:body use="literal" namespace="http://code.google.com/json"/>
</mime:part>
<mime:part>
<mime:content part="html" type="image/jpeg"/>
</mime:part>
</mime:multipartRelated>
 </wsdl:output>
</wsdl:operation>

</wsdl:binding>
  <wsdl:service name="ChartService">
    <wsdl:port name="ChartPortType"
               binding="tns:ChartBinding">
      <json:address location="http://localhost:8080/attachment/ChartService.json"/>
    </wsdl:port>
    <wsdl:port name="SOAPChartPortType"
               binding="tns:ChartBinding">
      <soap:address location="http://localhost:8080/attachment/ChartService.soap"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

2) Then run wsimport using jax-ws. It generate all necessaries interface and objects for the service.

3) Create implementation class
  @SOAPBinding(style = SOAPBinding.Style.RPC)
@WebService(name = "ChartPort", 
targetNamespace = "http://jsonwebservice.googlecode.com/attachment", 
endpointInterface = "com.googlecode.jsonwebservice.attachment.ChartPort")
public class ChartPortImpl implements ChartPort {

@Override
public HtmlStreamOutput getHTMLStream(TestInput arg0) {
HtmlStreamOutput html = new HtmlStreamOutput();
html.setOutputFormates("text/html");
try {
// Also look at 
//StreamingDataHandler
// Any html attachment 
html.setHtml(new DataHandler(new URLDataSource(new URL("http://code.google.com/p/jsonwebservice/wiki/GettingStarted"))));
} catch (MalformedURLException e) {
e.printStackTrace();
}
return html;
}

4) Create other war standard xml files (web.xml,sun-jaxws.xml) and run the app.

Sample end point look like http://localhost:8080/attachment/ChartService.json

That's it. Nothing special other then defining wsdl mime type.

My sample form for attachment call looks like bellow http://localhost:8080/attachment/chart.json?formgetHTMLStream#_output



When I submit I do get html attachment pop ed up.



If you have any problem or question feel free to contact or report issues in http://code.google.com/p/jsonwebservice/



For quick start you can download latest war file from http://code.google.com/p/jsonwebservice/source/browse/trunk/demos/attachment/attachment.war

also browse source in http://code.google.com/p/jsonwebservice/source/browse/#



2 comments:

  1. When using soap and json both end point it is important to speciy port in sun-jaxws.xml file port="{http://jsonwebservice.test.com/rpc}EncoderTest".

    When you use only JSON endpoint this port should not be there in sun-jaxws file.

    ReplyDelete
  2. @WebService(name="EncoderPort",serviceName = "RPCTestService", portName = "EncoderPort",
    targetNamespace = "http://jsonwebservice.test.com/rpc",
    endpointInterface="com.test.jsonwebservice.rpc.EncoderTest",
    wsdlLocation="WEB-INF/wsdl/rpc.wsdl")
    /*
    * IMPORTANT wsdlLocation important to read mime type declaration from wsdl.
    * Absence of wsdlLocation lead to jax-ws generation wsdl. jax-ws genearted wsdl dont havespecified mime content in wsdl.
    *
    * Also it is important to match service name and portname with wsdl
    */
    public class EncoderTestImpl implements EncoderTest {

    ReplyDelete