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.
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 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.
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.
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.
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 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,
schemaCollectionof 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.
- 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.
- 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).
- 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.
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.