cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stephan Zuercher <zuerc...@gmail.com>
Subject Proposal: Document-based SOAP generator and serializer
Date Mon, 29 Aug 2005 19:15:00 GMT
Hi all,
 As part of a project for my employer, I've developed a "SOAPGenerator" and 
"SOAPSerializer" that support creating pipelines that accept and process 
SOAP document style requests. My employer has given me the okay to 
contribute these to the Cocoon project. This e-mail is intended to describe 
the components I've created, explain why they're different from the existing 
Axis block, and solicit responses from the community as to whether this is 
generally useful functionality suitable for inclusion into Cocoon.
 First off, let me describe the use case this set of components is meant to 
solve. My employer currently serves some reports out of Cocoon generated by 
standard pipelines that access a database and perform various 
transformations. The URL of the report contains a pair of keys ( e.g. 
http://server/cocoon/report/KEY1/KEY2) and returns HTML content. In the near 
future, we'd like to return the report's contents in XML, and furthermore 
we'd like to obtain the report contents via a SOAP request. Not all Cocoon 
pipeline developers in our organization are up to speed on SOAP, so we 
desire a way to let them write pipelines that serve SOAP requests without 
having to deal with the SOAP envelope and its details.
 At first glance, we could create pipelines like this: 
 <map:pipeline>
 <map:match pattern="soap-based-report">
 <map:generate type="stream"/>
 <map:transform src="remove-soap-envelope.xsl"/>
  <!-- generate the report XML -->
 <map:transform .../>
  <map:transform src="wrap-with-soap-envelope.xsl"/>
 <map:serialize type="xml"/>
 </map:match>
</map:pipeline>
 This has some limitations. First, the StreamGenerator and "
remove-soap-envelope.xsl" don't insure that the request is actually a 
properly formed SOAP request, nor do they verify the type of request (RPC, 
document). The SOAP client can send any method name and if it sets 
'mustUnderstand="true"' in any SOAP headers, it will be silently ignored. 
Hence our SOAP implementation isn't compliant with the SOAP standard.
 Instead, we provide a SOAPGenerator and SOAPSerializer to handle these 
details: 
 <map:pipeline>
 <map:match pattern="soap-based-report">
 <map:generate type="soap">
 <parameter
 name="method-names"
 value="\{http://report.soap.employer.com\}process"/<http://report.soap.employer.com/}process"/>
>
 </map:generate>
  <!-- generate the report XML -->
 <map:transform .../>
  <map:serialize type="soap"/>
 </map:match>
</map:pipeline>
 This limits the pipeline author's knowledge of SOAP to the name of the SOAP 
method. The SOAPGenerator throws ProcessingException if the request is not 
made to the correct operation (the namespace-qualified element process in 
the example; this can be a list of names) or is not a SOAP document request. 
It also throws if there are any "mustUnderstand" SOAP headers. It's my 
understanding of the SOAP standard that headers not marked as 
"mustUnderstand" can be ignored. If anyone has any ideas on how to do more 
sophisticated SOAP header handling, I'm open to changing how this works.
 The SOAPSerializer simply wraps the response document in a SOAP envelope 
and body. I've also written some XSL templates that convert Cocoon 
exceptions into SOAP client or server faults. These are used in 
<map:handle-errors/> to generate SOAP error messages. 
 Finally, I've written a RequestParameterRegexSelector that extends 
RequestParameterSelector to allow the test expressions to be regular 
expressions. We use this to return WSDL, when appropriate. The 
RequestParameterSelector can be used for this, but if ever someone requested 
http://server/cocoon/soap-service?wsdl=yes, it would attempt to execute the 
service rather than returning the WSDL. 
 <map:pipeline>
 <map:match pattern="soap-service">
 <map:select type="request-parameter-regex">
 <map:parameter name="parameter-name" value="wsdl"/>
  <!-- if the URL parameter "wsdl" exists, return the .wsdl file; 
 regular request-parameter selector cannot discern between
 missing param and param with no value -->
 <map:when test=".*">
 <map:generate src="service.wsdl"/>
 <map:serialize type="xml"/>
 </map:when>
  <map:otherwise>
 <!-- SOAP process as above -->
 </map:otherwise>
 </map:select>
 </map:match>
</map:pipeline>
 The proposed generator and serializer are different from the existing Axis 
block because they allow the web service itself to be implemented as a 
Cocoon pipeline. It seems to me that the Axis block allows an existing SOAP 
service to be executed via a reader and allows calls to external SOAP 
services to be made. Our reports lend themselves to being written as Cocoon 
pipelines, so it seems wasteful to recreate them as SOAP services and just 
pass their output through Cocoon. 
 Thanks for making it this far. I tried to be as brief as I could. :-) 
Please let me know if you'd like to see this submitted as a contribution to 
Cocoon. If so, I'll do the necessary clean up (making sure it matches 
Cocoon's coding standards, unit tests and such) and submit it via bugzilla. 
 Thanks for your consideration.
 Stephan Zuercher

Mime
View raw message