The WireAdmin Producer class has a polled method that is similar that just
returns an Object. I've used Generics as a good programming practice, but
I'm aware it doesn't solve this problem.
There seems to be a use case for this nature of functionality. I've no idea
how frameworks like Camel are solving this problem in OSGi... do they just
hope for the best and push Objects are around and assume Producers and
Consumers are using the same versions?
I understand that the framework wouldn't know what T is, so I'd quite like
to tell the framework what T is.
Ie:
Properties props ...
props.put("providerClassName",Model.class.getName());
props.put("providerClassVersion",*
context.getImportVersion(Model.class.getPackage().getName()*); //this
doesn't exist
context.register(Provider.class,this,props);
However, there doesn't seem to be an easy way to do this, unless I've
missed something.
Many Thanks
Mark
On 14 June 2013 04:36, Richard S. Hall <[email protected]> wrote:
>
> On 6/13/13 20:55 , Mark Richards wrote:
>
>> I thought I'd implement an example of this and I get ClassCastExceptions
>> in
>> the Consumer.
>> Please feel free to checkout:
>> https://bitbucket.org/**markalanrichards/discussion-**points/overview<https://bitbucket.org/markalanrichards/discussion-points/overview>
>> It's not that big (each bundle has only one Java class in it).
>>
>> When these start (in order) everything is fine: service-api, model10,
>> model15, model20, model-provider10, model-provider15, model-provider20.
>> However, when I start modelConsumer10, model 1.0 and model 1.5 are fine
>> for
>> the consumer, but model 2.0 hits the ClassCastException.
>>
>> What did I miss?
>>
>
> You are basically hiding package dependencies behind generic types. There
> is no easy way for the framework to do a consistency check for "T
> provide()" in a Provider<T>. It can't do it at resolve time because there
> is no "uses" constraint on T since it doesn't know what it is; it
> technically might be able to figure it out at run time when doing service
> lookups, but that would be tricky and costly and still not complete since
> incompatible stuff could still be passed back in Objects or supertypes and
> accessed via downcasting.
>
> The only guarantees OSGi gives you are with respect to packages and their
> associated "uses" constraints, your example expects it to analyze all
> reachable types from a given service interface at run time. It doesn't do
> that.
>
> You would have to create specific concrete versions of your generic
> interface for each model type so that you could establish a "uses"
> constraint between the service interface and the concrete model it provides.
>
> -> richard
>
>
>
>> Many Thanks
>> Mark
>>
>> PS: If you don't wish to checkout/run this, but are interested in what
>> happens, the output when I start model-consumer10 is:
>> finding refs
>> objectClass: [Ljava.lang.String;@df54977
>> provides: com.example.markoffline.model.**Model
>> service.id: 226
>> TO STRING: Date: 1371160741853
>> Description: null
>> THE LONG: 1371160741853
>> objectClass: [Ljava.lang.String;@11df24ba
>> provides: com.example.markoffline.model.**Model
>> service.id: 227
>> TO STRING: Date: 1371160741856
>> Description: The time now
>> THE LONG: 1371160741856
>> objectClass: [Ljava.lang.String;@373984fd
>> provides: com.example.markoffline.model.**Model
>> service.id: 228
>> ---
>> --- Here the bundle hits an exception trace, probably not too useful
>> except
>> for:
>> ---
>> Caused by: java.lang.ClassCastException:
>> com.example.markoffline.model.**Model cannot be cast to
>> com.example.markoffline.model.**Model
>> at
>> com.example.markoffline.**consumer.ModelConsumer.start(**
>> ModelConsumer.java:27)
>>
>>
>>
>>
>>
>>
>> On 13 June 2013 11:27, Felix Meschberger <[email protected]> wrote:
>>
>> Hi
>>>
>>> Am 13.06.2013 um 12:18 schrieb Mark Richards:
>>>
>>> Thanks...
>>>> "In addition the service registry makes sure, that D only gets V1 Model
>>>> service instances and E only gets V2 Model service instances."
>>>> I assumed the registry would only care about the versions of Producer
>>>> and
>>>> Consumer, as the Models aren't bound directly to the service.
>>>>
>>> The service registry does not care for versions at all. It cares to make
>>> sure a consumer (retrieving the service) can use the service by making
>>> sure, the consumer and the service object see the same service object
>>> class
>>> objects and thus are compatible.
>>>
>>> Regards
>>> Felix
>>>
>>>
>>>> On 13 June 2013 09:56, Felix Meschberger <[email protected]> wrote:
>>>>
>>>> Hi
>>>>>
>>>>> OSGi wires API by import and export package version.
>>>>>
>>>>> In you example of two incompatible model classes, you might have bundle
>>>>>
>>>> B
>>>
>>>> export the Model API at version 1.0 and bundle C export the Model API at
>>>>> version 2.0.
>>>>>
>>>>> Your consumer bundles D and E would then import the appropriate Model
>>>>>
>>>> API
>>>
>>>> versions such as [1,2) and [2,3).
>>>>>
>>>>> The actual Model class objects are then different for D and E (even
>>>>>
>>>> though
>>>
>>>> the fully qualified class name is the same). In addition the service
>>>>> registry makes sure, that D only gets V1 Model service instances and E
>>>>>
>>>> only
>>>
>>>> gets V2 Model service instances.
>>>>>
>>>>> Hope this helps.
>>>>>
>>>>> Regards
>>>>> Felix
>>>>>
>>>>> Am 12.06.2013 um 17:56 schrieb Mark Richards:
>>>>>
>>>>> Hi,
>>>>>>
>>>>>> I'm new to this list and hopefully this question isn't too long...
>>>>>>
>>>>> please
>>>
>>>> let me know if you'd like further details.
>>>>>>
>>>>>> Context: I'd like to create a service architecture that represents
>>>>>>
>>>>> EIPs,
>>>
>>>> a
>>>>>
>>>>>> bit like Camel but more OSGi friendly, however the safe wiring of
>>>>>>
>>>>> objects
>>>
>>>> must ensure the producers are wired to consumers that provide and
>>>>>>
>>>>> consumer
>>>>>
>>>>>> compatible versions of the objects.
>>>>>>
>>>>>> Problem: How do you handle the versions dependencies of objects used a
>>>>>> layer beneath the services provided?
>>>>>>
>>>>>> I believe this issue also affects the listener model, if you wanted to
>>>>>>
>>>>> use
>>>>>
>>>>>> a generic listener model like so I'm hoping somebody has already
>>>>>> solved
>>>>>>
>>>>> it:
>>>>>
>>>>>> interface Listener<T> { //Listener class is handled by bundle
>>>>>>
>>>>> resolution
>>>
>>>> void Notify(T event); //but what about this T?
>>>>>> }
>>>>>>
>>>>>>
>>>>>> When you create an implementation you usually know T, so it's quite
>>>>>>
>>>>> easy
>>>
>>>> to
>>>>>
>>>>>> call "bundleContext.register(**Listener.class, this, props)" where
>>>>>> props
>>>>>> includes {"listenerOf":"t.class}" and to then filter the class.
>>>>>>
>>>>> However,
>>>
>>>> I'm not sure where to get the version for T from (it may be an imported
>>>>>> class) and versions are ranges with different rules for import and
>>>>>>
>>>>> export.
>>>>>
>>>>>> Any help advice or also, an idea of whether I'm the only one trying to
>>>>>>
>>>>> do
>>>
>>>> this would be useful.
>>>>>>
>>>>>> Thanks,
>>>>>> Mark
>>>>>>
>>>>>>
>>>>>> Ps: if it helps here is an example of the style of problem in
>>>>>>
>>>>> semi-pseudo
>>>
>>>> code.
>>>>>> If you cannot filter the version of the Model through the services
>>>>>>
>>>>> layer
>>>
>>>> ModelProvider will provide a Date object and ModelConsumer will try to
>>>>>>
>>>>> read
>>>>>
>>>>>> a Long. The two shouldn't be allowed to bind to each other.
>>>>>>
>>>>>>
>>>>>> bundle A: wiring-api
>>>>>> interface Provider<T> {
>>>>>> T giveMeAnObject();
>>>>>> }
>>>>>> interface Consumer<T> {
>>>>>> void hereIsAnObject(T object);
>>>>>> }
>>>>>>
>>>>>> bundle B: model version 1:
>>>>>> class Model {
>>>>>> long getDate();{ return (long) 99 }
>>>>>> }
>>>>>>
>>>>>> bundle C: model version 2:
>>>>>> class Model {
>>>>>> Date getDate() { return new Date(); }
>>>>>> }
>>>>>>
>>>>>> bundle D: model-provder version 2: import-packages wiring-api 1 and
>>>>>>
>>>>> model 2
>>>>>
>>>>>> class ModelProvider implements Provider <Model> implements
>>>>>> BundleActivator { {
>>>>>> void start(BundleContext context) {
>>>>>> context.register(Provider.**class, this, ???? )* // here
>>>>>> you'd
>>>>>> need to specify it is model 2, but how do you get this*
>>>>>> }
>>>>>> Model giveMeAnObject() {
>>>>>> return new Model();
>>>>>> }
>>>>>> }
>>>>>> bundle E: consumer imports wiring-api and model 1:
>>>>>> class ModelConsumer implements Consumer<Model>, BundleActivator {
>>>>>> void start(BundleContext context) {
>>>>>> context.register(Consumer.**class, this, ???? )* // here
>>>>>> you'd
>>>>>> need to specify it is model 1, but how do you get this**
>>>>>> * }*
>>>>>> *
>>>>>>
>>>>>> void hereIsAnObject(Model object) {
>>>>>> System.out.println(Long.**valueOf(model.getDate())); //
>>>>>> if no
>>>>>> object version filtering this will fail as bundle D should not be
>>>>>>
>>>>> connected
>>>>>
>>>>>> to bundle E
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> // here I envisage there should be a Provider Manager perhaps along
>>>>>> the
>>>>>> lines of that could be exposed to have wiring done through a UI,
>>>>>>
>>>>> interface
>>>>>
>>>>>> or config settings like WireAdmin
>>>>>> // this isn't too important at this point, except it would need some
>>>>>>
>>>>> way
>>>
>>>> to
>>>>>
>>>>>> manage this *version filtering/matching*!
>>>>>> bundle F: provider-service imports wiring-api
>>>>>> class ProviderManager {
>>>>>> Map<ClassVersion, Provider> providers;
>>>>>> Map<ClassVersion, Consumer, consumers
>>>>>> void registerProvider(ClassVersion<**T> provided, Provider<T>
>>>>>> provider);
>>>>>> void registerConsumer(ClassVersion<**T> consumed, Consumer<T>
>>>>>> provider);
>>>>>>
>>>>>> // methods to lookup and match providers with consumers
>>>>>> }
>>>>>>
>>>>>
>>>>> ------------------------------**------------------------------**
>>>>> ---------
>>>>> To unsubscribe, e-mail:
>>>>> users-unsubscribe@felix.**apache.org<[email protected]>
>>>>> For additional commands, e-mail: [email protected]
>>>>>
>>>>>
>>>>>
>>> ------------------------------**------------------------------**
>>> ---------
>>> To unsubscribe, e-mail:
>>> users-unsubscribe@felix.**apache.org<[email protected]>
>>> For additional commands, e-mail: [email protected]
>>>
>>>
>>>
>
> ------------------------------**------------------------------**---------
> To unsubscribe, e-mail:
> users-unsubscribe@felix.**apache.org<[email protected]>
> For additional commands, e-mail: [email protected]
>
>