I'm attempting to create 2 separate web services, both within one spring deployment, both with the wsdl's being generated from the same xsd schemas, yet have them be routed to two separate end points so i can handle the requests differently in the separate contexts.
Ex:
Webservice 1: subset of access, lower privileges and security constraints
Webservice 2: higher privileges
<sws:dynamic-wsdl id="spml-readonly"
portTypeName="SpmlReadOnlyService"
locationUri="SpmlReadOnly">
<sws:xsd location="/WEB-INF/xsd/spml/pstc_spmlv2_core.xsd"/>
</sws:dynamic-wsdl>
<sws:dynamic-wsdl id="spml-crud"
portTypeName="SpmlCrudService"
locationUri="SpmlCrud">
<sws:xsd location="/WEB-INF/xsd/spml/pstc_spmlv2_core.xsd"/>
<sws:xsd location="/WEB-INF/xsd/spml/pstc_spmlv2_search.xsd"/>
<sws:xsd location="/WEB-INF/xsd/spml/pstc_spmlv2_batch.xsd"/>
</sws:dynamic-wsdl>
Now since both wsdls are based off of the same xsds, the 'namespace' and 'localPart" of the requests come across the wire identical, regardless of which web service i'm hitting (/SpmlReadOnly or /SpmlCrud).
Therefore, that's ruling out the deprecated PayloadRootQNameEndpointMapping since the localPart and namespace are still identical, etc,... and my current config simply routes the requests to the same endpoint method handler, and i have no way of distinguishing which web service was called:
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "lookupRequest")
@ResponsePayload
public Source handleLookupRequest(SoapMessage message) throws Exception {
...
}
Is what I'm able to do even possible? If the xsd's are shared and have identical namespaces at the root of the schema, and the same localPart method requests, will there ever be a way to distinguish between them and map to two different end points? Any information on this would be useful! I'm hoping i don't have to set up two separate .wars and deploy them separately with their own code bases on a server!
Thanks, Damian
You need something that combines
URI
andPayloadRoot
mapping. Unfortunately Spring-Ws doesn't have something like this. But because it's very extensible it's really easy to achieve this.TL;DR
See This branch at GitHub for working example
Details
You need to create mapping of combined URI+QName to
org.springframework.ws.server.endpoint.MethodEndpoint
instances. Also you should minimize the code which would duplicate existing Spring-Ws functions.So 1) You need to explicitly configure Spring-Ws annotations without using
<sws:annotation-driven />
:This is your requirement (with my schemas):
This is all you need to do by hand which normally is configured by
<sws:annotation-driven />
(one adapter with one JAXB marshaller):This is custom mapping:
And 2) You should create your own mapping
which extends
org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping
. And all it does is extending the keys (QNames of payload root elements) of messages with the information extracted from the endpoint URI. I've used Spring's@org.springframework.web.bind.annotation.RequestMapping
annotation for that, but someone thinking it's a hack may create his/her own annotation.So for endpoint like this:
the key is not:
but this:
The
protected QName getLookupKeyForMessage(MessageContext messageContext)
method ensures that the mapping URI is independent of the WAR context, the application is deployed at.