Showing posts with label Web Services. Show all posts
Showing posts with label Web Services. Show all posts

Tuesday, February 27, 2018

Paging and Sorting using Spring Boot

Picture Credit : Pixabay


Please follow Rest API Server to see the big picture and GitHub repo details.

Paging and Sorting is an important use case for any application. Any web or mobile frontend, a listing will usually need such a capability.

To support Paging and sorting in a Spring boot application, we need to do the following.

The Spring data repository interface

Sunday, May 3, 2015

Invoking web services using Restlet

Restslet is a good framework to invoke rest based web services. Let's see through a simple program how to write a client to invoke Rest based webservices.

First  maven dependency

<repositories>
<repository>
<id>maven-restlet</id>
<name>Restlet repository</name>
<url>http://maven.restlet.com</url>
</repository>
</repositories>
<properties>
<restlet-version>2.3.1</restlet-version>
</properties>

Wednesday, April 1, 2015

Support for JDK8 types in Spring using Jackson

Spring has introduced RestController to handle rest based services. These controllers help in providing JSON based webservices using Jackson.  A typical REstcontroller based service looks like

@RestController
public class UserRestController{

@RequestMapping(value= "/user/{userId}", method = RequestMethod.GET)
public User getUser(@PathVariable Long userId){
    User user = userService.getUser(userId);
    return user;
  }
}

Sunday, September 21, 2014

Rest web services using Spring

Restful services are the most popular way of handling way services currently. And the favourite way of doing data exchange is JSON and not XML as JSON is quite compact and size of payload is quite less. Restful web services work over HTTP protocol and is literally about reading and wring JSON data structure. Spring support restful web services using the controller mechanism. Let's look into an example of Rest based web services using Spring 4.0.5.RELEASE version.

If you are using Spring mvc then a lot of infrastructure would have been already wired. However let's

Tuesday, August 19, 2014

Java Webservices Framework

A web services is primarily a software interaction. Softwares have been interacting with each other right from beginning, but web services make it better by providing a XML format exchange. Lately we are seeing web services being done with JSON style payload.

At the moment in Java landscape, there are many web services framework which provide both server and client side implementation framework. The prominent names doing round are as follows:

JAX-WS Provider

Web Service endpoints may choose to work at the XML message level by implementing the Provider interface. This is achieved by implementing either Provider<Source> or Provider<SOAPMessage> or Provider<DataSource>. The endpoint accesses the message or message payload using this low-level, generic API. This has to be a WSDL first approach. Let's assume that we have WSDL for getting the Price of the Product. the WSDL looks as follows:

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

JAX-WS EJB Endpoint

EJB3.0 specification has made writing web services much easier. You do not even need a web application to host the service. The web services can be hosted in EJB container in an easy way. To write the web service write a Stateless EJB and mark it as Web service

ProductPriceBean.java

@Stateless
@WebService
public class ProductPriceBean {

private Map productMap = new HashMap();
    
    {
        productMap.put("Java","500");
        productMap.put("C++","300");
    }

@WebMethod
public double getPrice(String symbol){
   String price = (String) productMap.get(symbol);
        if(price != null){
            return Double.parseDouble(price);
        }
   return -1;
}

Note that you donot have to write any interface like Local or Remote. Just write this, deploy it as a Jar in your EJB container and hit the ((WSDL)) at:

http://<hostName>/JAX_WS_EJB/ProductPriceBean?wsdl

More on Web services

JAX-WS JavaSE Service endpoint

JavaSE 6+ has support for publishing Webservice. The java version understands the @Webservice annotation.

Let's make a plain Java class:

@WebService
public class TemperatureConvertor {
    
    public double celsiusToFarenheit(double temp){
        return ((temp*1.8) + 32);
    }    
    public double farenheitToCelsius(double temp){
        return ((temp-32)/1.8);
    }

Generate the artifacts using wsgen tool. The tool will be located at your <JDK_HOME>/bin directory.

wsgen -keep -s <Directory where source to be generataed>
      -cp <Directory where Class files to be kept>
       <TemperatureConvertor class with full package>

Now write a main method:

TemperatureConvertor tc= new TemperatureConvertor();
Endpoint endpoint =     Endpoint.publish("http://localhost:8080/tempConv", tc);
System.out.println("Reached here");
//endpoint.stop(); //Uncommenting this will stop the service

Hit the wsdl at [http://example.com|http://localhost:8080/tempConv?wsdl]

Also you can hit the service at http://localhost:8080/tempConv using ((soapUI)) tool.

The service is hosted using an embedded HTTP server in JavaSE 6. Please refrain from using this server in production environment.

More on Web services

JAX-WS Server side Introduction

JAX-WS on the server side provide mechanisms to write web services and host them. There are predominately two approaches of writing web services.

  • Java to WSDL
  • WSDL to Java

In Java to WSDL approach, we first write a Java class or use existing Java class and convert it into a web service end point. In the WSDL to Java approach, the WSDL is already available. Using the WSDL the Java side code is generated which acts as the endpoint for the webservice. There is a third approach also which is a mid way approach. In real life you will often encounter this approach.

WSDL to Java or Java to WSDL
WSDL vs Java
WSDL First or Java First
More on Web services

JAX-WS Servlet Endpoint

The basic steps to write a Servlet end point approach is:
  • Write a POJO class
  • Annotate it
  • Configure in web.xml
  • Build and deploy.

WSDL file is generated automatically
Make a web application. In eclipse you can make a project which is a dynamic web project.

Let's write a POJO bean class which can be invoked by sending a SOAP Request which contains a string and it will return the response "Hello World" + input String.

POJO class:

@WebService
@SOAPBinding(style=SOAPBinding.Style.RPC)
public class HelloBean{

@WebMethod
public String hello(String name){
   return "Hello " + name;
  }
}

Note the annotation on the bean class. The class does not implements any interface.
Register this bean as a servlet in the web,xml

<servlet>
      <servlet-name>helloBean</servlet-name>
      <servlet-class>com.oyeJava.HelloBean</servlet-class>

  </servlet>
  <servlet-mapping>
      <servlet-name>helloBean</servlet-name>
      <url-pattern>/hello</url-pattern>
  </servlet-mapping>

Deploy the war in your server and hit the service at:

http://<hostname>/JAX_WS_HelloWorld/hello?wsdl

Please change the host name with your host name and JAX_WS_HelloWorld with your application context.
You can also follow the video:

JAX-WS Client Side

JAX-WS is designed in such a way that for the client the service invocation is similar to a local java method call.JAX-WS uses the SEI(Service End Point Interface). A dynamic proxy is created at runtime which handles the service invocation. JAX-WS does not uses stubs as its predecessor JAX-RPC

Let's use the web service hosted by JAX-WS Start From WSDL-doc style. Make a Java project and generate the code using wsimport utility. In Java 6+ the wsimport utility comes with the JDK. If your java is configured in the path, wsimport can be invoked at the command line.

wsimport.sh  -keep -s <source folder> -d <class folder> http://localhost:8080/JAX_WS_Servlet/TemperaturConvertor?wsdl

Change the WSDL location as per your configuration. This will generate the JAXB mapping and the Service endpoint.

TemperatureConvertorService service = new TemperatureConvertorService();
TemperatureConvertor port = service.getPort(TemperatureConvertor.class);

TemperatureCelsius celsius = new TemperatureCelsius();
celsius.setReturn(100.0);        
TemperatureFar fahr = port.celsiusToFarenheitOp(celsius);

System.out.println(fahr.getReturn());

For the client of RPC style services, again run the wsimport against RPC style wsdl. This will again generate the artifacts. Now from the main method call the service as follows:

TemperatureConvertorServiceRPC service = new TemperatureConvertorServiceRPC();
TemperatureConvertorRPC port = service.getPort(TemperatureConvertorRPC.class);

Holder<Double> fahr = new Holder<Double>();
fahr.value = 212.0;

port.farenheitToCelsiusOp(fahr);
System.out.println(fahr.value);

More on Web services

JAX-WS Start From WSDL - RPC style

JAX-WS supports the end point artifacts generation for RPC style also. However note that though there is some minor differences in the kind of code generation, it is more of a theoretical discussion from the perspective of artifacts generated by Java.

Let's have a WSDL which again is for Temperature conversion but this time the WSDL is RPC style.

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

<types/>

<message name="temperatureValue">
  <part name="parameters" type="xsd:double" />
</message>

<portType name="TemperatureConvertorRPC">
  <operation name="celsiusToFarenheitOp">
    <input message="tns:temperatureValue" />
    <output message="tns:temperatureValue" />
  </operation>
  <operation name="farenheitToCelsiusOp">
    <input message="tns:temperatureValue" />
    <output message="tns:temperatureValue" />
  </operation>
</portType>

<binding name="TemperatureConvertorPortBinding" type="tns:TemperatureConvertorRPC">
  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc" />
    <operation name="celsiusToFarenheitOp">
      <soap:operation soapAction="" />
      <input>
          <soap:body use="literal" namespace="http://ws.lalit.com/" />
      </input>
      <output>
           <soap:body use="literal" namespace="http://ws.lalit.com/" />
      </output>
    </operation>
    <operation name="farenheitToCelsiusOp">
      <soap:operation soapAction="" />
      <input><soap:body use="literal" namespace="http://ws.lalit.com/" />
      </input>
      <output><soap:body use="literal" namespace="http://ws.lalit.com/" />
      </output>
    </operation>
</binding>

<service name="TemperatureConvertorServiceRPC">
  <port name="TemperatureConvertorRPCPort" binding="tns:TemperatureConvertorPortBinding">
    <soap:address location="http://localhost:8081/tempConv" />
  </port>
</service>

</definitions>

Not the in message we have type in place of element.Again generate the artifact using wsimport

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

The generated interface looks as follows:

@WebService(name = "TemperatureConvertorRPC",     
                     targetNamespace = "http://ws.lalit.com/")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface TemperatureConvertorRPC{

    @WebMethod
    public void celsiusToFarenheitOp(
        @WebParam(name = "parameters",
           mode = WebParam.Mode.INOUT,
          partName = "parameters")
        Holder<Double> parameters);

Note that the parameter is type Holder<T>. It is a type of inout parameter where the argument is send as Holder<T> and is returned back using the same parameter.
Implement the interface

@WebService(endpointInterface="com.lalit.ws.TemperatureConvertorRPC")
public class TemperatureConvertorRPCService implements TemperatureConvertorRPC {

  public void celsiusToFarenheitOp(Holder<Double> parameters) {
      double celsius = parameters.value;
      double fahr = 1.8*celsius +32;
      parameters.value = fahr;
  }
...

Register the endpoint

<servlet>
  <servlet-name>TemperaturConvertorRPC</servlet-name>
<servlet-class>com.oyeJava.TemperatureConvertorRPCService</servlet-class>
</servlet>

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

Deploy it and hit the WSDL. Note that the WSDL is not same as you have provided. If you want to retain the WSDL than change the implementation as follows:

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

More on Web services

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

Monday, August 18, 2014

WS Security

WS-security specifies extensions to the SOAP message which provide security at message level. WS-security is an extensible protocol so that it can support multiple security models and encryption technology. WS-security focuses on the following areas of security 
  • Security token validation (authentication) : Authenticating that the sender is the same as she claims.
  • Message integrity : The message is not tampered on the way.
  • Message confidentiality (encryption and decryption) : The message is not read by unauthorised entities.

Like other WS* specification, WS-security implments the concept by putting extra elements in the SOAP header. The basic elements of the WS-security specifications are:

WS-Security Core Specification

The current version of WS-Security core specification is 1.1 which can be downloaded [http://www.oasis-open.org/committees/download.php/16790/wss-v1.1-spec-os...|here]. WS-security has strived to be extensible so that it can server the basic need of different security models which includes:
  • Multiple security token formats
  • Multiple trust domains
  • Multiple signature formats
  • Multiple encryption technologies
  • End-to-end message content security and not just transport-level security

What WS-security does is that it specifies a format in which the security information is sent. The information is sent as part of SOAP header. WS-security does not deals with the implementaion details like how the authentication context needs to be set up. In simple terms, WS-security tells that how to specify the security details in the SOAP header. People have been doing custom security handling by introducing their own headers. However this leads to non standardization and tools and frameworks cannot help out. WS-security supports both ((SOAP)) 1.1 and 1.2 version.

WS-security supports the following namespaces:

http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity263sec...
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity265uti...
http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd

All the information about security is put in SOAP header in a security element

<soap:Envelope>
   <soap:Header>
    ...
  <wsse:Security
    xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secex...
   soap:actor="..." soap:mustUnderstand="...">
  <!-- All the security information goes here. actor attribute tells who
    will process the request. mustUnderstand attribute signifies that this header
    should be processed. If unable to process SOAP fault should be raised.-->
 </wsse:Security>
 ...
 </soap:Header>
 ...
</soap:Envelope>

Sending Credentials

The user credentials can be passed as username and passwords.

<wsse:Security>
    <wsse:UsernameToken>
         <wsse:Username>oyejava</wsse:Username>
         <wsse:Password>oyejava</wsse:Password>
    </wsse:UsernameToken>
</wsse:Security>

The user credentials can be sent in encoded format also using BinarySecurityToken

<BinarySecurityToken Id=...
                      EncodingType=...
                      ValueType=.../>
  • Id - Label for the security token. It is an optional field.
  • ValueType - Defines the value type like X509 certificate.
  • EncodingType - Encoding format like  wsse:Base64Binary

Security Token Reference

Let's now understand security token reference. It helps us in refering to the different part of the SOAP message using id.

<soap:Envelope xmlns="...">
   <soap:Header>
      <wsse:Security
             xmlns:wsse="...">
        <ds:Signature>
            ...
            <ds:KeyInfo>
                <wsse:SecurityTokenReference>
                 <wsse:Reference URI="soapBody"/>
                </wsse:SecurityTokenReference>
            </ds:KeyInfo>
         </ds:Signature>
      </wsse:Security>
  </soap:Header>
  <soap:Body>
    ...
  </soap:Body>
</soap:Envelope>

Sunday, August 10, 2014

SOAP

SOAP used to stand for Simple Object access protocol. Now it's simply called as SOAP. SOAP is the message format that travels between applications. It was initially developed by Developer Mentor as a platform independent way of communicating. The big success of SOAP is attributed to it's ability to travel on HTTP. (Though that ability has nothing to do with SOAP specification as such). The success of SOAP can also be attributed to it being XML based and as their is wide support for tooling for XML, it helps in dealing with SOAP.
SOAP though is more popular over HTTP however SOAP can be sent over any protocol like ftp, smtp etc. SOAP at this point exists in both 1.1 and 1.2 version. We will outline the differences between the two versions at appropriate location. In Java world, JAX-RPC supports version 1.1 and ((JAX-WS)) supports both version 1.1 and 1.2.
  • SOAP message is an ordinary XML document which has following elements
  • Envelope (required) – Identifies XML document as SOAP message.
  • Header (optional) – Contains header information
  • Body (required) – Contains call and response information
  • Fault (optional) – Provides error occurred while processing the message
A typical SOAP message looks as follows:
<?xml version="1.0" encoding="UTF-8"?>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelop/">
  <soap:Header>
    …
  </soap:Header>
  <soap:body>
   …
  </soap:body>
</soap:Envelope>


Bring soapUI tool up and let's hit a webservice hosted by JavaSE Service endpoint. The SOAP request in this case looks like
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.lalit.com/">

   <soapenv:Header/>
   <soapenv:Body>
      <ws:celsiusToFarenheitOp>
         <arg0>?</arg0>
      </ws:celsiusToFarenheitOp>
   </soapenv:Body>
</soapenv:Envelope>

In place of ?, the value is send to the server. This the whole SOAP message which travels on the wire. If we put a value of 50 and call the webservice, the response we get is:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">

   <S:Body>
      <ns2:celsiusToFarenheitOpResponse xmlns:ns2="http://ws.lalit.com/">
         <return>122.0</return>
      </ns2:celsiusToFarenheitOpResponse>
   </S:Body>
</S:Envelope>

In essence SOAP represent the message that travels as part of request and response. The popularity of SOAP comes from it being in XML format which makes it language and platform independent. Travelling over HTTP helps it to cross firewalls also. Being a XML, SOAP is amenable to XML processsing tools. SOAP messages are for application to generate and consume. A video explaining the SOAP:

WSDL

WSDL stands for Webservice Description Language. It's an XML format which is used to document Webservices. WSDL contains everything what one requires to invoke a webservice. It has the location of the service. The operation that needs to be invoked and what kind of message needs to be send as part of request and what message one can expect as part of response. The message can be in SOAP format however WSDL is written in such a way that it can send the message in other format also. WSDL is meant for programmatic consumption. An application can read a WSDL and can generate the artifacts which can help it to call the web service. Let's look in a sample WSDL which is generated for webservice to convert Celsius to Fahrenheit and vice-versa
The WSDL file is as shown below:
<definitions targetNamespace="http://ws.lalit.com/" name="TemperatureConvertorService">
<types>

  <xsd:schema>

     <xsd:import namespace="http://ws.lalit.com/" schemaLocation="http://localhost:8081/tempConv?xsd=1"/>

   </xsd:schema>
</types>

<message name="celsiusToFarenheitOp">

   <part name="parameters" element="tns:celsiusToFarenheitOp"/>

</message>

<message name="celsiusToFarenheitOpResponse">

   <part name="parameters" element="tns:celsiusToFarenheitOpResponse"/>

</message>

<message name="farenheitToCelsiusOp">

   <part name="parameters" element="tns:farenheitToCelsiusOp"/>

</message>

<message name="farenheitToCelsiusOpResponse">

   <part name="parameters" element="tns:farenheitToCelsiusOpResponse"/>

</message>

<portType name="TemperatureConvertor">

   <operation name="celsiusToFarenheitOp">

      <input message="tns:celsiusToFarenheitOp"/>

      <output message="tns:celsiusToFarenheitOpResponse"/>
   </operation>
   <operation name="farenheitToCelsiusOp">
      <input message="tns:farenheitToCelsiusOp"/>
      <output message="tns:farenheitToCelsiusOpResponse"/>
   </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="http://localhost:8081/tempConv"/>

   </port>
</service>

</definitions>
WSDL contains the following 7 elements as part of XML:
  • types
  • import
  • message
  • portType
  • operations
  • binding
  • service
These elements are wrapped inside the root element definitions.
In the above XML the defintions is the top level element.

<definitions targetNamespace="http://ws.lalit.com/" name="TemperatureConvertorService">
types
In types, the element types are defined. These types are used to exchange the message between client and server. In the example above the types defined are:
<types>
  <xsd:schema>
     <xsd:import namespace="http://ws.lalit.com/" schemaLocation="http://localhost:8081/tempConv?xsd=1"/>
  </xsd:schema>
</types>

Here the schema is defined in another xsd which can be accessed at http://localhost:8081/tempConv?xsd=1
<xs:schema version="1.0" targetNamespace="http://ws.lalit.com/">
<xs:element name="celsiusToFarenheitOp" type="tns:celsiusToFarenheitOp"/>
<xs:element name="celsiusToFarenheitOpResponse" type="tns:celsiusToFarenheitOpResponse"/>
<xs:element name="farenheitToCelsiusOp" type="tns:farenheitToCelsiusOp"/>
<xs:element name="farenheitToCelsiusOpResponse" type="tns:farenheitToCelsiusOpResponse"/>

<xs:complexType name="farenheitToCelsiusOp">
  <xs:sequence>
    <xs:element name="arg0" type="xs:double"/>
  </xs:sequence>
</xs:complexType>
<xs:complexType name="farenheitToCelsiusOpResponse">
  <xs:sequence>
    <xs:element name="return" type="xs:double"/>
  </xs:sequence>
</xs:complexType>
<xs:complexType name="celsiusToFarenheitOp">
  <xs:sequence>
    <xs:element name="arg0" type="xs:double"/>
  </xs:sequence>
</xs:complexType>
<xs:complexType name="celsiusToFarenheitOpResponse">
  <xs:sequence>
    <xs:element name="return" type="xs:double"/>
  </xs:sequence>
</xs:complexType>
</xs:schema>

import
In the WSDL above there is no import element. The import element is used to bring the details from another WSDL defined by import. This import is different from the import we saw above in types section. The types section import is used to bring schema definitions of types. The WSDL import element must declare two attributes: namespace and location. The value of namespace must match the targetNamespace declared by the WSDL document imported. The location attribute must point to an actual WSDL document and cannot be empty or null.
message
message element describe the payload of the message used by webservices.The message element can be a request or a response. This distinction is done at operation.
<message name="celsiusToFarenheitOp">
   <part name="parameters" element="tns:celsiusToFarenheitOp"/>
</message>


<message name="celsiusToFarenheitOpResponse">
   <part name="parameters" element="tns:celsiusToFarenheitOpResponse"/>
</message>


<message name="farenheitToCelsiusOp">
   <part name="parameters" element="tns:farenheitToCelsiusOp"/>
</message>


<message name="farenheitToCelsiusOpResponse">
   <part name="parameters" element="tns:farenheitToCelsiusOpResponse"/>
</message>

The webservice style (RPC or Document) do differentiate here that how we are going to define part. In this case which is document type, the part is defined by using element. In case of RPC style the message definition would look like
<message name="GetProductPriceResponse">
   <part name="price" type="xsd:float" />
</message>

type is used to define the part.
portType and operation
The simplest analogy to port Type and operation is the interface and its operation in Java.Most of code generators map the WSDL in the similar way.
<portType name="TemperatureConvertor">
   <operation name="celsiusToFarenheitOp">
      <input message="tns:celsiusToFarenheitOp"/>
      <output message="tns:celsiusToFarenheitOpResponse"/>
   </operation>

   <operation name="farenheitToCelsiusOp">
      <input message="tns:farenheitToCelsiusOp"/>
      <output message="tns:farenheitToCelsiusOpResponse"/>
   </operation>
</portType>

operation uses message to define the request and response. As mentioned earlier, here we decide whether the message acts as a request or as a response. WSDL supports operation overloading similar to Java method overloading. Two operations may have same name, provided their input and output message differ. However this does not conforms to Basic Profile. Two or more porttypes can however define operation with same name. It's like having two different interfaces with same operation name.
binding
binding is the place where we attach the message to protocols. In this case we are binding the webservice with SOAP over HTTP.
<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>

This piece confuses a lot but just take it in this way that WSDL designers attempted to make the definition very generic so that the message can travel on any protocol. With binding you can make it to travel with SOAP on HTTP or anything else.Also binding element tells about RPC or Document style. With frameworks like JAX-WS the debate between RPC and Document style is more theoretical. Also the encoding style is defined here. Basic Profile only accepts literal style as encoding brings problem in interoperability.
service
service element is the place where we define the physical location of the webservice as per the binding.
<service name="TemperatureConvertorService">
   <port name="TemperatureConvertorPort" binding="tns:TemperatureConvertorPortBinding">
      <soap:address location="http://localhost:8081/tempConv"/>
   </port>
</service>

Please see the video also for the concepts