The other day I was discussing calling a Web Service from BPEL that does not return a result or returns a result that you don't care about: a Fire-and-Forget Web Service.
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.
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.