fixed initialization problem by using readResolve() on owners of race execution order caches (RegattaImpl and FlexibleLeaderboardImpl)

This commit is contained in:
Axel Uhl committed 2015-05-27 11:06:03 +02:00
1 parent 7fcc63a8cb
commit c236a3d0bf
7 files changed
+43 -14

No files matched your search

@@ -16,8 +16,6 @@ import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.util.SmartFutureCache;
import com.sap.sse.util.SmartFutureCache.EmptyUpdateInterval;
import difflib.PatchFailedException;
public abstract class AbstractRaceExecutionOrderProvider implements RaceExecutionOrderProvider, RaceColumnListenerWithDefaultAction {
private static final long serialVersionUID = 4795731834688229568L;
private transient SmartFutureCache<String, Map<TrackedRace, Set<TrackedRace>>, EmptyUpdateInterval> raceOrderCacheMappingRaceToItsPredecessor;
@@ -26,11 +24,16 @@ public abstract class AbstractRaceExecutionOrderProvider implements RaceExecutio
public AbstractRaceExecutionOrderProvider() {
raceOrderCacheMappingRaceToItsPredecessor = createRacesOrderCache();
raceOrderCacheMappingRaceToItsPredecessor.triggerUpdate(RACES_ORDER_LIST_CACHE_KEY, /* update interval */null);
triggerUpdate();
}
@Override
public void defaultAction() {
triggerUpdate();
}
@Override
public void triggerUpdate() {
raceOrderCacheMappingRaceToItsPredecessor.triggerUpdate(RACES_ORDER_LIST_CACHE_KEY, /* update interval */null);
}
@@ -59,7 +62,9 @@ public abstract class AbstractRaceExecutionOrderProvider implements RaceExecutio
predecessors = new HashSet<>();
raceIdListInExecutionOrder.put(trackedRaceInColumnForFleet, predecessors);
}
predecessors.add(predecessor);
if (predecessor != null) {
predecessors.add(predecessor);
}
predecessor = trackedRaceInColumnForFleet;
}
}
@@ -80,11 +85,13 @@ public abstract class AbstractRaceExecutionOrderProvider implements RaceExecutio
}
}, RACES_ORDER_LIST_LOCKS_NAME);
}
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException, PatchFailedException {
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
raceOrderCacheMappingRaceToItsPredecessor = createRacesOrderCache();
raceOrderCacheMappingRaceToItsPredecessor.triggerUpdate(RACES_ORDER_LIST_CACHE_KEY,/* update interval */null);
this.raceOrderCacheMappingRaceToItsPredecessor = createRacesOrderCache();
// don't call triggerUpdate() as of now because the cache's owner may not yet be fully initialized,
// so the getRaceColumnsOfSeries() method may not yet be able to do its work. The owner must call
// triggerUpdate when fully initialized.
}
@Override
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.base.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
@@ -209,6 +210,11 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
}
}
protected Object readResolve() throws ObjectStreamException {
raceExecutionOrderCache.triggerUpdate(); // now we're fully initialized and the cache can do its job
return this;
}
/**
* {@link RaceColumnListeners} may not be de-serialized (yet) when the regatta
* is de-serialized. Do avoid re-registering empty objects most probably leading
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.leaderboard.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -79,7 +80,7 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements
throw new IllegalArgumentException("A leaderboard's name must not be null");
}
this.name = name;
this.races = new ArrayList<FlexibleRaceColumn>();
this.races = new ArrayList<>();
this.raceLogStore = raceLogStore;
this.courseArea = courseArea;
this.regattaLikeHelper = new BaseRegattaLikeImpl(new FlexibleLeaderboardAsRegattaLikeIdentifier(this), regattaLogStore);
@@ -99,6 +100,11 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements
column.setRaceLogInformation(raceLogStore, new FlexibleLeaderboardAsRegattaLikeIdentifier(this));
}
}
protected Object readResolve() throws ObjectStreamException {
raceExecutionOrderProvider.triggerUpdate();
return this;
}
@Override
public String getName() {
@@ -16,4 +16,12 @@ public interface RaceExecutionOrderProvider {
* by this method must all have been finished before <code>race</code> can start.
*/
Set<TrackedRace> getPreviousRaceInExecutionOrder(TrackedRace race);
/**
* When the owner of this cache-like provider has initialized all its structures that this cache requires
* it shall call this method. This applies in particular after de-serializing the owner because during de-serialization,
* even during the <code>readObject</code> method, the owner's fields may not all be initialized. The
* <code>readResolve()</code> method is usually a good place to do so.
*/
void triggerUpdate();
}
@@ -681,8 +681,8 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
}
private Duration getConditionalTimeBeforeStartToTrackWind(){
Set<TrackedRace> previosRaceInExecutionOrder = getPreviousRacesFromAttachedRaceExecutionOrderProviders();
if (previosRaceInExecutionOrder == null || !previosRaceInExecutionOrder.stream().filter(tr->tr.getEndOfTracking() != null).findAny().isPresent()) {
Set<TrackedRace> previosRacesInExecutionOrder = getPreviousRacesFromAttachedRaceExecutionOrderProviders();
if (previosRacesInExecutionOrder == null || !previosRacesInExecutionOrder.stream().filter(tr->tr.getEndOfTracking() != null).findAny().isPresent()) {
return EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS;
} else {
return TIME_BEFORE_START_TO_TRACK_WIND_MILLIS;
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.tracking.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -55,11 +56,12 @@ public class TrackedRegattaImpl implements TrackedRegatta {
oos.defaultWriteObject();
}
}
/**
* Resolving replaces this de-serialized object (which has a <code>null</code> {@link #raceListeners} collection) by
* a new one into which all other collection contents are copied.
*/
private Object readResolve() {
private Object readResolve() throws ObjectStreamException {
TrackedRegattaImpl result = new TrackedRegattaImpl(this.regatta);
result.trackedRaces.putAll(this.trackedRaces);
result.trackedRacesByBoatClass.putAll(this.trackedRacesByBoatClass);
@@ -106,10 +106,10 @@ public class LeaderboardsResource extends AbstractSailingServerResource {
JSONArray jsonLeaderboards = new JSONArray();
Map<String, Leaderboard> leaderboards = getService().getLeaderboards();
for (String leaderboardName : leaderboards.keySet()) {
if (!leaderboardName.equals(LeaderboardNameConstants.DEFAULT_LEADERBOARD_NAME))
if (!leaderboardName.equals(LeaderboardNameConstants.DEFAULT_LEADERBOARD_NAME)) {
jsonLeaderboards.add(leaderboardName);
}
}
String json = jsonLeaderboards.toJSONString();
return Response.ok(json, MediaType.APPLICATION_JSON).build();
}