Implementation
I just recieved an email from Adam Ratcliffe with an initial implementation of this RT. I have attached the code to this page for review. Many thanks to Adam.
flowWebServices092504.zip (http://issues.apache.org/jira/browse/COCOON-1274)
What sparked the idea
I had to help someone with some coldfusion code for connecting to a webservice. As I'm no coldfusion guru, this involved a bit of research. One thing that I liked was coldfusion's ability to load a web service as an object and call its methods passing in coldfusion data types. This got me thinking, could this be possible in flow? I took a look at the Axis and the Rhino documentation and it should be possible. – Luke Hubbard
Calling Web Services from Flow
Why is this needed? Well for some web services such as services that return stock quotes or search results the WebServiceProxyGenerator is probably better suited. However for more transactional orientated web services it could be very usefull. Consider the following simple example flow script for placing an order using a web service.
// initialize some global varibles var partnerId = 443; // load a webservice given the uri of the wsdl file var bookshop = loadWebService('http://books.biz/ws/orderservice?WSDL'); var parcelService = loadWebService('http://shipping.com/ws/parcelservice?WSDL'); // define the prototype for a book object Book.prototype.isbn Book.prototype.price function placeOrder(){ var userId = cocoon.session['userId']; var book = new Book(); var quantity = 0; while(true){ // populate the book object book.isbn = cocoon.request['isbn']; quantity = cocoon.request['quantity']; // check to see if the book is in stock var stockCheck = bookshop.checkStock(book.isbn,quantity); // update the books price book.price = stockCheck.pricePerItem; // if there are enough books in stock break this loop if(stockCheck.number >= quantity) break; // if there are no copies available if(stockCheck.number == 0){ // send a page saying sorry cocoon.sendPage('view/sorry.jx', {message:'Sorry, but the book is sold out'}); // exit this order return; } // otherwise, tell the user they must modify the order var message = 'Sorry we do not have enough copies. ' + 'We only have ' + stockCheck.number + ' in stock. ' + 'Please modify your order. '; cocoon.sendPageAndWait('view/editOrder.jx', {book:book, message:message); } cocoon.sendPageAndWait('view/deliveryAddress.jx'); var deliveryAddress = cocoon.request['address']; // use the parcel service to calc the shipping costs var shippingInfo = parcelService.calculateShippingCost( {class:1, type:'book', quantity:quantity, address: deliveryAddress}); var totalCost = quantity * book.price; if(totalCost < 50){ // for orders under £50 add post and packaging totalCost += shippingInfo.cost; totalCost += quantity * 0.5; } // ask the user to confirm the order cocoon.sendPageAndWait('view/confirm.jx', {book:book,total:totalCost}); // go ahead and place the order var order = bookshop.placeOrder(partnerId,userId, {order:{isbn:book.isbn, quantity:quantity}},shippingInfo.trackingId); // now send a success page cocoon.sendPage('view/done.jx', {order:order,tracking:shippingInfo.trackingId}); }
Data type mapping.
|
|
WSDL data type |
number |
SOAP-ENC:double |
|
boolean |
SOAP-ENC:boolean |
|
String |
SOAP-ENC:string |
|
Array |
SOAP-ENC:Array |
|
Date |
xsd:dateTime |
|
Object |
complex type |
|
??? |
xsd:base64Binary |
Questions
Q: Should connecting to a web service be part of the model, is it mixing concerns to do the work in the flow layer? Or is this ok if you consider a web service simply a remote part of the model.
This is an excellent question. It seems that there is a very fine line to walk between controlling the flow of the application based on the result from a web service call, and using the web service to populate lots of data in the view. This should be investigated more, but it's looking good so far. – TonyCollen
Exposing Flow Scripts as Web Services
This is real can of worms. People have brought up the idea of modifying the pipeline design to support soap requests in the past. Stefano talks about the concept of "extractors" in this mail http://www.mail-archive.com/dev@cocoon.apache.org/msg01585.html and there was some interest during discussions relating to flow http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=102578062915328&w=2
Would it be possible to expose functions as web services?
Yes, I (JanHinzmann) did that! See WebServiceServer for a SOAP-Example.
How about the auto generation of the WSDL file?
Existing cocoon components
... related to web service intergration.