You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by mat127 <p3...@gmail.com> on 2010/09/30 15:44:20 UTC

Restlet HTTP status and message

Hi,

I am using the Restlet component for accessing a REST service and getting
some JSON data from it. What I need is to check the HTTP status of the
response but I do not know how. My route configuration is something like:

		<camel:route>
            <camel:from uri="direct:rest"/>
            <camel:to uri="restlet:http://somewhere.net/path/to/rest/api"/>
            <camel:process ref="header.logger" />
            <camel:unmarshal ref="json" />
		</camel:route>

The problem is that in case that REST returns something else than HTTP
status 200, the message body contains the error html message generated by
the web server and JSON unmarshaller than fails on it. I suppose the correct
way would be to check the HTTP status before the JSON unmarshalling and
react to HTTP status != 200. But how to get this value?

I tried to inspect the content of the Exchange generated by the restlet
component:

[DEBUG] [2010-09-30 14:57:47,017] [main]
c.b.i.c.a.l.ExchangeHeadersInspector: in.headers:
{org.restlet.http.headers=[Server: Apache-Coyote/1.1, Content-Type:
text/html;charset=utf-8, Content-Length: 1090, Date: Thu, 30 Sep 2010
12:57:46 GMT, Connection: close]}
[DEBUG] [2010-09-30 14:57:47,018] [main]
c.b.i.c.a.l.ExchangeHeadersInspector: exchange.properties:
{CamelToEndpoint=http://test.morosystems.cz:8086/ibillboardd/gwt/ds/kernel.adSpaceConfig/fetch}
[DEBUG] [2010-09-30 14:57:47,018] [main]
c.b.i.c.a.l.ExchangeHeadersInspector: exchange.failed: false

So the in.header[org.restlet.http.headers] header contains all the http
headers but the status is not here nor at any other place I tried
(Exchange.getProperties(), Exchange.isFailed()). Some hints anyone?

Petr
-- 
View this message in context: http://camel.465427.n5.nabble.com/Restlet-HTTP-status-and-message-tp3047023p3047023.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Restlet HTTP status and message

Posted by Claus Ibsen <cl...@gmail.com>.
Hi

Ah looks like an oversight in the restlet component. I have created a
ticket to add the status code and some other details missing
https://issues.apache.org/activemq/browse/CAMEL-3185


On Fri, Oct 1, 2010 at 10:00 AM, mat127 <p3...@gmail.com> wrote:
>
> I am afraid the restlet component does not set the HTTP response code
> anywhere. I am using a simple logger to inspect the Exchange instance
> comming from the restlet:
>
>        <bean id="header.logger"
>                 class="ExchangeHeadersInspector" />
>
> where the ExchengeHeadersInspector is coded in Scala:
>
> import org.apache.camel.Exchange
> import se.scalablesolutions.akka.util.Logging
>
> import org.apache.camel.Processor
>
> class ExchangeHeadersInspector extends Processor with Logging {
>
>   def process(exchange: Exchange): Unit = {
>       log.debug("in.headers: %s" format exchange.getIn.getHeaders)
>       log.debug("exchange.properties: %s" format exchange.getProperties)
>       log.debug("exchange.failed: %s" format exchange.isFailed)
>   }
>
> }
>
> As you can see from the log produced by it there is no key
> CamelHttpResponseCode within the exchange.getIn.getHeaders map:
>
> [DEBUG] [2010-09-30 14:57:47,017] [main]
> c.b.i.c.a.l.ExchangeHeadersInspector: in.headers:
> {org.restlet.http.headers=[Server: Apache-Coyote/1.1, Content-Type:
> text/html;charset=utf-8, Content-Length: 1090, Date: Thu, 30 Sep 2010
> 12:57:46 GMT, Connection: close]}
> [DEBUG] [2010-09-30 14:57:47,018] [main]
> c.b.i.c.a.l.ExchangeHeadersInspector: exchange.properties:
> {CamelToEndpoint=http:// ... }
> [DEBUG] [2010-09-30 14:57:47,018] [main]
> c.b.i.c.a.l.ExchangeHeadersInspector: exchange.failed: false
>
> Is it possible that it is stripped down from the Exchange while routing from
> the restlet to my process component?
>
> Anyway I also tried something similar that Claus suggested and inserted some
> validation before the JSON unmarshalling:
>
>                <camel:route>
>            <camel:from uri="direct:rest"/>
>            <camel:to uri="restlet:http://somewhere.net/path/to/rest/api"/>
>            <camel:process ref="header.logger" />
>            <camel:validate>
>                <camel:simple>${header.CamelHttpResponseCode} == 200</camel:simple>
>            </camel:validate>
>            <camel:unmarshal ref="json" />
>                </camel:route>
>
> And even in case of 200 response code I received exception as there is no
> CamelHttpResponseCode key in the headers map:
>
> SEVERE: Failed delivery for exchangeId:
> b71067ad-e305-4762-a4e7-f7baab6dd42d. Exhausted after delivery attempt: 1
> caught: org.apache.camel.processor.validation.PredicateValidationException:
> Validation failed for Predicate[header(CamelHttpResponseCode) == 200].
> Exchange[Message: ... ]
> org.apache.camel.processor.validation.PredicateValidationException:
> Validation failed for Predicate[header(CamelHttpResponseCode) == 200].
> Exchange[Message: ... ]
> ...
>
> Petr
> --
> View this message in context: http://camel.465427.n5.nabble.com/Restlet-HTTP-status-and-message-tp3047023p3068911.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>



-- 
Claus Ibsen
Apache Camel Committer

Author of Camel in Action: http://www.manning.com/ibsen/
Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus

Re: Restlet HTTP status and message

Posted by mat127 <p3...@gmail.com>.
I am afraid the restlet component does not set the HTTP response code
anywhere. I am using a simple logger to inspect the Exchange instance
comming from the restlet:

	<bean id="header.logger"
		 class="ExchangeHeadersInspector" />

where the ExchengeHeadersInspector is coded in Scala:

import org.apache.camel.Exchange
import se.scalablesolutions.akka.util.Logging

import org.apache.camel.Processor

class ExchangeHeadersInspector extends Processor with Logging {

   def process(exchange: Exchange): Unit = { 
       log.debug("in.headers: %s" format exchange.getIn.getHeaders)
       log.debug("exchange.properties: %s" format exchange.getProperties)
       log.debug("exchange.failed: %s" format exchange.isFailed)
   }

}

As you can see from the log produced by it there is no key
CamelHttpResponseCode within the exchange.getIn.getHeaders map:

[DEBUG] [2010-09-30 14:57:47,017] [main]
c.b.i.c.a.l.ExchangeHeadersInspector: in.headers:
{org.restlet.http.headers=[Server: Apache-Coyote/1.1, Content-Type:
text/html;charset=utf-8, Content-Length: 1090, Date: Thu, 30 Sep 2010
12:57:46 GMT, Connection: close]}
[DEBUG] [2010-09-30 14:57:47,018] [main]
c.b.i.c.a.l.ExchangeHeadersInspector: exchange.properties:
{CamelToEndpoint=http:// ... }
[DEBUG] [2010-09-30 14:57:47,018] [main]
c.b.i.c.a.l.ExchangeHeadersInspector: exchange.failed: false

Is it possible that it is stripped down from the Exchange while routing from
the restlet to my process component?

Anyway I also tried something similar that Claus suggested and inserted some
validation before the JSON unmarshalling:

                <camel:route>
            <camel:from uri="direct:rest"/>
            <camel:to uri="restlet:http://somewhere.net/path/to/rest/api"/>
            <camel:process ref="header.logger" />
            <camel:validate>
	        <camel:simple>${header.CamelHttpResponseCode} == 200</camel:simple>
            </camel:validate>
            <camel:unmarshal ref="json" />
                </camel:route>

And even in case of 200 response code I received exception as there is no
CamelHttpResponseCode key in the headers map:

SEVERE: Failed delivery for exchangeId:
b71067ad-e305-4762-a4e7-f7baab6dd42d. Exhausted after delivery attempt: 1
caught: org.apache.camel.processor.validation.PredicateValidationException:
Validation failed for Predicate[header(CamelHttpResponseCode) == 200].
Exchange[Message: ... ]
org.apache.camel.processor.validation.PredicateValidationException:
Validation failed for Predicate[header(CamelHttpResponseCode) == 200].
Exchange[Message: ... ]
...

Petr
-- 
View this message in context: http://camel.465427.n5.nabble.com/Restlet-HTTP-status-and-message-tp3047023p3068911.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Restlet HTTP status and message

Posted by Claus Ibsen <cl...@gmail.com>.
The HTTP response code should be set by the restlet component
http://camel.apache.org/restlet

So you can just test this code

<choice>
   <when>
        <simple>${header.CamelHttpResponseCode} == 200</simple>
        <to uri="xxx"/>
</when>
   <otherwise>
   ... not 200 so something is wrong
</otherwise>


On Thu, Sep 30, 2010 at 10:52 PM, mat127 <p3...@gmail.com> wrote:
>
> Hi Ashwin,
>
> thank you for your answer.
>
> You are right there is no exception handling in the code I posted. That is
> because the exception that is raised during the route execution is related
> to the parsing of the http response:
>
> SEVERE: Failed delivery for exchangeId:
> 26a0911d-9ffc-4366-9c46-cef2084e6a24. Exhausted after delivery attempt: 1
> caught: org.codehaus.jackson.JsonParseException: Unexpected character ('<'
> (code 60)): expected a valid value (number, String, array, object, 'true',
> 'false' or 'null')
>  at [Source: java.io.ByteArrayInputStream@1f0d7f5; line: 1, column: 2]
> org.codehaus.jackson.JsonParseException: Unexpected character ('<' (code
> 60)): expected a valid value (number, String, array, object, 'true', 'false'
> or 'null')
>  at [Source: java.io.ByteArrayInputStream@1f0d7f5; line: 1, column: 2]
>        at
> org.codehaus.jackson.impl.JsonParserBase._constructError(JsonParserBase.java:651)
>        at
> org.codehaus.jackson.impl.JsonParserBase._reportError(JsonParserBase.java:635)
>        at
> org.codehaus.jackson.impl.JsonParserBase._reportUnexpectedChar(JsonParserBase.java:576)
>        at
> org.codehaus.jackson.impl.Utf8StreamParser.nextToken(Utf8StreamParser.java:194)
>        at
> org.codehaus.jackson.map.ObjectMapper._initForReading(ObjectMapper.java:1039)
>        at
> org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:995)
>        at
> org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:818)
>        at
> org.apache.camel.component.jackson.JacksonDataFormat.unmarshal(JacksonDataFormat.java:70)
>        ...
>
> But this parsing is useless in case that HTTP status is not 200 as the body
> of the message does not contain expected JSON data but html error message
> instead. Handling this kind of exception would mean that the data is
> corrupted but received fine which is not true. That is why I want to find
> some access to http status that restlet component has received from the
> server and avoid any parsing (by filtering e.g.) in case it is not 200 OK.
>
> Imagine the route without the unmarshalling:
>
>                <camel:route>
>            <camel:from uri="direct:rest"/>
>            <camel:to uri="restlet:http://somewhere.net/path/to/rest/api"/>
>            <camel:process ref="header.logger" />
>                </camel:route>
>
> In this case there will be no exception even the REST API would respond with
> some HTTP status != 200.
>
> Anyway the exchange.getOut.isFailed() is false too as you can see from the
> log:
>
> [DEBUG] [2010-09-30 14:57:47,018] [main]
> c.b.i.c.a.l.ExchangeHeadersInspector: exchange.failed: false
>
> Petr
> --
> View this message in context: http://camel.465427.n5.nabble.com/Restlet-HTTP-status-and-message-tp3047023p3047644.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>



-- 
Claus Ibsen
Apache Camel Committer

Author of Camel in Action: http://www.manning.com/ibsen/
Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus

Re: Restlet HTTP status and message

Posted by mat127 <p3...@gmail.com>.
Hi Ashwin,

thank you for your answer.

You are right there is no exception handling in the code I posted. That is
because the exception that is raised during the route execution is related
to the parsing of the http response:

SEVERE: Failed delivery for exchangeId:
26a0911d-9ffc-4366-9c46-cef2084e6a24. Exhausted after delivery attempt: 1
caught: org.codehaus.jackson.JsonParseException: Unexpected character ('<'
(code 60)): expected a valid value (number, String, array, object, 'true',
'false' or 'null')
 at [Source: java.io.ByteArrayInputStream@1f0d7f5; line: 1, column: 2]
org.codehaus.jackson.JsonParseException: Unexpected character ('<' (code
60)): expected a valid value (number, String, array, object, 'true', 'false'
or 'null')
 at [Source: java.io.ByteArrayInputStream@1f0d7f5; line: 1, column: 2]
        at
org.codehaus.jackson.impl.JsonParserBase._constructError(JsonParserBase.java:651)
        at
org.codehaus.jackson.impl.JsonParserBase._reportError(JsonParserBase.java:635)
        at
org.codehaus.jackson.impl.JsonParserBase._reportUnexpectedChar(JsonParserBase.java:576)
        at
org.codehaus.jackson.impl.Utf8StreamParser.nextToken(Utf8StreamParser.java:194)
        at
org.codehaus.jackson.map.ObjectMapper._initForReading(ObjectMapper.java:1039)
        at
org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:995)
        at
org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:818)
        at
org.apache.camel.component.jackson.JacksonDataFormat.unmarshal(JacksonDataFormat.java:70)
        ...

But this parsing is useless in case that HTTP status is not 200 as the body
of the message does not contain expected JSON data but html error message
instead. Handling this kind of exception would mean that the data is
corrupted but received fine which is not true. That is why I want to find
some access to http status that restlet component has received from the
server and avoid any parsing (by filtering e.g.) in case it is not 200 OK.

Imagine the route without the unmarshalling:

                <camel:route>
            <camel:from uri="direct:rest"/>
            <camel:to uri="restlet:http://somewhere.net/path/to/rest/api"/>
            <camel:process ref="header.logger" />
                </camel:route> 

In this case there will be no exception even the REST API would respond with
some HTTP status != 200.

Anyway the exchange.getOut.isFailed() is false too as you can see from the
log:

[DEBUG] [2010-09-30 14:57:47,018] [main]
c.b.i.c.a.l.ExchangeHeadersInspector: exchange.failed: false

Petr
-- 
View this message in context: http://camel.465427.n5.nabble.com/Restlet-HTTP-status-and-message-tp3047023p3047644.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Restlet HTTP status and message

Posted by Ashwin Karpe <ak...@fusesource.com>.
Hi,

I do not see any exception handling code here. Check out 
http://camel.apache.org/exception-clause.html
http://camel.apache.org/exception-clause.html 

You can also look in the exchange.getOut.isFailed() to see if the exchange
returned has failed due to an exception or fault.

Cheers,

Ashwin...

-----
---------------------------------------------------------
Ashwin Karpe
Apache Camel Committer & Sr Principal Consultant
FUSESource (a Progress Software Corporation subsidiary)
http://fusesource.com http://fusesource.com 

Blog: http://opensourceknowledge.blogspot.com
http://opensourceknowledge.blogspot.com 
---------------------------------------------------------
-- 
View this message in context: http://camel.465427.n5.nabble.com/Restlet-HTTP-status-and-message-tp3047023p3047083.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Restlet HTTP status and message

Posted by Claus Ibsen <cl...@gmail.com>.
Hi

I have created a ticket
https://issues.apache.org/activemq/browse/CAMEL-3184

To add an option to the restlet component so it works more like the
http component. The http component will throw an exception if the code
!= 200.
I think we should do the same for the restlet. This makes it easier to
handle errors.


On Thu, Sep 30, 2010 at 3:44 PM, mat127 <p3...@gmail.com> wrote:
>
> Hi,
>
> I am using the Restlet component for accessing a REST service and getting
> some JSON data from it. What I need is to check the HTTP status of the
> response but I do not know how. My route configuration is something like:
>
>                <camel:route>
>            <camel:from uri="direct:rest"/>
>            <camel:to uri="restlet:http://somewhere.net/path/to/rest/api"/>
>            <camel:process ref="header.logger" />
>            <camel:unmarshal ref="json" />
>                </camel:route>
>
> The problem is that in case that REST returns something else than HTTP
> status 200, the message body contains the error html message generated by
> the web server and JSON unmarshaller than fails on it. I suppose the correct
> way would be to check the HTTP status before the JSON unmarshalling and
> react to HTTP status != 200. But how to get this value?
>
> I tried to inspect the content of the Exchange generated by the restlet
> component:
>
> [DEBUG] [2010-09-30 14:57:47,017] [main]
> c.b.i.c.a.l.ExchangeHeadersInspector: in.headers:
> {org.restlet.http.headers=[Server: Apache-Coyote/1.1, Content-Type:
> text/html;charset=utf-8, Content-Length: 1090, Date: Thu, 30 Sep 2010
> 12:57:46 GMT, Connection: close]}
> [DEBUG] [2010-09-30 14:57:47,018] [main]
> c.b.i.c.a.l.ExchangeHeadersInspector: exchange.properties:
> {CamelToEndpoint=http://test.morosystems.cz:8086/ibillboardd/gwt/ds/kernel.adSpaceConfig/fetch}
> [DEBUG] [2010-09-30 14:57:47,018] [main]
> c.b.i.c.a.l.ExchangeHeadersInspector: exchange.failed: false
>
> So the in.header[org.restlet.http.headers] header contains all the http
> headers but the status is not here nor at any other place I tried
> (Exchange.getProperties(), Exchange.isFailed()). Some hints anyone?
>
> Petr
> --
> View this message in context: http://camel.465427.n5.nabble.com/Restlet-HTTP-status-and-message-tp3047023p3047023.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>



-- 
Claus Ibsen
Apache Camel Committer

Author of Camel in Action: http://www.manning.com/ibsen/
Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus