Saturday, October 2, 2010

How does a Spring Web Service work ?

[WCF client for a Spring Webservice: An interoperabilty story. Part 3.]

    This post lists the basic components of a Spring  Web Service, then describes how all these work together to make a web service, in  the context of the web service example given in part 2 of this series.


    Figure 3.1. Spring-WS Component Diagram


    This component diagram(3.1) summarizes the components of the web service with their dependencies to each other. Now let us list and discuss each of these components.


MessageDispatcherServlet 


    As you can see in the diagram (Fig. 3.1), MessageDispatcherServlet intercepts all the requests (see URL pattern given in the web.xml). It then looks for a configuration file in the class-path, with a default file, following a file name pattern of [servlet-name]-servlet.xml. You can see the servlet name given for MessageDispatcherServlet in the web.xml is spring-ws, hence the configuration file name, spring-ws-servlet.xml. MessageDispatcherServlet uses this configuration file for its dependencies in the business of web service request processing.


    The primary responsibility of MessageDispatcherServlet is to find the appropriate Message/Payload Endpoint and dispatch the messages to it. It makes use of several other components for that business. For example, MessageDispatcherServlet uses the EndpointMapping component to locate the right EndPoint. 

    MessageDispatcherServlet does not directly call the Endpoint, rather it uses the EndpointAdapter as an intermediate component which adapts between the MessageDispatcherServlet and the Endpoint. The concrete implementations of all these components are wired in the configuration file, spring-ws-servlet.xml. 


EndpointMapping


   EndpointMapping is responsible for filtering and thus locating the appropriate Message/Payload Endpoint for any incoming HttpRequest to the URL. In our example, PayloadRootAnnotationMethodEndpointMapping is used for the mapping. Since it is an annotation driven object, the filter criteria is annotated inside the class itself.

    See the class level annotation, @Endpoint which declares the class as a MessageEndpoint. This class in fact serves multiple(two in the example) Operation Contracts, each delegated to methods annotated with @PayloadRoot annotation. See the methods getOrder and cancelOrder, each annotated with the corresponding payload-root elements specified with attribute, localPart and the namespace. 

Example, @PayloadRoot(localPart = "placeOrderRequest", namespace = "http://www.liverestaurant.com/OrderService/schema").

Looking at the annotations, EndpointMapping object determines the right Endpoint and returns it back to the MessageDispatcherServlet for further processing.

EndpointAdapter

    An EndpointAdapter is the special component which allows the MessageServlet indefinitely extensible. Whatever Endpoint type you build, as long as an appropriate EndpointAdapter is provided, you can process the client request. 

    In our example, GenericMarshallingMethodEndpointAdapter is used, because we opted to use the Object-XML-Marshalling ( OXM ) technique for the message processing. ie, we use marshal the Java object into XML at the client side, send it across the wire, finally unmarshal it back to the Java object using the same schema and mapping. The marshaller configured here is the JXB2Marshaller, compliant to the JAXB 2.0 specification


Endpoint


An Endpoint represents a Message Contract. It can serve one or more Operation Contracts, depending on the implementation. In our example, an annotation based Endpoint is used, annotated in the class file(using annotation, @Endpoint) and mapped using PayloadRootAnnotationMethodEndpointMapping. Hence, the methods exposed as Operation Contracts need to be annotated with @PayloadRoot, with the appropriate localPart values.

EndpointInterceptor

    EndpointInterceptors are designed to intercept the incoming and outgoing messages in order to perform certain actions. The only interceptor we used in the example is PayloadLoggingInterceptor, which just logs the payload XML into some log file, or the default logger. 

    Spring provides a basic set of interceptors. We can create our own interceptors too, implementing EndpointInterceptor interface, or extending the appropriate Spring implementations. We will see more interceptors in the upcoming posts, especially the ones which we employ to secure the web service.

DefaultWsdl11Definition



    DefaultWsdl11Definition is a very convenient component that  generates the WSDL ( Web Service Description Language ) of the web service which makes SOAP 1.1 or 1.2 binding based on naming conventions in one or more inlined XSD schemas. 

    If you look back to the configuration given in the previous post(part 2, Building a web service with Spring-WS), in the spring-ws-servlet.xml, you can see that how easily the component can be configured specifying the attributes such as schema, portType, locationURI and the targetNamespace. The schema attribute needs to be provided with an instance of XsdSchema, for which we are using one of its concrete implementation, SimpleXsdSchema. DefaultWsdl11Definition accepts a collection of schema instances, you can set this via propery, schemaCollection of type, XsdSchemaCollection instead of  attribute, schema.

    With these few values plugged in, the component dynamically generates the entire WSDL for free at run time. One important note to make here is, the (spring) bean id given for DefaultWsdl11Definition is used for generating the WSDL file name. For example, in our example, the bean id given is OrderService, and hence the file name, OrderService.wsdl.

Common exceptions and  their probable cause while configuring Endpoints

EndpointNotFound: This is the most common exception found during the service configuration.

Possible causes 

  1. Your PayloadRoot configuration(annotation, @PayloadRoot) is incorrect. Make sure attributes and values are correct. Remember that the XML is case sensitive, so make sure the value for localPart is in the correct case. Also, make sure the correctness of the namespace too.
  2. You forgot to annotate the class with @Endpoint.Or the import of the Endpoint is wrong (a possible mistake while selecting from many options in the IDE).
  3. The return type of the methods(which represents the OpeationContracts, annotated with @PayloadRoot) is incorrect - either it is not a JAXBElement, or it is not the right Java type of JAXBElement.
    Try these possibilities when you get that error, fix your endpoint mapping and move ahead with the further tasks.


Next ...


    At this point, we are quite comfortable with the web service, we know how it works and ready to go for the client program. 

    Next post will discuss the process of building the client program, for the Microsft .Net platform, using its popular tool, WCF ( Windows Communication Foundation ). We will see the magic of Visual Studio.Net in that process. Let me take a break now. 

2 comments:

  1. There is also a possible case in which we get the EndPoint not found error. This happens when you are using PayloadRootAnnotationEndPointMapping and using Jaxb as a o/x mapping tool. If you delete the package-info.java file that gets generated along with the other jaxb business object, thinking that this file has no significance, then you are in trouble. I almost tried different possibilities to solve the error and found out this root cause. It was a good learning and i think this comment might come handy if someone is looking to solve the No EndPoint Mapping found error.

    Thanks shameer for these good posts on web service. It was very much helpful...

    ReplyDelete
  2. That is good website in blogspot. SEO is a very importtant our website for Build the link.I also provided this service plz visit my site free seo Analysis Web OptimiA is a india based SEO service.

    ReplyDelete