The only way to retrain generic information at runtime is with a class that
extends from a generic one without declaring a generic signature itself.

For instance:

         class MyMap extends HashMap<Integer, String> {}

The compiler retains the generic information directly in the class. At that
point you can, at runtime, check if the type has generic arguments and
obtain what those argument types were.

        Type[] genericInterfaces = clazz.getGenericInterfaces();

        for (Type genericInterface : genericInterfaces) {
            if (!(genericInterface instanceof ParameterizedType)) {
                continue;
            }

            ParameterizedType parameterizedType =
                (ParameterizedType)genericInterface;

            Type rawType = parameterizedType.getRawType();

            ...
         }


However, you still can't register the service using generics:

         context.registerService(Map.class, new MyMap(), null)

But if you need you could technically impose the restriction from the other
side and ignore any services which don't have retrained generic information.

That might make things a little harder for developers to reason about but
if this is for "personal" use only, then it may do what you want.

- Ray


On Wed, Mar 18, 2015 at 9:11 AM, BJ Hargrave <hargr...@us.ibm.com> wrote:

> osgi-dev-boun...@mail.osgi.org wrote on 2015/03/18 09:04:08:
>
> > From: Frank Langel <fr...@frankjlangel.com>
> > Hi,
> >
> > I did some research, but didn¹t find a way to register a generic service.
> > I would like to do sth like this
> >
> >    context.registerService(Map<K,V>.class, service, properties), I.e.
> >    context.registerService(Map<Integer,String>.class, new
> > HashMap<Integer,String>(), null)
>
> 'Map<Integer,String>.class' does not exist at runtime. Only 'Map.class'
> exists at runtime due to generics erasure. So there is no way to look up a
> class using generics since they are erased at runtime.
>
> >
> > The injection should then only work if the registered and the injected K
> > and V are the same. Assuming I only have one service of type Map
> > registered,
> >
> >    @Reference
> >    public void setMapService(Map<Integer,String> mymap) {
> >        This.map = my map;
> >    }
> >
> >    Would succeed.
> >
> >    The following would fail as V (registered) != V(referenced service)
> >
> >    @Reference
> >    public void setMapService(Map<Integer,Integer> mymap) {
> >      this.map = mymap;
> >    }
> >
> > As a workaround, I could define K and V as service properties and filter
> > for them, but that¹s not very elegant and very error prone
> >
> > Any feedback would be appreciated
> > Frank
>
>
> --
>
>  *BJ Hargrave*
> Senior Technical Staff Member, IBM
> OSGi Fellow and CTO of the *OSGi Alliance* <http://www.osgi.org/>
> *hargr...@us.ibm.com* <hargr...@us.ibm.com>
>
> office: +1 386 848 1781
> mobile: +1 386 848 3788
>
>
> _______________________________________________
> OSGi Developer Mail List
> osgi-dev@mail.osgi.org
> https://mail.osgi.org/mailman/listinfo/osgi-dev
>



-- 
*Raymond Augé* <http://www.liferay.com/web/raymond.auge/profile>
 (@rotty3000)
Senior Software Architect *Liferay, Inc.* <http://www.liferay.com>
 (@Liferay)
Board Member & EEG Co-Chair, OSGi Alliance <http://osgi.org> (@OSGiAlliance)
_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to