I'm using:
Jersey 1.1.5
Atmosphere 0.52
GlassFish v2.1
What I have is a set of custom objects which all implement an interface,
i.e. CustomMessage. I want to create a MessageBodyWriter which always
produces "application/xml" content, however, it is up to the
implementation of each of these custom classes to generate the actual
XML string (they can have static content, or need to be generated
dynamically at writing time)
The reason for this is because these messages are being broadcasted
(scheduled, delayed) by Atmosphere, so the idea is that my custom
MessageBodyWriter will detect if the message requires dynamically
generated content, and if so it will do so before determining the size
and then writing it to the output stream.
This works fine, until my CustomMessage impl class has JAXB annotations
on it, and it seems to (inconsistently) choose mine, or the default
writer for JAXB classes.
By inconsistent, I mean that i have two atmosphere services. One
suspends, and one initiates a delayed broadcast. If request A suspends,
and request B initiates a broadcast, the writing of B's response hits my
message body writer, while the writing of A does not.
The return for B looks like this:
return new Broadcastable((CustomMessage) new CustomServerTimeMessage(),
topic);
Now, if CustomServerTimeMessage does not use any JAXB annotations, my
custom message body writer will be hit for both the response written to
B and A, but with JAXB annotations, my message body writer is only hit
for the response written to B.
The services defined for both B and A consume "application/xml".
How am I supposed to (correctly) guarantee that my MessageBodyWriter for
all instances of CustomMessage will be used?
My MessageBodyWriter looks like this:
package com.mycompany.acmm.comet.message.writer;
import com.mycompany.acmm.comet.message.CustomMessage;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
@Provider
@Produces( { MediaType.APPLICATION_XML })
public class CustomMessageWriter implements
MessageBodyWriter<CustomMessage> {
public CustomMessageWriter() {
}
@Override
public long getSize(final CustomMessage message, Class<?> type, final
Type genericType, final Annotation[] annotations, final MediaType
mediaType) {
if (!message.isStaticContent()) {
message.generateContent();
}
return message.getSize();
}
@Override
public boolean isWriteable(final Class<?> type, final Type
genericType, final Annotation[] annotations, final MediaType mediaType) {
return CustomMessage.class.isAssignableFrom(type);
}
@Override
public void writeTo(final CustomMessage message, final Class<?> type,
final Type genericType, final Annotation[] annotations, final MediaType
mediaType,
final MultivaluedMap<String, Object> httpHeaders, final
OutputStream entityStream) throws IOException, WebApplicationException {
entityStream.write(message.getBodyAsString().getBytes());
}
}