Custom JAXBElementTypedProvider for JAX-RS Services (CXF 3.4.1)

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

Custom JAXBElementTypedProvider for JAX-RS Services (CXF 3.4.1)

Stephen Evanchik
Hi everyone,

I am having trouble upgrading to CXF 3.4.1 from version 3.1.7

The issue is that the default JAXBElementProvider is being used instead of
the custom JAXBElementTypedProvider configured in my
JAXRSServerFactoryBean.setProviders() call.

The code in question from
https://github.com/apache/cxf/blob/master/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
:

protected static void initFactory(ProviderFactory factory) {
// ensure to not load providers not available in a module environment if
not needed
factory.setProviders(false,
false,
new BinaryDataProvider<Object>(),
new SourceProvider<Object>(),
DATA_SOURCE_PROVIDER_CLASS.tryCreateInstance(factory.getBus()),
new FormEncodingProvider<Object>(),
new StringTextProvider(),
new PrimitiveTextProvider<Object>(),
JAXB_PROVIDER_CLASS.tryCreateInstance(factory.getBus()),
JAXB_ELEMENT_PROVIDER_CLASS.tryCreateInstance(factory.getBus()),
MULTIPART_PROVIDER_CLASS.tryCreateInstance(factory.getBus()));

sets up a default list of providers.

Both JAXBElement providers are not configured correctly for my purpose
(because they have little to no configuration as expected).

Instead, I have a JAXBElementTypedProvider with a lot of configuration
injected in via the setProviders() call during initialization.

I assumed that because this is a "custom" provider and the
ProviderInfo.custom == true that my configured providers would take
precedence.

This seemed to be true in my trivial test case where I setup a bare bones
client/server application but is not true in the real application.

Upon examination of the state of the real application during initialization
I see that my custom JAXBElement providers sort first in the
MessageBodyWriter list. This is what I expected.

However, when I attempt to call the REST APIs, not only is the default
JAXBElementProvider  used but the MessageBodyWriter ArrayList has a
different sort with the customer JAXBElementTypedProvider after the default.

Is there a better way to control the providers? I'm simply instantiating
the existing JAXBElementTypedProvider class (no sub-classes).

Thanks,

--
Stephen Evanchik
Reply | Threaded
Open this post in threaded view
|

Re: Custom JAXBElementTypedProvider for JAX-RS Services (CXF 3.4.1)

Andy McCright
Hi Stephen,

From a purely JAX-RS perspective, you should be able to control the sort
order of the providers by using the `@Priority` annotation on the provider
classes (lower values in the annotation are executed before higher values)
in JAX-RS 2.1.  For JAX-RS 2.0 and earlier, any provider that you register
(either with the `@Provider` annotation or by specifying in the
getClasses() or getSingletons() method of an Application sub-class) should
take precedence over any built-in provider.

It sounds like the problem may be in how your custom provider is getting
registered.

Hope this helps,
Andy

On Wed, Feb 17, 2021 at 4:39 PM Stephen Evanchik <[hidden email]> wrote:

> Hi everyone,
>
> I am having trouble upgrading to CXF 3.4.1 from version 3.1.7
>
> The issue is that the default JAXBElementProvider is being used instead of
> the custom JAXBElementTypedProvider configured in my
> JAXRSServerFactoryBean.setProviders() call.
>
> The code in question from
>
> https://github.com/apache/cxf/blob/master/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
> :
>
> protected static void initFactory(ProviderFactory factory) {
> // ensure to not load providers not available in a module environment if
> not needed
> factory.setProviders(false,
> false,
> new BinaryDataProvider<Object>(),
> new SourceProvider<Object>(),
> DATA_SOURCE_PROVIDER_CLASS.tryCreateInstance(factory.getBus()),
> new FormEncodingProvider<Object>(),
> new StringTextProvider(),
> new PrimitiveTextProvider<Object>(),
> JAXB_PROVIDER_CLASS.tryCreateInstance(factory.getBus()),
> JAXB_ELEMENT_PROVIDER_CLASS.tryCreateInstance(factory.getBus()),
> MULTIPART_PROVIDER_CLASS.tryCreateInstance(factory.getBus()));
>
> sets up a default list of providers.
>
> Both JAXBElement providers are not configured correctly for my purpose
> (because they have little to no configuration as expected).
>
> Instead, I have a JAXBElementTypedProvider with a lot of configuration
> injected in via the setProviders() call during initialization.
>
> I assumed that because this is a "custom" provider and the
> ProviderInfo.custom == true that my configured providers would take
> precedence.
>
> This seemed to be true in my trivial test case where I setup a bare bones
> client/server application but is not true in the real application.
>
> Upon examination of the state of the real application during initialization
> I see that my custom JAXBElement providers sort first in the
> MessageBodyWriter list. This is what I expected.
>
> However, when I attempt to call the REST APIs, not only is the default
> JAXBElementProvider  used but the MessageBodyWriter ArrayList has a
> different sort with the customer JAXBElementTypedProvider after the
> default.
>
> Is there a better way to control the providers? I'm simply instantiating
> the existing JAXBElementTypedProvider class (no sub-classes).
>
> Thanks,
>
> --
> Stephen Evanchik
>
Reply | Threaded
Open this post in threaded view
|

Re: Custom JAXBElementTypedProvider for JAX-RS Services (CXF 3.4.1)

Stephen Evanchik
Hi Andy,

I was looking at the @Priority annotation to see if that would work but got
confused because in some of my tests, my provider (which is just an
instance of JAXBElementTypedProvider not a subclass) was sorting first. I
couldn't reproduce this behavior reliably.

My solution, for the moment, is to use reflection and remove the two
providers from the Message Reader/Writers arrays. Not pretty at all but I'd
rather not have default providers (for the JAXB stuff anyway) that cannot
be configured.

Stephen

On Fri, Feb 19, 2021 at 1:20 PM Andy McCright <[hidden email]>
wrote:

> Hi Stephen,
>
> From a purely JAX-RS perspective, you should be able to control the sort
> order of the providers by using the `@Priority` annotation on the provider
> classes (lower values in the annotation are executed before higher values)
> in JAX-RS 2.1.  For JAX-RS 2.0 and earlier, any provider that you register
> (either with the `@Provider` annotation or by specifying in the
> getClasses() or getSingletons() method of an Application sub-class) should
> take precedence over any built-in provider.
>
> It sounds like the problem may be in how your custom provider is getting
> registered.
>
> Hope this helps,
> Andy
>
> On Wed, Feb 17, 2021 at 4:39 PM Stephen Evanchik <[hidden email]>
> wrote:
>
> > Hi everyone,
> >
> > I am having trouble upgrading to CXF 3.4.1 from version 3.1.7
> >
> > The issue is that the default JAXBElementProvider is being used instead
> of
> > the custom JAXBElementTypedProvider configured in my
> > JAXRSServerFactoryBean.setProviders() call.
> >
> > The code in question from
> >
> >
> https://github.com/apache/cxf/blob/master/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
> > :
> >
> > protected static void initFactory(ProviderFactory factory) {
> > // ensure to not load providers not available in a module environment if
> > not needed
> > factory.setProviders(false,
> > false,
> > new BinaryDataProvider<Object>(),
> > new SourceProvider<Object>(),
> > DATA_SOURCE_PROVIDER_CLASS.tryCreateInstance(factory.getBus()),
> > new FormEncodingProvider<Object>(),
> > new StringTextProvider(),
> > new PrimitiveTextProvider<Object>(),
> > JAXB_PROVIDER_CLASS.tryCreateInstance(factory.getBus()),
> > JAXB_ELEMENT_PROVIDER_CLASS.tryCreateInstance(factory.getBus()),
> > MULTIPART_PROVIDER_CLASS.tryCreateInstance(factory.getBus()));
> >
> > sets up a default list of providers.
> >
> > Both JAXBElement providers are not configured correctly for my purpose
> > (because they have little to no configuration as expected).
> >
> > Instead, I have a JAXBElementTypedProvider with a lot of configuration
> > injected in via the setProviders() call during initialization.
> >
> > I assumed that because this is a "custom" provider and the
> > ProviderInfo.custom == true that my configured providers would take
> > precedence.
> >
> > This seemed to be true in my trivial test case where I setup a bare bones
> > client/server application but is not true in the real application.
> >
> > Upon examination of the state of the real application during
> initialization
> > I see that my custom JAXBElement providers sort first in the
> > MessageBodyWriter list. This is what I expected.
> >
> > However, when I attempt to call the REST APIs, not only is the default
> > JAXBElementProvider  used but the MessageBodyWriter ArrayList has a
> > different sort with the customer JAXBElementTypedProvider after the
> > default.
> >
> > Is there a better way to control the providers? I'm simply instantiating
> > the existing JAXBElementTypedProvider class (no sub-classes).
> >
> > Thanks,
> >
> > --
> > Stephen Evanchik
> >
>


--
Stephen Evanchik
Reply | Threaded
Open this post in threaded view
|

Re: Custom JAXBElementTypedProvider for JAX-RS Services (CXF 3.4.1)

Andy McCright
What sort of config do you need? Would a ContextResolver<JAXBContext>
provider work for you?

https://stackoverflow.com/questions/25817969/what-is-a-jaxb-provider-jaxb-handler-and-contextresolvers


On Fri, Feb 19, 2021 at 12:25 PM Stephen Evanchik <[hidden email]>
wrote:

> Hi Andy,
>
> I was looking at the @Priority annotation to see if that would work but got
> confused because in some of my tests, my provider (which is just an
> instance of JAXBElementTypedProvider not a subclass) was sorting first. I
> couldn't reproduce this behavior reliably.
>
> My solution, for the moment, is to use reflection and remove the two
> providers from the Message Reader/Writers arrays. Not pretty at all but I'd
> rather not have default providers (for the JAXB stuff anyway) that cannot
> be configured.
>
> Stephen
>
> On Fri, Feb 19, 2021 at 1:20 PM Andy McCright <[hidden email]
> >
> wrote:
>
> > Hi Stephen,
> >
> > From a purely JAX-RS perspective, you should be able to control the sort
> > order of the providers by using the `@Priority` annotation on the
> provider
> > classes (lower values in the annotation are executed before higher
> values)
> > in JAX-RS 2.1.  For JAX-RS 2.0 and earlier, any provider that you
> register
> > (either with the `@Provider` annotation or by specifying in the
> > getClasses() or getSingletons() method of an Application sub-class)
> should
> > take precedence over any built-in provider.
> >
> > It sounds like the problem may be in how your custom provider is getting
> > registered.
> >
> > Hope this helps,
> > Andy
> >
> > On Wed, Feb 17, 2021 at 4:39 PM Stephen Evanchik <[hidden email]>
> > wrote:
> >
> > > Hi everyone,
> > >
> > > I am having trouble upgrading to CXF 3.4.1 from version 3.1.7
> > >
> > > The issue is that the default JAXBElementProvider is being used instead
> > of
> > > the custom JAXBElementTypedProvider configured in my
> > > JAXRSServerFactoryBean.setProviders() call.
> > >
> > > The code in question from
> > >
> > >
> >
> https://github.com/apache/cxf/blob/master/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
> > > :
> > >
> > > protected static void initFactory(ProviderFactory factory) {
> > > // ensure to not load providers not available in a module environment
> if
> > > not needed
> > > factory.setProviders(false,
> > > false,
> > > new BinaryDataProvider<Object>(),
> > > new SourceProvider<Object>(),
> > > DATA_SOURCE_PROVIDER_CLASS.tryCreateInstance(factory.getBus()),
> > > new FormEncodingProvider<Object>(),
> > > new StringTextProvider(),
> > > new PrimitiveTextProvider<Object>(),
> > > JAXB_PROVIDER_CLASS.tryCreateInstance(factory.getBus()),
> > > JAXB_ELEMENT_PROVIDER_CLASS.tryCreateInstance(factory.getBus()),
> > > MULTIPART_PROVIDER_CLASS.tryCreateInstance(factory.getBus()));
> > >
> > > sets up a default list of providers.
> > >
> > > Both JAXBElement providers are not configured correctly for my purpose
> > > (because they have little to no configuration as expected).
> > >
> > > Instead, I have a JAXBElementTypedProvider with a lot of configuration
> > > injected in via the setProviders() call during initialization.
> > >
> > > I assumed that because this is a "custom" provider and the
> > > ProviderInfo.custom == true that my configured providers would take
> > > precedence.
> > >
> > > This seemed to be true in my trivial test case where I setup a bare
> bones
> > > client/server application but is not true in the real application.
> > >
> > > Upon examination of the state of the real application during
> > initialization
> > > I see that my custom JAXBElement providers sort first in the
> > > MessageBodyWriter list. This is what I expected.
> > >
> > > However, when I attempt to call the REST APIs, not only is the default
> > > JAXBElementProvider  used but the MessageBodyWriter ArrayList has a
> > > different sort with the customer JAXBElementTypedProvider after the
> > > default.
> > >
> > > Is there a better way to control the providers? I'm simply
> instantiating
> > > the existing JAXBElementTypedProvider class (no sub-classes).
> > >
> > > Thanks,
> > >
> > > --
> > > Stephen Evanchik
> > >
> >
>
>
> --
> Stephen Evanchik
>