I am not trying to solve any problem in particular, but rather I am on a learning path to jersey.
I have an entity class marked like this:
@Entity
@Table(name = "myentity")
@XmlRootElement
public class MyEntity implements serializable {
// lots of methods...
}
and the corresponding jersey service
@Stateless
@Path("entity")
public class EntityFacade {
@GET
@Path("{param}")
@Produces({"application/xml;charset=UTF-8"})
public List<MyEntity> find(@PathParam("param") String param) {
List entities = entityManager.getResultList(); // retrieve list from db
return entities;
}
}
Which give a correct XML response. Supposing I want to write a MessageBodyWriter which replicate same behavior, which is producing an XML response, how could I do that ?
@Provider
public class TrasformerMessageBodyWriter implements MessageBodyWriter<Object> {
@Override
public long getSize(Object o, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return 0;
}
@Override
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
// return true or false depending if I want to rewrite the response
}
@Override
public void writeTo(Object o, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException,
WebApplicationException {
// what do I need to write here...
}
}
by marking with @Provider annotation I can see the message body writer is correctly invoked.
When writeTo is invoked, Object o is a Vector and Type genericType is a List but at this point I am completely lost on how I could transform the object in XML.
Last, if everything is already provided by jersey and its annotations, how can a MessageBodyWriter be useful ?
Again, I am repeating that this is just an academic exercise.
Typically one would use a MessageBodyWriter
to convert objects to data formats that Jersey knows nothing about. Here's an example of translating a TableData
domain object to CSV:
@Singleton
@Produces("text/csv")
@Provider
public class FederationCsvWriter implements MessageBodyWriter<TableData> {
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return TableData.class.isAssignableFrom(type);
}
@Override
public long getSize(TableData data, Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType) {
return -1;
}
@Override
public void writeTo(TableData data, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, Object> headers, OutputStream out) throws IOException {
Writer osWriter = new OutputStreamWriter(out);
CSVWriter writer = new CSVWriter(osWriter, ',', '"', "\r\n");
if (data.getResultCount() > 0) {
//Write the header
writer.writeNext(data.getResult().get(0).keySet().toArray(new String[data.getResult().get(0).keySet().size()]));
//Write the data
for (ModelData row: data.getResult()) {
writer.writeNext(row.values().toArray(new String[row.values().size()]));
}
}
writer.flush();
}
}
In your example you could either create XML by inspecting the object yourself and feeding the result to the OutputStream
or your could use JAXB (which Jersey uses internally) to marshall the objects directly to the OutputStream
. For the purposes of your exercise JAXB is probably more interesting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With