How to use SOAP to deliver a Cocoon report?

View: New views
6 Messages — Rating Filter:   Alert me  

How to use SOAP to deliver a Cocoon report?

by David Beasley-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Can anyone help me with using the Axis-based Cocoon SOAP server?

I want to be able to deliver an XML-formatted report in response to a
SOAP request. I've written a pipeline that produces the report. Cocoon
will handle SOAP requests ok, but only as a Reader service (not a
Generator or Transformer). So, I'm trying to work out how I integrate
the SOAP request with the report-generating pipeline I've written.

It seems to me that I need to write some java code, to be invvoked by
the SOAP request, and have this code itself invoke Cocoon to generate
the XML report - which the java code then includes in the body of the
SOAP response.

Is this the best way to do it? And if so, does anyone have any
hints/tips/sample code?

Or is there some other way to integrate the result of a Cocoon pipeline
with the response to a SOAP request, that doesnt involve calling out to
a java routine which then calls back into Cocoon?

I'm thinking that life might be easier if there were a separate SOAP
Generator and SOAP Serializer, and I could then plug my
report-generating pipeline into the middle. Or is it not as simple as that?

David Beasley


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


Re: How to use SOAP to deliver a Cocoon report?

by Alexander Daniel :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 24.09.2009, at 17:56, David Beasley wrote:

> Can anyone help me with using the Axis-based Cocoon SOAP server?
>
> I want to be able to deliver an XML-formatted report in response to  
> a SOAP request. I've written a pipeline that produces the report.  
> Cocoon will handle SOAP requests ok, but only as a Reader service  
> (not a Generator or Transformer). So, I'm trying to work out how I  
> integrate the SOAP request with the report-generating pipeline I've  
> written.
>
> It seems to me that I need to write some java code, to be invvoked  
> by the SOAP request, and have this code itself invoke Cocoon to  
> generate the XML report - which the java code then includes in the  
> body of the SOAP response.
>
> Is this the best way to do it? And if so, does anyone have any hints/
> tips/sample code?
>
> Or is there some other way to integrate the result of a Cocoon  
> pipeline with the response to a SOAP request, that doesnt involve  
> calling out to a java routine which then calls back into Cocoon?
>
> I'm thinking that life might be easier if there were a separate SOAP  
> Generator and SOAP Serializer, and I could then plug my report-
> generating pipeline into the middle. Or is it not as simple as that?
>
> David Beasley

I can you provide some sample code for a SOAP transformer which  
expects as input the SOAP request surrounded by a special element  
which attributes specify the endpoint and the soapAction. The input is  
replaced by the SOAP response of the server.

Sitemap:
<map:generate src="soapRequest.xml"/>
<map:transform type="soap"/>
<map:serialize type="xml"/>

Sample soapRequest.xml:
<soapTransformer:call endpointUri="http://www50.brinkster.com/vbfacileinpt/np.asmx 
" soapAction="http://microsoft.com/webservices/GetPrimeNumbers"  
xmlns:soapTransformer="http://cocoon.apache.org/transformation/soap/ 
1.0">
        <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/ 
">
                <SOAP-ENV:Header/>
                <SOAP-ENV:Body>
                        <GetPrimeNumbers xmlns="http://microsoft.com/webservices/">
                                <max>11</max>
                        </GetPrimeNumbers>
                </SOAP-ENV:Body>
        </SOAP-ENV:Envelope>
</soapTransformer:call>

public class SoapTransformer extends AbstractSAXTransformer {

        private SoapClient soapClient;
        private String endpointUri;
        private String soapAction;

        public SoapTransformer() {
                defaultNamespaceURI = "http://cocoon.apache.org/transformation/soap/1.0 
";
        }

        @Override
        public void startTransformingElement(String uri, String name, String  
raw, Attributes attr) throws ProcessingException, IOException,  
SAXException {
                endpointUri = attr.getValue("endpointUri");
                soapAction = attr.getValue("soapAction");
                startSerializedXMLRecording(null);
        }

        @Override
        public void endTransformingElement(String uri, String name, String  
raw) throws ProcessingException, IOException, SAXException {
                String soapRequest = endSerializedXMLRecording();
                String soapResponse = getSoapClient().call(endpointUri, soapAction,  
soapRequest);
                toSax(soapResponse);
        }

        private void toSax(String soapResponse) throws SAXException,  
IOException {
                XMLReader xmlReader = XMLReaderFactory.createXMLReader();
                xmlReader.setContentHandler(contentHandler);
                xmlReader.parse(new InputSource(new StringReader(soapResponse)));
        }

        public void setSoapClient(SoapClient soapClient) {
                this.soapClient = soapClient;
        }

        public SoapClient getSoapClient() {
                return soapClient;
        }

}

public interface SoapClient {
        public String call(String endpointUri, String soapAction, String  
soapRequest);
}

public class SoapClientImpl implements SoapClient {

        private static final String ENCODING = "utf-8";

        @Override
        public String call(String endpointUri, String soapAction, String  
soapRequest) {
                try {
                        HttpURLConnection httpConn = createHttpConnection(endpointUri);
                        configureHttpHeaders(httpConn, soapAction, soapRequest);

                        OutputStream out = httpConn.getOutputStream();
                        out.write(soapRequest.getBytes(ENCODING));
                        out.close();
                       
                        return IOUtils.toString(httpConn.getInputStream(), ENCODING);
                } catch (Exception e) {
                        throw new SoapException(String.format("SOAP call to %s failed:  
soapAction='%s', soapRequest='%s'", endpointUri, soapAction,  
soapRequest), e);
                }
        }

        private void configureHttpHeaders(HttpURLConnection httpConn, String  
soapAction, String soapRequest) throws UnsupportedEncodingException,  
ProtocolException {
                httpConn.setRequestProperty("Content-Length", String.valueOf
(soapRequest.getBytes(ENCODING).length));
                httpConn.setRequestProperty("Content-Type", "text/xml; charset=" +  
ENCODING);
                httpConn.setRequestProperty("SOAPAction", soapAction);
                httpConn.setRequestMethod("POST");
                httpConn.setDoOutput(true);
                httpConn.setDoInput(true);
        }

        private HttpURLConnection createHttpConnection(String endpointUri)  
throws MalformedURLException, IOException {
                URL url = new URL(endpointUri);
                URLConnection connection = url.openConnection();
                HttpURLConnection httpConn = (HttpURLConnection) connection;
                return httpConn;
        }

}

Alex


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


Re: How to use SOAP to deliver a Cocoon report?

by Andreas Kuehne-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Alexander,

I didn't get your solution right, I guess ... as far as I understand Davids use case he will get a soap request, want's to fiddle out some parameters and return a report wrapped as a soap response. This fits into these sparse lines of sitemap :

             <map:generate type="stream"/>
              <map:transform src="soapInput.xsl"/>  <!-- check input and extract relevant values -->
              <map:transform type="cinclude"/> <!-- read the report content from another matcher ... -->
              <map:transform src="styles/soapOutput.xsl"/> <!-- wrap content into response -->
              <map:serialize type="xml"/>

We got some good results with this simple approach.
When it comes to web service security or big amount of base64-encoded data there is more effort required. We already did this and are happy to share it with any interested project.

But doesn't your solution show a way to _call_, not to _supply_ a web service ?

Greetings

Andreas



----- Original Message ----
From: Alexander Daniel <alexander.daniel@...>
To: users@...
Sent: Sunday, September 27, 2009 10:09:08 PM
Subject: Re: How to use SOAP to deliver a Cocoon report?

On 24.09.2009, at 17:56, David Beasley wrote:

> Can anyone help me with using the Axis-based Cocoon SOAP server?
>
> I want to be able to deliver an XML-formatted report in response to a SOAP request. I've written a pipeline that produces the report. Cocoon will handle SOAP requests ok, but only as a Reader service (not a Generator or Transformer). So, I'm trying to work out how I integrate the SOAP request with the report-generating pipeline I've written.
>
> It seems to me that I need to write some java code, to be invvoked by the SOAP request, and have this code itself invoke Cocoon to generate the XML report - which the java code then includes in the body of the SOAP response.
>
> Is this the best way to do it? And if so, does anyone have any hints/tips/sample code?
>
> Or is there some other way to integrate the result of a Cocoon pipeline with the response to a SOAP request, that doesnt involve calling out to a java routine which then calls back into Cocoon?
>
> I'm thinking that life might be easier if there were a separate SOAP Generator and SOAP Serializer, and I could then plug my report-generating pipeline into the middle. Or is it not as simple as that?
>
> David Beasley

I can you provide some sample code for a SOAP transformer which expects as input the SOAP request surrounded by a special element which attributes specify the endpoint and the soapAction. The input is replaced by the SOAP response of the server.

Sitemap:
<map:generate src="soapRequest.xml"/>
<map:transform type="soap"/>
<map:serialize type="xml"/>

Sample soapRequest.xml:
<soapTransformer:call endpointUri="http://www50.brinkster.com/vbfacileinpt/np.asmx" soapAction="http://microsoft.com/webservices/GetPrimeNumbers" xmlns:soapTransformer="http://cocoon.apache.org/transformation/soap/1.0">
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
        <SOAP-ENV:Header/>
        <SOAP-ENV:Body>
            <GetPrimeNumbers xmlns="http://microsoft.com/webservices/">
                <max>11</max>
            </GetPrimeNumbers>
        </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
</soapTransformer:call>

public class SoapTransformer extends AbstractSAXTransformer {

    private SoapClient soapClient;
    private String endpointUri;
    private String soapAction;

    public SoapTransformer() {
        defaultNamespaceURI = "http://cocoon.apache.org/transformation/soap/1.0";
    }

    @Override
    public void startTransformingElement(String uri, String name, String raw, Attributes attr) throws ProcessingException, IOException, SAXException {
        endpointUri = attr.getValue("endpointUri");
        soapAction = attr.getValue("soapAction");
        startSerializedXMLRecording(null);
    }

    @Override
    public void endTransformingElement(String uri, String name, String raw) throws ProcessingException, IOException, SAXException {
        String soapRequest = endSerializedXMLRecording();
        String soapResponse = getSoapClient().call(endpointUri, soapAction, soapRequest);
        toSax(soapResponse);
    }

    private void toSax(String soapResponse) throws SAXException, IOException {
        XMLReader xmlReader = XMLReaderFactory.createXMLReader();
        xmlReader.setContentHandler(contentHandler);
        xmlReader.parse(new InputSource(new StringReader(soapResponse)));
    }

    public void setSoapClient(SoapClient soapClient) {
        this.soapClient = soapClient;
    }

    public SoapClient getSoapClient() {
        return soapClient;
    }

}

public interface SoapClient {
    public String call(String endpointUri, String soapAction, String soapRequest);
}

public class SoapClientImpl implements SoapClient {

    private static final String ENCODING = "utf-8";

    @Override
    public String call(String endpointUri, String soapAction, String soapRequest) {
        try {
            HttpURLConnection httpConn = createHttpConnection(endpointUri);
            configureHttpHeaders(httpConn, soapAction, soapRequest);

            OutputStream out = httpConn.getOutputStream();
            out.write(soapRequest.getBytes(ENCODING));
            out.close();
           
            return IOUtils.toString(httpConn.getInputStream(), ENCODING);            
        } catch (Exception e) {
            throw new SoapException(String.format("SOAP call to %s failed: soapAction='%s', soapRequest='%s'", endpointUri, soapAction, soapRequest), e);
        }
    }

    private void configureHttpHeaders(HttpURLConnection httpConn, String soapAction, String soapRequest) throws UnsupportedEncodingException, ProtocolException {
        httpConn.setRequestProperty("Content-Length", String.valueOf(soapRequest.getBytes(ENCODING).length));
        httpConn.setRequestProperty("Content-Type", "text/xml; charset=" + ENCODING);
        httpConn.setRequestProperty("SOAPAction", soapAction);
        httpConn.setRequestMethod("POST");
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);
    }

    private HttpURLConnection createHttpConnection(String endpointUri) throws MalformedURLException, IOException {
        URL url = new URL(endpointUri);
        URLConnection connection = url.openConnection();
        HttpURLConnection httpConn = (HttpURLConnection) connection;
        return httpConn;
    }

}

Alex


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

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


Re: How to use SOAP to deliver a Cocoon report?

by Alexander Daniel :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 28.09.2009, at 09:50, Andreas Kuehne wrote:

> Hi Alexander,
>
> I didn't get your solution right, I guess ... as far as I understand  
> Davids use case he will get a soap request, want's to fiddle out  
> some parameters and return a report wrapped as a soap response. This  
> fits into these sparse lines of sitemap :

Hi Andreas,

I understood the use case of David differently: that he wants to  
generate a report based on a SOAP response from some Web service.

Now solutions for both uses cases are available :-)

Alex


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


Re: How to use SOAP to deliver a Cocoon report?

by David Beasley-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thanks for both your suggestions; Andreas' idea was what I was looking
for - a way to create a pipeline in Cocoon that takes a SOAP request as
an input XML document, and performs various transformations so as to
turn that into as SOAP response XML document. Yes, I can see now how it
could be done - but on second thoughts, I'm not sure that its a sensible
way to do it. This approach doesnt use the Axis Block, so I would have
to re-implement much of the functionality that Axis provides.

Andreas, I'm interested to know how you see the relative pros/cons of
your approach compared with using Axis?

regards
David

Alexander Daniel wrote:

> On 28.09.2009, at 09:50, Andreas Kuehne wrote:
>
>> Hi Alexander,
>>
>> I didn't get your solution right, I guess ... as far as I understand
>> Davids use case he will get a soap request, want's to fiddle out some
>> parameters and return a report wrapped as a soap response. This fits
>> into these sparse lines of sitemap :
>
> Hi Andreas,
>
> I understood the use case of David differently: that he wants to
> generate a report based on a SOAP response from some Web service.
>
> Now solutions for both uses cases are available :-)

--
David Beasley


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


Re: How to use SOAP to deliver a Cocoon report?

by David Beasley-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Andreas,

Having taken a closer look at what's involved in using Axis, I'm coming
back to the idea of just using a cocoon pipeline, as you suggest below.
I'd be grateful if you have any further sample code you could share with me.

regards
David

Andreas Kuehne wrote:

> ... as far as I understand Davids use case he will get a soap request, want's to fiddle out some parameters and return a report wrapped as a soap response. This fits into these sparse lines of sitemap :
>
>              <map:generate type="stream"/>
>               <map:transform src="soapInput.xsl"/>  <!-- check input and extract relevant values -->
>               <map:transform type="cinclude"/> <!-- read the report content from another matcher ... -->
>               <map:transform src="styles/soapOutput.xsl"/> <!-- wrap content into response -->
>               <map:serialize type="xml"/>
>
> We got some good results with this simple approach.
> When it comes to web service security or big amount of base64-encoded data there is more effort required. We already did this and are happy to share it with any interested project.


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