Hi Marcos
2011/3/21 Marcos Díez Fernández <[email protected]>
> Hi Sergey, thanks for replying
>
> I'm trying the second approach you suggest:
>
> ErrorDetail errorDetail = (ErrorDetail) jsonProvider.readFrom(
> (Class)ErrorDetail.class,
> (Class)ErrorDetail.class,
> new Annotation[]{},
>
> MediaType.APPLICATION_JSON_TYPE,
> response.getMetadata(),
>
> (InputStream)response.getEntity());
>
>
> But I get this compilation error:
>
> The method
> readFrom(Class<Object>, Type, Annotation[], MediaType,
> MultivaluedMap<String,String>, InputStream)
> in the type JSONProvider is not applicable for the arguments
> (Class, Class, Annotation[], MediaType,
> MultivaluedMap<String,Object>, InputStream)
>
>
> To make it compile, I've extracted the metadata values manually and
> inserted them into a MetadataMap<String,String>:
>
>
> The conversion is awkward, I know, so I just casted Map<String, Object> to
plain Map and then to Map<String, String> - this is hidden inside
ResponseReader...
> Unfortunately, this produces an exception inside the JSONProvider:
>
> javax.xml.stream.XMLStreamException:
> org.codehaus.jettison.json.JSONException: A JSONObject text must begin with
> '{' at character 0 of
>
> So it looks like the received entity is not well understood or something
> (?).
>
>
Make sure you don't use ServerWebApplicationException.getMessage() which
will consume the input stream.
Cheers, Sergey
> On the other hand, I've tried unmarshalling from the exception's
> errorMessage:
>
> InputStream is = new
> ByteArrayInputStream(e.getMessage().getBytes("UTF-8"));
>
> ErrorDetail errorDetail = (ErrorDetail) jsonProvider.readFrom(
> (Class)ErrorDetail.class,
> (Class)ErrorDetail.class,
> new Annotation[]{},
>
> MediaType.APPLICATION_JSON_TYPE,
> metadataMap,
> is);
>
> And this works fine! So at least I have a way to get the object I need if I
> can't get to get it from the entity.
> Apart from this, what could be the problem (if any) with the entity?
>
> In case it helps, the entity looks like this:
>
> Entity : HttpURLConnection$HttpInputStream (id=90)
> ---> cacheRequest : null
> ---> in : KeepAliveStream (id=94)
> ---> ---> closed : true
> ---> ---> count : 190
> ---> ---> expected : 190
> ---> ---> hc : null
> ---> ---> hurried : false
> ---> ---> in : null
> ---> ---> markedCount : 0
> ---> ---> markLimit : -1
> ---> ---> pi : null
> ---> ---> queuedForCleanup : false
> ---> inCache : 0
> ---> markCount : 0
> ---> marked : false
> ---> outputStream : null
> ---> skipBuffer : null
> ---> this$0 : HttpURLConnection (id=98)
> ---> ---> allowUserInteraction : false
> ---> ---> authObj : null
> ---> ---> cachedHeaders : null
> ---> ---> cachedInputStream : null
> ---> ---> cachedResponse : null
> ---> ---> cacheHandler : null
> ---> ---> cdata : (id=105)
> ---> ---> chunkLength : -1
> ---> ---> connected : true
> ---> ---> connectTimeout : 0
> ---> ---> connectTimeout : 30000
> ---> ---> cookieHandler : null
> ---> ---> currentProxyCredentials : null
> ---> ---> currentServerCredentials : null
> ---> ---> digestparams : null
> ---> ---> doingNTLM2ndStage : false
> ---> ---> doingNTLMp2ndStage : false
> ---> ---> doInput : true
> ---> ---> domain : null
> ---> ---> doOutput : true
> ---> ---> errorStream : null
> ---> ---> failedOnce : false
> ---> ---> fixedContentLength : -1
> ---> ---> handler : Handler (id=113)
> ---> ---> http : null
> ---> ---> ifModifiedSince : 0
> ---> ---> inputStream : HttpURLConnection$HttpInputStream (id=90)
> ---> ---> instanceFollowRedirects : false
> ---> ---> instProxy : null
> ---> ---> isUserProxyAuth : false
> ---> ---> isUserServerAuth : false
> ---> ---> method : "GET" (id=119)
> ---> ---> needToCheck : false
> ---> ---> pi : null
> ---> ---> poster : null
> ---> ---> proxyAuthKey : null
> ---> ---> ps : PrintStream (id=126)
> ---> ---> readTimeout : 60000
> ---> ---> readTimeout : 0
> ---> ---> rememberedException : IOException (id=133)
> ---> ---> requests : MessageHeader (id=135)
> ---> ---> requests : null
> ---> ---> responseCode : 400
> ---> ---> responseMessage : "Bad Request" (id=137)
> ---> ---> responses : MessageHeader (id=138)
> ---> ---> reuseClient : null
> ---> ---> serverAuthKey : null
> ---> ---> setRequests : true
> ---> ---> setUserCookies : true
> ---> ---> strOutputStream : null
> ---> ---> tryTransparentNTLMProxy : true
> ---> ---> tryTransparentNTLMServer : true
> ---> ---> tunnelState : HttpURLConnection$TunnelState (id=139)
> ---> ---> url : URL (id=142)
> ---> ---> useCaches : false
> ---> ---> userCookies : null
> ---> ---> userCookies2 : null
>
> Thanks and BR,
> Marcos.
>
>
> --------------------------Mensaje original----------------------------
> De: Sergey Beryozkin [mailto:[email protected]]
> Enviado el: lunes, 21 de marzo de 2011 13:14
> Para: [email protected]
> Asunto: Re: Extracting object from Response when
> ServerWebApplicationException occurs
>
> Hi
>
> sorry for a delay.
> I added a utility method to ResponseReader to simplify reading the error
> streams, ex:
>
> try {
> client.invoke();
> } catch (ServerWebApplicationException ex) {
>
> Error error = new ResponseReader().readEntity(client, ex.getResponse(),
> Error.class);
> }
>
> Using ResponseReader after the invocation has completed (for the correct
> provider, possibly the custom one be found) is a bit tricky, thus a client
> reference also needs to be passed to the readEntity method. WebClients can
> be passed as is, proxies - like this: WebClient.client(proxy).
>
> However, in your case, using ResponseReader may not be needed, I just
> realized that you have the custom JSONProvider instance in scope, so, when
> you catch the exception, try using the provider directly:
>
> try {
> client.invoke();
> } catch (ServerWebApplicationException ex) {
>
> Response r = ex.getResponse();
> jsonProvider.readFrom(Error.class, Error.class, new Annotation[]{},
> r.getMetadata(), MediaType.APPLICATION_JSON_TYPE,
> (InputStream)r.getEntity());
> }
>
> there could be some issues with this workaround due to the provider being
> used outside of the scope of the invocation, if yes - then please reuse
> ResponseReader code from the trunk till 2.3.4/2.4.0 is released
>
> Cheers, Sergey
>
> 2011/3/16 Marcos Díez Fernández <[email protected]>
>
> > Sorry maybe I didn't explained well, but I don't get an empty String. The
> > ServerWebApplicationException looks like:
> >
> > exception : ServerWebApplicationException (id=46)
> > ---> cause : null
> > ---> detailMessage : null
> > ---> errorMessage : "{"errorDetail":{"message":{"$":"custom error
> > message"}}}" (id=54)
> > ---> response : ResponseImpl (id=58)
> > ---> ---> entity : HttpURLConnection$HttpInputStream (id=61)
> > ---> ---> ---> cacheRequest : null
> > ---> ---> ---> in : KeepAliveStream (id=70)
> > ---> ---> ---> inCache : 0
> > ---> ---> ---> markCount : 0
> > ---> ---> ---> marked : false
> > ---> ---> ---> outputStream : null
> > ---> ---> ---> skipBuffer : null
> > ---> ---> ---> this$0 : HttpURLConnection (id=74)
> > ---> ---> metadata : MetadataMap<K,V> (id=64)
> > ---> ---> status : 400
> > ---> stackTrace : null
> >
> > In the errorMessage I get the JSON of the object I need and, at first
> look,
> > the entity of the response seemed empty to me (probably I was wrong).
> >
> > From this, which would be the way to obtain the object I need? I thought
> I
> > could get it from the response entity, since I insert it there in the
> server
> > side, in an exceptionMapper, like:
> >
> > return Response.status(code).entity(errorDetail).build();
> >
> > btw, I do work with Camel. It's something like:
> >
> > [client]<--->[JAXRS-Server]<--->[Camel-Pipeline]
> >
> > When an exception occurs in the pipeline, jaxrs-server inserts this
> > 'errorDetail' object as a response to the client. How do I retrieve it in
> > the client?
> >
> > thanks
> > BR,
> > Marcos.
> >
> > -----Mensaje original-----
> > De: Sergey Beryozkin [mailto:[email protected]]
> > Enviado el: martes, 15 de marzo de 2011 23:20
> > Para: [email protected]
> > Asunto: Re: Extracting object from Response when
> > ServerWebApplicationException occurs
> >
> > I can see that the ServerWebApplicationException reports a non-empty
> String
> > in my test - do you work with Camel by any chance ?
> >
> > However, ResponseReader is not checked in case of exceptions - so I'll
> try
> > to apply a little fix asap
> >
> > Cheers, Sergey
> >
> > 2011/3/15 Marcos Díez Fernández <[email protected]>
> >
> > > Ok, thank you Sergey, I'll wait for your reply.
> > >
> > > BR,
> > > Marcos.
> > >
> > > -----Mensaje original-----
> > > De: Sergey Beryozkin [mailto:[email protected]]
> > > Enviado el: martes, 15 de marzo de 2011 10:53
> > > Para: [email protected]
> > > Asunto: Re: Extracting object from Response when
> > > ServerWebApplicationException occurs
> > >
> > > Hi
> > >
> > > I haven't replied so far because I'll need to write a test but have yet
> > > another test in front of me to deal with...
> > >
> > > I'm not sure at the moment why the empty string is returned from
> > > ServerWebApplicationException so I'll have to investigate
> > >
> > > thanks, Sergey
> > >
> > >
> > > 2011/3/15 Marcos Díez Fernández <[email protected]>
> > >
> > > > Any help? Thanks.
> > > >
> > > > -----Mensaje original-----
> > > > De: Marcos Díez Fernández [mailto:[email protected]]
> > > > Enviado el: lunes, 14 de marzo de 2011 13:43
> > > > Para: [email protected]
> > > > Asunto: Extracting object from Response when
> > > ServerWebApplicationException
> > > > occurs
> > > >
> > > > Hi,
> > > >
> > > > I have a RESTful service provided by a JAXRS server that, when an
> > > exception
> > > > occurs, returns a custom error class serialized as JSON:
> > > >
> > > > ID: 763
> > > > Response-Code: 406
> > > > Content-Type: application/json
> > > > Headers: {Date=[Mon, 14 Mar 2011 11:44:50 GMT]}
> > > > Payload: {"errorDetail":{"message":{"$":"custom error message"}}}
> > > > --------------------------------------
> > > >
> > > > This produces a ServerWebApplicationException on the client side,
> which
> > I
> > > > catch:
> > > >
> > > > public ReturnType getOfNorm String fecha) throws RestClientException{
> > > > ReturnType respuesta = null;
> > > > try{
> > > > respuesta = proxy.getOfNorm(fecha);
> > > > }
> > > > catch(WebApplicationException e){
> > > > throwRestClientException(e);
> > > > }
> > > > return respuesta;
> > > > }
> > > >
> > > > Proxy initialized like this:
> > > >
> > > > List<Object> providers = new ArrayList<Object>();
> > > > JSONProvider jsonProvider = new RestClientJSONProvider();
> > > > jsonProvider.setConvention("badgerfish");
> > > > providers.add(jsonProvider);
> > > > proxy = JAXRSClientFactory.create(baseAddress, ConsultsService.class,
> > > > providers);
> > > >
> > > >
> > > > What I'd like to do is throwing from the client my own
> > > RestClientException
> > > > containing the info of the errorDetail, so I need to obtain the
> > > ErrorDetail
> > > > object in order to extract this info...
> > > >
> > > > First I thought I'd have to use the new ResponseReader, but the
> > response
> > > I
> > > > get from the ServerApplicationException does not contain the
> > ErrorDetail
> > > > (the entity looks empty), so I think I can't get it this way.
> However,
> > > the
> > > > exception does contain an errorMessage which is no other than the
> JSON
> > of
> > > > the errorDetail that I need...
> > > >
> > > > So, the (maybe noobie) question is: How can I get the object I need?
> Is
> > > > unmarshalling it from the errorMessage the only way?
> > > >
> > > > Thanks in advance,
> > > >
> > > > BR,
> > > >
> > > > Marcos
> > > >
> > > >
> > > >
> > >
> >
>
>
>
> --
> Sergey Beryozkin
>
> Application Integration Division of Talend <http://www.talend.com>
> http://sberyozkin.blogspot.com
>
--
Sergey Beryozkin
Application Integration Division of Talend <http://www.talend.com>
http://sberyozkin.blogspot.com