Creation and destruction of TrackedRegattas is now observable through

OSGi service registry-based listeners
This commit is contained in:
Steffen Schaefer committed 2016-03-31 11:05:44 +02:00
1 parent 56121e93d1
commit c7b8c594d1
6 files changed
+91 -9

No files matched your search

@@ -57,6 +57,8 @@ public class Activator implements BundleActivator {
private ServiceTracker<MasterDataImportClassLoaderService, MasterDataImportClassLoaderService> masterDataImportClassLoaderServiceTracker;
private ServiceTracker<PolarDataService, PolarDataService> polarDataServiceTracker;
private OSGiBasedTrackedRegattaListener trackedRegattaListener;
public Activator() {
clearPersistentCompetitors = Boolean.valueOf(System.getProperty(CLEAR_PERSISTENT_COMPETITORS_PROPERTY_NAME, ""+false));
@@ -68,12 +70,14 @@ public class Activator implements BundleActivator {
extenderBundleTracker = new ExtenderBundleTracker(context);
extenderBundleTracker.open();
trackedRegattaListener = new OSGiBasedTrackedRegattaListener(context);
// At this point the OSGi resolver is used as device type service finder.
// In the case that we are not in an OSGi context (e.g. running a JUnit test instead),
// this code block is not run, and the test case can inject some other type of finder
// instead.
serviceFinderFactory = new CachedOsgiTypeBasedServiceFinderFactory(context);
racingEventService = new RacingEventServiceImpl(clearPersistentCompetitors, serviceFinderFactory);
racingEventService = new RacingEventServiceImpl(clearPersistentCompetitors, serviceFinderFactory, trackedRegattaListener);
masterDataImportClassLoaderServiceTracker = new ServiceTracker<MasterDataImportClassLoaderService, MasterDataImportClassLoaderService>(
context, MasterDataImportClassLoaderService.class,
@@ -135,6 +139,7 @@ public class Activator implements BundleActivator {
for (ServiceRegistration<?> reg : registrations) {
reg.unregister();
}
trackedRegattaListener.close();
registrations.clear();
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
mbs.unregisterMBean(mBeanName);
@@ -0,0 +1,44 @@
package com.sap.sailing.server.impl;
import java.util.function.Consumer;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRegattaListener;
import com.sap.sse.util.ServiceTrackerFactory;
public class OSGiBasedTrackedRegattaListener implements TrackedRegattaListener {
private ServiceTracker<TrackedRegattaListener, TrackedRegattaListener> serviceTracker;
public OSGiBasedTrackedRegattaListener(BundleContext context) {
serviceTracker = ServiceTrackerFactory.createAndOpen(context, TrackedRegattaListener.class);
serviceTracker.open(true);
}
public void close() {
serviceTracker.close();
}
private void forEachListener(Consumer<TrackedRegattaListener> consumer) {
for(ServiceReference<TrackedRegattaListener> serviceReference : serviceTracker.getServiceReferences()) {
TrackedRegattaListener listener = serviceTracker.getService(serviceReference);
if(listener != null) {
consumer.accept(listener);
}
}
}
@Override
public void regattaAdded(TrackedRegatta trackedRegatta) {
forEachListener((listener) -> listener.regattaAdded(trackedRegatta));
}
@Override
public void regattaRemoved(TrackedRegatta trackedRegatta) {
forEachListener((listener) -> listener.regattaRemoved(trackedRegatta));
}
}
@@ -147,6 +147,7 @@ import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike;
import com.sap.sailing.domain.regattalog.RegattaLogStore;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
import com.sap.sailing.domain.tracking.EmptyTrackedRegattaListener;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.RaceChangeListener;
@@ -157,6 +158,7 @@ import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRaceStatus;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRegattaListener;
import com.sap.sailing.domain.tracking.WindStore;
import com.sap.sailing.domain.tracking.WindTracker;
import com.sap.sailing.domain.tracking.WindTrackerFactory;
@@ -405,6 +407,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
private SailingServerConfiguration sailingServerConfiguration;
private final TrackedRegattaListener trackedRegattaListener;
/**
* Providing the constructor parameters for a new {@link RacingEventServiceImpl} instance is a bit tricky
* in some cases because containment and initialization order of some types is fairly tightly coupled.
@@ -442,6 +446,10 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
this.bundleContext = bundleContext;
}
public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory) {
this(clearPersistentCompetitorStore, serviceFinderFactory, null);
}
/**
* Like {@link #RacingEventServiceImpl()}, but allows callers to specify that the persistent competitor collection
* be cleared before the service starts.
@@ -451,7 +459,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
* database collection cleared as well. Use with caution! When used with <code>false</code>, competitors
* created and stored during previous service executions will initially be loaded.
*/
public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory) {
public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListener trackedRegattaListener) {
this((final RaceLogResolver raceLogResolver)-> {
return new ConstructorParameters() {
private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory);
@@ -464,7 +472,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
@Override public DomainFactory getBaseDomainFactory() { return competitorStore.getBaseDomainFactory(); }
@Override public CompetitorStore getCompetitorStore() { return competitorStore; }
};
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), null, null, serviceFinderFactory);
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), null, null, serviceFinderFactory ,trackedRegattaListener);
}
private RacingEventServiceImpl(final boolean clearPersistentCompetitorStore, WindStore windStore,
@@ -481,7 +489,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
@Override public DomainFactory getBaseDomainFactory() { return competitorStore.getBaseDomainFactory(); }
@Override public CompetitorStore getCompetitorStore() { return competitorStore; }
};
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), windStore, sensorFixStore, serviceFinderFactory);
}, MediaDBFactory.INSTANCE.getDefaultMediaDB(), windStore, sensorFixStore, serviceFinderFactory, null);
}
/**
@@ -501,7 +509,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
@Override public DomainFactory getBaseDomainFactory() { return domainObjectFactory.getBaseDomainFactory(); }
@Override public CompetitorStore getCompetitorStore() { return getBaseDomainFactory().getCompetitorStore(); }
};
}, mediaDB, windStore, sensorFixStore, null);
}, mediaDB, windStore, sensorFixStore, null, null);
}
public RacingEventServiceImpl(final DomainObjectFactory domainObjectFactory, MongoObjectFactory mongoObjectFactory,
@@ -513,7 +521,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
@Override public DomainFactory getBaseDomainFactory() { return domainObjectFactory.getBaseDomainFactory(); }
@Override public CompetitorStore getCompetitorStore() { return getBaseDomainFactory().getCompetitorStore(); }
};
}, mediaDB, windStore, sensorFixStore, null);
}, mediaDB, windStore, sensorFixStore, null, null);
}
/**
@@ -526,7 +534,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
* associations per race tracked.
*/
public RacingEventServiceImpl(Function<RaceLogResolver, ConstructorParameters> constructorParametersProvider, MediaDB mediaDb,
final WindStore windStore, final SensorFixStore sensorFixStore, TypeBasedServiceFinderFactory serviceFinderFactory) {
final WindStore windStore, final SensorFixStore sensorFixStore, TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListener trackedRegattaListener) {
logger.info("Created " + this);
final ConstructorParameters constructorParameters = constructorParametersProvider.apply(this);
this.domainObjectFactory = constructorParameters.getDomainObjectFactory();
@@ -601,6 +609,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
this.configurationMap = new DeviceConfigurationMapImpl();
this.serviceFinderFactory = serviceFinderFactory;
this.trackedRegattaListener = trackedRegattaListener == null ? EmptyTrackedRegattaListener.INSTANCE : trackedRegattaListener;
sailingServerConfiguration = domainObjectFactory.loadServerConfiguration();
final Iterable<Pair<Event, Boolean>> loadedEventsWithRequireStoreFlag = loadStoredEvents();
loadStoredRegattas();
@@ -2107,6 +2117,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
replicate(new TrackRegatta(regatta.getRegattaIdentifier()));
regattaTrackingCache.put(regatta, result);
ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking(result);
trackedRegattaListener.regattaAdded(result);
}
return result;
} finally {
@@ -2130,6 +2142,7 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes
LockUtil.unlockAfterWrite(regattaTrackingCacheLock);
}
stopObservingRegattaForRedaultLeaderboardAndAutoLeaderboardLinking(trackedRegatta);
trackedRegattaListener.regattaRemoved(trackedRegatta);
}
@Override