users@jersey.java.net

Re: [Jersey] JSONP Outputfilter

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Fri, 24 Jul 2009 12:12:22 +0200

Hi,

You code looks almost OK :-)

I think you need to check:

   1) If a response entity is set, if (response.getEntity() != null);
and

   2) If the content-type of the response is "application/x-
javascript". It is not sufficient to check if that media type is
        acceptable because it might not be the most acceptable.

If you get the output "callback=(" then this can occur if a resource
method does not return an entity (one could view the fact that finish
is not called as a bug in this respect and it should be called
regardless of whether an entity is present or not).


It is clear from looking at the ContainerResponse class that there are
a number of ways this can be made easier for you, such as
ContainerResponse.getContentType can be made public.

It should be possible to wrap the entity around a JSONWithPadding
instance and then you do not need to adapt the
ContainerResponseWriter. The following can be done for cases when
GenericEntity is not used (which is created when stuff like List<T> is
used). So you can do:

     if (content type is "application/x-javascript" &&
response.getEntity() != null) {
       response.setEntity(new JSONWithPadding(response.getEntity());
     }



So i think you can get things to work, but in summary there also need
to be some improvements to make this easier:

1) ContainerResponseWriter.finish needs to be called when there is no
response entity.

2) ContainerResponse.getContentType should be a public method.

3) It should be possible to get the "raw" entity that was returned by
a resource method.

Paul.

On Jul 24, 2009, at 11:47 AM, tarjei wrote:

> Hi, I'm trying to implement JSONP on top of a solution that allready
> produces JSON and XML. As such, I do not want to rewrite my classes
> to return JSONWithPadding objects.
>
> I found some information [1] saying that I can do this by
> implementing an extra filter that adds wraps the JSON with a callback.
>
> I've tried implementing the filter, but somehow I'm missing an
> important line as the filter only returns callback=( and no content
> when I try to use it. The filter is below. I think I'm missing just
> something crucial, I just do not know what :)
>
> Is there a transparent way to do this in Jersey that I do not know
> about?
>
>
> /**
> * See: http://n2.nabble.com/JSONP-Callback-support-tc2260544.html
> */
> public class JSONCallbackResponseFilter implements
> ContainerResponseFilter {
> Logger log = Logger.getLogger(getClass());
> public ContainerResponse filter(ContainerRequest request,
> ContainerResponse response) {
> if (!request.getAcceptableMediaTypes() .contains("application/x-
> javascript")) {
> log.info("Request does not contain ok mediatype. returning normal
> info.");
> return response;
> }
>
> MultivaluedMap<String, String> queryParamsMapMulti =
> request.getQueryParameters();
> String callback = queryParamsMapMulti.getFirst("callback");
> log.debug("callback=" + callback);
> if (callback != null) {
> response.setContainerResponseWriter(
> new JSONCallbackResponseAdapter(
> response.getContainerResponseWriter(),
> callback));
> }
> return response;
> }
>
> /**
> * * * See:
> * http://n2.nabble.com/-Filter--how-to-customize-context-body---td2116754.html
> */
> public static final class JSONCallbackResponseAdapter implements
> ContainerResponseWriter {
> private final ContainerResponseWriter crw;
>
> private OutputStream out;
> private String callback;
>
> JSONCallbackResponseAdapter(ContainerResponseWriter crw, String
> callback) {
> this.crw = crw;
> this.callback = callback;
> }
>
> public OutputStream writeStatusAndHeaders(
> long contentLength,
> ContainerResponse response) throws IOException {
> out = crw.writeStatusAndHeaders(-1, response);
>
> out.write((this.callback + "(").getBytes());
> return out;
> }
>
> public void finish() throws IOException {
> out.write(")".getBytes());
> }
> }
> }
>
>
> 1. http://n2.nabble.com/JSONP-Callback-support-tc2260544.html
>
>
> Kind regards,
> Tarjei Huse
> Mobil: 920 63 413
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>