On Apr 21, 2010, at 11:19 PM, Laird Nelson wrote:
> I have a MessageBodyWriter intended to intercept essentially
> everything except a WrapperObject (see below), create a new
> WrapperObject around the original return value, and then hand the now
> "full" WrapperObject back off to the normal Jersey/JAXB XML
> marshalling process.
>
> To do this, my MessageBodyWriter is declared as
> MessageBodyWriter<Object>, is annotated with @Provider and
> @Produces("application/xml").
>
> Inside my isWriteable() method, if the incoming object is a
> WrapperObject, then I return false. This is so that (I hope) when
> Jersey is looking for a MessageBodyWriter, it passes me by in favor of
> any other pre-installed MessageBodyWriters that know how to marshal a
> WrapperObject. Since WrapperObject is all annotated with various JAXB
> elements, then the default JAXB message body writer shipped with
> Jersey should deal with it just fine.
>
> Inside my writeTo() method, I check to see if the incoming type is a
> WrapperObject, which it should not be. Once I've determined that it's
> something else, I create a new WrapperObject, wrap up the incoming
> object, use Providers#getMessageBodyWriter to get a MessageBodyWriter
> for a WrapperObject, and then forward the writeTo call to it.
>
> Again, the gist here is that I eat all resource class return values,
> wrap them in another object, and then allow Jersey to continue its
> normal processing.
>
> My first rudimentary question, which I'm sure is answered in some
> documentation somewhere, is: how do I make Jersey in a Java EE 6
> environment aware of my MessageBodyWriter? Is the classpath scanned
> for all @Providers, or must I also put it in META-INF/services?
>
Do not use META-INF/services.
Annotate the class with @Provider and make sure it gets registered.
https://jersey.dev.java.net/nonav/documentation/latest/user-
guide.html#d4e194
Application-based providers will take precedence over Jersey-based
providers.
> My second question which I hope is not rudimentary, is that I appear
> to be seeing that my MessageBodyWriter is bypassed entirely when the
> return type of a resource class is Collection<Something>. It appears,
> perhaps, that another MessageBodyWriter is getting selected, and mine
> never enters the mix. If the return type is, say, some regular old
> business object type class, then my Writer gets involved (and then I
> get a whole host of JAXB errors that make no sense; we'll tackle that
> later).
Can you send me a reproducible test case?
I find it so much easier to discuss with code than with just prose :-)
> If a MessageBodyWriter is registered for a type of
> <Collection> (by Jersey itself, presumably?), and then I come along
> and register a MessageBodyWriter for a type of <Object>, then which
> one will be selected? How can I override this, if registering a
> MessageBodyWriter<Object> is not the way to go?
>
It might be due to your isWriteable implementation method. Need code.
Jersey does not register any MBW with a generic type declaration of
Collection.
Here is the implementation of AbstractListElementProvider:
public abstract class AbstractListElementProvider extends
AbstractJAXBProvider<Object> {
...
public boolean isWriteable(Class<?> type, Type genericType,
Annotation annotations[], MediaType mediaType) {
if (List.class.isAssignableFrom(type)) {
return verifyGenericType(genericType) &&
isSupported(mediaType);
} else if (type.isArray()) {
return verifyArrayType(type) && isSupported(mediaType);
} else
return false;
}
...
}
Paul.