Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring configure two @Endpoint, each with a unique wsdl file

I've been able to get one @Endpoint with a wsdl file working:

@EnableWs
@Configuration
public class EventServerConfiguration extends WsConfigurerAdapter {
    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean(servlet, "/event");
    }


    @Bean(name = "wsdl-event")
    public Wsdl11Definition defaultWsdl11Definition() {
        SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition();
        wsdl11Definition.setWsdl(new ClassPathResource("/wsdl/event.wsdl"));
        return wsdl11Definition;
    }

    @Bean
    AnnotationActionEndpointMapping endpointMapping() {
        AnnotationActionEndpointMapping mapping = new AnnotationActionEndpointMapping();
        return mapping;
    }
}

But for my use case I have two wsdl files that I need to handle. Originally I set up a RestController and unmarshalled the body from a xml POST request, but I now want to try the pure spring way.

I assume I need to create two MessageDispatcherServlet, one for each wsdl definition, but I have no idea how to map or register my endpoints correctly.

Any ideas?

Fiddling around I created duplicate (with different wsdl and bean names) WSDLdefinition beans, and messageDispatcherServlet through ServletRegistrationBean has given me the error Servlet messageDispatcherServlet was not registered (possibly already registered?) while my endpoints seem to show up, but spring returns a 404 on any request to said endpoints.

Spring-ws version: 3

like image 655
andersfylling Avatar asked Mar 29 '18 12:03

andersfylling


1 Answers

My assumption was that I needed different paths for each Spring @Enpoint class. I realise now that I only need to register one MessageDispatcherServlet and define the wsdl files required to handle incoming requests.

Since I need two different wsdl files, I can support both by creating one ServletRegistrationBean that holds a MessageDispatcherServlet, two Wsdl11Definition beans (one for each wsdl file), and in my @Endpoint class I set the namespace and localPart as a part of the @PayloadRoot annotation.

Configuration class

// Configuration class
@EnableWs
@Configuration
public class SpringConfiguration 
{
    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) 
    {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);

        return new ServletRegistrationBean(servlet, "/soap");
    }

    @Bean
    AnnotationActionEndpointMapping annotationActionEndpointMapping() 
    {
        AnnotationActionEndpointMapping mapping = new AnnotationActionEndpointMapping();
        // add any interceptors here for features like logging
        return mapping;
    }

    // wsdl file A
    @Bean(name="wsdl-definition-A")
    public Wsdl11Definition wsdl11DefinitionA()
    {
        SimpleWsdl11Definition def = new SimpleWsdl11Definition();
        wsdl11Definition.setWsdl(new ClassPathResource("wsdl/A.wsdl"));

        return wsdl11Definition;
    }

    // wsdl file B
    @Bean(name="wsdl-definition-B")
    public Wsdl11Definition wsdl11DefinitionA()
    {
        SimpleWsdl11Definition def = new SimpleWsdl11Definition();
        wsdl11Definition.setWsdl(new ClassPathResource("wsdl/B.wsdl"));

        return wsdl11Definition;
    }
}

If you require different paths to your endpoints in stead of one. I assume you would need to tweak the ServletRegistrationBean defined above. Now everything is mapped to "/soap".

And here are the endpoints:

@Endpoint
public class AServer
{
    private final static String NAMESPACE_URI = "http://some.namespace/v3/idk/am/i/even/real";
    private final static String LOCALPART = "XMLElementName";
    private final SomeMarshaller marshaller;

    @Autowired
    public EventServer(EventReceiveMarshaller marshaller) 
    {
        // I use a marshaller class to simplify my life
        this.marshaller = marshaller; 
    }

    @Override
    @ResponsePayload
    @PayloadRoot(namespace = NAMESPACE_URI, localPart = LOCALPART)
    public JAXBElement<SomeResponseMessageType> triggerResponse(@RequestPayload JAXBElement<SomeRequestMessageType> msg) {

        // do something with the `msg` request

        // Send a OK response
        return this.marshaller.createReply(msg);
    }
}

And then BServer is exactly the same as AServer except the NAMESPACE_URI and LOCALPART as those depend on their respective wsdl files.

like image 177
andersfylling Avatar answered Nov 05 '22 22:11

andersfylling