Well, it supports it with sub-typing as Ray shows. This is perfectly type safe 
and does not require tricks. 

To support this in the API, we would need a TypeReference class that would be 
subclassed (I guess this what you mean with the supertype token pattern?). 

        new TypeReference<Map<String,String>>() {}

The TypeReference has a getGenericType method that returns the type information 
of the super class. The OSGi API would have to recognize this (sub) class and 
then carry the generic type information. 

        registerService( TypeReference<T> tref, T t, Map<String,Object> props );
        registerService( new TypeReference<Map<String,String>>() {}, new 
HashMap<String,String>(), null );

And then on ServiceReference<?>

        Type getGenericType()

And for the queries

        List<ServiceReference<T>> getServiceReferences( TypeReference<T> ref, 
String filter );

Guess this would actually be relatively easy to do. I guess the raw type can 
always provide backward compatibility, though are probably some nasty corner 
cases lurking.

Extension for R7?

Kind regards,

        Peter Kriens



> On 18 mrt. 2015, at 19:16, elias vasylenko <[email protected]> wrote:
> 
> Just to make it more clear for the sake of the discussion, there is no reason 
> we couldn't use the supertype token pattern to have a type safe service 
> registry for generic types, the osgi api just doesn't currently support it.
> 
> On 18 Mar 2015 14:00, "Raymond Auge" <[email protected] 
> <mailto:[email protected]>> wrote:
> 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 <[email protected] 
> <mailto:[email protected]>> wrote:
> [email protected] <mailto:[email protected]> wrote 
> on 2015/03/18 09:04:08:
> 
> > From: Frank Langel <[email protected] <mailto:[email protected]>> 
> > 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/>
> [email protected] <mailto:[email protected]>      
> 
> office: +1 386 848 1781 <tel:%2B1%20386%20848%201781>
> mobile: +1 386 848 3788 <tel:%2B1%20386%20848%203788>
> 
> 
> 
> _______________________________________________
> OSGi Developer Mail List
> [email protected] <mailto:[email protected]>
> https://mail.osgi.org/mailman/listinfo/osgi-dev 
> <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
> [email protected] <mailto:[email protected]>
> https://mail.osgi.org/mailman/listinfo/osgi-dev 
> <https://mail.osgi.org/mailman/listinfo/osgi-dev>
> _______________________________________________
> OSGi Developer Mail List
> [email protected]
> https://mail.osgi.org/mailman/listinfo/osgi-dev

_______________________________________________
OSGi Developer Mail List
[email protected]
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to