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