If you have a svn diff, please attach it to a JIRA whenever you have some
time and i'll take a close look, but it sounds like a reasonable enhancement
to the JAXPXPathExpression.

On Thu, Apr 3, 2008 at 9:33 PM, Tom Purcell <[EMAIL PROTECTED]>
wrote:

>
> Guillaume
>
> I've made some progress. This is what I did.
>
> First, I switched to JAXP instead of Jaxen. The ONLY reason for this is
> I'm
> on a corporate network and they will not allow access to any URL with the
> "jaxen" in it thus making research difficult. (not your problem, just
> venting).
>
> I understood what you were saying about using a SourceTransformer instead
> of
> toString() but the problem is that by the time my getContentToSend() gets
> the result of the XPath evaluation it is already a String with the XML
> tags
> stripped out.
>
> In the SMX JAXPXPathExpression class the evaluateXPath(Object object)
> method
> calls the javax.xml.xpath.XPathExpression evaluate(object) method. There
> are
> four implementations of that method in XPathExpression. The one being
> called
> in the SMX JAXPXPathExpression class returns a String. This String
> contains
> the VALUEs only, not the tags. This is great when you need a value to
> build
> a URL but not when you need the actual XML.
>
> I need the NodeSet. Another version of the XPathExpression evaluate
> method,
> evaluate(object, returnType), allows you to control the return type but
> the
> SMX JAXPXPathExpression does not expose a way to call it. I went into the
> SMX JAXPXPathExpression class and did the following:
>
> Changed:
> protected Object evaluateXPath(Object object) throws
> XPathExpressionException
> To:
> protected Object evaluateXPath(Object object, QName returnType) throws
> XPathExpressionException
>
> Added:
> public Object evaluate(MessageExchange exchange, NormalizedMessage
> message,
> QName returnType) throws MessagingException
>
> Changed:
> public Object evaluate(MessageExchange exchange, NormalizedMessage
> message)
> throws MessagingException
> To call the new version above. It passes in XPathConstants.STRING as the
> QName to provide backward compatibility.
>
> In my new RestProviderMarshaler:
> protected String getContentToSend(MessageExchange exchange,
> NormalizedMessage inMsg) throws Exception {
>   String content = null;
>
>   if (contentExpression != null) {
>       logger.debug("*** Evaluate toString: " +
> contentExpression.evaluate(exchange, inMsg));
>      Node node = (Node)contentExpression.evaluate(exchange, inMsg,
> XPathConstants.NODE);
>      content =  transformer.toString(new DOMSource(node));
>      logger.debug("*** Content toString: " + content);
>    }
>
>   if (content == null) {
>            throw new IllegalStateException("Unable to find Content for
> exchange");
>   }
>   return content;
> }
>
> NOTE:
> I have two calls to contentExpression.evaluate() method in
> JAXPXPathExpression. The first is just in the debug and is there to
> demonstrate the backward compatibility call. This is what it produces in
> the
> log (No XML Tags):
>
> 14:21:31,263 - DEBUG - RestProviderMarshaler          - *** Evaluate
> toString:  ServerAsset This is a Test ServerAsset, created from
> TestAssetPersistenceTwo. SGNS-0202 true true     REDHAT LINUX
> testserverassetc092803e-f2bd-9cb4-1f34-1da6f42053f1 sgns.net OS64 5.0.1
> 001
> 2048 2
>
> With the call to the new version (contentExpression.evaluate(exchange,
> inMsg, XPathConstants.NODE)) produces this (A nice healthy chunk of XML):
>
> 14:21:31,268 - DEBUG - RestProviderMarshaler          - *** Content
> toString: <?xml version="1.0" encoding="UTF-8"?><asset
> name="TestServerAsset1207250490590"> <class_type>ServerAsset</class_type>
> <description>This is a Test ServerAsset, created from
> TestAssetPersistenceTwo.</description>
> <serial_number>SGNS-0202</serial_number> <enabled>true</enabled>
> <managed>true</managed> <category
> guid="42E213B8-3F31-E288-05A7-7D855CF32329" value="Default"/> <type
> guid="30E6FD81-2D8E-B45B-CA53-703ADEDA3BDB" value="Default"/> <state
> guid="26BC358E-9F90-FE7F-5199-01DB9FBB72FE" value="Default"/> <mfgName/>
> <os>REDHAT LINUX</os>
> <host_name>testserverassetc092803e-f2bd-9cb4-1f34-1da6f42053f1</host_name>
> <domain_name>sgns.net</domain_name> <platform>OS64</platform>
> <os_version>5.0.1</os_version> <os_patch_level>001</os_patch_level>
> <memory>2048</memory> <cpus>2</cpus> </asset>
>
> I'm not out of the woods yet. My POST is getting to the webapp and the
> webapp is updating the database but things fall apart on the response. I'm
> not certain at this point whether its an issue with the wepapp's response
> or
> SMX's handling it or a little of both. I'll let you know what I find out.
>
> On the JAXPXPathExpression code, if there is another approach you think I
> should take or you'd like to get the code let me know.
>
> Thanks
> Tom
>
>
>
>
>
>
>
>
>
> Tom Purcell wrote:
> >
> > Guillaume
> >
> > Thabnks for the input. Responses inline
> >
> > gnodet wrote:
> >>
> >> Have you tried using the JaxenXPathExpression instead of the
> >> JaxenStringXPathExpression ?
> >>
> >> Yes, I got the same result.
> >>
> >> Also, I think you need to change the getContentToSend() method because
> >> using
> >> toString() on the result won't work.  Try using the
> >> org.apache.servicemix.jbi.jaxp.*SourceTransformer* to convert the DOM
> >> node
> >> to a String instead.
> >>
> >> Okay, I'll play with this but the call to contentExpression.evaluate()
> in
> >> getContentToSend() returns a String object. At any rate I'll give it a
> >> shot and let you know how it goes.
> >>
> >> Thanks
> >> Tom
> >>
> >> On Wed, Apr 2, 2008 at 11:27 PM, Tom Purcell
> >> <[EMAIL PROTECTED]>
> >> wrote:
> >>
> >>>
> >>> Guillaume
> >>>
> >>> Below is all of what I'm doing. Notice in the logs at the bottom that
> >>> what
> >>> comes in on the NM is of type DOMSource but the object returned by the
> >>> contentExpression.evaluate() method is of type String. I think it want
> I
> >>> want is for that to be a DOMSource too. I also see the "Content is not
> >>> allowed in prolog" meesage but I think that is caused by the fact that
> >>> my
> >>> content is just the values and not the XML.
> >>>
> >>> Here's the xbean config:
> >>>
> >>>    <http:provider service="wile:wileRestService"
> >>>                   interfaceName="wileCreate"
> >>>                   endpoint="wileRestCreate"
> >>>                   marshaler="#createMarshaler"/>
> >>>
> >>>    <bean id="createMarshaler"
> class="jbi.marshal.RestProviderMarshaler">
> >>>        <property name="locationURIExpression">
> >>>            <bean
> >>> class="org.apache.servicemix.expression.JaxenStringXPathExpression">
> >>>                <constructor-arg
> >>> value="concat('
> >>> http://localhost:8080/wile-www/assetmanagement/assetservice/
> >>> ',/assetRequest/perspective)"/>
> >>>            </bean>
> >>>        </property>
> >>>        <property name="method"
> >>>                  value="POST"/>
> >>>        <property name="contentType"
> >>>                  value="application/x-www-form-urlencoded"/>
> >>>        <property name="contentExpression">
> >>>            <bean
> >>> class="org.apache.servicemix.expression.JaxenStringXPathExpression">
> >>>                <constructor-arg value="//asset"/>
> >>>            </bean>
> >>>        </property>
> >>>    </bean>
> >>> </pre>
> >>>
> >>> In my RestProviderMarshaler class I added a property for
> >>> contentExpression
> >>> and replaced the createRequest method. Here are the relevant methods:
> >>>
> >>>    public void createRequest(MessageExchange exchange,
> NormalizedMessage
> >>> inMsg, SmxHttpExchange httpExchange) throws Exception {
> >>>        logger.debug("*** Before CREATE MessageExchange: " + exchange);
> >>>        logger.debug("*** NM In Content: " + inMsg.getContent());
> >>>        logger.debug("*** LocationURI: " + getLocationUri(exchange,
> >>> inMsg));
> >>>
> >>>        httpExchange.setURL(getLocationUri(exchange, inMsg));
> >>>        httpExchange.addRequestHeader(HttpHeaders.HOST_BUFFER, new
> >>> ByteArrayBuffer(new URI(getLocationUri(exchange, inMsg)).getHost()));
> >>>        httpExchange.setMethod(getMethod(exchange, inMsg));
> >>>        httpExchange.setRequestHeader(HttpHeaders.CONTENT_TYPE,
> >>> getContentType(exchange, inMsg));
> >>>
> >>>        if (getHeaders() != null) {
> >>>            for (Map.Entry<String, String> e : getHeaders().entrySet())
> {
> >>>                httpExchange.setRequestHeader(e.getKey(),
> e.getValue());
> >>>            }
> >>>        }
> >>>
> >>>        String contentToSend = getContentToSend(exchange, inMsg);
> >>>        logger.debug("*** Content: " + contentToSend);
> >>>
> >>>        if (contentToSend != null) {
> >>>            httpExchange.setRequestContent(new
> >>> ByteArrayBuffer(contentToSend.getBytes()));
> >>>        }
> >>>    }
> >>>
> >>>    protected String getContentToSend(MessageExchange exchange,
> >>> NormalizedMessage inMsg) throws Exception {
> >>>        String content = null;
> >>>        if (contentExpression != null) {
> >>>            Object o = contentExpression.evaluate(exchange, inMsg);
> >>>            logger.debug("*** Content Object Type: " + o.getClass());
> >>>            content = (o != null) ? o.toString() : null;
> >>>        }
> >>>        if (content == null) {
> >>>            throw new IllegalStateException("Unable to find Content for
> >>> exchange");
> >>>        }
> >>>        return content;
> >>>    }
> >>>
> >>> Here is what I see from the debugs:
> >>>
> >>> 16:18:59,407 - DEBUG - RestProviderMarshaler          - *** Before
> >>> CREATE
> >>> MessageExchange: InOut[
> >>>  id: ID:127.0.0.2-11910ec49ca-3:4
> >>>  status: Active
> >>>  role: provider
> >>>  service:
> >>> {http://www.sungard.com/wile}wileRestService<http://www.sungard.com/wile%7DwileRestService>
> <http://www.sungard.com/wile%7DwileRestService>
> >>>  endpoint: wileRestCreate
> >>>  in: <?xml version="1.0"
> >>> encoding="UTF-8"?><assetRequest><perspective>asset</perspective><asset
> >>> name="TestAsset"> <class_type>BigAsset</class_type> <description>This
> is
> >>> a
> >>> Test Asset</description> <serial_number>12345</serial_number>
> >>> <enabled>true</enabled> <category guid="67890" value="Default"/> <type
> >>> guid="09876" value="Default"/> <state guid="54321" value="Default"/>
> >>> </asset> </assetRequest>
> >>> ]
> >>> 16:18:59,408 - DEBUG - RestProviderMarshaler          - *** NM In
> >>> Content:
> >>> [EMAIL PROTECTED]
> >>> 16:18:59,408 - DEBUG - RestProviderMarshaler          - ***
> LocationURI:
> >>> http://localhost:8080/wile-www/assetmanagement/assetservice/asset
> >>> 16:18:59,409<
> http://localhost:8080/wile-www/assetmanagement/assetservice/asset16:18:59,409
> >-
> >>> DEBUG - RestProviderMarshaler          - *** Content Object
> >>> Type: class java.lang.String
> >>> 16:18:59,409 - DEBUG - RestProviderMarshaler          - *** Content:
> >>> BigAsset This is a Test Asset 12345 true
> >>> 16:18:59,446 - DEBUG - DeliveryChannelImpl            - Send
> >>> ID:127.0.0.2-11910ec49ca-3:4 in DeliveryChannel{servicemix-http}
> >>> [Fatal Error] :1:1: Content is not allowed in prolog.
> >>> 16:18:59,451 - TRACE - DeliveryChannelImpl            - Sent: InOut[
> >>>  id: ID:127.0.0.2-11910ec49ca-3:4
> >>>  status: Active
> >>>  role: provider
> >>>  service:
> >>> {http://www.sungard.com/wile}wileRestService<http://www.sungard.com/wile%7DwileRestService>
> <http://www.sungard.com/wile%7DwileRestService>
> >>>  endpoint: wileRestCreate
> >>>  in: <?xml version="1.0"
> >>> encoding="UTF-8"?><assetRequest><perspective>asset</perspective><asset
> >>> name="TestAsset"> <class_type>BigAsset</class_type> <description>This
> is
> >>> a
> >>> Test Asset</description> <serial_number>12345</serial_number>
> >>> <enabled>true</enabled> <category guid="67890" value="Default"/> <type
> >>> guid="09876" value="Default"/> <state guid="54321" value="Default"/>
> >>> </asset> </assetRequest>
> >>>  fault: Unable to display: org.xml.sax.SAXParseException: Content is
> not
> >>> allowed in prolog.
> >>> ]
> >>> 16:18:59,454 - DEBUG - SedaFlow                       - Called Flow
> send
> >>>
> >>> Thanks
> >>> Tom
> >>>
> >>>
> >>> gnodet wrote:
> >>> >
> >>> > I suppose the creation of the content does not support writing an
> xml
> >>> > element and maybe use toString() or something like that to create
> the
> >>> > content of the request.  Could you paste the endpoint definition and
> >>> > snippet
> >>> > of code, I'm not sure to fully understand your configuration.
> >>> > I think if you use a marshaler, you can really do anything you need.
> >>> I'm
> >>> > sure we could come with something reusable using an expression for
> the
> >>> > URL,
> >>> > the method and the content.
> >>> >
> >>> > On Wed, Apr 2, 2008 at 2:33 PM, Tom Purcell
> >>> > <[EMAIL PROTECTED]>
> >>> > wrote:
> >>> >
> >>> >>
> >>> >> Guillaume
> >>> >>
> >>> >> The message gets sent to the correct URI but the issue is the
> content
> >>> of
> >>> >> the
> >>> >> message. I need to send the XML (<foo>bar</foo>) but what gets
> >>> returned
> >>> >> by
> >>> >> contentExpression.evaluate(exchange, inMsg), subsequently sent to
> the
> >>> >> RESTful service, is just the values (bar).
> >>> >>
> >>> >> At this point I guess its really a Jaxen question. Can you get it
> to
> >>> >> return
> >>> >> the XML instead of just the values? Otherwise some other parsing
> >>> strategy
> >>> >> is
> >>> >> needed. However, I really liked the idea of just defining an XPath
> >>> >> expression on the endpoint. It seems it would make the marshaler
> >>> pretty
> >>> >> flexible.
> >>> >>
> >>> >> Thanks
> >>> >> Tom
> >>> >>
> >>> >>
> >>> >>
> >>> >> gnodet wrote:
> >>> >> >
> >>> >> > Well, it sounds realy good.
> >>> >> > What exactly does not work when using POST with your marshaler ?
> >>> >> >
> >>> >> > On Wed, Apr 2, 2008 at 12:00 AM, Tom Purcell
> >>> >> > <[EMAIL PROTECTED]>
> >>> >> > wrote:
> >>> >> >
> >>> >> >>
> >>> >> >> Guillaume
> >>> >> >>
> >>> >> >> Okay, I'm new to REST so I may be missing something there too
> but
> >>> this
> >>> >> is
> >>> >> >> where I'm at. SMX will receive a JMS message with an XML
> payload.
> >>> The
> >>> >> XML
> >>> >> >> will have two high level nodes. One node's value will be the
> >>> service
> >>> >> to
> >>> >> >> call
> >>> >> >> (will become part of the REST URL). The other node will be a big
> >>> chunk
> >>> >> of
> >>> >> >> XML to be POSTed to the service. The content-type is
> >>> >> >> x-www-form-urlencoded.
> >>> >> >>
> >>> >> >> I extended DefaultHttpProviderMarshaler and I call
> >>> >> >>
> httpExchange.setRequestContent(bigXmlChunkContentOfTheSecondNode).
> >>> >> >>
> >>> >> >> This almost works. I use JaxenStringXPathExpression to get the
> >>> value
> >>> >> of
> >>> >> >> the
> >>> >> >> first node and set the REST URL. Then my class has a new
> property,
> >>> >> >> contentExpression, also a JaxenStringXPathExpression. I use this
> >>> to
> >>> >> >> define
> >>> >> >> the XPath to the second node, the one with the big chunk of XML,
> >>> but
> >>> >> it
> >>> >> >> adds
> >>> >> >> the values of the second node. What I need is the chunk of XML,
> >>> >> elements,
> >>> >> >> attributes and all.
> >>> >> >>
> >>> >> >> I guess I could introduce a Saxon endpoint to do a
> transformation
> >>> and
> >>> >> a
> >>> >> >> router to send the message to different HTTP endpoints based on
> >>> the
> >>> >> first
> >>> >> >> node but that seems a lot less elegant than just dynamically
> >>> >> determining
> >>> >> >> the
> >>> >> >> REST URL in the marshaler. It works fine for GETs but then POST,
> >>> I'm
> >>> >> >> learning, is a different story.
> >>> >> >>
> >>> >> >> Any thoughts?
> >>> >> >>
> >>> >> >> Thanks
> >>> >> >> Tom
> >>> >> >>
> >>> >> >>
> >>> >> >> gnodet wrote:
> >>> >> >> >
> >>> >> >> > I really think the best way would be to create your own
> >>> marshaler
> >>> if
> >>> >> >> the
> >>> >> >> > default one does not work for you.  If you come up with
> >>> something
> >>> >> >> generic
> >>> >> >> > enough feel free to contribute it back.  However, the
> >>> >> >> > DefaultHttpProviderMarshaler should send a POST request if the
> >>> input
> >>> >> >> > message
> >>> >> >> > is not null, but this is more like a soap POST rather than a
> >>> form
> >>> >> post
> >>> >> >> > with
> >>> >> >> > key/value pairs.  Is that what you'd need ?  How do you
> extract
> >>> the
> >>> >> >> > key/value pairs from the exchange ?
> >>> >> >> >
> >>> >> >> > On Tue, Apr 1, 2008 at 3:26 PM, Tom Purcell
> >>> >> >> > <[EMAIL PROTECTED]>
> >>> >> >> > wrote:
> >>> >> >> >
> >>> >> >> >>
> >>> >> >> >> Hello
> >>> >> >> >>
> >>> >> >> >> I'm trying to use the servicemix-http http:provider to call a
> >>> >> RESTful
> >>> >> >> >> service. GET works fine but I'm having trouble trying to
> >>> configure
> >>> >> it
> >>> >> >> to
> >>> >> >> >> do
> >>> >> >> >> a post. It appears to me that DefaultHttpProviderMarshaler
> does
> >>> not
> >>> >> >> >> directly
> >>> >> >> >> support this and so I must write my own Marshaler to set the
> >>> >> content.
> >>> >> >> My
> >>> >> >> >> first question is just a request to verify that is correct
> and
> >>> that
> >>> >> >> I'm
> >>> >> >> >> not
> >>> >> >> >> missing something.
> >>> >> >> >>
> >>> >> >> >> My next question is about
> >>> >> >> >> http://issues.apache.org/activemq/browse/SM-580
> >>> >> >> >> SM-580 <http://issues.apache.org/activemq/browse/SM-580SM-580
> >
> >>> .
> >>> >> This
> >>> >> >> >> appears to address this situation although I'm not certain it
> >>> >> >> >> does so in a RESTful way (I'm new to REST). SM-580 appears to
> >>> be
> >>> >> >> >> scheduled
> >>> >> >> >> for 3.3 so is this what I would use once 3.3 is released and
> >>> when
> >>> >> is
> >>> >> >> 3.3
> >>> >> >> >> scheduled for release?
> >>> >> >> >>
> >>> >> >> >> Thanks
> >>> >> >> >> Tom
> >>> >> >> >> --
> >>> >> >> >> View this message in context:
> >>> >> >> >>
> >>> >> >>
> >>> >>
> >>>
> http://www.nabble.com/servicemix-http-Post-support-tp16418421s12049p16418421.html
> >>> >> >> >> Sent from the ServiceMix - User mailing list archive at
> >>> Nabble.com.
> >>> >> >> >>
> >>> >> >> >>
> >>> >> >> >
> >>> >> >> >
> >>> >> >> > --
> >>> >> >> > Cheers,
> >>> >> >> > Guillaume Nodet
> >>> >> >> > ------------------------
> >>> >> >> > Blog: http://gnodet.blogspot.com/
> >>> >> >> >
> >>> >> >> >
> >>> >> >>
> >>> >> >> --
> >>> >> >> View this message in context:
> >>> >> >>
> >>> >>
> >>>
> http://www.nabble.com/servicemix-http-Post-support-tp16418421p16427193.html
> >>> >> >> Sent from the ServiceMix - User mailing list archive at
> >>> Nabble.com.
> >>> >> >>
> >>> >> >>
> >>> >> >
> >>> >> >
> >>> >> > --
> >>> >> > Cheers,
> >>> >> > Guillaume Nodet
> >>> >> > ------------------------
> >>> >> > Blog: http://gnodet.blogspot.com/
> >>> >> >
> >>> >> >
> >>> >>
> >>> >> --
> >>> >> View this message in context:
> >>> >>
> >>>
> http://www.nabble.com/servicemix-http-Post-support-tp16418421p16446910.html
> >>> >> Sent from the ServiceMix - User mailing list archive at Nabble.com.
> >>> >>
> >>> >>
> >>> >
> >>> >
> >>> > --
> >>> > Cheers,
> >>> > Guillaume Nodet
> >>> > ------------------------
> >>> > Blog: http://gnodet.blogspot.com/
> >>> >
> >>> >
> >>>
> >>> --
> >>> View this message in context:
> >>>
> http://www.nabble.com/servicemix-http-Post-support-tp16418421p16452156.html
> >>> Sent from the ServiceMix - User mailing list archive at Nabble.com.
> >>>
> >>>
> >>
> >>
> >> --
> >> Cheers,
> >> Guillaume Nodet
> >> ------------------------
> >> Blog: http://gnodet.blogspot.com/
> >>
> >>
> >
> >
>
> --
> View this message in context:
> http://www.nabble.com/servicemix-http-Post-support-tp16418421p16469634.html
> Sent from the ServiceMix - User mailing list archive at Nabble.com.
>
>


-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/

Reply via email to