Spring配置两个@Endpoint,每个都有一个唯一的wsdl文件

时间:2018-03-29 12:50:03

标签: java spring soap spring-ws endpoint

我已经能够使用wsdl文件获得一个@Endpoint:

@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;
    }
}

但是对于我的用例,我需要处理两个wsdl文件。最初我设置了一个RestController并从xml POST请求解组了正文,但我现在想尝试纯粹的弹簧方式。

我假设我需要创建两个MessageDispatcherServlet,每个wsdl定义一个,但我不知道如何正确映射或注册我的端点。

有什么想法吗?

摆弄我创建了重复(使用不同的wsdl和bean名称)WSDLdefinition bean,而messageDispatcherServletServletRegistrationBean给了我错误Servlet messageDispatcherServlet was not registered (possibly already registered?),而我的端点似乎显示,但是弹簧在对所述端点的任何请求上返回404。

Spring-ws版本:3

1 个答案:

答案 0 :(得分:2)

我的假设是每个Spring @Enpoint类需要不同的路径。我现在意识到我只需要注册一个MessageDispatcherServlet并定义处理传入请求所需的wsdl文件。

由于我需要两个不同的wsdl文件,我可以通过创建一个ServletRegistrationBean来保存MessageDispatcherServlet,两个Wsdl11Definition bean(每个wsdl文件一个),并且在我的@Endpoint类我将命名空间和localPart设置为@PayloadRoot注释的一部分。

配置类

// 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;
    }
}

如果您需要使用不同的路径来代替端点。我假设您需要调整上面定义的ServletRegistrationBean。现在一切都映射到"/soap"

以下是终点:

@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);
    }
}

然后BServerAServer完全相同,但NAMESPACE_URILOCALPART除外,因为它们依赖于各自的wsdl文件。