Why not use DS?

On 19 sep. 2013, at 18:02, Daniel McGreal wrote:

> Hi OSGi-devs,
> 
> I have a question about utilising ServiceTracker to manage a class's 
> dependencies and blocking during the call, which I confess is probably well 
> trodden ground but for which I can't apparently find the right Google 
> terminology. Perhaps because I've been, until now, coddled by higher-level 
> service dynamism, like Blueprint.
> 
> I have a java.util.logging.Handler whose publish method needs a couple of 
> OSGi services to operate. Any LogRecords that are published during a refresh 
> of either of the dependencies should not be lost and should be reattempted 
> when services resume (which in practice might be a long time, the device this 
> application targets is incredibly primitive).
> 
> Currently I have the Activator and Handler in the same implementation (which 
> seems like it might be bad practice, if it is, I'd love to know why). Here's 
> a trimmed down version, with just one dependency:
> 
> public class RemoteLoggingHandler extends Handler implements BundleActivator {
>       private volatile Channel channel;
>       
>       private ServiceTracker<IAmqpChannelProvider, IAmqpChannelProvider> 
> channelProviderTracker;
>       
>       @Override public void start(BundleContext context) throws Exception {   
>         
>               channelProviderTracker = new 
> ServiceTracker<IAmqpChannelProvider, IAmqpChannelProvider>(context, 
> IAmqpChannelProvider.class, null){
>                       @Override public IAmqpChannelProvider 
> addingService(ServiceReference<IAmqpChannelProvider> reference) {
>                               IAmqpChannelProvider channelProvider = 
> super.addingService(reference);
>                               try {
>                                       channel = 
> channelProvider.createChannel();
>                                       //Some initialisation, can happen once 
> or multiple times, no problem.
>                                       
> channel.exchangeDeclare(LoggingConstants.LOGGING_EXG_NAME, "topic", true);
>                                       notifyAll();
>                               } catch (IOException e) {
>                                       e.printStackTrace();
>                               }
>                               return channelProvider;
>                       }
>                       
>                       @Override public synchronized void 
> modifiedService(ServiceReference<IAmqpChannelProvider> reference, 
> IAmqpChannelProvider service) {
>                               removedService(reference, service);
>                               addingService(reference);
>                       }
>                       
>                       @Override public void 
> removedService(ServiceReference<IAmqpChannelProvider> reference, 
> IAmqpChannelProvider service) {
>                               super.removedService(reference, service);
>                               channel = null;
>                       }
>               };
>               channelProviderTracker.open();
>                               
>               LogManager.getLogManager().getLogger("").addHandler(this);
>       }
> 
>       @Override public void stop(BundleContext context) throws Exception {
>               LogManager.getLogManager().getLogger("").removeHandler(this);
>       }
> 
>       @Override
>       public void publish(LogRecord record) {
>               try {
>                       synchronized (channelProviderTracker) {
>                               while(channel == null) 
> channelProviderTracker.wait();
>                               
>                               
> channel.basicPublish(LoggingConstants.LOGGING_EXG_NAME, 
> record.getLoggerName(),
>                                               null, 
> record.getMessage().getBytes());
>                       }
>               } catch (Exception e) {
>                   reportError(null, e, ErrorManager.WRITE_FAILURE);
>                   return;
>               }
>       }
>       
>       //Some boilerplate....
>       
>       @Override public void flush() {} //Unnecessary.
> 
>       @Override
>       public void close() throws SecurityException {
>               flush();
>               try {
>                       channel.close();
>               } catch (IOException e) {
>                       reportError("Amqp channel could not be closed", e, 
> ErrorManager.CLOSE_FAILURE);                 
>               }
>       }
>       
> }
> 
> I don't feel that I've been successful. The channel member field can still go 
> to null while it's being used in publish, and probably many other problems 
> I've missed! Can anyone point out to me either the standard procedure for 
> this, or any comments on my above attempt?
> 
> Many thanks,
> Dan.
> 
> 
> _______________________________________________
> 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