You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Steve Huston <sh...@riverace.com> on 2016/10/25 16:31:05 UTC

Trouble accessing Response body content from RESTful call

I am developing a route that calls a web service; said web service returns a JSON string (Not always the same type represented). I have this in a route as:

       from(myqueue)
        .bean(SetupCxfRequest.class)       // This sets up parameters for REST API call
        .convertBodyTo(org.apache.cxf.message.MessageContentsList.class)
        .to("cxfrs:bean:ws?throwExceptionOnFailure=false")
        .bean(WebServiceResponse.class)

SetupCxfRequest will:
      exchange.setPattern(ExchangePattern.InOut);
      // Indicate using Proxy API.
      in.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API, Boolean.FALSE);
      in.setHeader(CxfConstants.OPERATION_NAME, VerifyEmployeeRequest);

The web service interface method for the call in question is:
    @GET
    @Path(value="/authentication/{company}/employees/{id}")
    @Produces({ MediaType.APPLICATION_JSON })
    public Response VerifyEmployeeRequest(@PathParam("company") String scac,
                                          @PathParam("id") String id,
                                          @QueryParam("pin") String pin,
                                          @QueryParam("reason") String reason);

The case I'm working now is that the web service is called and it returns a 404 status with a body of JSON-marshaled stuff I need to get at.
From my route above, WebServiceResponse is then called as:

public class WebServiceResponse {

	@Handler
	public Object convertWebServiceResponse(Response wsResponse, Exchange exchange) throws IOException { 		   	              ObjectMapper unmarshaller = new ObjectMapper();
		Class<?> target = null;
		Message in = exchange.getIn();
		int opStatus = wsResponse.getStatus();
		if (opStatus == 200)
			target = EmployeeVerificationResponseAccept.class;
		else
			target = EmployeeVerificationResponseDeny.class;

So far, so good - opStatus is 404. I need to get the string which is the response body and then unmarshall it.
wsResponse.entity is a SequenceInputStream and one of the input streams appears to be the string I'm expecting from the web service; however, it has been completely consumed (length and position are the same). Where did it go, and how can I get it?

Thanks,
-Steve


RE: Trouble accessing Response body content from RESTful call

Posted by Steve Huston <sh...@riverace.com>.
Interesting... I turned on stream caching (thank you, Doug!) and there are two differences:

- I can find the text from the response body that I was expecting, but only if I remove the first parameter to the handler method and just accept Exchange. If I leave it as was,...

- I get an exception thrown because the message body can't be converted from org.apache.camel.converter.stream.InputStreamCache to javax.ws.rs.core.Response

> -----Original Message-----
> From: Doug Douglass [mailto:douglass.doug@gmail.com]
> Sent: Tuesday, October 25, 2016 1:15 PM
> To: users@camel.apache.org
> Subject: Re: Trouble accessing Response body content from RESTful call
> 
> I can't say where the response body is being consumed, but try enabling
> stream caching[1] and see what you get.
> 
> Doug
> 
> [1] http://camel.apache.org/stream-caching.html
> 
> On Tue, Oct 25, 2016 at 9:31 AM, Steve Huston <sh...@riverace.com>
> wrote:
> 
> > I am developing a route that calls a web service; said web service
> > returns a JSON string (Not always the same type represented). I have
> > this in a route as:
> >
> >        from(myqueue)
> >         .bean(SetupCxfRequest.class)       // This sets up parameters for
> > REST API call
> >         .convertBodyTo(org.apache.cxf.message.MessageContentsList.class)
> >         .to("cxfrs:bean:ws?throwExceptionOnFailure=false")
> >         .bean(WebServiceResponse.class)
> >
> > SetupCxfRequest will:
> >       exchange.setPattern(ExchangePattern.InOut);
> >       // Indicate using Proxy API.
> >       in.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API,
> > Boolean.FALSE);
> >       in.setHeader(CxfConstants.OPERATION_NAME,
> > VerifyEmployeeRequest);
> >
> > The web service interface method for the call in question is:
> >     @GET
> >     @Path(value="/authentication/{company}/employees/{id}")
> >     @Produces({ MediaType.APPLICATION_JSON })
> >     public Response VerifyEmployeeRequest(@PathParam("company")
> String
> > scac,
> >                                           @PathParam("id") String id,
> >                                           @QueryParam("pin") String pin,
> >                                           @QueryParam("reason") String
> > reason);
> >
> > The case I'm working now is that the web service is called and it
> > returns a 404 status with a body of JSON-marshaled stuff I need to get at.
> > From my route above, WebServiceResponse is then called as:
> >
> > public class WebServiceResponse {
> >
> >         @Handler
> >         public Object convertWebServiceResponse(Response wsResponse,
> > Exchange exchange) throws IOException { ObjectMapper unmarshaller =
> > new ObjectMapper();
> >                 Class<?> target = null;
> >                 Message in = exchange.getIn();
> >                 int opStatus = wsResponse.getStatus();
> >                 if (opStatus == 200)
> >                         target = EmployeeVerificationResponseAccept.class;
> >                 else
> >                         target =
> > EmployeeVerificationResponseDeny.class;
> >
> > So far, so good - opStatus is 404. I need to get the string which is
> > the response body and then unmarshall it.
> > wsResponse.entity is a SequenceInputStream and one of the input
> > streams appears to be the string I'm expecting from the web service;
> > however, it has been completely consumed (length and position are the
> > same). Where did it go, and how can I get it?
> >
> > Thanks,
> > -Steve
> >
> >

Re: Trouble accessing Response body content from RESTful call

Posted by Doug Douglass <do...@gmail.com>.
Again, stream caching will resolve this, but, as you said earlier, you get
an exception because stream caching changes the object in the message
payload. Apparently there's no converter from InputStreamCache to
javax.ws.rs.core.Response,
which is a bit surprising as this seems a common use case.

You can try writing your own type converters[1]

[1] http://camel.apache.org/type-converter.html

On Tue, Oct 25, 2016 at 3:01 PM, Steve Huston <sh...@riverace.com> wrote:

> I'm having trouble accessing the Response... in the debugger I stopped it
> and show the Response entity member as:
>
> entity  HttpURLConnection$HttpInputStream  (id=73)
>
> If I try to touch it it throws an exception that the stream is closed.
>
> On return from the web service call, I have these message properties:
> BodyType:org.apache.cxf.jaxrs.impl.ResponseImpl,
> Body:{"employeeID":"jdoe27","reason":"The specified employee does not
> exist."}
>
> -Steve
>
> > -----Original Message-----
> > From: Aravind Rajasekharan Pillai [mailto:aravindrajasekharan@gmail.com]
> > Sent: Tuesday, October 25, 2016 5:28 PM
> > To: users@camel.apache.org
> > Subject: Re: Trouble accessing Response body content from RESTful call
> >
> > Hi
> >
> >  I don't think you can do a direct conversion to string I think u need
> to read it
> > as a buffered input stream and convert to string. Can you try it that way
> >
> > Regards
> > Aravind
> >
> > > On Oct 25, 2016, at 4:41 PM, Steve Huston <sh...@riverace.com>
> wrote:
> > >
> > > Thank you for replying, Aravind!
> > >
> > > Also interesting - I had a LoggingFeature added to the
> > JAXRSClientFactoryBean with which I set up the web service. I removed
> that
> > (and removed the stream cache enabling to get back to starting point).
> With
> > that, I can get a Response into my handler after invoking the service,
> but
> > trying to read the response entity as:
> > >
> > > String body = wsResponse.readEntity(String.class);
> > >
> > > I get an exception:
> > > javax.ws.rs.client.ResponseProcessingException: Problem with reading
> the
> > data, class java.lang.String, ContentType: application/json;charset=UTF-
> 8.
> > >    at
> > org.apache.cxf.jaxrs.impl.ResponseImpl.reportMessageHandlerProblem(Res
> > ponseImpl.java:439)
> > >    at
> > org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:37
> > 9)
> > >    at
> > org.apache.cxf.jaxrs.impl.ResponseImpl.readEntity(ResponseImpl.java:320)
> > >    at
> > > org.apache.cxf.jaxrs.impl.ResponseImpl.readEntity(ResponseImpl.java:31
> > > 0)
> > > ... in my code
> > > Caused by: java.io.IOException: stream is closed
> > >    at
> > sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.ensureOp
> > en(HttpURLConnection.java:3308)
> > >    at
> > sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(Http
> > URLConnection.java:3333)
> > >    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
> > >    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
> > >    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
> > >    at java.io.InputStreamReader.read(InputStreamReader.java:184)
> > >    at java.io.Reader.read(Reader.java:140)
> > >    at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:316)
> > >    at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:304)
> > >    at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:288)
> > >    at
> > org.apache.cxf.jaxrs.provider.StringTextProvider.readFrom(
> StringTextProvid
> > er.java:45)
> > >    at
> > org.apache.cxf.jaxrs.provider.StringTextProvider.readFrom(
> StringTextProvid
> > er.java:36)
> > >    at
> > org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(JAXRSU
> > tils.java:1366)
> > >    at
> > org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:37
> > 0)
> > >    ... 23 more
> > >
> > >> -----Original Message-----
> > >> From: aravind r [mailto:aravindrajasekharan@gmail.com]
> > >> Sent: Tuesday, October 25, 2016 1:39 PM
> > >> To: users@camel.apache.org
> > >> Subject: Re: Trouble accessing Response body content from RESTful
> > >> call
> > >>
> > >> Hi Steve,
> > >>
> > >> Are u logging the Message body somewhere before consuming (say
> > Camel
> > >> logger in between),that could also lead to input stream consumption.
> > >>
> > >> Regards,
> > >> Aravind
> > >>
> > >> On Tue, Oct 25, 2016 at 1:15 PM, Doug Douglass
> > >> <do...@gmail.com>
> > >> wrote:
> > >>
> > >>> I can't say where the response body is being consumed, but try
> > >>> enabling stream caching[1] and see what you get.
> > >>>
> > >>> Doug
> > >>>
> > >>> [1] http://camel.apache.org/stream-caching.html
> > >>>
> > >>> On Tue, Oct 25, 2016 at 9:31 AM, Steve Huston <sh...@riverace.com>
> > >>> wrote:
> > >>>
> > >>>> I am developing a route that calls a web service; said web service
> > >>> returns
> > >>>> a JSON string (Not always the same type represented). I have this
> > >>>> in a route as:
> > >>>>
> > >>>>       from(myqueue)
> > >>>>        .bean(SetupCxfRequest.class)       // This sets up
> parameters for
> > >>>> REST API call
> > >>>>
> > .convertBodyTo(org.apache.cxf.message.MessageContentsList.class)
> > >>>>        .to("cxfrs:bean:ws?throwExceptionOnFailure=false")
> > >>>>        .bean(WebServiceResponse.class)
> > >>>>
> > >>>> SetupCxfRequest will:
> > >>>>      exchange.setPattern(ExchangePattern.InOut);
> > >>>>      // Indicate using Proxy API.
> > >>>>      in.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API,
> > >>>> Boolean.FALSE);
> > >>>>      in.setHeader(CxfConstants.OPERATION_NAME,
> > >>>> VerifyEmployeeRequest);
> > >>>>
> > >>>> The web service interface method for the call in question is:
> > >>>>    @GET
> > >>>>    @Path(value="/authentication/{company}/employees/{id}")
> > >>>>    @Produces({ MediaType.APPLICATION_JSON })
> > >>>>    public Response VerifyEmployeeRequest(@PathParam("company")
> > >>>> String scac,
> > >>>>                                          @PathParam("id") String id,
> > >>>>                                          @QueryParam("pin") String
> pin,
> > >>>>                                          @QueryParam("reason")
> > >>>> String reason);
> > >>>>
> > >>>> The case I'm working now is that the web service is called and it
> > >>>> returns a 404 status with a body of JSON-marshaled stuff I need to
> get
> > at.
> > >>>> From my route above, WebServiceResponse is then called as:
> > >>>>
> > >>>> public class WebServiceResponse {
> > >>>>
> > >>>>        @Handler
> > >>>>        public Object convertWebServiceResponse(Response wsResponse,
> > >>>> Exchange exchange) throws IOException { ObjectMapper unmarshaller
> > =
> > >>>> new ObjectMapper();
> > >>>>                Class<?> target = null;
> > >>>>                Message in = exchange.getIn();
> > >>>>                int opStatus = wsResponse.getStatus();
> > >>>>                if (opStatus == 200)
> > >>>>                        target = EmployeeVerificationResponseAc
> > >>> cept.class;
> > >>>>                else
> > >>>>                        target =
> > >>>> EmployeeVerificationResponseDeny.class;
> > >>>>
> > >>>> So far, so good - opStatus is 404. I need to get the string which
> > >>>> is the response body and then unmarshall it.
> > >>>> wsResponse.entity is a SequenceInputStream and one of the input
> > >>>> streams appears to be the string I'm expecting from the web
> > >>>> service; however, it has been completely consumed (length and
> > >>>> position are the same). Where
> > >>> did
> > >>>> it go, and how can I get it?
> > >>>>
> > >>>> Thanks,
> > >>>> -Steve
> > >>>>
> > >>>>
> > >>>
>

RE: Trouble accessing Response body content from RESTful call

Posted by Steve Huston <sh...@riverace.com>.
I'm having trouble accessing the Response... in the debugger I stopped it and show the Response entity member as:

entity	HttpURLConnection$HttpInputStream  (id=73)	

If I try to touch it it throws an exception that the stream is closed.

On return from the web service call, I have these message properties:
BodyType:org.apache.cxf.jaxrs.impl.ResponseImpl, Body:{"employeeID":"jdoe27","reason":"The specified employee does not exist."}

-Steve

> -----Original Message-----
> From: Aravind Rajasekharan Pillai [mailto:aravindrajasekharan@gmail.com]
> Sent: Tuesday, October 25, 2016 5:28 PM
> To: users@camel.apache.org
> Subject: Re: Trouble accessing Response body content from RESTful call
> 
> Hi
> 
>  I don't think you can do a direct conversion to string I think u need to read it
> as a buffered input stream and convert to string. Can you try it that way
> 
> Regards
> Aravind
> 
> > On Oct 25, 2016, at 4:41 PM, Steve Huston <sh...@riverace.com> wrote:
> >
> > Thank you for replying, Aravind!
> >
> > Also interesting - I had a LoggingFeature added to the
> JAXRSClientFactoryBean with which I set up the web service. I removed that
> (and removed the stream cache enabling to get back to starting point). With
> that, I can get a Response into my handler after invoking the service, but
> trying to read the response entity as:
> >
> > String body = wsResponse.readEntity(String.class);
> >
> > I get an exception:
> > javax.ws.rs.client.ResponseProcessingException: Problem with reading the
> data, class java.lang.String, ContentType: application/json;charset=UTF-8.
> >    at
> org.apache.cxf.jaxrs.impl.ResponseImpl.reportMessageHandlerProblem(Res
> ponseImpl.java:439)
> >    at
> org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:37
> 9)
> >    at
> org.apache.cxf.jaxrs.impl.ResponseImpl.readEntity(ResponseImpl.java:320)
> >    at
> > org.apache.cxf.jaxrs.impl.ResponseImpl.readEntity(ResponseImpl.java:31
> > 0)
> > ... in my code
> > Caused by: java.io.IOException: stream is closed
> >    at
> sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.ensureOp
> en(HttpURLConnection.java:3308)
> >    at
> sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(Http
> URLConnection.java:3333)
> >    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
> >    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
> >    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
> >    at java.io.InputStreamReader.read(InputStreamReader.java:184)
> >    at java.io.Reader.read(Reader.java:140)
> >    at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:316)
> >    at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:304)
> >    at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:288)
> >    at
> org.apache.cxf.jaxrs.provider.StringTextProvider.readFrom(StringTextProvid
> er.java:45)
> >    at
> org.apache.cxf.jaxrs.provider.StringTextProvider.readFrom(StringTextProvid
> er.java:36)
> >    at
> org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(JAXRSU
> tils.java:1366)
> >    at
> org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:37
> 0)
> >    ... 23 more
> >
> >> -----Original Message-----
> >> From: aravind r [mailto:aravindrajasekharan@gmail.com]
> >> Sent: Tuesday, October 25, 2016 1:39 PM
> >> To: users@camel.apache.org
> >> Subject: Re: Trouble accessing Response body content from RESTful
> >> call
> >>
> >> Hi Steve,
> >>
> >> Are u logging the Message body somewhere before consuming (say
> Camel
> >> logger in between),that could also lead to input stream consumption.
> >>
> >> Regards,
> >> Aravind
> >>
> >> On Tue, Oct 25, 2016 at 1:15 PM, Doug Douglass
> >> <do...@gmail.com>
> >> wrote:
> >>
> >>> I can't say where the response body is being consumed, but try
> >>> enabling stream caching[1] and see what you get.
> >>>
> >>> Doug
> >>>
> >>> [1] http://camel.apache.org/stream-caching.html
> >>>
> >>> On Tue, Oct 25, 2016 at 9:31 AM, Steve Huston <sh...@riverace.com>
> >>> wrote:
> >>>
> >>>> I am developing a route that calls a web service; said web service
> >>> returns
> >>>> a JSON string (Not always the same type represented). I have this
> >>>> in a route as:
> >>>>
> >>>>       from(myqueue)
> >>>>        .bean(SetupCxfRequest.class)       // This sets up parameters for
> >>>> REST API call
> >>>>
> .convertBodyTo(org.apache.cxf.message.MessageContentsList.class)
> >>>>        .to("cxfrs:bean:ws?throwExceptionOnFailure=false")
> >>>>        .bean(WebServiceResponse.class)
> >>>>
> >>>> SetupCxfRequest will:
> >>>>      exchange.setPattern(ExchangePattern.InOut);
> >>>>      // Indicate using Proxy API.
> >>>>      in.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API,
> >>>> Boolean.FALSE);
> >>>>      in.setHeader(CxfConstants.OPERATION_NAME,
> >>>> VerifyEmployeeRequest);
> >>>>
> >>>> The web service interface method for the call in question is:
> >>>>    @GET
> >>>>    @Path(value="/authentication/{company}/employees/{id}")
> >>>>    @Produces({ MediaType.APPLICATION_JSON })
> >>>>    public Response VerifyEmployeeRequest(@PathParam("company")
> >>>> String scac,
> >>>>                                          @PathParam("id") String id,
> >>>>                                          @QueryParam("pin") String pin,
> >>>>                                          @QueryParam("reason")
> >>>> String reason);
> >>>>
> >>>> The case I'm working now is that the web service is called and it
> >>>> returns a 404 status with a body of JSON-marshaled stuff I need to get
> at.
> >>>> From my route above, WebServiceResponse is then called as:
> >>>>
> >>>> public class WebServiceResponse {
> >>>>
> >>>>        @Handler
> >>>>        public Object convertWebServiceResponse(Response wsResponse,
> >>>> Exchange exchange) throws IOException { ObjectMapper unmarshaller
> =
> >>>> new ObjectMapper();
> >>>>                Class<?> target = null;
> >>>>                Message in = exchange.getIn();
> >>>>                int opStatus = wsResponse.getStatus();
> >>>>                if (opStatus == 200)
> >>>>                        target = EmployeeVerificationResponseAc
> >>> cept.class;
> >>>>                else
> >>>>                        target =
> >>>> EmployeeVerificationResponseDeny.class;
> >>>>
> >>>> So far, so good - opStatus is 404. I need to get the string which
> >>>> is the response body and then unmarshall it.
> >>>> wsResponse.entity is a SequenceInputStream and one of the input
> >>>> streams appears to be the string I'm expecting from the web
> >>>> service; however, it has been completely consumed (length and
> >>>> position are the same). Where
> >>> did
> >>>> it go, and how can I get it?
> >>>>
> >>>> Thanks,
> >>>> -Steve
> >>>>
> >>>>
> >>>

Re: Trouble accessing Response body content from RESTful call

Posted by Aravind Rajasekharan Pillai <ar...@gmail.com>.
Hi 

 I don't think you can do a direct conversion to string I think u need to read it as a buffered input stream and convert to string. Can you try it that way

Regards
Aravind

> On Oct 25, 2016, at 4:41 PM, Steve Huston <sh...@riverace.com> wrote:
> 
> Thank you for replying, Aravind!
> 
> Also interesting - I had a LoggingFeature added to the JAXRSClientFactoryBean with which I set up the web service. I removed that (and removed the stream cache enabling to get back to starting point). With that, I can get a Response into my handler after invoking the service, but trying to read the response entity as:
> 
> String body = wsResponse.readEntity(String.class);
> 
> I get an exception:
> javax.ws.rs.client.ResponseProcessingException: Problem with reading the data, class java.lang.String, ContentType: application/json;charset=UTF-8.
>    at org.apache.cxf.jaxrs.impl.ResponseImpl.reportMessageHandlerProblem(ResponseImpl.java:439)
>    at org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:379)
>    at org.apache.cxf.jaxrs.impl.ResponseImpl.readEntity(ResponseImpl.java:320)
>    at org.apache.cxf.jaxrs.impl.ResponseImpl.readEntity(ResponseImpl.java:310)
> ... in my code
> Caused by: java.io.IOException: stream is closed
>    at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.ensureOpen(HttpURLConnection.java:3308)
>    at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3333)
>    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
>    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
>    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
>    at java.io.InputStreamReader.read(InputStreamReader.java:184)
>    at java.io.Reader.read(Reader.java:140)
>    at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:316)
>    at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:304)
>    at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:288)
>    at org.apache.cxf.jaxrs.provider.StringTextProvider.readFrom(StringTextProvider.java:45)
>    at org.apache.cxf.jaxrs.provider.StringTextProvider.readFrom(StringTextProvider.java:36)
>    at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(JAXRSUtils.java:1366)
>    at org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:370)
>    ... 23 more
> 
>> -----Original Message-----
>> From: aravind r [mailto:aravindrajasekharan@gmail.com]
>> Sent: Tuesday, October 25, 2016 1:39 PM
>> To: users@camel.apache.org
>> Subject: Re: Trouble accessing Response body content from RESTful call
>> 
>> Hi Steve,
>> 
>> Are u logging the Message body somewhere before consuming (say Camel
>> logger in between),that could also lead to input stream consumption.
>> 
>> Regards,
>> Aravind
>> 
>> On Tue, Oct 25, 2016 at 1:15 PM, Doug Douglass <do...@gmail.com>
>> wrote:
>> 
>>> I can't say where the response body is being consumed, but try
>>> enabling stream caching[1] and see what you get.
>>> 
>>> Doug
>>> 
>>> [1] http://camel.apache.org/stream-caching.html
>>> 
>>> On Tue, Oct 25, 2016 at 9:31 AM, Steve Huston <sh...@riverace.com>
>>> wrote:
>>> 
>>>> I am developing a route that calls a web service; said web service
>>> returns
>>>> a JSON string (Not always the same type represented). I have this in
>>>> a route as:
>>>> 
>>>>       from(myqueue)
>>>>        .bean(SetupCxfRequest.class)       // This sets up parameters for
>>>> REST API call
>>>>        .convertBodyTo(org.apache.cxf.message.MessageContentsList.class)
>>>>        .to("cxfrs:bean:ws?throwExceptionOnFailure=false")
>>>>        .bean(WebServiceResponse.class)
>>>> 
>>>> SetupCxfRequest will:
>>>>      exchange.setPattern(ExchangePattern.InOut);
>>>>      // Indicate using Proxy API.
>>>>      in.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API,
>>>> Boolean.FALSE);
>>>>      in.setHeader(CxfConstants.OPERATION_NAME,
>>>> VerifyEmployeeRequest);
>>>> 
>>>> The web service interface method for the call in question is:
>>>>    @GET
>>>>    @Path(value="/authentication/{company}/employees/{id}")
>>>>    @Produces({ MediaType.APPLICATION_JSON })
>>>>    public Response VerifyEmployeeRequest(@PathParam("company")
>>>> String scac,
>>>>                                          @PathParam("id") String id,
>>>>                                          @QueryParam("pin") String pin,
>>>>                                          @QueryParam("reason")
>>>> String reason);
>>>> 
>>>> The case I'm working now is that the web service is called and it
>>>> returns a 404 status with a body of JSON-marshaled stuff I need to get at.
>>>> From my route above, WebServiceResponse is then called as:
>>>> 
>>>> public class WebServiceResponse {
>>>> 
>>>>        @Handler
>>>>        public Object convertWebServiceResponse(Response wsResponse,
>>>> Exchange exchange) throws IOException { ObjectMapper unmarshaller =
>>>> new ObjectMapper();
>>>>                Class<?> target = null;
>>>>                Message in = exchange.getIn();
>>>>                int opStatus = wsResponse.getStatus();
>>>>                if (opStatus == 200)
>>>>                        target = EmployeeVerificationResponseAc
>>> cept.class;
>>>>                else
>>>>                        target =
>>>> EmployeeVerificationResponseDeny.class;
>>>> 
>>>> So far, so good - opStatus is 404. I need to get the string which is
>>>> the response body and then unmarshall it.
>>>> wsResponse.entity is a SequenceInputStream and one of the input
>>>> streams appears to be the string I'm expecting from the web service;
>>>> however, it has been completely consumed (length and position are
>>>> the same). Where
>>> did
>>>> it go, and how can I get it?
>>>> 
>>>> Thanks,
>>>> -Steve
>>>> 
>>>> 
>>> 

RE: Trouble accessing Response body content from RESTful call

Posted by Steve Huston <sh...@riverace.com>.
Thank you for replying, Aravind!

Also interesting - I had a LoggingFeature added to the JAXRSClientFactoryBean with which I set up the web service. I removed that (and removed the stream cache enabling to get back to starting point). With that, I can get a Response into my handler after invoking the service, but trying to read the response entity as:

String body = wsResponse.readEntity(String.class);

I get an exception:
javax.ws.rs.client.ResponseProcessingException: Problem with reading the data, class java.lang.String, ContentType: application/json;charset=UTF-8.
	at org.apache.cxf.jaxrs.impl.ResponseImpl.reportMessageHandlerProblem(ResponseImpl.java:439)
	at org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:379)
	at org.apache.cxf.jaxrs.impl.ResponseImpl.readEntity(ResponseImpl.java:320)
	at org.apache.cxf.jaxrs.impl.ResponseImpl.readEntity(ResponseImpl.java:310)
... in my code
Caused by: java.io.IOException: stream is closed
	at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.ensureOpen(HttpURLConnection.java:3308)
	at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3333)
	at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
	at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
	at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
	at java.io.InputStreamReader.read(InputStreamReader.java:184)
	at java.io.Reader.read(Reader.java:140)
	at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:316)
	at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:304)
	at org.apache.cxf.helpers.IOUtils.toString(IOUtils.java:288)
	at org.apache.cxf.jaxrs.provider.StringTextProvider.readFrom(StringTextProvider.java:45)
	at org.apache.cxf.jaxrs.provider.StringTextProvider.readFrom(StringTextProvider.java:36)
	at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(JAXRSUtils.java:1366)
	at org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:370)
	... 23 more

> -----Original Message-----
> From: aravind r [mailto:aravindrajasekharan@gmail.com]
> Sent: Tuesday, October 25, 2016 1:39 PM
> To: users@camel.apache.org
> Subject: Re: Trouble accessing Response body content from RESTful call
> 
> Hi Steve,
> 
> Are u logging the Message body somewhere before consuming (say Camel
> logger in between),that could also lead to input stream consumption.
> 
> Regards,
> Aravind
> 
> On Tue, Oct 25, 2016 at 1:15 PM, Doug Douglass <do...@gmail.com>
> wrote:
> 
> > I can't say where the response body is being consumed, but try
> > enabling stream caching[1] and see what you get.
> >
> > Doug
> >
> > [1] http://camel.apache.org/stream-caching.html
> >
> > On Tue, Oct 25, 2016 at 9:31 AM, Steve Huston <sh...@riverace.com>
> > wrote:
> >
> > > I am developing a route that calls a web service; said web service
> > returns
> > > a JSON string (Not always the same type represented). I have this in
> > > a route as:
> > >
> > >        from(myqueue)
> > >         .bean(SetupCxfRequest.class)       // This sets up parameters for
> > > REST API call
> > >         .convertBodyTo(org.apache.cxf.message.MessageContentsList.class)
> > >         .to("cxfrs:bean:ws?throwExceptionOnFailure=false")
> > >         .bean(WebServiceResponse.class)
> > >
> > > SetupCxfRequest will:
> > >       exchange.setPattern(ExchangePattern.InOut);
> > >       // Indicate using Proxy API.
> > >       in.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API,
> > > Boolean.FALSE);
> > >       in.setHeader(CxfConstants.OPERATION_NAME,
> > > VerifyEmployeeRequest);
> > >
> > > The web service interface method for the call in question is:
> > >     @GET
> > >     @Path(value="/authentication/{company}/employees/{id}")
> > >     @Produces({ MediaType.APPLICATION_JSON })
> > >     public Response VerifyEmployeeRequest(@PathParam("company")
> > > String scac,
> > >                                           @PathParam("id") String id,
> > >                                           @QueryParam("pin") String pin,
> > >                                           @QueryParam("reason")
> > > String reason);
> > >
> > > The case I'm working now is that the web service is called and it
> > > returns a 404 status with a body of JSON-marshaled stuff I need to get at.
> > > From my route above, WebServiceResponse is then called as:
> > >
> > > public class WebServiceResponse {
> > >
> > >         @Handler
> > >         public Object convertWebServiceResponse(Response wsResponse,
> > > Exchange exchange) throws IOException { ObjectMapper unmarshaller =
> > > new ObjectMapper();
> > >                 Class<?> target = null;
> > >                 Message in = exchange.getIn();
> > >                 int opStatus = wsResponse.getStatus();
> > >                 if (opStatus == 200)
> > >                         target = EmployeeVerificationResponseAc
> > cept.class;
> > >                 else
> > >                         target =
> > > EmployeeVerificationResponseDeny.class;
> > >
> > > So far, so good - opStatus is 404. I need to get the string which is
> > > the response body and then unmarshall it.
> > > wsResponse.entity is a SequenceInputStream and one of the input
> > > streams appears to be the string I'm expecting from the web service;
> > > however, it has been completely consumed (length and position are
> > > the same). Where
> > did
> > > it go, and how can I get it?
> > >
> > > Thanks,
> > > -Steve
> > >
> > >
> >

Re: Trouble accessing Response body content from RESTful call

Posted by aravind r <ar...@gmail.com>.
Hi Steve,

Are u logging the Message body somewhere before consuming (say Camel logger
in between),that could also lead to input stream consumption.

Regards,
Aravind

On Tue, Oct 25, 2016 at 1:15 PM, Doug Douglass <do...@gmail.com>
wrote:

> I can't say where the response body is being consumed, but try enabling
> stream caching[1] and see what you get.
>
> Doug
>
> [1] http://camel.apache.org/stream-caching.html
>
> On Tue, Oct 25, 2016 at 9:31 AM, Steve Huston <sh...@riverace.com>
> wrote:
>
> > I am developing a route that calls a web service; said web service
> returns
> > a JSON string (Not always the same type represented). I have this in a
> > route as:
> >
> >        from(myqueue)
> >         .bean(SetupCxfRequest.class)       // This sets up parameters for
> > REST API call
> >         .convertBodyTo(org.apache.cxf.message.MessageContentsList.class)
> >         .to("cxfrs:bean:ws?throwExceptionOnFailure=false")
> >         .bean(WebServiceResponse.class)
> >
> > SetupCxfRequest will:
> >       exchange.setPattern(ExchangePattern.InOut);
> >       // Indicate using Proxy API.
> >       in.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API,
> > Boolean.FALSE);
> >       in.setHeader(CxfConstants.OPERATION_NAME, VerifyEmployeeRequest);
> >
> > The web service interface method for the call in question is:
> >     @GET
> >     @Path(value="/authentication/{company}/employees/{id}")
> >     @Produces({ MediaType.APPLICATION_JSON })
> >     public Response VerifyEmployeeRequest(@PathParam("company") String
> > scac,
> >                                           @PathParam("id") String id,
> >                                           @QueryParam("pin") String pin,
> >                                           @QueryParam("reason") String
> > reason);
> >
> > The case I'm working now is that the web service is called and it returns
> > a 404 status with a body of JSON-marshaled stuff I need to get at.
> > From my route above, WebServiceResponse is then called as:
> >
> > public class WebServiceResponse {
> >
> >         @Handler
> >         public Object convertWebServiceResponse(Response wsResponse,
> > Exchange exchange) throws IOException {
> > ObjectMapper unmarshaller = new ObjectMapper();
> >                 Class<?> target = null;
> >                 Message in = exchange.getIn();
> >                 int opStatus = wsResponse.getStatus();
> >                 if (opStatus == 200)
> >                         target = EmployeeVerificationResponseAc
> cept.class;
> >                 else
> >                         target = EmployeeVerificationResponseDeny.class;
> >
> > So far, so good - opStatus is 404. I need to get the string which is the
> > response body and then unmarshall it.
> > wsResponse.entity is a SequenceInputStream and one of the input streams
> > appears to be the string I'm expecting from the web service; however, it
> > has been completely consumed (length and position are the same). Where
> did
> > it go, and how can I get it?
> >
> > Thanks,
> > -Steve
> >
> >
>

Re: Trouble accessing Response body content from RESTful call

Posted by Doug Douglass <do...@gmail.com>.
I can't say where the response body is being consumed, but try enabling
stream caching[1] and see what you get.

Doug

[1] http://camel.apache.org/stream-caching.html

On Tue, Oct 25, 2016 at 9:31 AM, Steve Huston <sh...@riverace.com> wrote:

> I am developing a route that calls a web service; said web service returns
> a JSON string (Not always the same type represented). I have this in a
> route as:
>
>        from(myqueue)
>         .bean(SetupCxfRequest.class)       // This sets up parameters for
> REST API call
>         .convertBodyTo(org.apache.cxf.message.MessageContentsList.class)
>         .to("cxfrs:bean:ws?throwExceptionOnFailure=false")
>         .bean(WebServiceResponse.class)
>
> SetupCxfRequest will:
>       exchange.setPattern(ExchangePattern.InOut);
>       // Indicate using Proxy API.
>       in.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API,
> Boolean.FALSE);
>       in.setHeader(CxfConstants.OPERATION_NAME, VerifyEmployeeRequest);
>
> The web service interface method for the call in question is:
>     @GET
>     @Path(value="/authentication/{company}/employees/{id}")
>     @Produces({ MediaType.APPLICATION_JSON })
>     public Response VerifyEmployeeRequest(@PathParam("company") String
> scac,
>                                           @PathParam("id") String id,
>                                           @QueryParam("pin") String pin,
>                                           @QueryParam("reason") String
> reason);
>
> The case I'm working now is that the web service is called and it returns
> a 404 status with a body of JSON-marshaled stuff I need to get at.
> From my route above, WebServiceResponse is then called as:
>
> public class WebServiceResponse {
>
>         @Handler
>         public Object convertWebServiceResponse(Response wsResponse,
> Exchange exchange) throws IOException {
> ObjectMapper unmarshaller = new ObjectMapper();
>                 Class<?> target = null;
>                 Message in = exchange.getIn();
>                 int opStatus = wsResponse.getStatus();
>                 if (opStatus == 200)
>                         target = EmployeeVerificationResponseAccept.class;
>                 else
>                         target = EmployeeVerificationResponseDeny.class;
>
> So far, so good - opStatus is 404. I need to get the string which is the
> response body and then unmarshall it.
> wsResponse.entity is a SequenceInputStream and one of the input streams
> appears to be the string I'm expecting from the web service; however, it
> has been completely consumed (length and position are the same). Where did
> it go, and how can I get it?
>
> Thanks,
> -Steve
>
>