users@jersey.java.net

Re: [Jersey] Locale-Sensitive MessageBodyWriter

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Thu, 27 May 2010 18:20:08 +0200

On May 27, 2010, at 5:59 PM, Charles Overbeck wrote:

> Hi Paul,
>
> I'm not clear on how I would inject into the message body writer. It
> is what I would like to do, but I don't see how.
>
> I am modeling my writer on the Jersey entity-provider sample, so I
> have something like this:
>
> @Provider
> @Produces("application/pdf")
> public class PdfJAXBElementWriter implements
> MessageBodyWriter<JAXBElement<?>> {
> ...
> public void writeTo(JAXBElement<?> t, Class<?> type, Type
> genericType,
> Annotation[] annotations, MediaType mediaType,
> MultivaluedMap<String, Object> httpHeaders,
> OutputStream entityStream) throws IOException,
> WebApplicationException {
>
> // Would like to determine Accept-Language header here.
> // Generate PDF...
>
> ...
>
> I don't think I can inject the HttpHeaders into a field, because,
> based on debugging and println's, it looks like my
> PdfJAXBElementWriter is only instantiated once total, and not once
> per request. Wouldn't there be synchronization issues?
>

A thread local proxy is injected so it is safe to inject as a
constructor parameter, setter method parameter or a field. Do not
access the injected value when a request is not in scope otherwise an
IllegalStateException will be thrown.

Paul.


> I can't inject it into the writeTo method, because then I would no
> longer be implementing the MessageBodyWriter interface.
>
> Am I missing something obvious here?
>
> >>What will happen if an acceptable language is not supported?<<
>
> I'll probably just fall back to English.
>
> Thanks,
>
> Charles
>
>
>
> From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
> To: users_at_jersey.dev.java.net
> Sent: Thu, May 27, 2010 12:30:45 AM
> Subject: Re: [Jersey] Locale-Sensitive MessageBodyWriter
>
> Hi Charles,
>
> You can inject HttpHeaders and use:
>
> https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/core/HttpHeaders.html
> #getAcceptableLanguages%28%29
>
> to obtain the Accept-Language values.
>
> The @Produces can only be used for media types, it cannot be used to
> match the content language.
>
> To match on language can use the variants support if you wish:
>
> https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/core/Request.html
> #selectVariant%28java.util.List%29
>
> You can choose to do this in the resource method or in the message
> body writer, arguably the latter might better suit your needs. For
> the latter just be sure you set the header value before you write
> anything to the output stream.
>
> What will happen if an acceptable language is not supported?
>
> Paul.
>
> On May 27, 2010, at 3:18 AM, Charles Overbeck wrote:
>
>> Hi,
>>
>> I'm writing my first MessageBodyWriter, one that produces PDFs. Our
>> PDFs can be localized to various languages, so I want to use the
>> HTTP Accept-Language header to determine the language that the PDF
>> should be generated in.
>>
>> The MessageBodyWriter.writeTo() method has an HttpHeaders
>> parameter, but it is the outbound headers, not the inbound ones.
>>
>> The only think I can think of is to set the Content-Language header
>> in my annotated GET method, and then read the outbound header in my
>> writeTo() method. It changes my resource code from this though:
>>
>> @GET
>> @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_JSON})
>> public JAXBElement<InvoiceType> retrieveInvoice(@PathParam("id")
>> Long id) {
>> InvoiceType invoice = findInvoice(id);
>> return OBJECT_FACTORY.createInvoice(invoice);
>> }
>>
>> to:
>>
>> @Context
>> protected HttpServletRequest httpRequest;
>> ...
>> @GET
>> @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_JSON,
>> "application/pdf"})
>> public Response retrieveInvoice(@PathParam("id") Long id) {
>> InvoiceType invoice = findInvoice(id);
>> GenericEntity<JAXBElement<InvoiceType>> entity = new
>> GenericEntity<JAXBElement<InvoiceType>>(
>> invoice) {
>> };
>> return
>> Response
>> .status
>> (Status.OK).entity(entity).header(HttpHeaders.CONTENT_LANGUAGE,
>> determineContentLanguage(httpRequest).build();
>> }
>>
>> I'm hoping I'm missing something, and that I can keep my first
>> method, only having to change the @Produces.
>>
>> I'm using Jersey 1.5.1.1.
>>
>> Any help or thoughts appreciated in advance.
>>
>> Thanks,
>>
>> Charles
>
>