Separating the two consumers into separate components would be a far better 
encapsulation. There is no reason that one component should be doing both MQTT 
and WebSocket work - in fact the configuration that you provide doesn’t even 
configure the MQTT reference, meaning that it could get bound to anything!

You should really separate the two consumers into separate components. What 
happens then is down to how the consumed data is supposed to be used. It 
appears as though there is no use of “pushed” data (i.e. there is a get method 
and that’s it), which seems a bit odd for a data stream like this. I would 
really expect the converted data to be published to an Event Admin Topic. The 
person who wants to use the data can then register an event listener, and will 
get told whenever the data is updated.

In any event, the correct way to handle the original ordering dependency that 
you asked about is to do the initialisation in the activate method 
(https://github.com/timothyjward/com.easyiot.device/blob/df6999f1cb741a4c55b0ce217169ec912afc6741/com.easyiot.LT100H.device.provider/src/com/easyiot/LT100H/device/provider/LT100HDeviceImpl.java
 
<https://github.com/timothyjward/com.easyiot.device/blob/df6999f1cb741a4c55b0ce217169ec912afc6741/com.easyiot.LT100H.device.provider/src/com/easyiot/LT100H/device/provider/LT100HDeviceImpl.java>).
 

Note that I still think that this is a poorly constructed component, as the 
optional references aren’t really optional, just two mandatory components stuck 
together. I also don’t think that the code needs to be dynamic, but if you want 
it to be then I leave the thread safety as an exercise for the reader ;).

Regards,

Tim
> On 14 Oct 2016, at 08:15, Daghan ACAY <daghana...@hotmail.com> wrote:
> 
> Hi Peter,
> 
> This looks great. I thought about white board pattern but problem is this, 
> there is no single mqttProtocolProvider! they are also created through 
> factory configuration and bind to device through configuration. Please see 
> the actual configuration used in application project here. 
> 
> https://github.com/daghanacay/com.easyiot.application/blob/master/com.easyiot.heatmap.application/configuration/configuration.json
>  
> <https://github.com/daghanacay/com.easyiot.application/blob/master/com.easyiot.heatmap.application/configuration/configuration.json>
> Correct me if i am wrong but Whiteboard pattern assumes there is only one 
> mqttprotocolprovider. Peter, I still can work with the code that you have 
> explained but still won't be as clean. I am thinking of using service tracker 
> may be in the device but then it is not DS. I think it is an interesting case 
> that might be worthy of you experts time :)
> 
> PS: please excuse me if i misunderstand you or i am making this something 
> more complicated then it should be.
> 
> Cheers
> Daghan
> 
> Sent by MailWise <http://www.mail-wise.com/installation/2> – See your emails 
> as clean, short chats.
> 
> 
> 
> -------- Original Message --------
> From: Peter Kriens <peter.kri...@aqute.biz>
> Sent: Friday, October 14, 2016 05:58 PM
> To: OSGi Developer Mail List <osgi-dev@mail.osgi.org>
> Subject: Re: [osgi-dev] DS component life cycle.
> 
> @Christian: The MQTT client is optional and dynamic. So the activate method 
> cannot be used. You need to subscribe/unsubscribe based on the availability 
> of the mqtt server.
> 
> @Daghan:
> 
> Divide and conquer! You’re trying to do multiple responsibilities in one 
> component and that is the antithesis of modularity, also called lack of 
> cohesion. This is a perfect example of how things could get simpler by 
> choosing the right decomposition.
> 
> The best solution imho is to introduce a second,component. Let the Device 
> component just be a Device, it should not have to worry about Mqtt. After 
> all, you could be connected to other event queues. (It also makes it easier 
> to test.) You made mqtt optional to reflect this. This is exactly the reason 
> the Whiteboard Pattern was invented!
> 
> This would look like:
> 
> 
>         @Component( property = “subscriptionChannel=” )
>         public class LT100HDeviceImpl implements Device, 
> TtnMqttMessageListener {
>                 // remove the mqtt subscription code but
>                 // implement the TtnMqttMessageListener
>        }
> 
> And the whiteboard component. Notice the _ in the _mqtt field. This ensures 
> it is set before the event method that has a name that will appear in a 
> sorted list later. (References are sorted by name.) (I vaguely recall field 
> references are done before bind methods but this makes it certain.)
> 
>         @Component(immediate=true)
>         public class MQTTWhiteboard {
> 
>                 @Reference
>                 TtnMqttProtocol _mqtt;
> 
>                 @Reference( cardinality = ReferenceCardinality.OPTIONAL, 
> policy = ReferencePolicy.DYNAMIC )
>                 void addMqttListener( TtnMqttMessageListener l, 
> Map<String,Object> props ) {
>                         String channel = props.get( “subscriptionChannel” );
>                         if ( channel != null && !channel.isEmpty() ) {
>                                 _mqtt. subscribe( channel, l );
>                 }
> 
>                 void removeMqttListener( TtnMqttMessageListener l, 
> Map<String,Object> props ) {
>                         String channel = props.get( “subscriptionChannel” );
>                         if ( channel != null && !channel.isEmpty() ) {
>                                 _mqtt.unsubscribe( channel );
> 
>                 }
>         }
> 
> You now created a whiteboard service that can also be used by other Device 
> implementations while significantly reducing the complexity of your 
> implementation. 
> 
> This is why after all those years I still love OSGi … you can only do this 
> when you have dynamic components. As your struggle showed, trying to manage 
> this is quickly becoming quite complex. Whenever you enter in such a 
> struggle, think, lack of cohesion is often your problem.
> 
> Kind regards,
> 
>         Peter Kriens
> 
> 
> > 
> > On 14 okt. 2016, at 08:09, Christian Schneider <ch...@die-schneider.net> 
> > wrote:
> > 
> > In your case simply inject the ttnMqttClient in the @Reference and do the 
> > subscribe in @Activate when you get the config and the unsubscribe in 
> > @Deactivate.
> > 
> > Christian
> > 
> > 2016-10-13 23:00 GMT+02:00 Daghan ACAY <daghana...@hotmail.com>:
> > Hi all,
> > 
> > I am trying to create a component that is instantiated by ConfigAdmin and 
> > uses multiple references to operate. Basically the component should 
> > instantiate through a factory configuration and use that configuration to 
> > set up its own @Reference s. You can see the code here:
> > 
> > https://github.com/daghanacay/com.easyiot.device/blob/master/com.easyiot.LT100H.device.provider/src/com/easyiot/LT100H/device/provider/LT100HDeviceImpl.java
> >  
> > <https://github.com/daghanacay/com.easyiot.device/blob/master/com.easyiot.LT100H.device.provider/src/com/easyiot/LT100H/device/provider/LT100HDeviceImpl.java>
> > 
> > All the mentioned @Reference ed components are instantiated by 
> > configuration as well, so at a given time the @Reference might not be 
> > available but my own component should still work. yet should the Reference 
> > available then it should be injected, basic 0-1 strategy.
> > 
> > Problem I am facing with the current form of the code is that, the 
> > @Reference injection is happening before the @Activate method is called. 
> > This leads to NPE in the @Reference method due to null configuration. Is it 
> > possible to make this code work such that config is provided to the 
> > component before the dependency injection?
> > 
> > I have tried annotating the class fields and set them "volatile". I even 
> > make them a list and use the class fields in the activate method this time 
> > the class fields were null due to 0-1 strategy. so I end up with annotating 
> > the methods.
> > 
> > I might have designed this all wrong, so any help simple or fundamental is 
> > appreciated.
> > 
> > Regards
> > 
> > -Daghan
> > 
> > Sent by MailWise – See your emails as clean, short chats.
> > 
> > 
> > _______________________________________________
> > OSGi Developer Mail List
> > osgi-dev@mail.osgi.org
> > https://mail.osgi.org/mailman/listinfo/osgi-dev 
> > <https://mail.osgi.org/mailman/listinfo/osgi-dev>
> > 
> > 
> > 
> > -- 
> > -- 
> > Christian Schneider
> > http://www.liquid-reality.de <http://www.liquid-reality.de/>
> > 
> > Open Source Architect
> > http://www.talend.com <http://www.talend.com/>
> > _______________________________________________
> > OSGi Developer Mail List
> > osgi-dev@mail.osgi.org
> > https://mail.osgi.org/mailman/listinfo/osgi-dev 
> > <https://mail.osgi.org/mailman/listinfo/osgi-dev>
> 
> _______________________________________________
> OSGi Developer Mail List
> osgi-dev@mail.osgi.org
> https://mail.osgi.org/mailman/listinfo/osgi-dev

_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to