Tuesday, August 19, 2014

JAX-WS Start From WSDL-doc style

JAX-WS supports both Start from Java and Start from WSDL approach. Let's look into how we can build a web service with a WSDL first approach. Again the WSDL can be of doc style or rpc style. From Java perspective that does not make much of difference. The difference in doc style and rpc style make more of difference in how you think about when you first write WSDL for web service.

Let's suppose we have a WSDL   which is a doc style. Let's have a WSDL which is for Temperature conversion. This WSDL provides two service. To convert Fahrenheit to Celsius and vice versa.

WSDL:

<definitions targetNamespace="http://ws.lalit.com/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://ws.lalit.com/"
xmlns:omTypes="http://lalit.com/omTypes"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
name="TemperatureConvertorService">

<types>
<xsd:schema targetNamespace="http://lalit.com/omTypes"
    xmlns="http://www.w3.org/2001/XMLSchema"
    xmlns:omTypes="http://lalit.com/omTypes"
    elementFormDefault="qualified">

<complexType name="temperatureCelsius">
  <sequence>
    <element name="return" type="xsd:double" />
  </sequence>
</complexType>

<element name="temperatureCelsiusValue" type="omTypes:temperatureCelsius" />

<complexType name="temperatureFar">
  <sequence>
    <element name="return" type="xsd:double" />
  </sequence>
</complexType>

<element name="temperatureFarValue" type="omTypes:temperatureFar" />

</xsd:schema>
</types>

<message name="temperatureCelsiusValue">
  <part name="parameters" element="omTypes:temperatureCelsiusValue" />
</message>

<message name="temperatureFarValue">
  <part name="parameters" element="omTypes:temperatureFarValue" />
</message>

<portType name="TemperatureConvertor">
  <operation name="celsiusToFarenheitOp">
    <input message="tns:temperatureCelsiusValue" />
    <output message="tns:temperatureFarValue" />
  </operation>
  <operation name="farenheitToCelsiusOp">
    <input message="tns:temperatureFarValue" />
    <output message="tns:temperatureCelsiusValue" />
    </operation>
</portType>

<binding name="TemperatureConvertorPortBinding" type="tns:TemperatureConvertor">
  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
    <operation name="celsiusToFarenheitOp">
      <soap:operation soapAction="" />
        <input>    <soap:body use="literal"/></input>
        <output><soap:body use="literal" /></output>
    </operation>
    <operation name="farenheitToCelsiusOp">
      <soap:operation soapAction="" />
        <input>    <soap:body use="literal" /></input>
        <output><soap:body use="literal" /></output>
    </operation>
</binding>

<service name="TemperatureConvertorService">
   <port name="TemperatureConvertorPort" binding="tns:TemperatureConvertorPortBinding">
     <soap:address location="REPLACE_WITH_URL" />
   </port>
</service>

</definitions>

Make a dynamic web application and put the above WSDL at WEB-INF/wsdl/. 
Let's name this WSDL as temperatureConvertor.wsdl

Now run the wsimport tool and generate the artifacts

wsimport -keep -s <source_folder_location> -d <generated_compiled_class>  <WSDL location with WSDL Name>

-keep will keep the generated file.

After the above command runs successfully, a TemperatureConvertor Interface is generated. The generated interface looks as follows:

@WebService(name = "TemperatureConvertor", 
            targetNamespace = "http://ws.lalit.com/")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@XmlSeeAlso({ObjectFactory.class})
public interface TemperatureConvertor {

   @WebMethod
    @WebResult(name = "temperatureFarValue",
    targetNamespace = "http://lalit.com/omTypes", 
    partName = "parameters")
    public TemperatureFar celsiusToFarenheitOp(    
       @WebParam(name = "temperatureCelsiusValue",
                  targetNamespace = "http://lalit.com/omTypes",
                  partName = "parameters") TemperatureCelsius parameters);
}

Also note that it will generate JAXB binding classes of type TemperaturFar and TemperatureClesius.
Now implement this class which will become the service end point

@WebService(
     endpointInterface="com.lalit.ws.TemperatureConvertor")
public class TemperatureConvertorImpl implements TemperatureConvertor {

  public TemperatureFar celsiusToFarenheitOp(TemperatureCelsius parameters) {
    double celsius = parameters.getReturn();
    double fahr = 1.8*celsius + 32;
    TemperatureFar tempFar = new TemperatureFar();
    tempFar.setReturn(fahr);
    return tempFar;
  }
...

Register this Web service endpoint in web.xml

<servlet>
  <servlet-name>TemperaturConvertor</servlet-name>
  <servlet-class>com.oyeJava.TemperatureConvertorImpl</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>TemperaturConvertor</servlet-name>
  <url-pattern>/TemperaturConvertor</url-pattern>
</servlet-mapping>

Deploy the war and hit the WSDL. However you will note that this WSDL is not similar to what you have provided. The server generates its own WSDL. If you want to force the server to use your WSDL than change the following:

@WebService(name = "TemperatureConvertor",
    endpointInterface="com.lalit.ws.TemperatureConvertor",
    targetNamespace = "http://ws.lalit.com/",
    wsdlLocation = "WEB-INF/wsdl/TemperatureConvertorDocStyle.wsdl")
public class TemperatureConvertorService implements TemperatureConvertor {
     ....

More on Web services

No comments:

Post a Comment