调用SimpleWebServiceInboundGateway.invoke方法

时间:2018-05-03 03:03:38

标签: spring-integration spring-ws

这是我第一次尝试使用Spring Integration调用SOAP Web服务。下面是我的bean配置类。

    @Configuration
@EnableIntegration
@PropertySource(value = { "application.properties" })
public class SoapGatewayConfiguration {

    /**
     * URL mappings used by WS endpoints
     */
    public static final String[] WS_URL_MAPPINGS = { "/services/*", "*.wsdl", "*.xsd" };
    public static final String GATEWAY_INBOUND_CHANNEL_NAME = "wsGatewayInboundChannel";
    public static final String GATEWAY_OUTBOUND_CHANNEL_NAME = "wsGatewayOutboundChannel";

    @Bean
    public ServletWebServerFactory servletWebServerFactory() {
        TomcatServletWebServerFactory f = new TomcatServletWebServerFactory();
        f.setPort(9000);
        return f;
    }

    /**
     * Register the servlet mapper, note that it uses MessageDispatcher
     */
    @Bean
    public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServlet(
            ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        servlet.setTransformSchemaLocations(true);
        servlet.setPublishEvents(true);
        ServletRegistrationBean<MessageDispatcherServlet> servletDef = new ServletRegistrationBean<>(servlet,
                WS_URL_MAPPINGS);
        servletDef.setLoadOnStartup(1);
        return servletDef;
    }

    /**
     * Create a new Direct channels to handle the messages
     */
    @Bean
    public MessageChannel wsGatewayInboundChannel() {
        return MessageChannels.direct(GATEWAY_INBOUND_CHANNEL_NAME).get();
    }

    @Bean
    public MessageChannel wsGatewayOutboundChannel() {
        return MessageChannels.direct(GATEWAY_OUTBOUND_CHANNEL_NAME).get();
    }

    /**
     * Startup the WebServiceInboundGateway Endpoint, this will handle the incoming
     * SOAP requests and place them onto the request channel
     */
    @Bean
    @Gateway
    public SimpleWebServiceInboundGateway webServiceInboundGateway(
            @Value("${spring.ws.request.timeout:1000}") long requestTimeout,
            @Value("${spring.ws.reply.timeout:1000}") long replyTimeout,
            @Value("${spring.ws.should.track:true}") boolean shouldTrack) {
        SimpleWebServiceInboundGateway wsg = new SimpleWebServiceInboundGateway();
        wsg.setRequestChannel(wsGatewayInboundChannel());
        wsg.setReplyChannel(wsGatewayOutboundChannel());
        wsg.setExtractPayload(false); // Send the full RAW SOAPMessage and not just payload
        wsg.setLoggingEnabled(true);
        wsg.setShouldTrack(shouldTrack);
        wsg.setReplyTimeout(replyTimeout); // Do not believe this prop supported currently
        wsg.setRequestTimeout(requestTimeout); // Do not believe this prop is supported currently
        wsg.setCountsEnabled(true);
        return wsg;
    }

    /**
     * You must enable debug logging on
     * org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor
     * to see the logs from this interceptor
     */
    @Bean
    public EndpointInterceptor soapMessageLoggingInterceptor() {
        SoapEnvelopeLoggingInterceptor li = new SoapEnvelopeLoggingInterceptor();
        li.setLogRequest(true);
        li.setLogResponse(true);
        li.setLogFault(true);
        return li;
    }

    /**
     * Validate the incoming web service against the schema
     * 
     * @throws IOException
     */
    @Bean
    public AbstractValidatingInterceptor payloadValidatingInterceptor(XsdSchema xsdSchema,
            @Value("${spring.ws.soap.validate.request:true}") boolean soapValidateRequest,
            @Value("${spring.ws.soap.validate.reply:true}") boolean soapValidateResponse,
            @Value("${spring.ws.soap.validate.addErrorDetail:true}") boolean soapAddValidationErrorDetail

    ) throws IOException {
        PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
        interceptor.setXsdSchema(xsdSchema);
        interceptor.setValidateRequest(soapValidateRequest);
        interceptor.setValidateResponse(soapValidateResponse);
        return interceptor;
    }

    /**
     * Map the allowable service Uri's.
     */
    @Bean
    public EndpointMapping uriEndpointMapping(PayloadValidatingInterceptor payloadValidatingInterceptor,
            SimpleWebServiceInboundGateway webServiceInboundGateway,
            SoapEnvelopeLoggingInterceptor loggingInterceptor) {
        UriEndpointMapping mapping = new UriEndpointMapping();
        mapping.setUsePath(true);
        mapping.setDefaultEndpoint(webServiceInboundGateway(1000L, 1000L, true));
        // mapping.setInterceptors({loggingInterceptor, payloadValidatingInterceptor});
        return mapping;
    }


    @Bean
    public Wsdl11Definition defaultWsdl11Definition() {
        SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition();
        wsdl11Definition.setWsdl(new ClassPathResource("employees.wsdl.xml"));
        return wsdl11Definition;
    }

    /**
     * Expose the xsd at http://localhost:8080/services/mySchema.xsd
     **/
    @Bean
    public XsdSchema mySchema() {
        return new SimpleXsdSchema(new ClassPathResource("Employee.xsd"));
    }
}

我怀疑在创建soap请求时我犯了一些错误。下面是我创建soap请求的代码片段

SimpleWebServiceInboundGateway employeeSearchInboundGateway = context
        .getBean(SimpleWebServiceInboundGateway.class);
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SaajSoapMessageFactory saaj = new SaajSoapMessageFactory(messageFactory);

String requestXML = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:myNamespace=\"http://www.springpoc.com/employee-ws\">"
        + " <SOAP-ENV:Header/> " + " <SOAP-ENV:Body> "
        + " <findEmployeeByIdRequest>  <employeeId>12345</employeeId> </findEmployeeByIdRequest> "
        + " </SOAP-ENV:Body> " + " </SOAP-ENV:Envelope> ";

SaajSoapMessage request = new SaajSoapMessage(messageFactory.createMessage(new MimeHeaders(),
        new ByteArrayInputStream(requestXML.getBytes(Charset.defaultCharset()))));
SoapEnvelope soapEnvelope = request.getEnvelope();

SoapHeader header = request.getSoapHeader();

String myNamespace = "myNamespace";
String myNamespaceURI = "http://www.springpoc.com/employee-ws";
soapEnvelope.addNamespaceDeclaration(myNamespace, myNamespaceURI);

MessageContext arg0 = new DefaultMessageContext(request, saaj);
employeeSearchInboundGateway.invoke(arg0);

我收到如下错误:

Exception in thread "main" org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers, failedMessage=GenericMessage [payload=SaajSoapMessage findEmployeeByIdRequest, headers={ws_soapAction="", replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@73163d48, history=webServiceInboundGateway, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@73163d48, id=d40a8603-903c-d5a5-b7a8-96177d1f4114, timestamp=1525316363103}]

问题:

需要建议我们是否需要设置 replyChannel&amp; SOAP请求标头中的errorChannel 属性?如果是的话,请告诉我怎么做。

编辑1: 以下是 @ServiceActivator 端点

的配置
@ServiceActivator(inputChannel = "wsGatewayOutboundChannel")
public void makeCall(Message<Employee> pr) {
    Employee response = pr.getPayload();
    System.out.println(response);
}

1 个答案:

答案 0 :(得分:1)

您需要确保订阅wsGatewayInboundChannel的内容。这就是你从中获得异常的地方。

换句话说,WS入站网关向通道发送消息,但在通道的另一侧没有任何东西可以处理它。