users@jersey.java.net

Re: Problem with ContextResolver, generics...

From: Tatu Saloranta <tsaloranta_at_gmail.com>
Date: Tue, 28 Apr 2009 15:05:39 -0700

On Tue, Apr 28, 2009 at 2:47 PM, Tatu Saloranta <tsaloranta_at_gmail.com> wrote:
> Hmmh. I think the problems are more due to my forgetting to add
>
> @Context Providers providers;
>
> injection, which is then to be used for locating actual things I need.
> That works with providers; I'll see how simple I can make it, starting
> from state that works. :)

Ok, second try. I don't know if this is a bug or not, but it seems suspicious.
So, given super-class like:

---
    static abstract class SimpleResolver<T>
        implements ContextResolver<T>
    {
        final T _context;
        protected SimpleResolver(T ctxt) {
            _context = ctxt;
        }
        public T getContext(Class<?> type) {
            return _context;
        }
    }
---
following sub-class does NOT work wrt provider registration:
---
    @Provider
    static class ObjectMapperResolver
        extends SimpleResolver<ObjectMapper>
    {
        public ObjectMapperResolver(ObjectMapper m) { super(m); }
    }
---
however, adding 'implements' in there, like so:
---
    @Provider
    static class ObjectMapperResolver
        extends SimpleResolver<ObjectMapper>
        implements ContextResolver<ObjectMapper>
    {
        public ObjectMapperResolver(ObjectMapper m) { super(m); }
    }
---
makes it click. I don't if that's due to introspection code not
following super-class hierarchy to find implemented interfaces (since
implemented super-interfaces are NOT included in Class information for
sub-class); or if it's that implemented interface is ContextResolver<T
== Object>,
or if it's compiler adding synthetic bridge methods. So many ways to
get it wrong. :)
If latter, it means that whereas super class basically has equivalent of:
public Object getContext(Class);
(due to type erasure etc)
compiler does synthesize method like:
public ObjectMapper getContext(Class)
for sub-class, to make things works; these are I think called "bridge" methods.
In the end, perhaps there should be an exception or warning if anyone
tries to register "ContextResolver<Object>" (or type variable)?
That seems like a common failure mode; and I can't think of a reason
to register resolver for Object.class.
-+ Tatu +-