
Understanding Soap Header and Spring Web service Interceptor
Posted by johnnyren in Johnny ren's Blog on Sep 17, 2011 9:23:01 AMWhy Soap Header and Spring Interceptor
- SOAP Header element can contain additional application-specific information such as authentication, payment about the SOAP
- Spring web service interceptor allows you to extract the header information
Steps to develop Spring WS with JAXB and Spring Interceptor:
- Create WSDL service contract
- Generate the JAXB Java classes from the xml schema file
- Create Java Endpoint classes
- Define and wire Endpoint in Spring context file
- Compile, package and deploy the code to Tomcat
- Test the code: “http://localhost:8080/holiday/holiday.wsdl”
Create the WSDL contract
<?xml version="1.0" encoding="UTF-8"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://mycompany.hr.com/hr/v1" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://mycompany.hr.com/hr/v1" targetNamespace="http://mycompany.hr.com/hr/v1">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://mycompany.hr.com/hr/v1">
<xs:element name="HolidayRequest" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:sequence xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="EmployeeName" type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
<xs:element name="StartDate" type="xs:date" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
<xs:element name="EndDate" type="xs:date" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="HolidayResponse" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:sequence xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Answer" type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="HolidayRequestHeader" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:sequence xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="requestTimestamp" type="xs:dateTime" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="HolidayRequest">
<wsdl:part element="tns:HolidayRequest" name="HolidayRequest">
</wsdl:part>
</wsdl:message>
<wsdl:message name="HolidayResponse">
<wsdl:part element="tns:HolidayResponse" name="HolidayResponse">
</wsdl:part>
</wsdl:message>
<wsdl:message name="HolidayHeader">
<wsdl:part element="tns:HolidayRequestHeader" name="HolidayHeader">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="holiday">
<wsdl:operation name="Holiday">
<wsdl:input message="tns:HolidayRequest" name="HolidayRequest">
</wsdl:input>
<wsdl:output message="tns:HolidayResponse" name="HolidayResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="holidaySoap11" type="tns:holiday">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="Holiday">
<soap:operation soapAction=""/>
<wsdl:input name="HolidayRequest">
<soap:header message="tns:HolidayHeader" part="HolidayHeader" use="literal" />
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="HolidayResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="holidayService">
<wsdl:port binding="tns:holidaySoap11" name="holidaySoap11">
<soap:address location="http://localhost:8080/holiday/"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
- This service exposes “HolidayRequest” and returns “HolidayResponse”
- This service defines “HolidayRequestHeader” Soap Header element
Generate JAXB Java classes from the schema file
Executing “xjc -p com.mycompany.hr.jaxb.holidayService hr.xsd” will generate the following classes:
- com\mycompany\hr\jaxb\holidayService\HolidayRequest.java
- com\mycompany\hr\jaxb\holidayService\HolidayResponse.java
- com\mycompany\hr\jaxb\holidayService\HolidayRequestHeader.java
- com\mycompany\hr\jaxb\holidayService\ObjectFactory.java
- com\mycompany\hr\jaxb\holidayService\package-info.java
Create Java Endpoint
package com.mycompany.hr.ws;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import com.mycompany.hr.jaxb.holidayService.HolidayRequest;
import com.mycompany.hr.jaxb.holidayService.HolidayResponse;
@Endpoint
public class HolidayEndpoint {
@PayloadRoot(localPart= "HolidayRequest", namespace="http://mycompany.hr.com/hr/v1")
public HolidayResponse serveRequest(HolidayRequest request){
HolidayResponse response = new HolidayResponse();
response.setAnswer("Approved");
return response;
}
}
- Spring @PayloadRoot annotation instructs Spring to map xml “HolidayRequest” to “serveRequest” Java method.
- The serveRequest method returns a HolidayResponse object
Define Spring WS Interceptor
public class HolidayInterceptor implements SoapEndpointInterceptor {
private static final Log logger = LogFactory.getLog(HolidayInterceptor.class);
private Jaxb2Marshaller marshaller;
public boolean understands(SoapHeaderElement header) {
boolean u = header.getName().getNamespaceURI()
.equalsIgnoreCase("http://mycompany.hr.com/hr/v1");
return u;
}
public boolean handleRequest(MessageContext messageContext, Object endpoint)
throws Exception {
SoapMessage soapMsg = (SoapMessage) messageContext.getRequest();
SoapHeader soapHeader = soapMsg.getSoapHeader();
Iterator<SoapHeaderElement> iter = soapHeader.examineAllHeaderElements();
boolean found= false;
while (iter.hasNext() & (!found)) {
SoapHeaderElement she = (SoapHeaderElement) iter.next();
if (understands(she)) {
// Process the header
process(she);
found =true;
}
}
if(found)
{
return true;
}
else
{
Exception ex= new Exception();
throw ex;
}
}
private void process(SoapHeaderElement she) {
DOMResult result = (DOMResult)she.getResult();
Node node= result.getNode();
DOMSource ds= new DOMSource(node);
HolidayRequestHeader RequestHeader = (HolidayRequestHeader)marshaller.unmarshal(ds);
logger.debug("request time: "+RequestHeader.getRequestTimestamp());
}
- The handleReques method extracts HolidayRequestHeader object from soap header
Define and wire Endpoint in Spring
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="holiday" class="org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition">
<property name="wsdl" value="classpath:holiday.wsdl" />
</bean>
<bean id="schema" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="classpath:hr.xsd" />
</bean>
<!-- Register PayloadRootAnnotationMethodEndpointMapping -->
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping" >
<property name="interceptors">
<list merge="true">
<ref bean="holiday.interceptor"/>
</list>
</property>
</bean>
<bean name="holiday.interceptor"
class="com.mycompany.hr.interceptor.HolidayInterceptor" >
<property name="marshaller" ref="marshaller" />
</bean>
<!-- Register Endpoint -->
<bean id="HolidayEndpoint" class="com.mycompany.hr.ws.HolidayEndpoint">
<description>
</description>
</bean>
<!-- Configure XML Marshaller -->
<bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
<constructor-arg ref="marshaller" />
</bean>
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>com.mycompany.hr.jaxb.holidayService.HolidayRequest</value>
<value>com.mycompany.hr.jaxb.holidayService.HolidayResponse</value>
<value>com.mycompany.hr.jaxb.holidayService.HolidayRequestHeader</value>
</list>
</property>
</bean>
</beans>
- Spring bean “HolidayEndpoint” defines the end point mapping
- Spring bean “marshaller” un-marshalls the xml requests to Java objects and marshalls the response objects to xml response
Source code and war files are attached.
Deploy the code to Tomcat and let me what happened
-
holiday.war 12.5 MB
-
holidayService.zip 14.7 KB
Comments