You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cocoon.apache.org by Jan Hinzmann <ja...@geeksonly.de> on 2005/03/30 10:59:05 UTC

cocoon as webservice (SOAP-Server)

Hi *,

I'm working on a little Webservice and I'm needing help on generating and
serializing xml-content from the flowscript to the sitemap and viceversa.

My approach is to generate a received SOAP-Envelope with a StreamGenerator and 
extracting the called method and the arguments using xslt and flow. Then I will 
be using the flowscript to compute the request and finally serialize an 
answer-envelope to the client.

For the ones of you who are in a hurry: go to the bottom of this mail to find my 
questions.


Let me introduce a (little) example (I'm sorry, it has become a bit bigger than 
I expected. But I hope it is worth reading it):

Imagine, there is a little Webservice, which has a echo-method:

public class Webservice(){
	public synchronised String echo(String echo){
		return echo;
	}
}

Now customers are sending SOAP-envelopes (using a middleware like axis) like the 
following:

   <?xml version="1.0" encoding="ISO-8859-1"?>
   <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <soapenv:Body>
       <ns1:echo soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="CodataWS">
         <ns1:arg0 xsi:type="xsd:string">Hello Echo!?</ns1:arg0>
       </ns1:echo>
     </soapenv:Body>
   </soapenv:Envelope>

this I'm generating with a org.apache.cocoon.generation.StreamGenerator and
forward it from the sitemap to the flowscript with:

<!-- == Webservice by Cocoon == -->
       <map:pipeline>
       	<map:match pattern="webservice">
       		<map:call function="mainWS"/>
       	</map:match>
	
	<!-- getting the soap-envelope -->
       	<map:match pattern="soapData">
       		<map:generate type="stream"/>
             <map:serialize type="xml"/>
       	</map:match>
...

The first matcher calls a flowscript, which will request the envelope and save 
it in an ByteArrayOutputStream using the second matcher:

   function mainWS(){
	var soapData     = new java.io.ByteArrayOutputStream();
	
	clog("SOAP-envelope received, processing the request:\n");
	
	//getting the envelope out of the request (can be done only once)
	cocoon.processPipelineTo("soapData", null, soapData);
	clog("Request was:\n" + soapData + "\n");
   ...

now that I have saved the soapData in an ByteArrayOutputStream, I'm sending it
back to the Sitemap, to get the Method out of the envelope ('echo' in this case) 
using xslt:

   var soapMethod   = new java.io.ByteArrayOutputStream();
   cocoon.processPipelineTo("soapMethod", {"soapData":soapData}, soapMethod);	
   clog("soapMethod: " + soapMethod + "\n");

OR
   var soapMethod   = new java.io.ByteArrayOutputStream();
   var pipeutil = 
cocoon.createObject(Packages.org.apache.cocoon.components.flow.util.PipelineUtil);
   pipeutil.processToStream("soapMethod",  {"soapData":soapData}, soapMethod);	
	
both methods seem to affect the same(?)

Back in the sitemap I've tried to generate this parameter with

   <!-- which Method is called? -->
   <map:match pattern="soapMethod">
     <map:generate type="stream" src="{flow-attribute:soapData}"/>
   ...

but that doesn't seem to work. Here (and generally :)) I would appreciate any 
suggestions!

For now I'm passing the content as parameter to the transformation:

   <!-- which Method is called? -->
   <map:match pattern="soapMethod">
     <map:generate src="xml/dummy.xml"/>
     <map:transform src="xsl/soapMethod.xsl">
       <map:parameter name="soapData" value="{flow-attribute:soapData}"/>
     </map:transform>
     <map:transform src="xsl/soapMethodNow.xsl"/>
     <map:serialize type="xml"/>
   </map:match>

the two stylesheets should extract the name of the method to be called (this 
will be found as local-name() in the first node after /Envelope/Body) and 
therefore looks like:

the first stylesheet should simply inject the soap-envelope-content soapMethod.xsl:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml"/>
   <xsl:param name="soapData"/>
	
   <xsl:template match="/">
	<xsl:value-of select="$soapData"/>
   </xsl:template>

</xsl:stylesheet>

and the second one should lookup the methodname
soapMethodNow.xsl:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="text"/>
	
	<xsl:template match="/Envelope/Body">
		<xsl:apply-templates/>
	</xsl:template>
	
	<xsl:template match="*[1]">
		<xsl value-of select="local-name()"/>
	</xsl:template>

</xsl:stylesheet>

strangely the first stylesheet produces output like:

  <?xml version="1.0" encoding="ISO-8859-1"?>
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
&lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
  &lt;soapenv:Body&gt;
   &lt;ns1:echo 
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:ns1="CodataWS"&gt;
    &lt;ns1:arg0 xsi:type="xsd:string"&gt;Hello Echo!?&lt;/ns1:arg0&gt;
   &lt;/ns1:echo&gt;
  &lt;/soapenv:Body&gt;
&lt;/soapenv:Envelope&gt;

So why are the '<' and '>' are replaced with there corresponding htmlthingies?


What do you think about this approach?
Any suggestions are welcome.

-- 
Gruss, Jan Hinzmann




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@cocoon.apache.org
For additional commands, e-mail: users-help@cocoon.apache.org


Re: cocoon as webservice (SOAP-Server)

Posted by Jan Hinzmann <ja...@geeksonly.de>.
Me again :)

I had a lot of thinking today and a lot of help from the irc 
(irc.freenode.net#cocoon). Thanks joose and ugocei!

since it is kind of working now, i have set up a wikipage and hope. its not that 
  crappy:

	http://wiki.apache.org/cocoon/WebServiceServer

hth, jan

Jan Hinzmann wrote:
> Hi *,
> 
> I'm working on a little Webservice and I'm needing help on generating and
> serializing xml-content from the flowscript to the sitemap and viceversa.
> 
> My approach is to generate a received SOAP-Envelope with a 
> StreamGenerator and extracting the called method and the arguments using 
> xslt and flow. Then I will be using the flowscript to compute the 
> request and finally serialize an answer-envelope to the client.
> 
> For the ones of you who are in a hurry: go to the bottom of this mail to 
> find my questions.
> 
> 
> Let me introduce a (little) example (I'm sorry, it has become a bit 
> bigger than I expected. But I hope it is worth reading it):
> 
> Imagine, there is a little Webservice, which has a echo-method:
> 
> public class Webservice(){
>     public synchronised String echo(String echo){
>         return echo;
>     }
> }
> 
> Now customers are sending SOAP-envelopes (using a middleware like axis) 
> like the following:
> 
>   <?xml version="1.0" encoding="ISO-8859-1"?>
>   <soapenv:Envelope 
> xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
> xmlns:xsd="http://www.w3.org/2001/XMLSchema"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
>     <soapenv:Body>
>       <ns1:echo 
> soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
> xmlns:ns1="CodataWS">
>         <ns1:arg0 xsi:type="xsd:string">Hello Echo!?</ns1:arg0>
>       </ns1:echo>
>     </soapenv:Body>
>   </soapenv:Envelope>
> 
> this I'm generating with a org.apache.cocoon.generation.StreamGenerator and
> forward it from the sitemap to the flowscript with:
> 
> <!-- == Webservice by Cocoon == -->
>       <map:pipeline>
>           <map:match pattern="webservice">
>               <map:call function="mainWS"/>
>           </map:match>
>     
>     <!-- getting the soap-envelope -->
>           <map:match pattern="soapData">
>               <map:generate type="stream"/>
>             <map:serialize type="xml"/>
>           </map:match>
> ...
> 
> The first matcher calls a flowscript, which will request the envelope 
> and save it in an ByteArrayOutputStream using the second matcher:
> 
>   function mainWS(){
>     var soapData     = new java.io.ByteArrayOutputStream();
>     
>     clog("SOAP-envelope received, processing the request:\n");
>     
>     //getting the envelope out of the request (can be done only once)
>     cocoon.processPipelineTo("soapData", null, soapData);
>     clog("Request was:\n" + soapData + "\n");
>   ...
> 
> now that I have saved the soapData in an ByteArrayOutputStream, I'm 
> sending it
> back to the Sitemap, to get the Method out of the envelope ('echo' in 
> this case) using xslt:
> 
>   var soapMethod   = new java.io.ByteArrayOutputStream();
>   cocoon.processPipelineTo("soapMethod", {"soapData":soapData}, 
> soapMethod);   
>   clog("soapMethod: " + soapMethod + "\n");
> 
> OR
>   var soapMethod   = new java.io.ByteArrayOutputStream();
>   var pipeutil = 
> cocoon.createObject(Packages.org.apache.cocoon.components.flow.util.PipelineUtil); 
> 
>   pipeutil.processToStream("soapMethod",  {"soapData":soapData}, 
> soapMethod);   
>     
> both methods seem to affect the same(?)
> 
> Back in the sitemap I've tried to generate this parameter with
> 
>   <!-- which Method is called? -->
>   <map:match pattern="soapMethod">
>     <map:generate type="stream" src="{flow-attribute:soapData}"/>
>   ...
> 
> but that doesn't seem to work. Here (and generally :)) I would 
> appreciate any suggestions!
> 
> For now I'm passing the content as parameter to the transformation:
> 
>   <!-- which Method is called? -->
>   <map:match pattern="soapMethod">
>     <map:generate src="xml/dummy.xml"/>
>     <map:transform src="xsl/soapMethod.xsl">
>       <map:parameter name="soapData" value="{flow-attribute:soapData}"/>
>     </map:transform>
>     <map:transform src="xsl/soapMethodNow.xsl"/>
>     <map:serialize type="xml"/>
>   </map:match>
> 
> the two stylesheets should extract the name of the method to be called 
> (this will be found as local-name() in the first node after 
> /Envelope/Body) and therefore looks like:
> 
> the first stylesheet should simply inject the soap-envelope-content 
> soapMethod.xsl:
> 
> <?xml version="1.0"?>
> <xsl:stylesheet version="1.0" 
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
>   <xsl:output method="xml"/>
>   <xsl:param name="soapData"/>
>     
>   <xsl:template match="/">
>     <xsl:value-of select="$soapData"/>
>   </xsl:template>
> 
> </xsl:stylesheet>
> 
> and the second one should lookup the methodname
> soapMethodNow.xsl:
> 
> <?xml version="1.0"?>
> <xsl:stylesheet version="1.0" 
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
>     <xsl:output method="text"/>
>     
>     <xsl:template match="/Envelope/Body">
>         <xsl:apply-templates/>
>     </xsl:template>
>     
>     <xsl:template match="*[1]">
>         <xsl value-of select="local-name()"/>
>     </xsl:template>
> 
> </xsl:stylesheet>
> 
> strangely the first stylesheet produces output like:
> 
>  <?xml version="1.0" encoding="ISO-8859-1"?>
> &lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
> &lt;soapenv:Envelope 
> xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
> xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
>  &lt;soapenv:Body&gt;
>   &lt;ns1:echo 
> soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
> xmlns:ns1="CodataWS"&gt;
>    &lt;ns1:arg0 xsi:type="xsd:string"&gt;Hello Echo!?&lt;/ns1:arg0&gt;
>   &lt;/ns1:echo&gt;
>  &lt;/soapenv:Body&gt;
> &lt;/soapenv:Envelope&gt;
> 
> So why are the '<' and '>' are replaced with there corresponding 
> htmlthingies?
> 
> 
> What do you think about this approach?
> Any suggestions are welcome.
> 

-- 
Gruss, Jan Hinzmann

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@cocoon.apache.org
For additional commands, e-mail: users-help@cocoon.apache.org