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.

  • JavaScript data type*

 

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.

Related Technologies

Articles

Axis DynamicInvoker

Discussions on Cocoon Dev Mailinglist

  • No labels