ソースを参照

Slight method name changes (deriveStatusFromHandling => deriveDeliveryProgress).

Fixed cloning of Date in a few places.

Explicitly roll back transaction if handling event registration fails.

Using single-parameter validation + message in more places (instead of arrays)
peter_backlund 17 年 前
コミット
26a7aed12d

+ 2
- 2
dddsample/src/main/java/se/citerus/dddsample/application/impl/CargoInspectionServiceImpl.java ファイルの表示

@@ -40,9 +40,9 @@ public class CargoInspectionServiceImpl implements CargoInspectionService {
40 40
       return;
41 41
     }
42 42
 
43
-    final List<HandlingEvent> deliveryHistory = handlingEventRepository.findEventsForCargo(trackingId);
43
+    final List<HandlingEvent> handlingEvents = handlingEventRepository.findEventsForCargo(trackingId);
44 44
 
45
-    cargo.deriveStatusFromHandling(deliveryHistory);
45
+    cargo.deriveDeliveryProgress(handlingEvents);
46 46
 
47 47
     if (cargo.isMisdirected()) {
48 48
       applicationEvents.cargoWasMisdirected(cargo);

+ 3
- 1
dddsample/src/main/java/se/citerus/dddsample/application/impl/HandlingEventServiceImpl.java ファイルの表示

@@ -3,6 +3,7 @@ package se.citerus.dddsample.application.impl;
3 3
 import org.apache.commons.logging.Log;
4 4
 import org.apache.commons.logging.LogFactory;
5 5
 import org.springframework.transaction.annotation.Transactional;
6
+import static org.springframework.transaction.interceptor.TransactionAspectSupport.currentTransactionStatus;
6 7
 import se.citerus.dddsample.application.ApplicationEvents;
7 8
 import se.citerus.dddsample.application.HandlingEventService;
8 9
 import se.citerus.dddsample.domain.model.cargo.TrackingId;
@@ -58,7 +59,8 @@ public final class HandlingEventServiceImpl implements HandlingEventService {
58 59
     } catch (CannotCreateHandlingEventException e) {
59 60
       /* This may be a bogus attempt, for example containing a tracking id
60 61
          that doesn't match any cargo that we're tracking. */
61
-      logger.error(e, e);
62
+      logger.error(e);
63
+      currentTransactionStatus().setRollbackOnly();
62 64
     }
63 65
   }
64 66
 

+ 2
- 2
dddsample/src/main/java/se/citerus/dddsample/application/util/SampleDataGenerator.java ファイルの表示

@@ -255,7 +255,7 @@ public class SampleDataGenerator implements ServletContextListener {
255 255
         }
256 256
 
257 257
         List<HandlingEvent> handlingEvents = handlingEventRepository.findEventsForCargo(trackingId);
258
-        abc123.deriveStatusFromHandling(handlingEvents);
258
+        abc123.deriveDeliveryProgress(handlingEvents);
259 259
 
260 260
         session.update(abc123);
261 261
 
@@ -300,7 +300,7 @@ public class SampleDataGenerator implements ServletContextListener {
300 300
         }
301 301
 
302 302
         List<HandlingEvent> handlingEvents1 = handlingEventRepository.findEventsForCargo(trackingId1);
303
-        jkl567.deriveStatusFromHandling(handlingEvents1);
303
+        jkl567.deriveDeliveryProgress(handlingEvents1);
304 304
 
305 305
         session.update(jkl567);
306 306
       }

+ 7
- 7
dddsample/src/main/java/se/citerus/dddsample/domain/model/cargo/Cargo.java ファイルの表示

@@ -61,7 +61,7 @@ public class Cargo implements Entity<Cargo> {
61 61
     this.trackingId = trackingId;
62 62
     this.origin = origin;
63 63
     this.routeSpecification = routeSpecification;
64
-    deriveStatusFromHandling(Collections.<HandlingEvent>emptyList());
64
+    deriveDeliveryProgress(Collections.<HandlingEvent>emptyList());
65 65
   }
66 66
 
67 67
   /**
@@ -165,12 +165,12 @@ public class Cargo implements Entity<Cargo> {
165 165
    * @return estimated time of arrival
166 166
    */
167 167
   public Date estimatedTimeOfArrival() {
168
-    return eta;
168
+    return new Date(eta.getTime());
169 169
   }
170 170
 
171 171
   /**
172 172
    * Updates all aspects of the cargo aggregate status
173
-   * based on the current route specification, itinerary and delivery history.
173
+   * based on the current route specification, itinerary and handling of the cargo.
174 174
    * <p/>
175 175
    * When either of those three changes, i.e. when a new route is specified for the cargo,
176 176
    * the cargo is assigned to a route or when the cargo is handled, the status must be
@@ -181,12 +181,12 @@ public class Cargo implements Entity<Cargo> {
181 181
    * but changes to the delivery history (when a cargo is handled) cause the status update
182 182
    * to happen <b>asynchronously</b> since {@link HandlingEvent} is in a different aggregate.
183 183
    *
184
-   * @param deliveryHistory all handling events for this cargo
184
+   * @param handlingEvents all handling events for this cargo
185 185
    */
186
-  public void deriveStatusFromHandling(final List<HandlingEvent> deliveryHistory) {
186
+  public void deriveDeliveryProgress(final List<HandlingEvent> handlingEvents) {
187 187
     // Delivery is a value object, so we can simply discard the old one
188
-    // and replace with a new
189
-    this.delivery = Delivery.derivedFrom(deliveryHistory);
188
+    // and replace it with a new
189
+    this.delivery = Delivery.derivedFrom(handlingEvents);
190 190
     this.routingStatus = deriveRoutingStatus();
191 191
     this.misdirected = deriveMisdirectionStatus();
192 192
     this.eta = deriveEta();

+ 1
- 1
dddsample/src/main/java/se/citerus/dddsample/domain/model/cargo/Itinerary.java ファイルの表示

@@ -117,7 +117,7 @@ public class Itinerary implements ValueObject<Itinerary> {
117 117
     if (lastLeg == null) {
118 118
       return new Date(END_OF_DAYS.getTime());
119 119
     } else {
120
-      return lastLeg.unloadTime();
120
+      return new Date(lastLeg.unloadTime().getTime());
121 121
     }
122 122
   }
123 123
 

+ 2
- 2
dddsample/src/main/java/se/citerus/dddsample/domain/model/cargo/RouteSpecification.java ファイルの表示

@@ -33,7 +33,7 @@ public class RouteSpecification extends AbstractSpecification<Itinerary> impleme
33 33
 
34 34
     this.origin = origin;
35 35
     this.destination = destination;
36
-    this.arrivalDeadline = arrivalDeadline;
36
+    this.arrivalDeadline = (Date) arrivalDeadline.clone();
37 37
   }
38 38
 
39 39
   /**
@@ -54,7 +54,7 @@ public class RouteSpecification extends AbstractSpecification<Itinerary> impleme
54 54
    * @return Arrival deadline.
55 55
    */
56 56
   public Date arrivalDeadline() {
57
-    return arrivalDeadline;
57
+    return new Date(arrivalDeadline.getTime());
58 58
   }
59 59
 
60 60
   @Override

+ 1
- 1
dddsample/src/main/java/se/citerus/dddsample/domain/model/handling/CannotCreateHandlingEventException.java ファイルの表示

@@ -2,7 +2,7 @@ package se.citerus.dddsample.domain.model.handling;
2 2
 
3 3
 /**
4 4
  * If a {@link se.citerus.dddsample.domain.model.handling.HandlingEvent} can't be
5
- * created from an incoming {@link #se.citerus.dddsample.application.HandlingEventRegistrationAttempt},
5
+ * created from a given set of parameters.
6 6
  *
7 7
  * It is a checked exception because it's not a programming error, but rather a
8 8
  * special case that the application is built to handle. It can occur during normal

+ 11
- 6
dddsample/src/main/java/se/citerus/dddsample/domain/model/handling/HandlingEvent.java ファイルの表示

@@ -107,9 +107,12 @@ public final class HandlingEvent implements DomainEvent<HandlingEvent> {
107 107
                        final Type type,
108 108
                        final Location location,
109 109
                        final Voyage voyage) {
110
-    Validate.noNullElements(new Object[]
111
-      {cargo, completionTime, registrationTime, type, location, voyage}
112
-    );
110
+    Validate.notNull(cargo, "Cargo is required");
111
+    Validate.notNull(completionTime, "Completion time is required");
112
+    Validate.notNull(registrationTime, "Registration time is required");
113
+    Validate.notNull(type, "Handling event type is required");
114
+    Validate.notNull(location, "Location is required");
115
+    Validate.notNull(voyage, "Voyage is required");
113 116
 
114 117
     if (type.prohibitsVoyage()) {
115 118
       throw new IllegalArgumentException("Voyage is not allowed with event type " + type);
@@ -135,9 +138,11 @@ public final class HandlingEvent implements DomainEvent<HandlingEvent> {
135 138
                        final Date registrationTime,
136 139
                        final Type type,
137 140
                        final Location location) {
138
-    Validate.noNullElements(new Object[]
139
-      {cargo, completionTime, registrationTime, type, location}
140
-    );
141
+    Validate.notNull(cargo, "Cargo is required");
142
+    Validate.notNull(completionTime, "Completion time is required");
143
+    Validate.notNull(registrationTime, "Registration time is required");
144
+    Validate.notNull(type, "Handling event type is required");
145
+    Validate.notNull(location, "Location is required");
141 146
 
142 147
     if (type.requiresVoyage()) {
143 148
       throw new IllegalArgumentException("Voyage is required for event type " + type);

+ 0
- 7
dddsample/src/main/java/se/citerus/dddsample/domain/model/handling/HandlingEventFactory.java ファイルの表示

@@ -1,6 +1,5 @@
1 1
 package se.citerus.dddsample.domain.model.handling;
2 2
 
3
-import org.apache.commons.lang.Validate;
4 3
 import se.citerus.dddsample.domain.model.cargo.Cargo;
5 4
 import se.citerus.dddsample.domain.model.cargo.CargoRepository;
6 5
 import se.citerus.dddsample.domain.model.cargo.TrackingId;
@@ -44,12 +43,6 @@ public class HandlingEventFactory {
44 43
    */
45 44
   public HandlingEvent createHandlingEvent(Date registrationTime, Date completionTime, TrackingId trackingId, VoyageNumber voyageNumber, UnLocode unlocode, HandlingEvent.Type type)
46 45
     throws CannotCreateHandlingEventException {
47
-
48
-    // Voyage number may be null for certain event types
49
-    Validate.noNullElements(new Object[]
50
-      {registrationTime, completionTime, trackingId, unlocode, type}
51
-    );
52
-
53 46
     final Cargo cargo = findCargo(trackingId);
54 47
     final Voyage voyage = findVoyage(voyageNumber);
55 48
     final Location location = findLocation(unlocode);

+ 1
- 1
dddsample/src/main/webapp/WEB-INF/jsp/admin/selectItinerary.jsp ファイルの表示

@@ -21,7 +21,7 @@
21 21
   </table>
22 22
   <c:url value="/admin/assignItinerary.html" var="postUrl"/>
23 23
 
24
-  <c:forEach items="${itineraryCandidates}" var="it" varStatus="itStatus">
24
+  <c:forEach items="${routeCandidates}" var="it" varStatus="itStatus">
25 25
       <form action="${postUrl}" method="post">
26 26
         <input type="hidden" name="trackingId" value="${cargo.trackingId}"/>
27 27
         <table>

+ 14
- 14
dddsample/src/test/java/se/citerus/dddsample/domain/model/cargo/CargoTest.java ファイルの表示

@@ -118,7 +118,7 @@ public class CargoTest extends TestCase {
118 118
     // Adding an event unrelated to unloading at final destination
119 119
     events.add(
120 120
       new HandlingEvent(cargo, new Date(10), new Date(), HandlingEvent.Type.RECEIVE, HANGZOU));
121
-    cargo.deriveStatusFromHandling(events);
121
+    cargo.deriveDeliveryProgress(events);
122 122
     assertFalse(cargo.isUnloadedAtDestination());
123 123
 
124 124
     Voyage voyage = new Voyage.Builder(new VoyageNumber("0123"), HANGZOU).
@@ -128,19 +128,19 @@ public class CargoTest extends TestCase {
128 128
     // Adding an unload event, but not at the final destination
129 129
     events.add(
130 130
       new HandlingEvent(cargo, new Date(20), new Date(), HandlingEvent.Type.UNLOAD, TOKYO, voyage));
131
-    cargo.deriveStatusFromHandling(events);
131
+    cargo.deriveDeliveryProgress(events);
132 132
     assertFalse(cargo.isUnloadedAtDestination());
133 133
 
134 134
     // Adding an event in the final destination, but not unload
135 135
     events.add(
136 136
       new HandlingEvent(cargo, new Date(30), new Date(), HandlingEvent.Type.CUSTOMS, NEWYORK));
137
-    cargo.deriveStatusFromHandling(events);
137
+    cargo.deriveDeliveryProgress(events);
138 138
     assertFalse(cargo.isUnloadedAtDestination());
139 139
 
140 140
     // Finally, cargo is unloaded at final destination
141 141
     events.add(
142 142
       new HandlingEvent(cargo, new Date(40), new Date(), HandlingEvent.Type.UNLOAD, NEWYORK, voyage));
143
-    cargo.deriveStatusFromHandling(events);
143
+    cargo.deriveDeliveryProgress(events);
144 144
     assertTrue(cargo.isUnloadedAtDestination());
145 145
   }
146 146
 
@@ -150,7 +150,7 @@ public class CargoTest extends TestCase {
150 150
 
151 151
     HandlingEvent he = new HandlingEvent(cargo, getDate("2007-12-01"), new Date(), HandlingEvent.Type.RECEIVE, STOCKHOLM);
152 152
     events.add(he);
153
-    cargo.deriveStatusFromHandling(events);
153
+    cargo.deriveDeliveryProgress(events);
154 154
 
155 155
     return cargo;
156 156
   }
@@ -159,7 +159,7 @@ public class CargoTest extends TestCase {
159 159
     final Cargo cargo = populateCargoOffMelbourne();
160 160
 
161 161
     events.add(new HandlingEvent(cargo, getDate("2007-12-09"), new Date(), HandlingEvent.Type.CLAIM, MELBOURNE));
162
-    cargo.deriveStatusFromHandling(events);
162
+    cargo.deriveDeliveryProgress(events);
163 163
 
164 164
     return cargo;
165 165
   }
@@ -174,7 +174,7 @@ public class CargoTest extends TestCase {
174 174
     events.add(new HandlingEvent(cargo, getDate("2007-12-03"), new Date(), HandlingEvent.Type.LOAD, HAMBURG, voyage));
175 175
     events.add(new HandlingEvent(cargo, getDate("2007-12-04"), new Date(), HandlingEvent.Type.UNLOAD, HONGKONG, voyage));
176 176
 
177
-    cargo.deriveStatusFromHandling(events);
177
+    cargo.deriveDeliveryProgress(events);
178 178
     return cargo;
179 179
   }
180 180
 
@@ -185,7 +185,7 @@ public class CargoTest extends TestCase {
185 185
     events.add(new HandlingEvent(cargo, getDate("2007-12-02"), new Date(), HandlingEvent.Type.UNLOAD, HAMBURG, voyage));
186 186
     events.add(new HandlingEvent(cargo, getDate("2007-12-03"), new Date(), HandlingEvent.Type.LOAD, HAMBURG, voyage));
187 187
 
188
-    cargo.deriveStatusFromHandling(events);
188
+    cargo.deriveDeliveryProgress(events);
189 189
     return cargo;
190 190
   }
191 191
 
@@ -201,7 +201,7 @@ public class CargoTest extends TestCase {
201 201
     events.add(new HandlingEvent(cargo, getDate("2007-12-05"), new Date(), HandlingEvent.Type.LOAD, HONGKONG, voyage));
202 202
     events.add(new HandlingEvent(cargo, getDate("2007-12-07"), new Date(), HandlingEvent.Type.UNLOAD, MELBOURNE, voyage));
203 203
 
204
-    cargo.deriveStatusFromHandling(events);
204
+    cargo.deriveDeliveryProgress(events);
205 205
     return cargo;
206 206
   }
207 207
 
@@ -216,7 +216,7 @@ public class CargoTest extends TestCase {
216 216
 
217 217
     events.add(new HandlingEvent(cargo, getDate("2007-12-05"), new Date(), HandlingEvent.Type.LOAD, HONGKONG, voyage));
218 218
 
219
-    cargo.deriveStatusFromHandling(events);
219
+    cargo.deriveDeliveryProgress(events);
220 220
     return cargo;
221 221
   }
222 222
 
@@ -242,7 +242,7 @@ public class CargoTest extends TestCase {
242 242
     handlingEvents.add(new HandlingEvent(cargo, new Date(130), new Date(140), HandlingEvent.Type.CUSTOMS, GOTHENBURG));
243 243
 
244 244
     events.addAll(handlingEvents);
245
-    cargo.deriveStatusFromHandling(events);
245
+    cargo.deriveDeliveryProgress(events);
246 246
     assertFalse(cargo.isMisdirected());
247 247
 
248 248
     //Try a couple of failing ones
@@ -252,7 +252,7 @@ public class CargoTest extends TestCase {
252 252
 
253 253
     handlingEvents.add(new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.RECEIVE, HANGZOU));
254 254
     events.addAll(handlingEvents);
255
-    cargo.deriveStatusFromHandling(events);
255
+    cargo.deriveDeliveryProgress(events);
256 256
 
257 257
     assertTrue(cargo.isMisdirected());
258 258
 
@@ -266,7 +266,7 @@ public class CargoTest extends TestCase {
266 266
     handlingEvents.add(new HandlingEvent(cargo, new Date(70), new Date(80), HandlingEvent.Type.LOAD, ROTTERDAM, voyage));
267 267
 
268 268
     events.addAll(handlingEvents);
269
-    cargo.deriveStatusFromHandling(events);
269
+    cargo.deriveDeliveryProgress(events);
270 270
 
271 271
     assertTrue(cargo.isMisdirected());
272 272
 
@@ -280,7 +280,7 @@ public class CargoTest extends TestCase {
280 280
     handlingEvents.add(new HandlingEvent(cargo, new Date(), new Date(), HandlingEvent.Type.CLAIM, ROTTERDAM));
281 281
 
282 282
     events.addAll(handlingEvents);
283
-    cargo.deriveStatusFromHandling(events);
283
+    cargo.deriveDeliveryProgress(events);
284 284
 
285 285
     assertTrue(cargo.isMisdirected());
286 286
   }

+ 1
- 1
dddsample/src/test/java/se/citerus/dddsample/infrastructure/persistence/inmemory/CargoRepositoryInMem.java ファイルの表示

@@ -89,7 +89,7 @@ public class CargoRepositoryInMem implements CargoRepository {
89 89
 
90 90
     final RouteSpecification routeSpecification = new RouteSpecification(origin, destination, new Date());
91 91
     final Cargo cargo = new Cargo(trackingId, origin, routeSpecification);
92
-    cargo.deriveStatusFromHandling(new ArrayList<HandlingEvent>(events));
92
+    cargo.deriveDeliveryProgress(new ArrayList<HandlingEvent>(events));
93 93
 
94 94
     return cargo;
95 95
   }

+ 1
- 1
dddsample/src/test/java/se/citerus/dddsample/interfaces/tracking/CargoTrackingViewAdapterTest.java ファイルの表示

@@ -23,7 +23,7 @@ public class CargoTrackingViewAdapterTest extends TestCase {
23 23
     events.add(new HandlingEvent(cargo, new Date(3), new Date(4), HandlingEvent.Type.LOAD, HANGZOU, CM001));
24 24
     events.add(new HandlingEvent(cargo, new Date(5), new Date(6), HandlingEvent.Type.UNLOAD, HELSINKI, CM001));
25 25
 
26
-    cargo.deriveStatusFromHandling(events);
26
+    cargo.deriveDeliveryProgress(events);
27 27
 
28 28
     StaticApplicationContext applicationContext = new StaticApplicationContext();
29 29
     applicationContext.addMessage("cargo.status.IN_PORT", Locale.GERMAN, "In port {0}");