Thanks for expanding on that Peter, this is indeed what I meant.
I agree that it should be relatively easy. A couple of tricky points off
the top of my head:
- Trying to instantiate a TypeReference which mentions a type variable
should probably throw an exception, as registering and requesting a
services with e.g. new TypeReference<MyService<T>>() {} could cause type
safety violations (and there is no way it could ever really be useful).
- The TypeReference parser for declarative service registration would have
to manually check that parameterizations are valid wrt the boundings on the
type variables, which I guess should be as simple as substituting those
parameterizations into bounds which mention type variables, then checking
assignability between parameter types and their bounds.
This would be a very powerful tool, I would kill to be able to do this in
R7!
It also might be a nice marketing bullet point, since proper generic type
safety seems pretty rare for things like this ;).
On 19 March 2015 at 17:03, Peter Kriens <[email protected]> wrote:
> 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]> 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]> wrote:
>>
>>> [email protected] wrote on 2015/03/18 09:04:08:
>>>
>>> > From: Frank Langel <[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]* <[email protected]>
>>>
>>> office: +1 386 848 1781
>>> mobile: +1 386 848 3788
>>>
>>>
>>>
>>> _______________________________________________
>>> OSGi Developer Mail List
>>> [email protected]
>>> 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]
>> 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
>
_______________________________________________
OSGi Developer Mail List
[email protected]
https://mail.osgi.org/mailman/listinfo/osgi-dev