8

I created a SOAP web service server with SpringBoot and I was able to successfully create one endpoint. However, I cannot create multiple endpoints and access them with different URLs. I want to handle the process by URL to access.

The SOAP message received by each endpoint has the same schema. (Namespace and localpart are the same !!!) And I don't want to make the WSDL public.

For example.

userA sends the following SOAP message to the following URL: http://soap.example.com/ws/userA

<S:Envelope>
    <SOAP-ENV:Header>
    </SOAP-ENV:Header>
    <S:Body>
        <testsoap:post
            xmlns:testsoap="http://soap.example.com/">
            <testsoap:message>
                I am UserA
            </testsoap:message>
        </testsoap:post>
    </S:Body>
</S:Envelope>

userB sends the following SOAP message to the URL: http://soap.example.com/ws/userB

<S:Envelope>
    <SOAP-ENV:Header>
    </SOAP-ENV:Header>
    <S:Body>
        <testsoap:post
            xmlns:testsoap="http://soap.example.com/">
            <testsoap:message>
                I am UserB
            </testsoap:message>
        </testsoap:post>
    </S:Body>
</S:Envelope>

The source code is as follows.

@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {

    @Autowired
    CustomConfig customConfig;

    @Bean
    public ServletRegistrationBean<MessageDispatcherServlet> messageDispatherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean<MessageDispatcherServlet>(servlet, "/ws/*");
    }
}

I want to access at http://soap.example.com/ws/userA

@Endpoint
public class SoapRequestEndpoint {
    private static final String NAMESPACE_URI = "http://soap.example.com/";

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "post")
    @ResponsePayload
    public JAXBElement<PostResponse> postForA(MessageContext messageContext) {
        // do something for userA
    }
}

I want to access at http://soap.example.com/ws/userB

@Endpoint
public class SoapRequestEndpoint {
    private static final String NAMESPACE_URI = "http://soap.example.com/";

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "post")
    @ResponsePayload
    public JAXBElement<PostResponse> postForB(MessageContext messageContext) {
        // do something for userB
    }
}

Thanks.

Updated on September 24th, 2019
I have worked hard since then, but I still don't understand. I don't think it's written in the official reference. Do you have any ideas?

Updated on October 3, 2019
I haven't solved it yet. If this is the case, it will be difficult to work. Please help someone.

fsk5304
  • 395
  • 1
  • 3
  • 11
  • 1
    While I haven't used Spring Boot yet to expose SOAP services, I had to design a SOAP service in the past that made use of multiple endpoints to separate concerns. The [sample WSDL](https://github.com/RovoMe/CamelCxfJetty/blob/master/src/main/resources/wsdl/test.wsdl) is used by a Camel-CXF setup (project is outdated though). Not sure if it can help to spot setup issues within your WSDL configuration or not – Roman Vottner Oct 03 '19 at 10:51

1 Answers1

5

Try to create an additional Wsdl11Definition method in the WebServiceConfig class and annotate the method with @Bean(name = "UserB").

You have only shown a snippet from your WebServiceConfig class, I am assuming that this is absent from the class.

Your class should look similar to this:

@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {

    @Autowired
    CustomConfig customConfig;

    @Bean
    public ServletRegistrationBean<MessageDispatcherServlet> messageDispatherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean<MessageDispatcherServlet>(servlet, "/ws/*");
    }
}

@Bean(name = "userA")
    public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema [randomMethodSchema]) {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("userAPort");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setTargetNamespace("http://soap.example.com/");
        wsdl11Definition.setSchema([randomMethodSchema]);
        return wsdl11Definition;
    }

@Bean(name = "userB")
    public DefaultWsdl11Definition defaultWsdl11Definition2(XsdSchema [randomMethodSchema]) {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("userBPort");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setTargetNamespace("http://soap.example.com/");
        wsdl11Definition.setSchema([randomMethodSchema]);
        return wsdl11Definition;
    }

    @Bean
    public XsdSchema [randomMethodSchema]() {
        return new SimpleXsdSchema(new ClassPathResource([schema name].xsd));
    }
}

HTH

Sam
  • 78
  • 1
  • 7
  • Thank you for your answer. Sorry for lack of knowledge. Please tell me a little more. 1- What does randomMethodSchema () mean? 2- How should I define @Endpoint Class? – fsk5304 Dec 02 '19 at 00:07
  • 1
    The randomMethodSchema() is just an arbitrary name I came up with for my method name. You can give it any name you choose. (I have updated my answer to show this) – Sam Dec 02 '19 at 22:55
  • 3
    Your current @Endpoint class will create two operations(postForA & postForB) for both URLs (soap.example.com/ws/userA & soap.example.com/ws/user). if that is what you want, then no need to change what you have. If it isn't, which I suspect is the case, I'm not sure how to about that. You might need another endpoint class for the second URL or find a way to link what you currently have to each bean in the WebServiceConfig – Sam Dec 02 '19 at 23:09