интеграция spring: исключение SpelEvaluationException: EL1004E: (пункт 8): Вызов метода: Метод getResponseForSample(javax.xml.bind.JAXBElement)

#spring-integration #spring-ws

#весенняя интеграция #spring-ws

Вопрос:

Я новичок в интеграции Spring и сталкиваюсь с проблемой при отмене сопоставления запроса SOAP. У меня есть приведенный ниже пример xsd:

 <?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://tempuri.org/" xmlns:tns="http://tempuri.org/"
    version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:element name="FFSampleRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Timestamp" type="xs:string" minOccurs="1"
                    form="qualified" />
                <xs:element name="SampleType" type="xs:int" form="qualified" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="FFSampleResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Timestamp" type="xs:string" minOccurs="1" />
                <xs:element name="SampleType" type="xs:int" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="getResponseForSample" type="tns:getResponseForSample" />
    <xs:element name="getResponseForSampleResponse" type="tns:getResponseForSampleResponse" />
    <xs:complexType name="getResponseForSample">
        <xs:sequence>
            <xs:element name="arg0" minOccurs="1">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="Timestamp" type="xs:string"
                            minOccurs="1" form="qualified" />
                        <xs:element name="SampleType" type="xs:int" form="qualified" />
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="getResponseForSampleResponse">
        <xs:sequence>
            <xs:element name="return" minOccurs="1">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="Timestamp" type="xs:string"
                            minOccurs="1" />
                        <xs:element name="SampleType" type="xs:int" />
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:schema>
  

Теперь я создал файлы java с помощью компилятора jaxbmarshaller xjc, ниже приведен файл ObjectFactory.другими сгенерированными файлами являются FFSampleRequest, FFSampleResponse, GetResponseForSample, GetResponseForSampleResponse, package-info. поместите все эти файлы в

 //
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2014.07.07 at 06:00:25 PM GST 
//




import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;


  @XmlRegistry
public class ObjectFactory {

    private final static QName _GetResponseForSample_QNAME = new QName("http://tempuri.org/", "getResponseForSample");
    private final static QName _GetResponseForSampleResponse_QNAME = new QName("http://tempuri.org/", "getResponseForSampleResponse");
        public ObjectFactory() {
    }

    /**
     * Create an instance of {@link GetResponseForSample }
     * 
     */
    public GetResponseForSample createGetResponseForSample() {
        return new GetResponseForSample();
    }

    /**
     * Create an instance of {@link GetResponseForSampleResponse }
     * 
     */
    public GetResponseForSampleResponse createGetResponseForSampleResponse() {
        return new GetResponseForSampleResponse();
    }

    /**
     * Create an instance of {@link FFSampleRequest }
     * 
     */
    public FFSampleRequest createFFSampleRequest() {
        return new FFSampleRequest();
    }

    /**
     * Create an instance of {@link FFSampleResponse }
     * 
     */
    public FFSampleResponse createFFSampleResponse() {
        return new FFSampleResponse();
    }

    /**
     * Create an instance of {@link GetResponseForSample.Arg0 }
     * 
     */
    public GetResponseForSample.Arg0 createGetResponseForSampleArg0() {
        return new GetResponseForSample.Arg0();
    }

    /**
     * Create an instance of {@link GetResponseForSampleResponse.Return }
     * 
     */
    public GetResponseForSampleResponse.Return createGetResponseForSampleResponseReturn() {
        return new GetResponseForSampleResponse.Return();
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link GetResponseForSample }{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "http://tempuri.org/", name = "getResponseForSample")
    public JAXBElement<GetResponseForSample> createGetResponseForSample(GetResponseForSample value) {
        return new JAXBElement<GetResponseForSample>(_GetResponseForSample_QNAME, GetResponseForSample.class, null, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link GetResponseForSampleResponse }{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "http://tempuri.org/", name = "getResponseForSampleResponse")
    public JAXBElement<GetResponseForSampleResponse> createGetResponseForSampleResponse(GetResponseForSampleResponse value) {
        return new JAXBElement<GetResponseForSampleResponse>(_GetResponseForSampleResponse_QNAME, GetResponseForSampleResponse.class, null, value);
    }

}
  

web.xml файл для обработки запроса soap:

 <servlet>
        <servlet-name>spring-ws</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>WEB-INF/spring-ws-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring-ws</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
  

и использовал приведенные ниже настройки в файле конфигурации для вызова метода service для этого запроса:

 <int:channel id="FFSampleRequestChannel"/>

<int-ws:inbound-gateway id="ws-ffsample-gateway" request-channel="FFSampleRequestChannel" marshaller="marshaller" unmarshaller="marshaller"/>

<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="contextPath" value="com.java.MyChannel.model" />
    </bean>

<int:service-activator input-channel="FFSampleRequestChannel">
    <bean class="com.java.MyChannel.serviceImpl.FFSampleImpl">
    <constructor-arg ref = "ffSampleRequest"></constructor-arg>

<bean id="ffSampleRequest" class="com.java.MyChannel.model.FFSampleRequest"></bean>
    <bean id="ffSampleResponse" class="com.java.MyChannel.model.FFSampleResponse"></bean>
  

my soap request hits service class successfully but I am getting the exception.

   /**
     * @author Vinay Agrawal
     */
    @XmlRegistry
    public class FFSampleImpl implements FFSampleInterface
    {

        @Autowired
        FFSampleRequest request;
        @Autowired
        FFSampleJdbc ffSampleJdbc;
        public FFSampleImpl() {
        }

        public FFSampleImpl(FFSampleRequest request) {
            super();
            this.request = request;
        }

        @Override
        @PayloadRoot(localPart = "getResponseForSample" , namespace = "http://tempuri.org/")
        @ResponsePayload
        public FFSampleResponse getResponseForSample(@RequestPayload FFSampleRequest request){
            List<FFSampleResponse> ffSampleResponse = new ArrayList<FFSampleResponse>();

            return ffSampleResponse ;

        }
    }
  

Soap request is as below:

 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://tempuri.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <ser:getResponseForSample>
         <!--Optional:-->
         <arg0>

            <ser:Timestamp>"100"</ser:Timestamp>
            <ser:SampleType>15</ser:SampleType>
         </arg0>
      </ser:getResponseForSample>
   </soapenv:Body>
</soapenv:Envelope>
  

I receive the below exception as below:

    19:20:34.472 WARN  [tomcat-http--15][org.springframework.integration.ws.MarshallingWebServiceInboundGateway] failure occurred in gateway sendAndReceive
    org.springframework.messaging.MessageHandlingException: org.springframework.expression.spel.SpelEvaluationException: EL1004E:(pos 8): Method call: Method getResponseForSample(javax.xml.bind.JAXBElement) cannot be found on com.java.myChannel.serviceImpl.FFSampleImpl type
        at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:78)
        at org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:71)
        at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:170)
        at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
        at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
        at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
        at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
        at org.springframework.integration.channel.AbstractSubscribablmyChannel.doSend(AbstractSubscribablmyChannel.java:77)
        at org.springframework.integration.channel.AbstractMessagmyChannel.send(AbstractMessagmyChannel.java:255)
        at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:114)
        at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:154)
        at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:44)
        at org.springframework.messaging.core.AbstractMessagingTemplate.sendAndReceive(AbstractMessagingTemplate.java:75)
        at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:250)
        at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceiveMessage(MessagingGatewaySupport.java:224)
        at org.springframework.integration.ws.MarshallingWebServiceInboundGateway.doInvoke(MarshallingWebServiceInboundGateway.java:105)
        at org.springframework.integration.ws.AbstractWebServiceInboundGateway.invoke(AbstractWebServiceInboundGateway.java:54)
        at org.springframework.ws.server.endpoint.adapter.MessageEndpointAdapter.invoke(MessageEndpointAdapter.java:41)
        at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:233)
        at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:173)
        at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:88)
        at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:59)
        at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:292)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:409)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1044)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
  

Я изменил параметр метода service ниже, но при попытке получить значения, указанные в сообщении SOAP, не являются обязательными, и я получаю нулевые значения для «SampleType» и «Timestamp».

   public class FFSampleImpl implements FFSampleInterface
    {

        @Autowired
        FFSampleRequest request;
        public FFSampleImpl() {
        }

        public FFSampleImpl(FFSampleRequest request) {
            super();
            this.request = request;
        }

        @Override
        @PayloadRoot(localPart = "getResponseForSample" , namespace = "http://tempuri.org/")
        @ResponsePayload
        public FFSampleResponse getResponseForSample(@RequestPayload JAXBElement<FFSampleRequest> ffreq){
            FFSampleResponse ffSampleResponse2 = new FFSampleResponse();
            return ffSampleResponse2;

        /*  return FFSampleResponse;*/
        }
  

Я подозреваю, что записи, созданные на фабрике объектов, неверны, потому что чувствую, что я сталкиваюсь с проблемой только из-за этих записей (ниже записей). Пожалуйста, дайте мне знать, есть ли у нас какие-либо ограничения на использование jAXBMARSHALLER и компилятора xjc также с интеграцией spring для целей маршалинга / демонтажа, потому что я сталкиваюсь с множеством проблем с отображением soap из сгенерированных xjc объектов java. Пожалуйста, укажите ваш inpur и дайте мне знать, чего мне не хватает для привязки моих параметров soap.

 /**
     * Create an instance of {@link JAXBElement }{@code <}{@link GetResponseForSample }{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "http://tempuri.org/", name = "getResponseForSample")
    public JAXBElement<FFSampleRequest> createGetResponseForSample(FFSampleRequest value) {
        return new JAXBElement<FFSampleRequest>(_GetResponseForSample_QNAME, FFSampleRequest.class, null, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link GetResponseForSampleResponse }{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "http://tempuri.org/", name = "getResponseForSampleResponse")
    public JAXBElement<GetResponseForSampleResponse> createGetResponseForSampleResponse(GetResponseForSampleResponse value) {
        return new JAXBElement<GetResponseForSampleResponse>(_GetResponseForSampleResponse_QNAME, GetResponseForSampleResponse.class, null, value);
    }
  

Ответ №1:

Я никогда не использовал JAXBElement , однако это может быть полезно. Я генерирую классы для XSD и помечаю их как элементы JaxB, например:

 @XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "feeRequest", propOrder = {
        "billerId",
        "amount"
})
@XmlRootElement(name = "feeRequest")
public class FeeReqData {

    @XmlElement(required = true)
    protected Long billerId;

    @XmlElement(required = true)
    protected Double amount;
}
  

И используйте ObjectFactory только вручную и не полагайтесь на эту магию JaxB.

Этого достаточно для меня, чтобы получить правильный объект модели на основе входящего XML.

С другой стороны, если вы используете FFSampleImpl в качестве интеграции Spring <service-activator> , нет причин помечать его методы аннотациями Spring-WS.

Комментарии:

1. Большое тебе спасибо, Артем. На самом деле удивлен, но факт, что файлы, созданные jaxbmarshaller xjc, не всегда корректны. Я исправил записи вручную в файлах Pojo и фабрике объектов, и теперь это работает нормально.