This is not a very common use case. Usually, you call a Web Service from BPEL and you use the result to determine what the next step will be, or you use the result to check that the call was successful. But that doesn't mean it never happens.
I decided to try two different use cases:
- Calling a Web Service that was generated with JAX WS annotations from a Java class that has a 'void' return type.
- Calling a Web Service that was defined top down with a WSDL with no output message for the operation.
Bottom up
The example is very simple, a Java class with JAX WS annotation with one operation:
package nl.vennster.demo.blog;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService(name="HelloWorldService")
public class HelloWorld {
@WebMethod
public void helloWorld(String greeting){
System.out.println("I do nothing with this " + greeting);
}
}
The resulting WSDL snippet looks like this:
...
</types>
<message name="helloWorld">
<part name="parameters" element="tns:helloWorld"/>
</message>
<message name="helloWorldResponse">
<part name="parameters" element="tns:helloWorldResponse"/>
</message>
<portType name="HelloWorldService">
<operation name="helloWorld">
<input message="tns:helloWorld"/>
<output message="tns:helloWorldResponse"/>
</operation>
</portType>
<binding name="HelloWorldServicePortBinding" type="tns:HelloWorldService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="helloWorld">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
....
As you can see, an empty response is returned, if you call this Web Service with this request:
POST http://localhost:7101/Blog-HelloWorldService-context-root/HelloWorldServicePort HTTP/1.1
Content-Type: text/xml; charset=UTF-8
SOAPAction: ""
Host: localhost:7101
Content-Length: 212
X-HTTPAnalyzer-Rules: 1@localhost:8099
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://blog.demo.vennster.nl/">
<env:Header/>
<env:Body>
<ns1:helloWorld>
<arg0>Lonneke</arg0>
</ns1:helloWorld>
</env:Body>
</env:Envelope>
You get the following response:
HTTP/1.1 200 OK
Content-Type: text/xml;charset=UTF-8
X-Powered-By: Servlet/2.5 JSP/2.1
Date: Mon, 26 Nov 2012 20:55:04 GMT
X-ORACLE-DMS-ECID: 11d1def534ea1be0:-6225fc35:13b3e7a6f94:-8000-000000000000002a
Content-Length: 199
X-HTTPAnalyzer-RuleName: Pass through :
<?xml version = '1.0' encoding = 'UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:helloWorldResponse xmlns:ns2="http://blog.demo.vennster.nl/"/>
</S:Body>
</S:Envelope>
Obviously, you don't care about this answer in your BPEL process: it is always the same and has nothing you can use. However, if you invoke this service without defining the output variable BPEL will throw an error:
Error(77): <invoke/> missing output variable specification
Top Down
Now let's see what happens if we define a WSDL with no output message:
...
<message name="helloWorld">
<part name="parameters" element="tns:helloWorld"/>
</message>
<portType name="HelloWorldService">
<operation name="helloWorld">
<input message="tns:helloWorld"/>
</operation>
</portType>
<binding name="HelloWorldServicePortBinding" type="tns:HelloWorldService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="helloWorld">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
</operation>
</binding>
<service name="HelloWorldService">
<port name="HelloWorldServicePort" binding="tns:HelloWorldServicePortBinding">
<soap:address location="http://localhost:7101/Blog-HelloWorldService-context-root/HelloWorldServicePort"/>
</port>
</service>
</definitions>
If you invoke this BPEL, there is no option to define an output variable, this field is disabled.
If you invoke this BPEL, there is no option to define an output variable, this field is disabled.
Conclusion
Fire-and-forget Web Services are supported in BPEL, but only if the WSDL is defined as such. If there is a response, then you have to create an output variable. Which you can then use, or ignore.
Hi,
ReplyDeleteif you really want an one-way BPEL then you can better use JMS. With the HTTP adapter BPEL does not report back directly and waits for the execution and reports back with an empty HTTP response with status code 202 (accepted) to the client
also with the mediator you also got a one.way.returns.fault property in which you can control to report back the soap fault, beside http code 500.
http://docs.oracle.com/cd/E21764_01/integration.1111/e10224/med_interactions.htm#CJAGACJH
thanks Edwin
I am not giving advice in this post about when to use what, I was merely showing that you can use fire-and-forget web services in BPEL and that BPEL handles that as expected.
DeleteMaybe I should write a post about JMS versus web Services. That would be a MUCH longer one though ;)
You can get a better fire-and-forget behaviour from a JAX-WS service if you put a @OneWay annotation on the service method. This should result in the service returning a http status code reply only, instead of an empty soap envelope.
ReplyDeletethanks, that is a good point. In that case BPEL would not require you to create an output variable on the invoke of the service.
Delete