2017-11-30 4 views
0

Ich versuche, meinen Kopf rund um die Frühjahrsintegration zu wickeln und würde mich am liebsten von der XML-basierten Konfiguration fernhalten.SOAP-Proxy mit Spring-Integration

Was würde ich tun möchte, ist folgendes:

  1. eine SOAP-Anforderung Accept auf einem bestimmten Endpunkt
  2. weiterleiten Anfrage an einen nachgeschalteten SOAP-Dienst, ohne jegliche Modifikation (vorerst nur die ich will Grundlagen zu arbeiten)
  3. das Ergebnis zurück an den Client

Dies scheint es ziemlich einfach sein sollte, aber ich habe nicht die leiseste Ahnung, wo zu beginnen. Ist das mit SI überhaupt möglich? Wie ich es verstehe, und bitte korrigieren Sie mich, wenn ich falsch liege, wird SI hauptsächlich für asynchrone Datenflüsse verwendet.

Ich habe das Integration Sample-Repository ausgecheckt, das Beispiel eingehende WS-Anfragen enthält, aber diese sind alle in XML konfiguriert, was ich, wie gesagt, lieber fern von mir lassen würde.

Alle Zeiger würden sehr geschätzt werden; Ich habe in den letzten zwei Tagen die Dokumentation gelesen und bin nicht klüger!

Antwort

2

Wenn Ihre Anwendung nur ein Proxy über einen anderen SOAP-Dienst ist, sollten Sie nur HTTP-Inbound-Gateway und HTTP-Outbound-Gateway verwenden.

Sie erhalten ein XML vom Client und senden es an den Downstream-Service. Erhalte von dort wieder ein XML und schiebe es einfach zurück an die Antwort für den Client.

Zu diesem Zweck ich HTTP-Proxy-Lösung über Java DSL vorschlagen kann:

@Bean 
    public IntegrationFlow httpProxyFlow() { 
     return IntegrationFlows 
       .from(Http.inboundGateway("/service")) 
       .handle(Http.outboundGateway("/service/internal") 
           .expectedResponseType(String.class)) 
       .get(); 
    } 

Das Problem mit dem SimpleWebServiceInboundGateway und SimpleWebServiceOutboundGateway Paar, dass sie eine Anfrage und analysiert eine respose zu (un) wickeln zu/aus dem Extrakt Seifenhülle. Das sieht nach einem Overhead für Ihren einfachen Proxy-Anwendungsfall aus.

0

Ich habe es funktioniert dank Artems Antwort, mit einem kleinen zwicken. Nicht sicher, warum die Kanäle benötigt werden, aber zumindest funktioniert es jetzt.

package com.example.integration; 

import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.context.annotation.Bean; 
import org.springframework.integration.channel.DirectChannel; 
import org.springframework.integration.config.EnableIntegration; 
import org.springframework.integration.dsl.IntegrationFlow; 
import org.springframework.integration.dsl.IntegrationFlows; 
import org.springframework.integration.dsl.http.Http; 
import org.springframework.integration.http.config.EnableIntegrationGraphController; 
import org.springframework.messaging.MessageChannel; 

@SpringBootApplication 
@EnableIntegration 
@EnableIntegrationGraphController(allowedOrigins = "*") 
public class IntegrationApplication { 

    public static void main(String[] args) { 
     SpringApplication.run(IntegrationApplication.class, args); 
    } 

    @Bean 
    public DirectChannel directChannel() { 
     return new DirectChannel(); 
    } 

    @Bean 
    public IntegrationFlow httpProxyFlow(MessageChannel directChannel) { 
     return IntegrationFlows 
       .from(Http.inboundGateway("/thing").requestChannel(directChannel).replyChannel(directChannel)) 
       .enrichHeaders(h -> h.header("Content-Type", "application/soap+xml; charset=utf-8")) 
       .handle(Http.outboundGateway("http://www.webservicex.net/geoipservice.asmx").expectedResponseType(String.class)) 
       .channel(directChannel) 
       .get(); 
    } 
} 
+0

Das ist wirklich seltsam: Sie brauchen keine Kanäle dort ... –

+0

@ ArtemBilan so das ist seltsam. Letzte Nacht gab es mir einen Fehler über "Kanal hat keine Abonnenten" ohne die Kanäle. Ich habe das ohne die Kanäle schnell erneut versucht, jetzt funktioniert es. Keine Ahnung. Der Frühling ist lustig, denke ich. – iLikeBreakfast

0

Hier ist ein Beispiel mit dem SimpleWebServiceInboundGateway. In diesem Beispiel setzen wir auch "ExtractPayload" auf "false", sodass die RAW-Soap-Nachricht gesendet wird. Aber stimme mit oben überein, möglicherweise ist HTTPInboundRequest für deinen Anwendungsfall besser. Ich habe auch nicht viele Beispiele gefunden, die DSL für SoapInboundGateway verwenden, also teilen wollte und hoffe, dass es jemand anderem hilft.

@Configuration 
@EnableIntegration 
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"; 


    /** 
    * Register the servlet mapper, note that it uses MessageDispatcher 
    */ 
    @Bean 
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) { 
     MessageDispatcherServlet servlet = new MessageDispatcherServlet(); 
     servlet.setApplicationContext(applicationContext); 
     servlet.setTransformWsdlLocations(true); 
     servlet.setTransformSchemaLocations(true); 
     servlet.setPublishEvents(true); 
     ServletRegistrationBean 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 
    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 
    */ 
    @Bean 
    public EndpointInterceptor 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 

    ) { 
     PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor(); 
     interceptor.setXsdSchema(xsdSchema); 
     interceptor.setValidateRequest(soapValidateRequest); 
     interceptor.setValidateResponse(soapValidateResponse); 
     interceptor.setAddValidationErrorDetail(soapAddValidationErrorDetail); 
     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()); 
     mapping.setInterceptors(new EndpointInterceptor[]{loggingInterceptor, payloadValidatingInterceptor}); 
     return mapping; 
    } 

    /** 
    * Expose the wsdl at http://localhost:8080/services/myService.wsdl 
    **/  
    @Bean 
    public Wsdl11Definition defaultWsdl11Definition() { 
     SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition(); 
     wsdl11Definition.setWsdl(new ClassPathResource("META-INF/myService.wsdl")); 
     return wsdl11Definition; 
    } 

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

    @Bean 
    public IntegrationFlow itemLookupFlow() { 
     return IntegrationFlows.from("wsGatewayInboundChannel") 
       .log(LoggingHandler.Level.INFO) 
       .handle(myBeanName, "execute") 
       .log(LoggingHandler.Level.TRACE, "afterExecute") 
       .get(); 
    } 

}