Should the JAX-RS Client pay attention to ContextResolver[s]?

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Should the JAX-RS Client pay attention to ContextResolver[s]?

exabrial12
I'm having trouble finding whether or not this is in the specification or
not, but lets say I want the JAX-RS client to use a custom JAXB Context that
I universally manage with CDI:
@ApplicationScopedpublic class JaxbContextResolver implements
ContextResolver {  @Inject  private JAXBContext jaxbContext;  @Override
public JAXBContext getContext(Class<?> type) {    return jaxbContext;  }}
I then call an endpoint that requires XML:
...@Injectprivate JaxbContextResolver jaxbContextResolver;...  Client client
= ClientBuilder.newClient();  client.register(jaxbContextResolver);
client.target("https://example.com").request("application/xml").post(Entity.entity(payload,
"application/xml"), Response.class);..
The problem I'm having is that the jax-rs client is never calling my
jaxbContextResolver.getContext() method. Are ContextResolver[s] supported on
the jax-rs client or is that not in the spec? I did notice that CXF attempts
to use a ContextResolver but it's not finding mine:
https://github.com/apache/cxf/blob/master/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java#L479




--
Sent from: http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
Reply | Threaded
Open this post in threaded view
|

Re: Should the JAX-RS Client pay attention to ContextResolver[s]?

Romain Manni-Bucau
Hello

AFAIK cxf does not support it client side and spec is silent on it even if
the api is always associated with server references ("resources"). Maybe
open a feature request, no reason the clientproviderfactory cant support it.

Now for your issue you can wire it in the provider when creating your
client so no real need of the resolver ;)

Le ven. 26 oct. 2018 18:38, exabrial12 <[hidden email]> a écrit :

> I'm having trouble finding whether or not this is in the specification or
> not, but lets say I want the JAX-RS client to use a custom JAXB Context
> that
> I universally manage with CDI:
> @ApplicationScopedpublic class JaxbContextResolver implements
> ContextResolver {  @Inject  private JAXBContext jaxbContext;  @Override
> public JAXBContext getContext(Class<?> type) {    return jaxbContext;  }}
> I then call an endpoint that requires XML:
> ...@Injectprivate JaxbContextResolver jaxbContextResolver;...  Client
> client
> = ClientBuilder.newClient();  client.register(jaxbContextResolver);
> client.target("https://example.com
> ").request("application/xml").post(Entity.entity(payload,
> "application/xml"), Response.class);..
> The problem I'm having is that the jax-rs client is never calling my
> jaxbContextResolver.getContext() method. Are ContextResolver[s] supported
> on
> the jax-rs client or is that not in the spec? I did notice that CXF
> attempts
> to use a ContextResolver but it's not finding mine:
>
> https://github.com/apache/cxf/blob/master/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java#L479
>
>
>
>
> --
> Sent from:
> http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
Reply | Threaded
Open this post in threaded view
|

Re: Should the JAX-RS Client pay attention to ContextResolver[s]?

exabrial12
Thanks for the information, I'll take a look at ClientProviderFactory and see
what would be involved.


I didn't understand what you mean though by "wire it in the provider"
though. Is there a way to specify a JAXB Context on the client?



--
Sent from: http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
Reply | Threaded
Open this post in threaded view
|

Re: Should the JAX-RS Client pay attention to ContextResolver[s]?

Romain Manni-Bucau
The messagebody reader/writer are trivial to impl if you have the context
so yes, just dont try to reuse cxf but just jaxrs here. Cxf logic is mainly
grabbing the jaxbcontext so if you have it no nees of that cxf logic.

You register you provider(s) and cxf should let it be taken cause user
providers are higher priority for the same media type.

Le ven. 26 oct. 2018 22:22, exabrial12 <[hidden email]> a écrit :

> Thanks for the information, I'll take a look at ClientProviderFactory and
> see
> what would be involved.
>
>
> I didn't understand what you mean though by "wire it in the provider"
> though. Is there a way to specify a JAXB Context on the client?
>
>
>
> --
> Sent from:
> http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
>
Reply | Threaded
Open this post in threaded view
|

Re: Should the JAX-RS Client pay attention to ContextResolver[s]?

exabrial12
Romain Manni-Bucau wrote
> You register you provider(s) and cxf should let it be taken cause user
> providers are higher priority for the same media type.

Got it, so create our own handlers for XML.


Romain Manni-Bucau wrote
> The messagebody reader/writer are trivial to impl if you have the context
> so yes, just dont try to reuse cxf but just jaxrs here. Cxf logic is
> mainly
> grabbing the jaxbcontext so if you have it no nees of that cxf logic.

Apologies, I'm not understanding what you're saying.

Given this:
https://github.com/apache/cxf/blob/master/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java#L479

I would suspect the "correct" way to fix it would be to to simply put all of
the Providers into the CXF MessageContext somehow?

Or, if you can tell me the best place to do it, I'll see if I can put a
patch together, just try to be as specific as possible. Thank you!



--
Sent from: http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
Reply | Threaded
Open this post in threaded view
|

Re: Should the JAX-RS Client pay attention to ContextResolver[s]?

Romain Manni-Bucau
Here what i has in mind:


public class MyClient {
    private MyClient() {
        // no-op
    }

    public static void main(final String[] args) throws JAXBException {
        Client client = ClientBuilder.newClient();
        try {
            client.register(new
MyJaxbProvider<>(JAXBContext.newInstance(MyRoot.class)))
                  .target("http://foo.bar")
                  .request()
                  .get();
        } finally {
            client.close();
        }
    }

    @XmlRootElement
    public static class MyRoot {
        // ...
    }

    // note: base impl, error handling + stream security to enhance etc
    public static class MyJaxbProvider<T> implements
MessageBodyReader<T>, MessageBodyWriter<T> {
        private final JAXBContext context;

        public MyJaxbProvider(final JAXBContext context) {
            this.context = context;
        }

        private boolean isJaxb(final Class<?> type) {
            return type.isAnnotationPresent(XmlRootElement.class) ||
type.isAnnotationPresent(XmlType.class);
        }

        @Override
        public boolean isReadable(final Class<?> type, final Type genericType,
                                  final Annotation[] annotations,
final MediaType mediaType) {
            return isJaxb(type);
        }

        @Override
        public T readFrom(final Class<T> type, final Type genericType,
Annotation[] annotations,
                          final MediaType mediaType, final
MultivaluedMap<String, String> httpHeaders,
                          final InputStream entityStream)
                throws WebApplicationException {
            // customize the xml size etc if no other protection in
front - see AbsrtactJAXBProvider configureReader
            try {
                return
context.createUnmarshaller().unmarshal(StaxUtils.createXMLStreamReader(entityStream),
type).getValue();
            } catch (final JAXBException e) {
                throw new WebApplicationException(Response.Status.BAD_REQUEST);
            }
        }

        @Override
        public boolean isWriteable(final Class<?> type, final Type genericType,
                                   final Annotation[] annotations,
final MediaType mediaType) {
            return isJaxb(type);
        }

        @Override
        public void writeTo(final T t, final Class<?> type, final Type
genericType,
                            final Annotation[] annotations, final
MediaType mediaType,
                            final MultivaluedMap<String, Object>
httpHeaders, final OutputStream entityStream)
                throws WebApplicationException {
            try {
                context.createMarshaller().marshal(t,
StaxUtils.createXMLStreamWriter(entityStream));
            } catch (final JAXBException e) {
                throw new WebApplicationException(Response.Status.BAD_REQUEST);
            }
        }
    }
}


Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


Le lun. 29 oct. 2018 à 15:41, exabrial12 <[hidden email]> a écrit :

> Romain Manni-Bucau wrote
> > You register you provider(s) and cxf should let it be taken cause user
> > providers are higher priority for the same media type.
>
> Got it, so create our own handlers for XML.
>
>
> Romain Manni-Bucau wrote
> > The messagebody reader/writer are trivial to impl if you have the
> context
> > so yes, just dont try to reuse cxf but just jaxrs here. Cxf logic is
> > mainly
> > grabbing the jaxbcontext so if you have it no nees of that cxf logic.
>
> Apologies, I'm not understanding what you're saying.
>
> Given this:
>
> https://github.com/apache/cxf/blob/master/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java#L479
>
> I would suspect the "correct" way to fix it would be to to simply put all
> of
> the Providers into the CXF MessageContext somehow?
>
> Or, if you can tell me the best place to do it, I'll see if I can put a
> patch together, just try to be as specific as possible. Thank you!
>
>
>
> --
> Sent from:
> http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
>
Reply | Threaded
Open this post in threaded view
|

Re: Should the JAX-RS Client pay attention to ContextResolver[s]?

exabrial12
In reply to this post by exabrial12
Actually, I just wrote my own MessageBodyReader/writer, annotated it with
@Provider, and it is _definitely not_ being invoked while using the JAXRS
client. Is that the expected behavior?

It *does* work if you call client.register(), but I thought anything
annotated @Provider was supposed to be picked up automatically.



--
Sent from: http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
Reply | Threaded
Open this post in threaded view
|

Re: Should the JAX-RS Client pay attention to ContextResolver[s]?

Romain Manni-Bucau
Yep, except you instantiate yourself the client outside any container so
you are the one to pick it up ;)

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


Le lun. 29 oct. 2018 à 16:32, exabrial12 <[hidden email]> a écrit :

> Actually, I just wrote my own MessageBodyReader/writer, annotated it with
> @Provider, and it is _definitely not_ being invoked while using the JAXRS
> client. Is that the expected behavior?
>
> It *does* work if you call client.register(), but I thought anything
> annotated @Provider was supposed to be picked up automatically.
>
>
>
> --
> Sent from:
> http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
>
Reply | Threaded
Open this post in threaded view
|

Re: Should the JAX-RS Client pay attention to ContextResolver[s]?

exabrial12
So, currently I'm not instantiating it. I tried both managing it with CDI
(@ApplicationScoped AND @Provider), no management (Just annotating
@Provider) and it didn't get picked up automatically. The only thing that
worked was @ApplicationScoped it and calling client.register on the CDI
managed instance. Is that expected behavior?



--
Sent from: http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
Reply | Threaded
Open this post in threaded view
|

Re: Should the JAX-RS Client pay attention to ContextResolver[s]?

Romain Manni-Bucau
yes

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


Le lun. 29 oct. 2018 à 16:41, exabrial12 <[hidden email]> a écrit :

> So, currently I'm not instantiating it. I tried both managing it with CDI
> (@ApplicationScoped AND @Provider), no management (Just annotating
> @Provider) and it didn't get picked up automatically. The only thing that
> worked was @ApplicationScoped it and calling client.register on the CDI
> managed instance. Is that expected behavior?
>
>
>
> --
> Sent from:
> http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
>
Reply | Threaded
Open this post in threaded view
|

Re: Should the JAX-RS Client pay attention to ContextResolver[s]?

exabrial12
So the @Provider annotation does nothing for the jaxrs client essentially. Is
this correct?



--
Sent from: http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
Reply | Threaded
Open this post in threaded view
|

Re: Should the JAX-RS Client pay attention to ContextResolver[s]?

Romain Manni-Bucau
yes

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


Le lun. 29 oct. 2018 à 16:53, exabrial12 <[hidden email]> a écrit :

> So the @Provider annotation does nothing for the jaxrs client essentially.
> Is
> this correct?
>
>
>
> --
> Sent from:
> http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
>