WSDL operation and SOAP: how this actually works? - web-services

I'm trying to figure out how WS SOAP server knows what operation to execute when receiving a SOAP. So, can someone pls clarify the following?
There are number of examples on the web that have something like this:
<wsdl:operation name="function1">
<wsdl:input message="function1Request"/>
<wsdl:output message="function1Response"/>
<wsdl:fault message="someFault"/>
</wsdl:operation>
<wsdl:operation name="function2">
<wsdl:input message="function2Request"/>
<wsdl:output message="function2Response"/>
<wsdl:fault message="someFault"/>
</wsdl:operation>
and then SOAP request for calling the function1 looks like this:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<m:function1Request xmlns:m="http://namespaces.com">
...
</m:function1Request>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
So, the operation itself is not sent in the SOAP. It contains just the payload of the request. Then, I presume, the server has to match the request type with the operation definitions from the WSDL in order to find out which operation is actually required to be called.
Ok, this works in case of 1 to 1 relation between the operation and the input parameter type.
But, what if I have 2 operations with the same input type? Something like this:
<wsdl:operation name="function1">
<wsdl:input message="function1Request"/>
<wsdl:output message="function1Response"/>
<wsdl:fault message="someFault"/>
</wsdl:operation>
<wsdl:operation name="function2">
<wsdl:input message="function1Request"/>
<wsdl:output message="function2Response"/>
<wsdl:fault message="someFault"/>
</wsdl:operation>
How will the server know which operation to execute?

It's described in the binding section of the WSDL.
There are several ways of letting server know which operation to call.
You can specify binding based on the header section of the SOAP for example.
In this particular case however, the binding will be made based on the soap body type.
I think that having duplicate input definitions will be considered as invalid.
Here are links with more info:
https://msdn.microsoft.com/en-us/library/ms996486.aspx
https://www.w3.org/TR/wsdl#_bindings

Related

Can I mock a message-enricher in mule unit testing?

I have a message-enricher , inside that I have a call to data base to get sequence value. Here is the component of my flow
<enricher doc:name="Enrich Flow Variable">
<db:select config-ref="LocalhostPostgres" doc:name="Database">
<db:parameterized-query><![CDATA[Select (nextval('batch_id_seq'))]]></db:parameterized-query>
</db:select>
<enrich source="#[payload[0].nextval]" target="#[flowVars.flow_batch_id]" />
<enrich source="#['INPUT_CSV']" target="#[flowVars.flow_source_name]" />
</enricher>
what I want,, in my unit testing I want to mock it so that I can pass constant values to my flow_batch_id.
Is there any way to do it?. Please help me.
I wouldn't mock the enricher. Instead I would mock the db:select to return a sample result. You can either mock the db:select operation, or move the db:select to a sub-flow/private flow and mock that instead. Take a look at the munit mock documentation: https://docs.mulesoft.com/munit/v/1.1.1/mock-message-processor

SOAP address picked wrong webservice for EJB as a WebService

I am deploying JAVA EE application in WildFly 8.1.0 Final. After deployments its replaces address in SOAP address location to Remote Interface rather than to Stateless EJB WebService.
E.g,
#Remote
public interface SbbAccess {
...
}
#WebService(name="SbbAccess", serviceName="pfmjainslee11_diagram", targetNamespace="http://jee.v1.sbb.profile" )
#Addressing
#HandlerChain(file = "jaxws-handlers.xml")
#TransactionManagement(TransactionManagementType.BEAN)
public #Stateless class SbbAccessBean implements SbbAccess {
...
}
WSDL available from wildlfy is
<wsdl:port binding="tns:pfmjainslee11_diagramSoapBinding" name="SbbAccessPort">
<soap:address location="http://linus:8080/sbb---v1.EJB/pfmjainslee11_diagram/SbbAccess"/>
</wsdl:port>
this should have been like
<wsdl:port binding="tns:pfmjainslee11_diagramSoapBinding" name="SbbAccessPort">
<soap:address location="http://linus:8080/sbb---v1.EJB/pfmjainslee11_diagram/SbbAccessBean"/>
</wsdl:port>
Any suggestion what is causing this behavior?
Regards,
That's the expected behaviour as a result of at least two of the following :
Your SLSB implements an #Remote interface
It's recommended by the specification that the interface name is mandatory in the JNDI lookup naming, when the SLSB implements a business interface.
The SLSB is being accessed remotely
The naming lookup options are:
[/application name]/module name/enterprise bean name[/interface name]
In theory, you're not required to implement #Remote, so if it's causing you any discomfort, you could remove the interface implementation and you'll be fine

Sub-Flow with reuse and concurrency

I am working with preparing a solution for one of my uscases.
My solution is something that might look like this in abstract.
My question here is, when the two main flows are calling the same sub-flow cuncurrently,
it is going to work without any issues ?
Also do I need to write the code as thread safe for all the classes that are being used as
custom components/trnasformers in the sub-flow ?
My abstract configuration looks as given below.
<flow name="mainflow_1" >
<inbound-endpoint/>
<transformer ....>
<component ....>
<flow-ref name="subflow_1"></flow-ref>
<transformer ....>
<component ...>
<outbound-endpoint ....>
</flow>
<flow name="mainflow_2" >
<inbound-endpoint type="request-response" />
<transformer ....>
<component ....>
<flow-ref name="subflow_1"></flow-ref>
<transformer ....>
<component ...>
</flow>
<sub-flow name="subflow_1" >
<transformer ....>
<component ....>
<outbound-endpoint call to some service >
<transformer ....>
<component ...>
</sub-flow>
Please guide me.
A sub-flow acts like a macro: execution wise, it's as if the elements of the sub-flow were copied in the calling flow.
Thus it's the threading behaviour of the calling flow that will determine the threading behaviour of the sub-flow.
Whether they're used in sub-flows or main flows, you should write your component classes to be thread safe if you use singleton instances of them (the common use case). If you use prototype instances (one instance created per request) or pooled instances (limited number of instances, bottlenecks the threads), your component classes can be thread unsafe.
As a rule of thumb, strive for thread-safe stateless component classes as much as you can to save you potential optimization pain down the road.

How to change Jax-WS WSDL #IDREF binding

I'm sucessfully exposing a contract-first JAX-WS web service on a Tomcat servlet container with Jax-WS Spring support. I'm having troulbes with xs:idref types though. The original XSD file contains a complex type
<xs:complexType name="DocumentScopeOptionalTypeReferenceIdentifier">
<xs:simpleContent>
<xs:extension base="DocumentScopeReferenceIdentifierContent">
...
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="DocumentScopeReferenceIdentifierContent">
<xs:restriction base="xs:IDREF">
<xs:minLength value="1"/>
<xs:maxLength value="64"/>
</xs:restriction>
</xs:simpleType>
which xjc correctly compiles to
public class DocumentScopeOptionalTypeReferenceIdentifier {
#XmlValue
#XmlIDREF
protected Object value;
...
}
When I deploy the webservice, however, the #XmlIDREF annotation gets ignored and I end up with an xs:anyType in the namespace declaration of the resulting WSDL
<xs:complexType name="DocumentScopeOptionalRoleReferenceIdentifier">
<xs:simpleContent>
<xs:extension base="xs:anyType">
...
</xs:extension>
</xs:simpleContent>
</xs:complexType>
Clients of the webservice in question report, that they cannot generate Client stubs (using C#) with this anyType present. How would I change that back to xs:idref? Thanks.
Ok, I guess my approach was a little bit too naiv. After doing a bit of research I came to the conclusion that customizing the generated WSDL is not possible. I now switched to a contract first approach and specify a hand-crafted WSDL file manually.
I've read that any WSDL file located under META-INF/wsdl should be picked up automatically by JAX-WS, if it contains a corresponding service and port name. This didn't work for me, so I had to specify the WSDL file explicitely using the wsdlLocation attribute on the #WebService annotation
#WebService(
targetNamespace = "...",
serviceName = "...",
portName = "...",
wsdlLocation = "/META-INF/wsdl/mywebservice.wsdl"
)
public class MyWebService { ... }
Deploying the webservice on Tomcat was straight forward following the instructions on the Jax-WS community page

wsimport how to create web service client from WSDL for http:binding GET/POST

I have wsdl and I create classes with wsimport tool. Everything is going ok for SOAP messages but for http:binding GET/POST I get error. Part of the WSDL follows:
<wsdl:binding name="DictServiceHttpPost" type="tns:DictServiceHttpPost">
<http:binding verb="POST" />
...
...
...
<wsdl:port name="DictServiceHttpGet" binding="tns:DictServiceHttpGet">
<http:address location="http://services.aonaware.com/DictService/DictService.asmx" />
</wsdl:port>
<wsdl:port name="DictServiceHttpPost" binding="tns:DictServiceHttpPost">
<http:address location="http://services.aonaware.com/DictService/DictService.asmx" />
</wsdl:port>
wsimport generates classes, for SOAP port its working but for GET/POST but when I use them, I receive error.
Caused by: com.sun.xml.internal.ws.model.RuntimeModelerException: runtime modeler error: SEI invoker.DictServiceHttpPost has method match annotated as BARE but it has more than one parameter bound to body. This is invalid. Please annotate the method with annotation: #SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
at com.sun.xml.internal.ws.model.RuntimeModeler.validateDocBare(RuntimeModeler.java:1247)
at com.sun.xml.internal.ws.model.RuntimeModeler.processDocBareMethod(RuntimeModeler.java:1236)
at com.sun.xml.internal.ws.model.RuntimeModeler.processMethod(RuntimeModeler.java:609)
at com.sun.xml.internal.ws.model.RuntimeModeler.processClass(RuntimeModeler.java:401)
at com.sun.xml.internal.ws.model.RuntimeModeler.buildRuntimeModel(RuntimeModeler.java:240)
at com.sun.xml.internal.ws.client.WSServiceDelegate.createSEIPortInfo(WSServiceDelegate.java:687)
at com.sun.xml.internal.ws.client.WSServiceDelegate.addSEI(WSServiceDelegate.java:675)
at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:330)
at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:313)
at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:295)
at javax.xml.ws.Service.getPort(Service.java:92)
at invoker.DictService.getDictServiceHttpPost(DictService.java:124)
... 29 more
com.sun.xml.internal.ws.model.RuntimeModelerException: runtime modeler error: SEI invoker.DictServiceHttpPost has method match annotated as BARE but it has more than one parameter bound to body. This is invalid. Please annotate the method with annotation: #SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
This happened to me, the problem was that I had a public method in the service implementation, that had more than one parameter but this method was not a service operation. Services marked with: SOAPBinding.ParameterStyle.BARE should only have public methods with only one parameter. My solution was mark this method as private since I was using it from one public method of the service (operation).
Make sure you don't have any public method in your service implementation that has more than one parameter.