Selaa lähdekoodia

Moved handling of failure to create handling event out of the application layer, letting the exception mark transaction for rollback.

peter_backlund 17 vuotta sitten
vanhempi
commit
6fbb5acf47

+ 5
- 1
dddsample/src/main/java/se/citerus/dddsample/application/HandlingEventService.java Näytä tiedosto

@@ -1,6 +1,7 @@
1 1
 package se.citerus.dddsample.application;
2 2
 
3 3
 import se.citerus.dddsample.domain.model.cargo.TrackingId;
4
+import se.citerus.dddsample.domain.model.handling.CannotCreateHandlingEventException;
4 5
 import se.citerus.dddsample.domain.model.handling.HandlingEvent;
5 6
 import se.citerus.dddsample.domain.model.location.UnLocode;
6 7
 import se.citerus.dddsample.domain.model.voyage.VoyageNumber;
@@ -21,11 +22,14 @@ public interface HandlingEventService {
21 22
    * @param voyageNumber voyage number
22 23
    * @param unLocode UN locode for the location where the event occurred
23 24
    * @param type type of event
25
+   * @throws se.citerus.dddsample.domain.model.handling.CannotCreateHandlingEventException
26
+   *  if a handling event that represents an actual event that's relevant to a cargo we're tracking
27
+   *  can't be created from the parameters 
24 28
    */
25 29
   void registerHandlingEvent(Date completionTime,
26 30
                              TrackingId trackingId,
27 31
                              VoyageNumber voyageNumber,
28 32
                              UnLocode unLocode,
29
-                             HandlingEvent.Type type);
33
+                             HandlingEvent.Type type) throws CannotCreateHandlingEventException;
30 34
 
31 35
 }

+ 0
- 12
dddsample/src/main/java/se/citerus/dddsample/application/impl/BookingServiceImpl.java Näytä tiedosto

@@ -1,6 +1,5 @@
1 1
 package se.citerus.dddsample.application.impl;
2 2
 
3
-import org.apache.commons.lang.Validate;
4 3
 import org.apache.commons.logging.Log;
5 4
 import org.apache.commons.logging.LogFactory;
6 5
 import org.springframework.transaction.annotation.Transactional;
@@ -35,9 +34,6 @@ public final class BookingServiceImpl implements BookingService {
35 34
   public TrackingId bookNewCargo(final UnLocode originUnLocode,
36 35
                                  final UnLocode destinationUnLocode,
37 36
                                  final Date arrivalDeadline) {
38
-    Validate.notNull(originUnLocode);
39
-    Validate.notNull(destinationUnLocode);
40
-
41 37
     // TODO modeling this as a cargo factory might be suitable
42 38
     final TrackingId trackingId = cargoRepository.nextTrackingId();
43 39
     final Location origin = locationRepository.find(originUnLocode);
@@ -55,8 +51,6 @@ public final class BookingServiceImpl implements BookingService {
55 51
   @Override
56 52
   @Transactional
57 53
   public List<Itinerary> requestPossibleRoutesForCargo(final TrackingId trackingId) {
58
-    Validate.notNull(trackingId);
59
-
60 54
     final Cargo cargo = cargoRepository.find(trackingId);
61 55
 
62 56
     if (cargo == null) {
@@ -69,9 +63,6 @@ public final class BookingServiceImpl implements BookingService {
69 63
   @Override
70 64
   @Transactional
71 65
   public void assignCargoToRoute(final Itinerary itinerary, final TrackingId trackingId) {
72
-    Validate.notNull(itinerary);
73
-    Validate.notNull(trackingId);
74
-                                
75 66
     final Cargo cargo = cargoRepository.find(trackingId);
76 67
     if (cargo == null) {
77 68
       throw new IllegalArgumentException("Can't assign itinerary to non-existing cargo " + trackingId);
@@ -86,9 +77,6 @@ public final class BookingServiceImpl implements BookingService {
86 77
   @Override
87 78
   @Transactional
88 79
   public void changeDestination(final TrackingId trackingId, final UnLocode unLocode) {
89
-    Validate.notNull(trackingId);
90
-    Validate.notNull(unLocode);
91
-
92 80
     final Cargo cargo = cargoRepository.find(trackingId);
93 81
     final Location newDestination = locationRepository.find(unLocode);
94 82
 

+ 21
- 26
dddsample/src/main/java/se/citerus/dddsample/application/impl/HandlingEventServiceImpl.java Näytä tiedosto

@@ -20,7 +20,7 @@ public final class HandlingEventServiceImpl implements HandlingEventService {
20 20
   private final ApplicationEvents applicationEvents;
21 21
   private final HandlingEventRepository handlingEventRepository;
22 22
   private final HandlingEventFactory handlingEventFactory;
23
-  private static final Log logger = LogFactory.getLog(HandlingEventServiceImpl.class);
23
+  private final Log logger = LogFactory.getLog(HandlingEventServiceImpl.class);
24 24
 
25 25
   public HandlingEventServiceImpl(final HandlingEventRepository handlingEventRepository,
26 26
                                   final ApplicationEvents applicationEvents,
@@ -31,35 +31,30 @@ public final class HandlingEventServiceImpl implements HandlingEventService {
31 31
   }
32 32
 
33 33
   @Override
34
-  @Transactional
34
+  @Transactional(rollbackFor = CannotCreateHandlingEventException.class)
35 35
   public void registerHandlingEvent(final Date completionTime,
36 36
                                     final TrackingId trackingId,
37 37
                                     final VoyageNumber voyageNumber,
38 38
                                     final UnLocode unLocode,
39
-                                    final HandlingEvent.Type type) {
40
-    try {
41
-      /* Using a factory to create a HandlingEvent (aggregate). This is where
42
-         it is determined wether the incoming data, the attempt, actually is capable
43
-         of representing a real handling event. */
44
-      final HandlingEvent event = handlingEventFactory.createHandlingEvent(
45
-        new Date(), completionTime, trackingId, voyageNumber, unLocode, type
46
-      );
47
-
48
-      /* Store the new handling event, which updates the persistent
49
-         state of the handling event aggregate (but not the cargo aggregate -
50
-         that happens asynchronously!)
51
-       */
52
-      handlingEventRepository.store(event);
53
-
54
-      /* Publish an event stating that a cargo has been handled. */
55
-      applicationEvents.cargoWasHandled(event);
56
-
57
-      logger.info("Registered handling event");
58
-    } catch (CannotCreateHandlingEventException e) {
59
-      /* This may be a bogus attempt, for example containing a tracking id
60
-         that doesn't match any cargo that we're tracking. */
61
-      logger.error(e);
62
-    }
39
+                                    final HandlingEvent.Type type) throws CannotCreateHandlingEventException {
40
+    final Date registrationTime = new Date();
41
+    /* Using a factory to create a HandlingEvent (aggregate). This is where
42
+       it is determined wether the incoming data, the attempt, actually is capable
43
+       of representing a real handling event. */
44
+    final HandlingEvent event = handlingEventFactory.createHandlingEvent(
45
+      registrationTime, completionTime, trackingId, voyageNumber, unLocode, type
46
+    );
47
+
48
+    /* Store the new handling event, which updates the persistent
49
+       state of the handling event aggregate (but not the cargo aggregate -
50
+       that happens asynchronously!)
51
+     */
52
+    handlingEventRepository.store(event);
53
+
54
+    /* Publish an event stating that a cargo has been handled. */
55
+    applicationEvents.cargoWasHandled(event);
56
+
57
+    logger.info("Registered handling event");
63 58
   }
64 59
 
65 60
 }

+ 8
- 83
dddsample/src/test/java/se/citerus/dddsample/application/HandlingEventServiceTest.java Näytä tiedosto

@@ -12,9 +12,7 @@ import se.citerus.dddsample.domain.model.handling.HandlingEventFactory;
12 12
 import se.citerus.dddsample.domain.model.handling.HandlingEventRepository;
13 13
 import se.citerus.dddsample.domain.model.location.LocationRepository;
14 14
 import static se.citerus.dddsample.domain.model.location.SampleLocations.*;
15
-import se.citerus.dddsample.domain.model.location.UnLocode;
16
-import se.citerus.dddsample.domain.model.voyage.SampleVoyages;
17
-import se.citerus.dddsample.domain.model.voyage.VoyageNumber;
15
+import static se.citerus.dddsample.domain.model.voyage.SampleVoyages.CM001;
18 16
 import se.citerus.dddsample.domain.model.voyage.VoyageRepository;
19 17
 
20 18
 import java.util.Date;
@@ -26,10 +24,8 @@ public class HandlingEventServiceTest extends TestCase {
26 24
   private VoyageRepository voyageRepository;
27 25
   private HandlingEventRepository handlingEventRepository;
28 26
   private LocationRepository locationRepository;
29
-  private HandlingEventFactory handlingEventFactory;
30 27
 
31
-  private final Cargo cargoABC = new Cargo(new TrackingId("ABC"), new RouteSpecification(HAMBURG, TOKYO, new Date()));
32
-  private final Cargo cargoXYZ = new Cargo(new TrackingId("XYZ"), new RouteSpecification(HONGKONG, HELSINKI, new Date()));
28
+  private final Cargo cargo = new Cargo(new TrackingId("ABC"), new RouteSpecification(HAMBURG, TOKYO, new Date()));
33 29
 
34 30
   protected void setUp() throws Exception{
35 31
     cargoRepository = createMock(CargoRepository.class);
@@ -37,7 +33,8 @@ public class HandlingEventServiceTest extends TestCase {
37 33
     handlingEventRepository = createMock(HandlingEventRepository.class);
38 34
     locationRepository = createMock(LocationRepository.class);
39 35
     applicationEvents = createMock(ApplicationEvents.class);
40
-    handlingEventFactory = new HandlingEventFactory(cargoRepository, voyageRepository, locationRepository);
36
+
37
+    HandlingEventFactory handlingEventFactory = new HandlingEventFactory(cargoRepository, voyageRepository, locationRepository);
41 38
     service = new HandlingEventServiceImpl(handlingEventRepository, applicationEvents, handlingEventFactory);
42 39
   }
43 40
 
@@ -46,87 +43,15 @@ public class HandlingEventServiceTest extends TestCase {
46 43
   }
47 44
 
48 45
   public void testRegisterEvent() throws Exception {
49
-    final TrackingId trackingId = new TrackingId("ABC");
50
-    expect(cargoRepository.find(trackingId)).andReturn(cargoABC);
51
-
52
-    final VoyageNumber voyageNumber = new VoyageNumber("AAA_BBB");
53
-    expect(voyageRepository.find(voyageNumber)).andReturn(SampleVoyages.CM001);
54
-
55
-    final UnLocode unLocode = new UnLocode("SESTO");
56
-    expect(locationRepository.find(unLocode)).andReturn(STOCKHOLM);
57
-
58
-    // TODO: does not inspect the handling event instance in a sufficient way
59
-    handlingEventRepository.store(isA(HandlingEvent.class));
60
-    applicationEvents.cargoWasHandled(isA(HandlingEvent.class));
61
-
62
-    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, applicationEvents);
63
-
64
-    final HandlingEventRegistrationAttempt attempt = new HandlingEventRegistrationAttempt(
65
-      new Date(), new Date(), trackingId, voyageNumber, HandlingEvent.Type.LOAD, unLocode
66
-    );
67
-    service.registerHandlingEvent(attempt.getCompletionTime(), attempt.getTrackingId(), attempt.getVoyageNumber(), attempt.getUnLocode(), attempt.getType());
68
-  }
69
-
70
-  public void testRegisterEventWithoutCarrierMovement() throws Exception {
71
-    final TrackingId trackingId = new TrackingId("ABC");
72
-    expect(cargoRepository.find(trackingId)).andReturn(cargoABC);
73
-
46
+    expect(cargoRepository.find(cargo.trackingId())).andReturn(cargo);
47
+    expect(voyageRepository.find(CM001.voyageNumber())).andReturn(CM001);
48
+    expect(locationRepository.find(STOCKHOLM.unLocode())).andReturn(STOCKHOLM);
74 49
     handlingEventRepository.store(isA(HandlingEvent.class));
75 50
     applicationEvents.cargoWasHandled(isA(HandlingEvent.class));
76 51
 
77
-    expect(locationRepository.find(STOCKHOLM.unLocode())).andReturn(STOCKHOLM);
78
-
79 52
     replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, applicationEvents);
80 53
 
81
-    final HandlingEventRegistrationAttempt attempt = new HandlingEventRegistrationAttempt(
82
-      new Date(), new Date(), trackingId, null, HandlingEvent.Type.RECEIVE, STOCKHOLM.unLocode()
83
-    );
84
-    service.registerHandlingEvent(attempt.getCompletionTime(), attempt.getTrackingId(), attempt.getVoyageNumber(), attempt.getUnLocode(), attempt.getType());
54
+    service.registerHandlingEvent(new Date(), cargo.trackingId(), CM001.voyageNumber(), STOCKHOLM.unLocode(), HandlingEvent.Type.LOAD);
85 55
   }
86
-  
87 56
 
88
-  public void testRegisterEventInvalidCarrier() throws Exception {
89
-    final VoyageNumber voyageNumber = new VoyageNumber("AAA_BBB");
90
-    expect(voyageRepository.find(voyageNumber)).andReturn(null);
91
-
92
-    final TrackingId trackingId = new TrackingId("XYZ");
93
-    expect(cargoRepository.find(trackingId)).andReturn(new Cargo(trackingId, new RouteSpecification(CHICAGO, STOCKHOLM, new Date())));
94
-
95
-    expect(locationRepository.find(MELBOURNE.unLocode())).andReturn(MELBOURNE);
96
-
97
-    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, applicationEvents);
98
-
99
-    final HandlingEventRegistrationAttempt attempt = new HandlingEventRegistrationAttempt(
100
-      new Date(), new Date(), trackingId, voyageNumber, HandlingEvent.Type.UNLOAD, MELBOURNE.unLocode()
101
-    );
102
-    service.registerHandlingEvent(attempt.getCompletionTime(), attempt.getTrackingId(), attempt.getVoyageNumber(), attempt.getUnLocode(), attempt.getType());
103
-  }
104
-  
105
-  public void testRegisterEventInvalidCargo() throws Exception {
106
-    final TrackingId trackingId = new TrackingId("XYZ");
107
-    expect(cargoRepository.find(trackingId)).andReturn(null);
108
-
109
-    expect(locationRepository.find(HONGKONG.unLocode())).andReturn(HONGKONG);
110
-
111
-    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, applicationEvents);
112
-
113
-    final HandlingEventRegistrationAttempt attempt = new HandlingEventRegistrationAttempt(
114
-      new Date(), new Date(), trackingId, new VoyageNumber("V001"), HandlingEvent.Type.CLAIM, HONGKONG.unLocode()
115
-    );
116
-    service.registerHandlingEvent(attempt.getCompletionTime(), attempt.getTrackingId(), attempt.getVoyageNumber(), attempt.getUnLocode(), attempt.getType());
117
-  }
118
-  
119
-  public void testRegisterEventInvalidLocation() throws Exception {
120
-    final TrackingId trackingId = new TrackingId("XYZ");
121
-    expect(cargoRepository.find(trackingId)).andReturn(cargoXYZ);
122
-    UnLocode wayOff = new UnLocode("XXYYY");
123
-    expect(locationRepository.find(wayOff)).andReturn(null);
124
-
125
-    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, applicationEvents);
126
-
127
-    final HandlingEventRegistrationAttempt attempt = new HandlingEventRegistrationAttempt(
128
-      new Date(), new Date(), trackingId, null, HandlingEvent.Type.CLAIM, wayOff
129
-    );
130
-    service.registerHandlingEvent(attempt.getCompletionTime(), attempt.getTrackingId(), attempt.getVoyageNumber(), attempt.getUnLocode(), attempt.getType());
131
-  }
132 57
 }