Announcement Announcement Module
Collapse
No announcement yet.
Configuring JiBXMarshaller with GenericMarshallingMethodEndpointAdapter Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Configuring JiBXMarshaller with GenericMarshallingMethodEndpointAdapter

    Hello,
    I am developing a prototype to show how JIBXMarshaller can be used with Spring-WS. I modified the STS Spring-ws tutorial to provide 2 methods on the endpoint using the @PayloadRoot annotation as follows.

    @PayloadRoot(localPart = "HolidayRequest", namespace = "http://mycompany.com/hr/schemas")
    public void bookHoliday(HolidayRequest holidayRequest) throws Exception {

    Date startDate = holidayRequest.getHoliday().getStartDate();
    Date endDate = holidayRequest.getHoliday().getEndDate();
    String empName = holidayRequest.getEmployee().getFirstName() + " " + holidayRequest.getEmployee().getLastName();
    humanResourceService.bookHoliday(startDate, endDate, empName);
    }

    @PayloadRoot(localPart = "Employee", namespace = "http://mycompany.com/hr/schemas")
    public Holiday getHoliday(Employee employee) throws Exception {
    return humanResourceService.getHoliday(employee.getFirstN ame() + " " + employee.getLastName());
    }


    My spring configuration file looks like this.

    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oxm="http://www.springframework.org/schema/oxm"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schem...-beans-2.0.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-1.5.xsd">


    <bean id="holidayEndpoint" class="com.mycompany.hr.ws.HolidayAnnotationEndpoi nt">
    <constructor-arg ref="hrService"/>
    </bean>

    <bean id="hrService" class="com.mycompany.hr.service.StubHumanResourceS ervice"/>

    <bean class="org.springframework.ws.server.endpoint.mapp ing.PayloadRootAnnotationMethodEndpointMapping">
    <property name="interceptors">
    <bean class="org.springframework.ws.server.endpoint.inte rceptor.PayloadLoggingInterceptor"/>
    </property>
    </bean>

    <bean id="holidayRequestMAdapter" class="org.springframework.ws.server.endpoint.adap ter.GenericMarshallingMethodEndpointAdapter">
    <constructor-arg ref="holidayRequestM"/>
    </bean>

    <bean id="holidayMAdapter" class="org.springframework.ws.server.endpoint.adap ter.GenericMarshallingMethodEndpointAdapter">
    <constructor-arg ref="holidayM"/>
    </bean>
    <bean id="employeeMAdapter" class="org.springframework.ws.server.endpoint.adap ter.GenericMarshallingMethodEndpointAdapter">
    <constructor-arg ref="employeeM"/>
    </bean>

    <oxm:jibx-marshaller id="holidayRequestM" target-class="com.mycompany.hr.model.HolidayRequest"/>
    <oxm:jibx-marshaller id="holidayM" target-class="com.mycompany.hr.model.Holiday"/>
    <oxm:jibx-marshaller id="employeeM" target-class="com.mycompany.hr.model.Employee"/>


    <bean id="holiday" class="org.springframework.ws.wsdl.wsdl11.DynamicW sdl11Definition">
    <property name="builder">
    <bean class="org.springframework.ws.wsdl.wsdl11.builder. XsdBasedSoap11Wsdl4jDefinitionBuilder">
    <property name="schema" value="/WEB-INF/hr.xsd"/>
    <property name="portTypeName" value="HumanResource"/>
    <property name="locationUri" value="http://localhost:8082/ws-tutorial/services"/>
    <property name="targetNamespace" value="http://mycompany.com/hr/definitions"/>
    </bean>
    </property>
    </bean>

    </beans>


    Although I am able to successfully call the method bookHoliday() where the HolidayRequest rootElement gets uinmarshalled to the HolidayRequest object, I get the following error while trying to call getHoliday() method. I do not know why even though I have provided the end point adapter for the objects being received and returned by this method as you can see above.
    *****************
    Stack Trace Begin
    ***************
    2009-06-25 15:40:27,795 DEBUG [org.springframework.ws.soap.server.SoapMessageDisp atcher] - Testing endpoint adapter [org.springframework.ws.server.endpoint.adapter.Gen ericMarshallingMethodEndpointAdapter@33c658]
    2009-06-25 15:40:27,857 DEBUG [org.springframework.ws.server.endpoint.adapter.Gen ericMarshallingMethodEndpointAdapter] - Unmarshalled payload request to [com.mycompany.hr.model.HolidayRequest@1f10a67]
    2009-06-25 15:40:27,857 INFO [com.mycompany.hr.service.StubHumanResourceService] - Booking holiday for [Sun Dec 16 16:00:00 PST 2001-Wed Jul 16 17:00:00 PDT 2003] for [Rajesh Nerurkar]
    2009-06-25 15:40:27,857 DEBUG [org.springframework.ws.server.MessageTracing.sent] - MessageDispatcher with name 'spring-ws' sends no response for request [SaajSoapMessage {http://mycompany.com/hr/schemas}HolidayRequest]
    2009-06-25 15:40:27,857 DEBUG [org.springframework.ws.transport.http.MessageDispa tcherServlet] - Successfully completed request
    2009-06-25 15:40:27,873 DEBUG [org.springframework.ws.transport.http.WebServiceMe ssageReceiverHandlerAdapter] - Accepting incoming [org.springframework.ws.transport.http.HttpServletC onnection@1cee792] to [http://localhost:8082/ws-tutorial/services]
    2009-06-25 15:40:27,873 DEBUG [org.springframework.ws.server.MessageTracing.recei ved] - Received request [SaajSoapMessage {http://mycompany.com/hr/schemas}Employee]
    2009-06-25 15:40:27,873 DEBUG [org.springframework.ws.server.endpoint.mapping.Pay loadRootAnnotationMethodEndpointMapping] - Looking up endpoint for [{http://mycompany.com/hr/schemas}Employee]
    2009-06-25 15:40:27,873 DEBUG [org.springframework.ws.soap.server.SoapMessageDisp atcher] - Endpoint mapping [org.springframework.ws.server.endpoint.mapping.Pay loadRootAnnotationMethodEndpointMapping@16b9e62] maps request to endpoint [public com.mycompany.hr.model.Holiday com.mycompany.hr.ws.HolidayAnnotationEndpoint.getH oliday(com.mycompany.hr.model.Employee) throws java.lang.Exception]
    2009-06-25 15:40:27,873 DEBUG [org.springframework.ws.server.endpoint.interceptor .PayloadLoggingInterceptor] - Request: <hr:Employee xmlns:hr="http://mycompany.com/hr/schemas"><hr:Number>1</hr:Number><hr:FirstName>Rajesh</hr:FirstName><hr:LastName>Nerurkar</hr:LastName></hr:Employee>
    2009-06-25 15:40:27,873 DEBUG [org.springframework.ws.soap.server.SoapMessageDisp atcher] - Testing endpoint adapter [org.springframework.ws.server.endpoint.adapter.Gen ericMarshallingMethodEndpointAdapter@33c658]
    2009-06-25 15:40:27,873 DEBUG [org.springframework.ws.soap.server.SoapMessageDisp atcher] - Testing endpoint adapter [org.springframework.ws.server.endpoint.adapter.Gen ericMarshallingMethodEndpointAdapter@1f2af1c]
    2009-06-25 15:40:27,873 DEBUG [org.springframework.ws.soap.server.SoapMessageDisp atcher] - Testing endpoint adapter [org.springframework.ws.server.endpoint.adapter.Gen ericMarshallingMethodEndpointAdapter@1c6866d]
    2009-06-25 15:40:27,873 DEBUG [org.springframework.ws.soap.server.SoapMessageDisp atcher] - Endpoint invocation resulted in exception - responding with Fault
    java.lang.IllegalStateException: No adapter for endpoint [public com.mycompany.hr.model.Holiday com.mycompany.hr.ws.HolidayAnnotationEndpoint.getH oliday(com.mycompany.hr.model.Employee) throws java.lang.Exception]: Does your endpoint implement a supported interface like MessageHandler or PayloadEndpoint? at org.springframework.ws.server.MessageDispatcher.ge tEndpointAdapter(MessageDispatcher.java:279)
    at org.springframework.ws.server.MessageDispatcher.di spatch(MessageDispatcher.java:220)
    at org.springframework.ws.server.MessageDispatcher.re ceive(MessageDispatcher.java:168)
    at org.springframework.ws.transport.support.WebServic eMessageReceiverObjectSupport.handleConnection(Web ServiceMessageReceiverObjectSupport.java:88)
    at org.springframework.ws.transport.http.WebServiceMe ssageReceiverHandlerAdapter.handle(WebServiceMessa geReceiverHandlerAdapter.java:57)
    at org.springframework.ws.transport.http.MessageDispa tcherServlet.doService(MessageDispatcherServlet.ja va:230)
    at org.springframework.web.servlet.FrameworkServlet.p rocessRequest(FrameworkServlet.java:476)
    at org.springframework.web.servlet.FrameworkServlet.d oPost(FrameworkServlet.java:441)
    at javax.servlet.http.HttpServlet.service(HttpServlet .java:710)
    at javax.servlet.http.HttpServlet.service(HttpServlet .java:803)
    at org.apache.catalina.core.ApplicationFilterChain.in ternalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.do Filter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invo ke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invo ke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardHostValve.invoke( StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke (ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invok e(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.servic e(CoyoteAdapter.java:263)
    at org.apache.coyote.http11.Http11Processor.process(H ttp11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11Conn ectionHandler.process(Http11Protocol.java:584)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run( JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:595)
    2009-06-25 15:40:27,873 DEBUG [org.springframework.ws.server.MessageTracing.sent] - Sent response [SaajSoapMessage {http://schemas.xmlsoap.org/soap/envelope/}Fault] for request [SaajSoapMessage {http://mycompany.com/hr/schemas}Employee]
    2009-06-25 15:40:27,873 DEBUG [org.springframework.ws.transport.http.MessageDispa tcherServlet] - Successfully completed request

    **************
    Stack Trace End
    *************
    Any help on this will be really appreciated!!
    Last edited by rnerurkar; Jun 25th, 2009, 06:40 PM. Reason: Incomplete first time

  • #2
    Have you set the namespace of the mappings?
    something like:
    <namespace uri="http://mycompany.com/hr/schemas" default="elements" prefix="tns" />

    There is another thing that is causing me a problem and it's too many GenericMarshallingMethodEndpointAdapter. I don't know why but it always get the first one. In you case would be holidayRequestMAdapter.

    I hope this helps you.

    Regards,

    torimpo

    Comment


    • #3
      to solve the problem of many marshallings I created a class called PayloadRootAnnotationMethodEndPointAdapter

      It's related to the PayloadRootAnnotationMethodEndpointMapping.

      Based on the localPart is the marshaller that uses.

      Here is the class.

      Code:
      import java.io.IOException;
      import java.lang.reflect.Method;
      import java.util.HashMap;
      import java.util.Iterator;
      
      import javax.xml.namespace.QName;
      import javax.xml.transform.TransformerFactory;
      
      import org.springframework.oxm.GenericUnmarshaller;
      import org.springframework.oxm.Marshaller;
      import org.springframework.oxm.Unmarshaller;
      import org.springframework.ws.WebServiceMessage;
      import org.springframework.ws.context.MessageContext;
      import org.springframework.ws.server.endpoint.MethodEndpoint;
      import org.springframework.ws.server.endpoint.adapter.AbstractMethodEndpointAdapter;
      import org.springframework.ws.server.endpoint.support.PayloadRootUtils;
      import org.springframework.ws.support.MarshallingUtils;
      
      public class PayloadRootAnnotationMethodEndPointAdapter extends
      		AbstractMethodEndpointAdapter {
      
      	private HashMap<String, Marshaller> marshallers;
      	private HashMap<String, Unmarshaller> unmarshallers;
      	private static TransformerFactory transformerFactory;
      
      	static {
      		transformerFactory = TransformerFactory.newInstance();
      	}
      
      	public PayloadRootAnnotationMethodEndPointAdapter(
      			HashMap<String, Marshaller> marshallers) {
      
      		this.marshallers = marshallers;
      		this.unmarshallers = new HashMap<String, Unmarshaller>();
      		for (String key : marshallers.keySet()) {
      			unmarshallers.put(key, (Unmarshaller) marshallers.get(key));
      		}
      	}
      
      	public PayloadRootAnnotationMethodEndPointAdapter(
      			HashMap<String, Marshaller> marshallers,
      			HashMap<String, Unmarshaller> unmarshallers) {
      		this.marshallers = marshallers;
      		this.unmarshallers = unmarshallers;
      	}
      
      	private Object unmarshalRequest(WebServiceMessage request)
      			throws IOException, Exception {
      
      		Object requestObject = MarshallingUtils.unmarshal(
      				getUnmarshaller(getLocalPart(request)), request);
      
      		if (logger.isDebugEnabled()) {
      			logger.debug("Unmarshalled payload request to [" + requestObject
      					+ "]");
      		}
      
      		return requestObject;
      	}
      
      	protected void invokeInternal(MessageContext messageContext, MethodEndpoint methodEndpoint) throws Exception {
      		WebServiceMessage request = messageContext.getRequest();
      		Object requestObject = unmarshalRequest(request);
      		Object responseObject = methodEndpoint.invoke(new Object[] { requestObject });
      		if (responseObject != null) {
      			WebServiceMessage response = messageContext.getResponse();
      			marshalResponse(responseObject, response, getLocalPart(request));
      		}
      	}
      
      	private void marshalResponse(Object responseObject, WebServiceMessage response, String localPart) throws IOException, Exception {
      		if (logger.isDebugEnabled()) {
      			logger.debug("Marshalling [" + responseObject + "] to response payload");
      		}
      		MarshallingUtils.marshal(getMarshaller(localPart), responseObject, response);
      	}
      
      	/**
      	 * @param methodEndpoint
      	 * @return
      	 * @see org.springframework.ws.server.endpoint.adapter.AbstractMethodEndpointAdapter#supportsInternal(org.springframework.ws.server.endpoint.MethodEndpoint)
      	 */
      	@Override
      	protected boolean supportsInternal(MethodEndpoint methodEndpoint) {
      		Method method = methodEndpoint.getMethod();
      		return supportsReturnType(method) && supportsParameters(method);
      	}
      
      	private boolean supportsReturnType(Method method) {
      		boolean support = false;
      		if (Void.TYPE.equals(method.getReturnType())) {
      			return true;
      		} else {
      			Iterator<Marshaller> it = marshallers.values().iterator();
      			while (it.hasNext() && support == false) {
      				Marshaller marshaller = it.next();
      				if (marshaller instanceof GenericUnmarshaller) {
      					GenericUnmarshaller genericUnmarshaller = (GenericUnmarshaller) marshaller;
      					support = genericUnmarshaller.supports(method.getGenericParameterTypes()[0]);
      				} else {
      					support = marshaller.supports(method.getParameterTypes()[0]);
      				}
      			}
      		}
      		return support;
      	}
      
      	private boolean supportsParameters(Method method) {
      		boolean support = false;
      		if (method.getParameterTypes().length >= 1) {
      			Iterator<Unmarshaller> it = unmarshallers.values().iterator();
      			while (it.hasNext() && support == false) {
      				Unmarshaller unmarshaller = it.next();
      				if (unmarshaller instanceof GenericUnmarshaller) {
      					GenericUnmarshaller genericUnmarshaller = (GenericUnmarshaller) unmarshaller;
      					support = genericUnmarshaller.supports(method.getGenericParameterTypes()[0]);
      				} else {
      					support = unmarshaller.supports(method.getParameterTypes()[0]);
      				}
      			}
      		}
      		return support;
      	}
      
      	private Unmarshaller getUnmarshaller(String key) throws Exception {
      			return unmarshallers.get(key);
      	}
      
      	private Marshaller getMarshaller(String key) throws Exception {
      			return marshallers.get(key);
      	}
      	
      	private String getLocalPart(WebServiceMessage message) throws Exception{
      		QName qname = PayloadRootUtils.getPayloadRootQName(message.getPayloadSource(), transformerFactory);
      		return qname.getLocalPart();
      	}
      }
      Is there another option?

      Thanks in advance,

      torimpo
      Last edited by torimpo; Jul 5th, 2009, 12:42 AM.

      Comment

      Working...
      X