You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@servicemix.apache.org by Cedric de Launois <ce...@gmail.com> on 2011/08/10 14:49:38 UTC
Bugs found and feedback about facading a REST web service
Hi all,
I discovered what it seems to be multiple bugs while trying to implement a
REST webservice that facades an existing one.
The goal is to define on the ESB a REST webservice that simply forwards
incoming requests to the real REST webservice (that exists outside the ESB).
The facade must be transparent, i.e. it must reply with the same HTTP error
codes and the same HTTP responses as those returned by the real service.
Here is the (blueprint) route that I got nearly working (after several
hours...) :
<route id="restproxy">
<from uri="restlet:http://localhost:9080/oe/ws/offre/{id}"/>
<doTry>
<to uri="restlet:http://bla.dot.com:8080/oe/ws/offre/{id}"/>
<doCatch>
<exception>org.apache.camel.CamelException</exception>
<setOutHeader headerName="CamelHttpResponseCode">
<simple>${exception.statusCode}</simple>
</setOutHeader>
<setBody>
<simple>${exception.responseBody}</simple>
</setBody>
<log message="RB=${exception.responseBody}
SC=${exception.statusCode} URI=${exception.uri}"/>
</doCatch>
</doTry>
</route>
The problems I got/get are the following :
1) The real REST service may return a HTTP 404 with some content in the
response body. However, this body get lost by the exception handling.
In the route, this results in ${exception.responseBody} being something
like "org.restlet.data.Response@17bf0a7".
After investigation, the problem is located in the class RestletProducer
(in camel-restlet 2.6.0) at line 126. The body is taken by the statement
String copy = response.toString();
This is obviously wrong. It should be instead something like :
String copy = null;
if (response.getEntity() != null) {
// get content text
copy = response.getEntity().getText();
}
Additionnally, I would remove the statement LOG.warn(headers) that stand
the line just after (or at least set the LOG level to DEBUG).
2) Another problem is that the value of ${exception.uri} appears to be the
uri of the facade REST service (i.e.
restlet:http://localhost:9080/oe/ws/offre/{id}) while it should be instead
the uri of the endpoint that threw the exception (i.e.
restlet:http://bla.dot.com:8080/oe/ws/offre/{id}). This problem can be
corrected in the same class RestletProducer, at line 123, by replacing
String uri = exchange.getFromEndpoint().getEndpointUri();
by
String uri = response.getRequest().getResourceRef()
3) I would like to catch only
org.apache.camel.component.restlet.RestletOperationException exception, i.e.
write :
<exception>org.apache.camel.component.restlet.RestletOperationException</exception>
However, if I do this, I get a NullPointerException :
java.lang.NullPointerException
at
org.apache.camel.processor.CatchProcessor.catches(CatchProcessor.java:71)[68:org.apache.camel.camel-core:2.6.0]
at
org.apache.camel.processor.TryProcessor$DoCatchProcessor.process(TryProcessor.java:226)[68:org.apache.camel.camel-core:2.6.0]
at
org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:70)[68:org.apache.camel.camel-core:2.6.0]
...
After investigation, the problem lies in CatchDefinition.java (in
camel-core 2.6.0) at line 260 where the statement
ObjectHelper.loadClass(name, getClass().getClassLoader()) on the string
"org.apache.camel.component.restlet.RestletOperationException" returns null,
unless dynamic import is turned on on the camel-core bundle.
Regards,
Cedric
--
View this message in context: http://servicemix.396122.n5.nabble.com/Bugs-found-and-feedback-about-facading-a-REST-web-service-tp4685700p4685700.html
Sent from the ServiceMix - User mailing list archive at Nabble.com.
Re: Bugs found and feedback about facading a REST web service
Posted by Cedric de Launois <ce...@gmail.com>.
Hi Claus,
I initially tried with the camel-http component and the bridgeEndpoint, but
unfortunately with no success.
The problem I had was that I needed to pass the {id} parameter that stands
in the REST url, and that does not seem to be supported in an http uri, i.e.
I tried doing something like :
<route id="proxy">
<from uri="restlet:http://localhost:9080/oe/ws/offre/{id}"/>
<removeHeaders pattern="*"/>
<setHeader headerName="Exchange.HTTP_PATH">
<simple>http://bla.dot.com:8080/oe/ws/offre/{id}</simple>
</setHeader>
<to uri="
http://bla.dot.com:8080/this/url/will/be/overwritten?bridgeEndpoint=true&throwExceptionOnFailure=false
"/>
</route>
I could not achieve to make it work for the following reason :
- I cannot directly use <to uri="
http://bla.dot.com:8080/oe/ws/offre/{id}?bridgeEndpoint=true&throwExceptionOnFailure=false"/>
because "{id}" is not valid for camel-http.
- If I try to modify the uri using setHeader, then I lose the options
?bridgeEndpoint=true&throwExceptionOnFailure=false, and the service is
no longer working.
- If I try to re-set these option in the <simple> tag, then the options are
part of the url and not interpreted as option for camel-http (if I remember
correctly)
- then I decided to try with camel-restlet ;)
For the tickets : I'll try to find the time to create the tickets.
Cedric
2011/8/10 Claus Ibsen-2 [via ServiceMix] <
ml-node+4685746-926394743-197431@n5.nabble.com>
> Hi
>
> Thanks for the feedback. Do you mind creating a ticket in the Camel tracker
>
> http://camel.apache.org/support
>
> You are welcome to work on patches for the issues you have discovered.
> Then we can get it fixed faster. Unit tests is much welcome to go
> along.
>
> Also consider creating a new ticket for the bridgeEndpoint option that
> we have in other components. This allows you to use the restlet
> component in a proxy mode which is what you want to do.
>
> As well as the throwExceptionOnFailure option.
>
> See for example http component which has these option
> http://camel.apache.org/http
>
>
>
> On Wed, Aug 10, 2011 at 2:49 PM, Cedric de Launois
> <[hidden email] <http://user/SendEmail.jtp?type=node&node=4685746&i=0>>
> wrote:
>
> > Hi all,
> >
> > I discovered what it seems to be multiple bugs while trying to implement
> a
> > REST webservice that facades an existing one.
> >
> > The goal is to define on the ESB a REST webservice that simply forwards
> > incoming requests to the real REST webservice (that exists outside the
> ESB).
> > The facade must be transparent, i.e. it must reply with the same HTTP
> error
> > codes and the same HTTP responses as those returned by the real service.
> >
> > Here is the (blueprint) route that I got nearly working (after several
> > hours...) :
> >
> > <route id="restproxy">
> >
> > <from uri="restlet:http://localhost:9080/oe/ws/offre/{id}"/>
> >
> >
> > <doTry>
> > <to uri="restlet:http://bla.dot.com:8080/oe/ws/offre/{id}"/>
>
> > <doCatch>
> > <exception>org.apache.camel.CamelException</exception>
>
> > <setOutHeader headerName="CamelHttpResponseCode">
> > <simple>${exception.statusCode}</simple>
> > </setOutHeader>
> > <setBody>
> > <simple>${exception.responseBody}</simple>
> > </setBody>
> > <log message="RB=${exception.responseBody}
> > SC=${exception.statusCode} URI=${exception.uri}"/>
> > </doCatch>
> > </doTry>
> > </route>
> >
> > The problems I got/get are the following :
> >
> > 1) The real REST service may return a HTTP 404 with some content in the
> > response body. However, this body get lost by the exception handling.
> > In the route, this results in ${exception.responseBody} being something
>
> > like "org.restlet.data.Response@17bf0a7".
> > After investigation, the problem is located in the class
> RestletProducer
> > (in camel-restlet 2.6.0) at line 126. The body is taken by the statement
> > String copy = response.toString();
> >
> > This is obviously wrong. It should be instead something like :
> > String copy = null;
> > if (response.getEntity() != null) {
> > // get content text
> > copy = response.getEntity().getText();
> > }
> >
> > Additionnally, I would remove the statement LOG.warn(headers) that
> stand
> > the line just after (or at least set the LOG level to DEBUG).
> >
> >
> > 2) Another problem is that the value of ${exception.uri} appears to be
> the
> > uri of the facade REST service (i.e.
> > restlet:http://localhost:9080/oe/ws/offre/{id}) while it should be
> instead
> > the uri of the endpoint that threw the exception (i.e.
> > restlet:http://bla.dot.com:8080/oe/ws/offre/{id}). This problem can be
> > corrected in the same class RestletProducer, at line 123, by replacing
> > String uri = exchange.getFromEndpoint().getEndpointUri();
> > by
> > String uri = response.getRequest().getResourceRef()
> >
> >
> > 3) I would like to catch only
> > org.apache.camel.component.restlet.RestletOperationException exception,
> i.e.
> > write :
> >
> >
> <exception>org.apache.camel.component.restlet.RestletOperationException</exception>
>
> >
> > However, if I do this, I get a NullPointerException :
> > java.lang.NullPointerException
> > at
> >
> org.apache.camel.processor.CatchProcessor.catches(CatchProcessor.java:71)[68:org.apache.camel.camel-core:2.6.0]
>
> > at
> >
> org.apache.camel.processor.TryProcessor$DoCatchProcessor.process(TryProcessor.java:226)[68:org.apache.camel.camel-core:2.6.0]
>
> > at
> >
> org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:70)[68:org.apache.camel.camel-core:2.6.0]
>
> > ...
> >
> > After investigation, the problem lies in CatchDefinition.java (in
> > camel-core 2.6.0) at line 260 where the statement
> > ObjectHelper.loadClass(name, getClass().getClassLoader()) on the string
> > "org.apache.camel.component.restlet.RestletOperationException" returns
> null,
> > unless dynamic import is turned on on the camel-core bundle.
> >
> > Regards,
> > Cedric
> >
> >
> >
> > --
> > View this message in context:
> http://servicemix.396122.n5.nabble.com/Bugs-found-and-feedback-about-facading-a-REST-web-service-tp4685700p4685700.html
> > Sent from the ServiceMix - User mailing list archive at Nabble.com.
> >
>
>
>
> --
> Claus Ibsen
> -----------------
> FuseSource
> Email: [hidden email]<http://user/SendEmail.jtp?type=node&node=4685746&i=1>
> Web: http://fusesource.com
> Twitter: davsclaus, fusenews
> Blog: http://davsclaus.blogspot.com/
> Author of Camel in Action: http://www.manning.com/ibsen/
>
>
> ------------------------------
> If you reply to this email, your message will be added to the discussion
> below:
>
> http://servicemix.396122.n5.nabble.com/Bugs-found-and-feedback-about-facading-a-REST-web-service-tp4685700p4685746.html
> To unsubscribe from Bugs found and feedback about facading a REST web
> service, click here<http://servicemix.396122.n5.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=4685700&code=Y2VkcmljLmRlbGF1bm9pc0BnbWFpbC5jb218NDY4NTcwMHwxMTM0MjUzMjg1>.
>
>
--
View this message in context: http://servicemix.396122.n5.nabble.com/Bugs-found-and-feedback-about-facading-a-REST-web-service-tp4685700p4685795.html
Sent from the ServiceMix - User mailing list archive at Nabble.com.
Re: Bugs found and feedback about facading a REST web service
Posted by Claus Ibsen <cl...@gmail.com>.
Hi
Thanks for the feedback. Do you mind creating a ticket in the Camel tracker
http://camel.apache.org/support
You are welcome to work on patches for the issues you have discovered.
Then we can get it fixed faster. Unit tests is much welcome to go
along.
Also consider creating a new ticket for the bridgeEndpoint option that
we have in other components. This allows you to use the restlet
component in a proxy mode which is what you want to do.
As well as the throwExceptionOnFailure option.
See for example http component which has these option
http://camel.apache.org/http
On Wed, Aug 10, 2011 at 2:49 PM, Cedric de Launois
<ce...@gmail.com> wrote:
> Hi all,
>
> I discovered what it seems to be multiple bugs while trying to implement a
> REST webservice that facades an existing one.
>
> The goal is to define on the ESB a REST webservice that simply forwards
> incoming requests to the real REST webservice (that exists outside the ESB).
> The facade must be transparent, i.e. it must reply with the same HTTP error
> codes and the same HTTP responses as those returned by the real service.
>
> Here is the (blueprint) route that I got nearly working (after several
> hours...) :
>
> <route id="restproxy">
>
> <from uri="restlet:http://localhost:9080/oe/ws/offre/{id}"/>
>
>
> <doTry>
> <to uri="restlet:http://bla.dot.com:8080/oe/ws/offre/{id}"/>
> <doCatch>
> <exception>org.apache.camel.CamelException</exception>
> <setOutHeader headerName="CamelHttpResponseCode">
> <simple>${exception.statusCode}</simple>
> </setOutHeader>
> <setBody>
> <simple>${exception.responseBody}</simple>
> </setBody>
> <log message="RB=${exception.responseBody}
> SC=${exception.statusCode} URI=${exception.uri}"/>
> </doCatch>
> </doTry>
> </route>
>
> The problems I got/get are the following :
>
> 1) The real REST service may return a HTTP 404 with some content in the
> response body. However, this body get lost by the exception handling.
> In the route, this results in ${exception.responseBody} being something
> like "org.restlet.data.Response@17bf0a7".
> After investigation, the problem is located in the class RestletProducer
> (in camel-restlet 2.6.0) at line 126. The body is taken by the statement
> String copy = response.toString();
>
> This is obviously wrong. It should be instead something like :
> String copy = null;
> if (response.getEntity() != null) {
> // get content text
> copy = response.getEntity().getText();
> }
>
> Additionnally, I would remove the statement LOG.warn(headers) that stand
> the line just after (or at least set the LOG level to DEBUG).
>
>
> 2) Another problem is that the value of ${exception.uri} appears to be the
> uri of the facade REST service (i.e.
> restlet:http://localhost:9080/oe/ws/offre/{id}) while it should be instead
> the uri of the endpoint that threw the exception (i.e.
> restlet:http://bla.dot.com:8080/oe/ws/offre/{id}). This problem can be
> corrected in the same class RestletProducer, at line 123, by replacing
> String uri = exchange.getFromEndpoint().getEndpointUri();
> by
> String uri = response.getRequest().getResourceRef()
>
>
> 3) I would like to catch only
> org.apache.camel.component.restlet.RestletOperationException exception, i.e.
> write :
>
> <exception>org.apache.camel.component.restlet.RestletOperationException</exception>
>
> However, if I do this, I get a NullPointerException :
> java.lang.NullPointerException
> at
> org.apache.camel.processor.CatchProcessor.catches(CatchProcessor.java:71)[68:org.apache.camel.camel-core:2.6.0]
> at
> org.apache.camel.processor.TryProcessor$DoCatchProcessor.process(TryProcessor.java:226)[68:org.apache.camel.camel-core:2.6.0]
> at
> org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:70)[68:org.apache.camel.camel-core:2.6.0]
> ...
>
> After investigation, the problem lies in CatchDefinition.java (in
> camel-core 2.6.0) at line 260 where the statement
> ObjectHelper.loadClass(name, getClass().getClassLoader()) on the string
> "org.apache.camel.component.restlet.RestletOperationException" returns null,
> unless dynamic import is turned on on the camel-core bundle.
>
> Regards,
> Cedric
>
>
>
> --
> View this message in context: http://servicemix.396122.n5.nabble.com/Bugs-found-and-feedback-about-facading-a-REST-web-service-tp4685700p4685700.html
> Sent from the ServiceMix - User mailing list archive at Nabble.com.
>
--
Claus Ibsen
-----------------
FuseSource
Email: cibsen@fusesource.com
Web: http://fusesource.com
Twitter: davsclaus, fusenews
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/