cxf-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Marcos Díez Fernández <md...@tecsisa.com>
Subject RE: Extracting object from Response when ServerWebApplicationException occurs
Date Mon, 21 Mar 2011 16:09:57 GMT
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>:
	
	MultivaluedMap<String,Object> responseMetadataMap = response.getMetadata();
	MetadataMap<String,String> metadataMap = new MetadataMap<String, String>();
	Iterator i = responseMetadataMap.entrySet().iterator();
	while(i.hasNext()){
		Map.Entry entry = (Map.Entry)i.next();
		String str1 = (String)entry.getKey();
		String str2 = (String)((ArrayList<Object>)entry.getValue()).get(0);
		metadataMap.add(str1, str2);			
	}
	
	
	ErrorDetail errorDetail = (ErrorDetail) jsonProvider.readFrom(
						(Class)ErrorDetail.class, 
						(Class)ErrorDetail.class,
						new Annotation[]{}, 
						MediaType.APPLICATION_JSON_TYPE,
						metadataMap, 
						(InputStream)response.getEntity());


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 (?).

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:sberyozkin@gmail.com] 
Enviado el: lunes, 21 de marzo de 2011 13:14
Para: users@cxf.apache.org
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 <mdiez@tecsisa.com>

> 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:sberyozkin@gmail.com]
> Enviado el: martes, 15 de marzo de 2011 23:20
> Para: users@cxf.apache.org
> 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 <mdiez@tecsisa.com>
>
> > Ok, thank you Sergey, I'll wait for your reply.
> >
> > BR,
> > Marcos.
> >
> > -----Mensaje original-----
> > De: Sergey Beryozkin [mailto:sberyozkin@gmail.com]
> > Enviado el: martes, 15 de marzo de 2011 10:53
> > Para: users@cxf.apache.org
> > 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 <mdiez@tecsisa.com>
> >
> > > Any help? Thanks.
> > >
> > > -----Mensaje original-----
> > > De: Marcos Díez Fernández [mailto:mdiez@tecsisa.com]
> > > Enviado el: lunes, 14 de marzo de 2011 13:43
> > > Para: users@cxf.apache.org
> > > 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

Mime
View raw message