[jax-rs-spec users] [jsr339-experts] Re: HEADS-UP: ParamConverter API issues.

From: Sergey Beryozkin <>
Date: Thu, 11 Oct 2012 10:23:43 +0100

On 10/10/12 17:01, Marek Potociar wrote:
> Hi all,
> when implementing the support for ParamConverter and
> ParamConverterProvider we found some unclear points I'd like to discuss
> with you:
> *1. HeaderDelegate vs. ParamConverter priority*
> ParamConverter is documented to work also for header parameters, which
> clashes with existing JAX-RS HeaderDelegate concept. We may either
> decide to not support ParamConverters in case of header value conversion
> or we need to define the resolution priorities. The suggestion is to
> define following priority-based resolution algorithm for header data
> conversion:
> 1. Custom (user supplied) ParamConverter (not null ParamConverter
> returned from ParamConverterProvider)
> 2. Implementation specific HeaderDelegate
> 3. Implementation specific ParamConverter

Is HeaderDelegate supposed to be called directly by the runtime ?

IMHO it would be much simpler to state that if a particular
HeaderDelegate implementation want to act as ParamConverter then let it
implement ParamConverterProvider

> Also, a HeaderDelegate could extend from ParamConverter as the APIs are
> essentially identical.
> *
> 2. ParamConverter used in ResponseBuilder (as defined by current javadoc)*
> The problem is that a ResponseBuilder instance is created via
> RuntimeDelegate, which is not application scoped, but is shared among
> all application. As such, the RuntimeDelegate instance has no access to
> application providers. (Btw. I'm wondering whether any of your
> implementations does provide access to application providers in your
> RuntimeDelegate impl.) This means the application level providers cannot
> be passed to the response builder instance being created. Consequently,
> when the user calls Response#getStringHeaders() on the built response,
> some of the passed headers may not be convertible, e.g.:
> // cannot use ParamConverter to convert MyBean instance.
> Response.ok().header("response-header", new
> MyBean("header")).build().getStringHeaders();
> One solution (although not the most elegant) would be to document that
> ParamConverter will not convert headers passed into Response (only
> toString() will be called on them). However, header parameters passed in
> ContainerResponseFilter or WriterInterceptor will still be convertible.
> For example, assume a registered ParamConverter<MyBean> on the server
> (using MyBeanParamConverterProvider) and the following resource method
> @GET
> public Response get() {
> Response response = Response.ok()
> .header("response-header", new MyBean("header"))
> .build();
> // the code bellow would fail.
> response.getHeaderString("response-header");
> ...
> return response;
> }
> ...which returns a response processed by a response filter:
> public static class MyFilter implements ContainerResponseFilter {
> @Override
> public void filter(ContainerRequestContext requestContext,
> ContainerResponseContext responseContext) {
> // the code bellow would pass.
> response.getHeaderString("response-header");
> ...
> }
> }
> The above looks a bit inconsistent which is why I'm mentioning it.
> Obviously, the any Response instance returned as a result of a the
> client-side request invocation will have access to application providers
> and as such the conversion would work fine.

I'd propose to limit the scope of where ParamConverters can be applied,
specifically they can only be applied when populating the (method)
request parameters

> *3. WebTarget vs. UriBuilder*
> The API docs defines that ParamConverters are supported in the Client
> API. IOW, any parameters passed to WebTarget (headerParam, queryParam,
> resolveTemplate, ...) but also parameter values passed by
> resolveTemplate should be convertible using the available
> ParamConverters configured in the WebTarget's configuration. Note
> however, that while WebTarget and UriBuilder share similar interface,
> the parameter conversion would work only in WebTarget instance and not
> in an arbitrary UriBuilder instance directly as UriBuilder (akin to
> ResponseBuilder) is created by a RuntimeDelegate instance and as such is
> not bound to a specific application runtime. Only UriBuilder instances
> returned by WebTarget may be capable of using ParamConverters (albeit
> UriBuilder documentation specifically talks only about calling
> toString() method in these cases).
> So the question is whether we should support ParamConverters in
> UriBuilder instances created by a WebTarget, or not:
> final WebTarget target = /... some web targe/t
> target.queryParam("a", new MyBean("aaa")); // works using ParamConverters
> UriBuilder uriBuilder = target.getUriBuilder();
> uriBuilder.queryParam("b", new MyBean("bbb")).build(); // may work using
> ParamConverters
> UriBuilder.fromPath(...)..queryParam("c", new MyBean("ccc")).build() //
> will only use MyBean.toString()
> I think the inconsistency illustrated in the example above is obvious,
> which may be confusing to JAX-RS users. Not sure however how to address
> it. A possible way would be to try to make the RuntimeDelegate instances
> bound to applications. But that would be quite complicated. In any case,
> we need to find a clean solution. If we're not able to find one at the
> moment, we should perhaps postpone introduction of the ParamConverter API.
IMHO trying to get ParamConvertes applicable at different API levels
complicates things a lot.


> Any thoughts or ideas?
> Thanks,
> Marek