FYI - I was playing with the Axis block earlier in the week (which is where I need to use the variable resolver). I discovered a couple things: 1. Some of the classes are still using Composable. I've converted them all to Servicable in my sandbox and can check them in tomorrow if noone objects. This might break code for anyone using the Axis block though. 2. We were trying to use an XML schema to validate the incoming SOAP request without parsing it twice. I discovered that we can replace the SAX parser factory so that we can set the schema location and other features that need to be set. I haven't actually finished doing this as we decided to take another approach, but I'd be happy to finish this if anyone is interested in it.

Ralph

Carsten Ziegeler wrote:

Stephan Zuercher wrote:
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.

Hi Stephan,

yes, I think this is a nice feature and I'm interested to have a look at
it. I think you're right with your assumption about the axis block.
However I think your contribution should go into the axis block as well
to bundle all ws related stuff in one place.
Can you please file everything into bugzilla?

Thanks for your contribution
Carsten


Reply via email to