Discussion:
Unmarshal WebApplicationException Response JSON entity
DmitryM
2010-02-27 07:46:51 UTC
Permalink
Hello, guys

Sorry for a dumb question but I'm kinda new to CXF (and web services in
general).

Here is the issue:
- I created an ExceptionMapper to translate checked exceptions into Response
with 500 code and a JSON body.
That works perfectly fine. I see properly marshalled/serialized JSON wrapper
like this:
Payload:
{"exceptionHolder":[{"exceptionClassName":"com.xxx.exceptions.MyException"}]}

- But I failed to find a proper way (on both Nabble and CXF site) to
unmarshal the incoming Request body.
Is there an elegant (as little code as possible) way to do that?
Should it be done via data bindings or via some other way?
Any directions, please?

Thanks,
Dmitry
--
View this message in context: http://old.nabble.com/Unmarshal-WebApplicationException-Response-JSON-entity-tp27726278p27726278.html
Sent from the cxf-user mailing list archive at Nabble.com.
DmitryM
2010-02-27 22:35:42 UTC
Permalink
A bit of clarification about what I would like to achieve.

When I'm doing exception mapping I do simple
Response.serverError().entity(xxx).build() and it produces perfectly
formatted JSON response.

On the client side I have a Java proxy which in this case gets
WebApplicationException.

I can get the JSON text from it (produced by the server-side marshaller).

But my question is: is there any simple/easy way to have that JSON
unmarshalled into the same class' instance which was used by the server-side
marshaller?
Does it have anything to do with data bindings?
Can you please point me to an example?
--
View this message in context: http://old.nabble.com/Unmarshal-WebApplicationException-Response-JSON-entity-tp27726278p27731548.html
Sent from the cxf-user mailing list archive at Nabble.com.
Sergey Beryozkin
2010-02-28 15:09:02 UTC
Permalink
Hi

You said in the follow-up email that you were using a proxy on the client side. So you may want to register a ResponseExceptionHandler :
http://cxf.apache.org/docs/jax-rs.html#JAX-RS-Handlingexceptions

This handler may create an instance of JSONProvider and pass the JSON-formatted string to it and then return the resulting instance, possibly by adding it to a custom WebApplicationException

Cheers, Sergey

-----Original Message-----
From: DmitryM [mailto:nskmda_forspam-JGs/***@public.gmane.org]
Sent: 27 February 2010 07:47
To: users-qJ/***@public.gmane.org
Subject: Unmarshal WebApplicationException Response JSON entity


Hello, guys

Sorry for a dumb question but I'm kinda new to CXF (and web services in
general).

Here is the issue:
- I created an ExceptionMapper to translate checked exceptions into Response
with 500 code and a JSON body.
That works perfectly fine. I see properly marshalled/serialized JSON wrapper
like this:
Payload:
{"exceptionHolder":[{"exceptionClassName":"com.xxx.exceptions.MyException"}]}

- But I failed to find a proper way (on both Nabble and CXF site) to
unmarshal the incoming Request body.
Is there an elegant (as little code as possible) way to do that?
Should it be done via data bindings or via some other way?
Any directions, please?

Thanks,
Dmitry
--
View this message in context: http://old.nabble.com/Unmarshal-WebApplicationException-Response-JSON-entity-tp27726278p27726278.html
Sent from the cxf-user mailing list archive at Nabble.com.
DmitryM
2010-03-01 05:12:56 UTC
Permalink
Sergey, thanks a lot for the response.

I'm a little confused here. I couldn't find ResponseExceptionHandler in the
latest API doc (the link from the main CXF page).

Is there an example how to do that handler registration?

Did you mean it was possible to have a generic handler for a
WebApplicationException on the client side which could replace the
WebApplicationException's Response's entity (which I currently see as a
formatted JSON) with a specific Java class?

Thanks,
Dmitry
Post by Sergey Beryozkin
You said in the follow-up email that you were using a proxy on the client
http://cxf.apache.org/docs/jax-rs.html#JAX-RS-Handlingexceptions
This handler may create an instance of JSONProvider and pass the
JSON-formatted string to it and then return the resulting instance,
possibly by adding it to a custom WebApplicationException
Cheers, Sergey
--
View this message in context: http://old.nabble.com/Unmarshal-WebApplicationException-Response-JSON-entity-tp27726278p27740239.html
Sent from the cxf-user mailing list archive at Nabble.com.
Sergey Beryozkin
2010-03-01 11:10:06 UTC
Permalink
Hi

please see comments inline

cheers, Sergey
Post by DmitryM
Sergey, thanks a lot for the response.
I'm a little confused here. I couldn't find ResponseExceptionHandler in the
latest API doc (the link from the main CXF page).
S.B : It's linked to from the page I linked to in the previous email,
here's another link :
http://svn.apache.org/repos/asf/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ResponseExceptionMapper.java

(actually, it's not a ResponseExceptionHandler, sorry)
Post by DmitryM
Is there an example how to do that handler registration?
S.B : If you're creating a proxy from the code then one of the
JAXRSClientFactory create methods will accept a list of providers. If you're
injecting a proxy using jaxrs:client then you can use
jaxrs:client/jaxrs:providers to inject a list of providers...
Post by DmitryM
Did you mean it was possible to have a generic handler for a
WebApplicationException on the client side which could replace the
WebApplicationException's Response's entity (which I currently see as a
formatted JSON) with a specific Java class?
S.B : ResponseExceptionMapper would be given a chance to react when it is
HTTP 500 (and similar). If it is not available or returns null then
WebApplicationException is thrown, otherwise it can convert a Response into
whatever exception it needs, so what it can do is to convert an
(InputStream)Response.getEntity into a specific Java class using a default
JSONProvider and then 'attach' it to some exception instance,
WebApplicationException or some other one...
Post by DmitryM
Thanks,
Dmitry
You said in the follow-up email that you were using a proxy on the client
http://cxf.apache.org/docs/jax-rs.html#JAX-RS-Handlingexceptions
This handler may create an instance of JSONProvider and pass the
JSON-formatted string to it and then return the resulting instance,
possibly by adding it to a custom WebApplicationException
Cheers, Sergey
--
http://old.nabble.com/Unmarshal-WebApplicationException-Response-JSON-entity-tp27726278p27740239.html
Sent from the cxf-user mailing list archive at Nabble.com.
DmitryM
2010-03-01 20:20:57 UTC
Permalink
Sergey,
Post by Sergey Beryozkin
please see comments inline
Thanks for the comments.
Looks like I'm getting closer.
But I still have a question.
Can you please comment on the parameters value for the JSONProvider.readFrom
method
(on those except for the apparent first and last one):

public java.lang.Object readFrom(java.lang.Class<java.lang.Object> type,
java.lang.reflect.Type genericType,
java.lang.annotation.Annotation[] anns,
javax.ws.rs.core.MediaType mt,

javax.ws.rs.core.MultivaluedMap<java.lang.String,java.lang.String> headers,
java.io.InputStream is) throws
java.io.IOException

Thanks,
Dmitry
--
View this message in context: http://old.nabble.com/Unmarshal-WebApplicationException-Response-JSON-entity-tp27726278p27748553.html
Sent from the cxf-user mailing list archive at Nabble.com.
Sergey Beryozkin
2010-03-01 21:37:16 UTC
Permalink
Hi

Please see

https://jsr311.dev.java.net/nonav/releases/1.0/javax/ws/rs/ext/MessageBodyReader.html#isReadable(java.lang.Class,%20java.lang.reflect.Type,%20java.lang.annotation.Annotation[],%20javax.ws.rs.core.MediaType)

some more comments inline

cheers, Sergey
Post by DmitryM
Sergey,
Post by Sergey Beryozkin
please see comments inline
Thanks for the comments.
Looks like I'm getting closer.
But I still have a question.
Can you please comment on the parameters value for the
JSONProvider.readFrom
method
public java.lang.Object readFrom(java.lang.Class<java.lang.Object> type,
java.lang.reflect.Type genericType,
java.lang.annotation.Annotation[] anns,
javax.ws.rs.core.MediaType mt,
javax.ws.rs.core.MultivaluedMap<java.lang.String,java.lang.String> headers,
java.io.InputStream is) throws
java.io.IOException
Post by Sergey Beryozkin
genericType - can be the same as the first parameter
anns - annotations attached to a method parameter representing a
request/response body
Post by DmitryM
mt - media type of the request/response
headers : request/response HTTP headers
when invoking JSONProvider directly you can probably only set a genericType
parameter, pass an empty annotations array, then MediaType.APPLICATION_JSON,
and null for headers. Benson was keen for providers like JSONProvider to be
parameterized by T but I did not get to fixing it



Thanks,
Post by DmitryM
Dmitry
--
http://old.nabble.com/Unmarshal-WebApplicationException-Response-JSON-entity-tp27726278p27748553.html
Sent from the cxf-user mailing list archive at Nabble.com.
DmitryM
2010-03-01 22:19:44 UTC
Permalink
Sergey,

Looks like parametrizing JSONProvider could be a good idea, but I managed to
get away with the following code:

MyExceptionWrapper unmarshalledObject =
(MyExceptionWrapper)jsonProvider.readFrom(
(Class)((Object)new MyExceptionWrapper()).getClass(),
null, null, MediaType.APPLICATION_JSON_TYPE, null,
(InputStream)new
ByteArrayInputStream(response.getEntity().toString().getBytes()));
exceptionWrapper = (MyExceptionWrapper)unmarshalledObject;
exClass = (Class<PimsCheckedException>)
Class.forName(exceptionWrapper.exceptionClassName);

It does look a little ugly (especially because I had to cast my class to
Object since JSONProvider implements ), but it works.
Please, if you have a few minutes, let me know if it could have been done in
a simpler way (I could not figure out how to get a specific writer for a
specific class)

Thanks,
Dmitry
Post by Sergey Beryozkin
Please see
https://jsr311.dev.java.net/nonav/releases/1.0/javax/ws/rs/ext/MessageBodyReader.html#isReadable(java.lang.Class,%20java.lang.reflect.Type,%20java.lang.annotation.Annotation[],%20javax.ws.rs.core.MediaType)
--
View this message in context: http://old.nabble.com/Unmarshal-WebApplicationException-Response-JSON-entity-tp27726278p27749802.html
Sent from the cxf-user mailing list archive at Nabble.com.
Sergey Beryozkin
2010-03-02 09:48:24 UTC
Permalink
Hi

JSONProvider is not really meant to be used as a utility class, the way
you're using it, I suggested it for you be able to get the exception bean
populated quickly. I think all the code is there at the ProviderFactory
level for users be able to do JSONProvider<Bar> but there could be some
custom providers extending JSONProvider out there so properly parameterizing
JSONProvider can have side-effects. It has to be done eventually. In
reality, it is mainly the users doing the unit testing which have to write
the rather 'clumsy' code similar to the one you did.

I guess what you really would like to do is to write some simple
Jettison-specific code to be used inside of your exception mapper which will
use a statically allocated JAXBContext (for your exception data bean) to get
an Unmarshaller and then use it to read from a basic XMLStreamReader created
by Jettison, please have a look at JSOnProvider.readFrom, 2/3 lines of code
can be found there showing how to create a basic JSON-aware reader

hope it helps, Sergey
Post by DmitryM
Sergey,
Looks like parametrizing JSONProvider could be a good idea, but I managed to
MyExceptionWrapper unmarshalledObject =
(MyExceptionWrapper)jsonProvider.readFrom(
(Class)((Object)new
MyExceptionWrapper()).getClass(),
null, null,
MediaType.APPLICATION_JSON_TYPE, null,
(InputStream)new
ByteArrayInputStream(response.getEntity().toString().getBytes()));
exceptionWrapper =
(MyExceptionWrapper)unmarshalledObject;
exClass = (Class<PimsCheckedException>)
Class.forName(exceptionWrapper.exceptionClassName);
It does look a little ugly (especially because I had to cast my class to
Object since JSONProvider implements ), but it works.
Please, if you have a few minutes, let me know if it could have been done in
a simpler way (I could not figure out how to get a specific writer for a
specific class)
Thanks,
Dmitry
Post by Sergey Beryozkin
Please see
https://jsr311.dev.java.net/nonav/releases/1.0/javax/ws/rs/ext/MessageBodyReader.html#isReadable(java.lang.Class,%20java.lang.reflect.Type,%20java.lang.annotation.Annotation[],%20javax.ws.rs.core.MediaType)<https://jsr311.dev.java.net/nonav/releases/1.0/javax/ws/rs/ext/MessageBodyReader.html#isReadable%28java.lang.Class,%20java.lang.reflect.Type,%20java.lang.annotation.Annotation%5B%5D,%20javax.ws.rs.core.MediaType%29>
--
http://old.nabble.com/Unmarshal-WebApplicationException-Response-JSON-entity-tp27726278p27749802.html
Sent from the cxf-user mailing list archive at Nabble.com.
DmitryM
2010-03-02 17:37:32 UTC
Permalink
Sergey, thanks a lot for your response.
Post by Sergey Beryozkin
I guess what you really would like to do is to write some simple
Jettison-specific code to be used inside of your exception mapper which will
use a statically allocated JAXBContext (for your exception data bean) to get
an Unmarshaller and then use it to read from a basic XMLStreamReader created
by Jettison, please have a look at JSOnProvider.readFrom, 2/3 lines of code
can be found there showing how to create a basic JSON-aware reader
I took a look into the JSONProvider source code.
To me it doesn't really look as a 2-3 lines of code.
There is actually a whole bunch of methods to create context, unmarshaller
(it's inherited from the AbstractJaxbProvider), then create xml stream
reader and so on and on and on.
If I go this way my code would not be as simple as it's now.

I guess, I will stick to 1-line JSONProvider call (though ugly but not
really making me copy-paste the CXF code which is already available via that
readFrom call).

Anyway, thank a lot for all the help.
It was really useful.

Dmitry
--
View this message in context: http://old.nabble.com/Unmarshal-WebApplicationException-Response-JSON-entity-tp27726278p27758769.html
Sent from the cxf-user mailing list archive at Nabble.com.
Loading...