Browse Source

Renamed DomainEventNotifer to SystemEvents and moved out to application layer.

Moved handling of rejected registration attempts into HandlingEventService, making the JMS consumer pure delegation.
peter_backlund 18 years ago
parent
commit
c44996ccef

+ 1
- 3
dddsample/src/main/java/se/citerus/dddsample/application/HandlingEventService.java View File

1
 package se.citerus.dddsample.application;
1
 package se.citerus.dddsample.application;
2
 
2
 
3
 import se.citerus.dddsample.application.messaging.HandlingEventRegistrationAttempt;
3
 import se.citerus.dddsample.application.messaging.HandlingEventRegistrationAttempt;
4
-import se.citerus.dddsample.domain.model.handling.CannotCreateHandlingEventException;
5
 
4
 
6
 
5
 
7
 /**
6
 /**
14
    * parties that an event has been registered.
13
    * parties that an event has been registered.
15
    *
14
    *
16
    * @param attempt handling event registration attempt
15
    * @param attempt handling event registration attempt
17
-   * @throws se.citerus.dddsample.domain.model.handling.CannotCreateHandlingEventException
18
    */
16
    */
19
-  void register(HandlingEventRegistrationAttempt attempt) throws CannotCreateHandlingEventException;
17
+  void register(HandlingEventRegistrationAttempt attempt);
20
 
18
 
21
 }
19
 }

+ 32
- 0
dddsample/src/main/java/se/citerus/dddsample/application/SystemEvents.java View File

1
+package se.citerus.dddsample.application;
2
+
3
+import se.citerus.dddsample.application.messaging.HandlingEventRegistrationAttempt;
4
+import se.citerus.dddsample.domain.model.cargo.Cargo;
5
+import se.citerus.dddsample.domain.model.handling.CannotCreateHandlingEventException;
6
+import se.citerus.dddsample.domain.model.handling.HandlingEvent;
7
+
8
+/**
9
+ * This interface provides a way to let other parts
10
+ * of the system know about events that have occurred.
11
+ * <p/>
12
+ * It may be implemented synchronously or asynchronously, using
13
+ * for example JMS.
14
+ */
15
+public interface SystemEvents {
16
+
17
+  /**
18
+   * A cargo has been handled.
19
+   *
20
+   * @param event handling event
21
+   */
22
+  void cargoWasHandled(HandlingEvent event);
23
+
24
+  void cargoWasMisdirected(Cargo cargo);
25
+
26
+  void cargoHasArrived(Cargo cargo);
27
+
28
+  void rejectHandlingEventRegistrationAttempt(HandlingEventRegistrationAttempt attempt, CannotCreateHandlingEventException problem);
29
+
30
+  //void scheduleWasChanged(Voyage voyage);
31
+
32
+}

+ 1
- 1
dddsample/src/main/java/se/citerus/dddsample/application/impl/BookingServiceImpl.java View File

28
   }
28
   }
29
 
29
 
30
   @Override
30
   @Override
31
-  @Transactional(readOnly = false)
31
+  @Transactional
32
   public TrackingId bookNewCargo(final UnLocode originUnLocode, final UnLocode destinationUnLocode) {
32
   public TrackingId bookNewCargo(final UnLocode originUnLocode, final UnLocode destinationUnLocode) {
33
     Validate.notNull(originUnLocode);
33
     Validate.notNull(originUnLocode);
34
     Validate.notNull(destinationUnLocode);
34
     Validate.notNull(destinationUnLocode);

+ 13
- 9
dddsample/src/main/java/se/citerus/dddsample/application/impl/HandlingEventServiceImpl.java View File

2
 
2
 
3
 import org.springframework.transaction.annotation.Transactional;
3
 import org.springframework.transaction.annotation.Transactional;
4
 import se.citerus.dddsample.application.HandlingEventService;
4
 import se.citerus.dddsample.application.HandlingEventService;
5
+import se.citerus.dddsample.application.SystemEvents;
5
 import se.citerus.dddsample.application.messaging.HandlingEventRegistrationAttempt;
6
 import se.citerus.dddsample.application.messaging.HandlingEventRegistrationAttempt;
6
 import se.citerus.dddsample.domain.model.handling.CannotCreateHandlingEventException;
7
 import se.citerus.dddsample.domain.model.handling.CannotCreateHandlingEventException;
7
 import se.citerus.dddsample.domain.model.handling.HandlingEvent;
8
 import se.citerus.dddsample.domain.model.handling.HandlingEvent;
8
 import se.citerus.dddsample.domain.model.handling.HandlingEventFactory;
9
 import se.citerus.dddsample.domain.model.handling.HandlingEventFactory;
9
 import se.citerus.dddsample.domain.model.handling.HandlingEventRepository;
10
 import se.citerus.dddsample.domain.model.handling.HandlingEventRepository;
10
-import se.citerus.dddsample.domain.service.DomainEventNotifier;
11
 
11
 
12
 public final class HandlingEventServiceImpl implements HandlingEventService {
12
 public final class HandlingEventServiceImpl implements HandlingEventService {
13
 
13
 
14
   private final HandlingEventRepository handlingEventRepository;
14
   private final HandlingEventRepository handlingEventRepository;
15
-  private final DomainEventNotifier domainEventNotifier;
15
+  private final SystemEvents systemEvents;
16
   private final HandlingEventFactory handlingEventFactory;
16
   private final HandlingEventFactory handlingEventFactory;
17
 
17
 
18
-  public HandlingEventServiceImpl(HandlingEventRepository handlingEventRepository, DomainEventNotifier domainEventNotifier, HandlingEventFactory handlingEventFactory) {
18
+  public HandlingEventServiceImpl(HandlingEventRepository handlingEventRepository, SystemEvents systemEvents, HandlingEventFactory handlingEventFactory) {
19
     this.handlingEventRepository = handlingEventRepository;
19
     this.handlingEventRepository = handlingEventRepository;
20
-    this.domainEventNotifier = domainEventNotifier;
20
+    this.systemEvents = systemEvents;
21
     this.handlingEventFactory = handlingEventFactory;
21
     this.handlingEventFactory = handlingEventFactory;
22
   }
22
   }
23
 
23
 
33
      are enforced by asynchronous updates, after the commit of this transaction.
33
      are enforced by asynchronous updates, after the commit of this transaction.
34
   */
34
   */
35
   @Override
35
   @Override
36
-  @Transactional(readOnly = false, rollbackFor = {CannotCreateHandlingEventException.class})
37
-  public void register(HandlingEventRegistrationAttempt attempt) throws CannotCreateHandlingEventException {
38
-    final HandlingEvent event = handlingEventFactory.createHandlingEvent(attempt.getDate(), attempt.getTrackingId(), attempt.getVoyageNumber(), attempt.getUnLocode(), attempt.getType());
39
-    handlingEventRepository.save(event);
40
-    domainEventNotifier.cargoWasHandled(event);
36
+  @Transactional
37
+  public void register(HandlingEventRegistrationAttempt attempt) {
38
+    try {
39
+      final HandlingEvent event = handlingEventFactory.createHandlingEvent(attempt.getDate(), attempt.getTrackingId(), attempt.getVoyageNumber(), attempt.getUnLocode(), attempt.getType());
40
+      handlingEventRepository.save(event);
41
+      systemEvents.cargoWasHandled(event);
42
+    } catch (CannotCreateHandlingEventException e) {
43
+      systemEvents.rejectHandlingEventRegistrationAttempt(attempt, e);
44
+    }
41
   }
45
   }
42
 
46
 
43
 }
47
 }

+ 7
- 7
dddsample/src/main/java/se/citerus/dddsample/application/impl/TrackingServiceImpl.java View File

4
 import org.apache.commons.logging.Log;
4
 import org.apache.commons.logging.Log;
5
 import org.apache.commons.logging.LogFactory;
5
 import org.apache.commons.logging.LogFactory;
6
 import org.springframework.transaction.annotation.Transactional;
6
 import org.springframework.transaction.annotation.Transactional;
7
+import se.citerus.dddsample.application.SystemEvents;
7
 import se.citerus.dddsample.application.TrackingService;
8
 import se.citerus.dddsample.application.TrackingService;
8
 import se.citerus.dddsample.domain.model.cargo.Cargo;
9
 import se.citerus.dddsample.domain.model.cargo.Cargo;
9
 import se.citerus.dddsample.domain.model.cargo.CargoRepository;
10
 import se.citerus.dddsample.domain.model.cargo.CargoRepository;
10
 import se.citerus.dddsample.domain.model.cargo.TrackingId;
11
 import se.citerus.dddsample.domain.model.cargo.TrackingId;
11
-import se.citerus.dddsample.domain.service.DomainEventNotifier;
12
 
12
 
13
 public class TrackingServiceImpl implements TrackingService {
13
 public class TrackingServiceImpl implements TrackingService {
14
 
14
 
15
-  private final DomainEventNotifier domainEventNotifier;
15
+  private final SystemEvents systemEvents;
16
   private final CargoRepository cargoRepository;
16
   private final CargoRepository cargoRepository;
17
   private final Log logger = LogFactory.getLog(getClass());
17
   private final Log logger = LogFactory.getLog(getClass());
18
 
18
 
19
-  public TrackingServiceImpl(DomainEventNotifier domainEventNotifier, CargoRepository cargoRepository) {
20
-    this.domainEventNotifier = domainEventNotifier;
19
+  public TrackingServiceImpl(SystemEvents systemEvents, CargoRepository cargoRepository) {
20
+    this.systemEvents = systemEvents;
21
     this.cargoRepository = cargoRepository;
21
     this.cargoRepository = cargoRepository;
22
   }
22
   }
23
 
23
 
24
   @Override
24
   @Override
25
-  @Transactional
25
+  @Transactional(readOnly = true)
26
   public void onCargoHandled(final TrackingId trackingId) {
26
   public void onCargoHandled(final TrackingId trackingId) {
27
     Validate.notNull(trackingId, "Tracking ID is required");
27
     Validate.notNull(trackingId, "Tracking ID is required");
28
 
28
 
35
     // TODO cargo delivery status update would happen here
35
     // TODO cargo delivery status update would happen here
36
 
36
 
37
     if (cargo.isMisdirected()) {
37
     if (cargo.isMisdirected()) {
38
-      domainEventNotifier.cargoWasMisdirected(cargo);
38
+      systemEvents.cargoWasMisdirected(cargo);
39
     }
39
     }
40
 
40
 
41
     if (cargo.isUnloadedAtDestination()) {
41
     if (cargo.isUnloadedAtDestination()) {
42
-      domainEventNotifier.cargoHasArrived(cargo);
42
+      systemEvents.cargoHasArrived(cargo);
43
     }
43
     }
44
   }
44
   }
45
 
45
 

+ 1
- 2
dddsample/src/main/java/se/citerus/dddsample/application/messaging/CargoHandledConsumer.java View File

2
 
2
 
3
 import org.apache.commons.logging.Log;
3
 import org.apache.commons.logging.Log;
4
 import org.apache.commons.logging.LogFactory;
4
 import org.apache.commons.logging.LogFactory;
5
-import org.springframework.transaction.annotation.Transactional;
6
 import se.citerus.dddsample.application.TrackingService;
5
 import se.citerus.dddsample.application.TrackingService;
7
 import se.citerus.dddsample.domain.model.cargo.TrackingId;
6
 import se.citerus.dddsample.domain.model.cargo.TrackingId;
8
 
7
 
19
   private TrackingService trackingService;
18
   private TrackingService trackingService;
20
   private final Log logger = LogFactory.getLog(getClass());
19
   private final Log logger = LogFactory.getLog(getClass());
21
 
20
 
22
-  @Transactional(readOnly = true)  
21
+  @Override  
23
   public void onMessage(final Message message) {
22
   public void onMessage(final Message message) {
24
     if (logger.isDebugEnabled()) {
23
     if (logger.isDebugEnabled()) {
25
       logger.debug("Received message " + message);
24
       logger.debug("Received message " + message);

+ 8
- 25
dddsample/src/main/java/se/citerus/dddsample/application/messaging/HandlingEventRegistrationAttemptConsumer.java View File

2
 
2
 
3
 import org.apache.commons.logging.Log;
3
 import org.apache.commons.logging.Log;
4
 import org.apache.commons.logging.LogFactory;
4
 import org.apache.commons.logging.LogFactory;
5
-import org.springframework.jms.core.JmsOperations;
6
-import org.springframework.jms.core.MessageCreator;
7
 import se.citerus.dddsample.application.HandlingEventService;
5
 import se.citerus.dddsample.application.HandlingEventService;
8
-import se.citerus.dddsample.domain.model.handling.CannotCreateHandlingEventException;
9
 
6
 
10
-import javax.jms.*;
7
+import javax.jms.Message;
8
+import javax.jms.MessageListener;
9
+import javax.jms.ObjectMessage;
11
 
10
 
12
 /**
11
 /**
12
+ * Consumes handling event registration attempt messages and delegates to
13
+ * proper registration.
14
+ * 
13
  */
15
  */
14
 public class HandlingEventRegistrationAttemptConsumer implements MessageListener {
16
 public class HandlingEventRegistrationAttemptConsumer implements MessageListener {
15
 
17
 
16
   private HandlingEventService handlingEventService;
18
   private HandlingEventService handlingEventService;
17
-  private JmsOperations jmsOperations;
18
-  private Destination rejectedRegistrationAttemptsQueue;
19
   private static final Log logger = LogFactory.getLog(HandlingEventRegistrationAttemptConsumer.class);
19
   private static final Log logger = LogFactory.getLog(HandlingEventRegistrationAttemptConsumer.class);
20
 
20
 
21
   @Override
21
   @Override
22
   public void onMessage(final Message message) {
22
   public void onMessage(final Message message) {
23
     try {
23
     try {
24
       final ObjectMessage om = (ObjectMessage) message;
24
       final ObjectMessage om = (ObjectMessage) message;
25
-      final HandlingEventRegistrationAttempt attempt = (HandlingEventRegistrationAttempt) om.getObject();
26
-      try {
27
-        handlingEventService.register(attempt);
28
-      } catch (CannotCreateHandlingEventException e) {
29
-        jmsOperations.send(rejectedRegistrationAttemptsQueue, new MessageCreator() {
30
-          public Message createMessage(Session session) throws JMSException {
31
-            
32
-            return session.createObjectMessage(attempt);
33
-          }
34
-        });
35
-      }
36
-    } catch (JMSException e) {
25
+      handlingEventService.register((HandlingEventRegistrationAttempt) om.getObject());
26
+    } catch (Exception e) {
37
       logger.error(e, e);
27
       logger.error(e, e);
38
     }
28
     }
39
   }
29
   }
42
     this.handlingEventService = handlingEventService;
32
     this.handlingEventService = handlingEventService;
43
   }
33
   }
44
 
34
 
45
-  public void setJmsOperations(JmsOperations jmsOperations) {
46
-    this.jmsOperations = jmsOperations;
47
-  }
48
-
49
-  public void setRejectedRegistrationAttemptsQueue(Destination rejectedRegistrationAttemptsQueue) {
50
-    this.rejectedRegistrationAttemptsQueue = rejectedRegistrationAttemptsQueue;
51
-  }
52
 }
35
 }

+ 83
- 0
dddsample/src/main/java/se/citerus/dddsample/application/messaging/JmsSystemEventsImpl.java View File

1
+package se.citerus.dddsample.application.messaging;
2
+
3
+import org.springframework.jms.core.JmsOperations;
4
+import org.springframework.jms.core.MessageCreator;
5
+import se.citerus.dddsample.application.SystemEvents;
6
+import se.citerus.dddsample.domain.model.cargo.Cargo;
7
+import se.citerus.dddsample.domain.model.handling.CannotCreateHandlingEventException;
8
+import se.citerus.dddsample.domain.model.handling.HandlingEvent;
9
+
10
+import javax.jms.Destination;
11
+import javax.jms.JMSException;
12
+import javax.jms.Message;
13
+import javax.jms.Session;
14
+
15
+/**
16
+ * JMS based implementation.
17
+ */
18
+public final class JmsSystemEventsImpl implements SystemEvents {
19
+
20
+  private JmsOperations jmsOperations;
21
+  private Destination cargoHandledTopic;
22
+  private Destination misdirectedCargoTopic;
23
+  private Destination deliveredCargoTopic;
24
+  private Destination rejectedRegistrationAttemptsQueue;
25
+
26
+  @Override
27
+  public void cargoWasHandled(final HandlingEvent event) {
28
+    final Cargo cargo = event.cargo();
29
+    jmsOperations.send(cargoHandledTopic, new MessageCreator() {
30
+      public Message createMessage(final Session session) throws JMSException {
31
+        return session.createTextMessage(cargo.trackingId().idString());
32
+      }
33
+    });
34
+  }
35
+
36
+  @Override
37
+  public void cargoWasMisdirected(final Cargo cargo) {
38
+    jmsOperations.send(misdirectedCargoTopic, new MessageCreator() {
39
+      public Message createMessage(Session session) throws JMSException {
40
+        return session.createTextMessage(cargo.trackingId().idString());
41
+      }
42
+    });
43
+  }
44
+
45
+  @Override
46
+  public void cargoHasArrived(final Cargo cargo) {
47
+    jmsOperations.send(deliveredCargoTopic, new MessageCreator() {
48
+      public Message createMessage(Session session) throws JMSException {
49
+        return session.createTextMessage(cargo.trackingId().idString());
50
+      }
51
+    });
52
+  }
53
+
54
+  @Override
55
+  public void rejectHandlingEventRegistrationAttempt(final HandlingEventRegistrationAttempt attempt, CannotCreateHandlingEventException problem) {
56
+    // TODO include error message in JMS message
57
+    jmsOperations.send(rejectedRegistrationAttemptsQueue, new MessageCreator() {
58
+      public Message createMessage(Session session) throws JMSException {
59
+        return session.createObjectMessage(attempt);
60
+      }
61
+    });
62
+  }
63
+
64
+  public void setJmsOperations(final JmsOperations jmsOperations) {
65
+    this.jmsOperations = jmsOperations;
66
+  }
67
+
68
+  public void setCargoHandledTopic(final Destination cargoHandledTopic) {
69
+    this.cargoHandledTopic = cargoHandledTopic;
70
+  }
71
+
72
+  public void setMisdirectedCargoTopic(Destination misdirectedCargoTopic) {
73
+    this.misdirectedCargoTopic = misdirectedCargoTopic;
74
+  }
75
+
76
+  public void setDeliveredCargoTopic(Destination deliveredCargoTopic) {
77
+    this.deliveredCargoTopic = deliveredCargoTopic;
78
+  }
79
+
80
+  public void setRejectedRegistrationAttemptsQueue(Destination rejectedRegistrationAttemptsQueue) {
81
+    this.rejectedRegistrationAttemptsQueue = rejectedRegistrationAttemptsQueue;
82
+  }
83
+}

+ 3
- 2
dddsample/src/main/resources/context-messaging-jms.xml View File

16
   <amq:topic id="misdirectedCargoTopic" name="MisdirectedCargoTopic"/>
16
   <amq:topic id="misdirectedCargoTopic" name="MisdirectedCargoTopic"/>
17
   <amq:topic id="deliveredCargoTopic" name="DeliveredCargoTopic"/>
17
   <amq:topic id="deliveredCargoTopic" name="DeliveredCargoTopic"/>
18
   <amq:queue id="handlingEventRegistrationAttemptQueue" name="HandlingEventRegistrationAttemptQueue"/>
18
   <amq:queue id="handlingEventRegistrationAttemptQueue" name="HandlingEventRegistrationAttemptQueue"/>
19
+  <amq:queue id="rejectedRegistrationAttemptsQueue" name="RejectedRegistrationAttemptsQueue"/>
19
 
20
 
20
   <jms:listener-container connection-factory="jmsConnectionFactory">
21
   <jms:listener-container connection-factory="jmsConnectionFactory">
21
     <jms:listener destination="cargoHandledTopic" ref="cargoHandledConsumer" />
22
     <jms:listener destination="cargoHandledTopic" ref="cargoHandledConsumer" />
30
     <property name="connectionFactory" ref="jmsConnectionFactory"/>
31
     <property name="connectionFactory" ref="jmsConnectionFactory"/>
31
   </bean>
32
   </bean>
32
 
33
 
33
-  <bean id="domainEventNotifier" class="se.citerus.dddsample.application.messaging.JmsDomainEventNotifierImpl">
34
+  <bean id="systemEvents" class="se.citerus.dddsample.application.messaging.JmsSystemEventsImpl">
34
     <property name="jmsOperations" ref="jmsOperations"/>
35
     <property name="jmsOperations" ref="jmsOperations"/>
35
     <property name="cargoHandledTopic" ref="cargoHandledTopic"/>
36
     <property name="cargoHandledTopic" ref="cargoHandledTopic"/>
36
     <property name="misdirectedCargoTopic" ref="misdirectedCargoTopic"/>
37
     <property name="misdirectedCargoTopic" ref="misdirectedCargoTopic"/>
37
     <property name="deliveredCargoTopic" ref="deliveredCargoTopic"/>
38
     <property name="deliveredCargoTopic" ref="deliveredCargoTopic"/>
39
+    <property name="rejectedRegistrationAttemptsQueue" ref="rejectedRegistrationAttemptsQueue"/>
38
   </bean>
40
   </bean>
39
 
41
 
40
   <bean id="cargoHandledConsumer" class="se.citerus.dddsample.application.messaging.CargoHandledConsumer">
42
   <bean id="cargoHandledConsumer" class="se.citerus.dddsample.application.messaging.CargoHandledConsumer">
42
   </bean>
44
   </bean>
43
 
45
 
44
   <bean id="handlingEventRegistrationAttemptConsumer" class="se.citerus.dddsample.application.messaging.HandlingEventRegistrationAttemptConsumer">
46
   <bean id="handlingEventRegistrationAttemptConsumer" class="se.citerus.dddsample.application.messaging.HandlingEventRegistrationAttemptConsumer">
45
-    <property name="handlingEventFactory" ref="handlingEventFactory"/>
46
     <property name="handlingEventService" ref="handlingEventService"/>
47
     <property name="handlingEventService" ref="handlingEventService"/>
47
   </bean>
48
   </bean>
48
   
49
   

+ 3
- 4
dddsample/src/main/resources/context-service.xml View File

15
 
15
 
16
   <bean id="trackingService" class="se.citerus.dddsample.application.impl.TrackingServiceImpl">
16
   <bean id="trackingService" class="se.citerus.dddsample.application.impl.TrackingServiceImpl">
17
     <constructor-arg ref="cargoRepository"/>
17
     <constructor-arg ref="cargoRepository"/>
18
-    <constructor-arg ref="domainEventNotifier"/>
18
+    <constructor-arg ref="systemEvents"/>
19
   </bean>
19
   </bean>
20
 
20
 
21
   <bean id="handlingEventService" class="se.citerus.dddsample.application.impl.HandlingEventServiceImpl">
21
   <bean id="handlingEventService" class="se.citerus.dddsample.application.impl.HandlingEventServiceImpl">
22
     <constructor-arg ref="handlingEventRepository"/>
22
     <constructor-arg ref="handlingEventRepository"/>
23
-    <constructor-arg ref="domainEventNotifier"/>
23
+    <constructor-arg ref="handlingEventFactory"/>
24
+    <constructor-arg ref="systemEvents"/>
24
   </bean>
25
   </bean>
25
 
26
 
26
   <bean id="handlingEventFactory" class="se.citerus.dddsample.domain.model.handling.HandlingEventFactory">
27
   <bean id="handlingEventFactory" class="se.citerus.dddsample.domain.model.handling.HandlingEventFactory">
29
     <constructor-arg ref="locationRepository"/>
30
     <constructor-arg ref="locationRepository"/>
30
   </bean>
31
   </bean>
31
 
32
 
32
-  <!-- Aplication services below -->
33
-
34
   <tx:annotation-driven transaction-manager="transactionManager"/>
33
   <tx:annotation-driven transaction-manager="transactionManager"/>
35
 
34
 
36
   <bean id="routingService" class="se.citerus.dddsample.application.routing.ExternalRoutingService">
35
   <bean id="routingService" class="se.citerus.dddsample.application.routing.ExternalRoutingService">

+ 30
- 31
dddsample/src/test/java/se/citerus/dddsample/application/HandlingEventServiceTest.java View File

10
 import se.citerus.dddsample.domain.model.carrier.SampleVoyages;
10
 import se.citerus.dddsample.domain.model.carrier.SampleVoyages;
11
 import se.citerus.dddsample.domain.model.carrier.VoyageNumber;
11
 import se.citerus.dddsample.domain.model.carrier.VoyageNumber;
12
 import se.citerus.dddsample.domain.model.carrier.VoyageRepository;
12
 import se.citerus.dddsample.domain.model.carrier.VoyageRepository;
13
-import se.citerus.dddsample.domain.model.handling.*;
13
+import se.citerus.dddsample.domain.model.handling.CannotCreateHandlingEventException;
14
+import se.citerus.dddsample.domain.model.handling.HandlingEvent;
15
+import se.citerus.dddsample.domain.model.handling.HandlingEventFactory;
16
+import se.citerus.dddsample.domain.model.handling.HandlingEventRepository;
14
 import se.citerus.dddsample.domain.model.location.LocationRepository;
17
 import se.citerus.dddsample.domain.model.location.LocationRepository;
15
 import static se.citerus.dddsample.domain.model.location.SampleLocations.*;
18
 import static se.citerus.dddsample.domain.model.location.SampleLocations.*;
16
 import se.citerus.dddsample.domain.model.location.UnLocode;
19
 import se.citerus.dddsample.domain.model.location.UnLocode;
17
-import se.citerus.dddsample.domain.service.DomainEventNotifier;
18
 
20
 
19
 import java.util.Date;
21
 import java.util.Date;
20
 
22
 
21
 public class HandlingEventServiceTest extends TestCase {
23
 public class HandlingEventServiceTest extends TestCase {
22
   private HandlingEventServiceImpl service;
24
   private HandlingEventServiceImpl service;
23
-  private DomainEventNotifier domainEventNotifier;
25
+  private SystemEvents systemEvents;
24
   private CargoRepository cargoRepository;
26
   private CargoRepository cargoRepository;
25
   private VoyageRepository voyageRepository;
27
   private VoyageRepository voyageRepository;
26
   private HandlingEventRepository handlingEventRepository;
28
   private HandlingEventRepository handlingEventRepository;
36
     voyageRepository = createMock(VoyageRepository.class);
38
     voyageRepository = createMock(VoyageRepository.class);
37
     handlingEventRepository = createMock(HandlingEventRepository.class);
39
     handlingEventRepository = createMock(HandlingEventRepository.class);
38
     locationRepository = createMock(LocationRepository.class);
40
     locationRepository = createMock(LocationRepository.class);
39
-    domainEventNotifier = createMock(DomainEventNotifier.class);
41
+    systemEvents = createMock(SystemEvents.class);
40
     handlingEventFactory = new HandlingEventFactory(cargoRepository, voyageRepository, locationRepository);
42
     handlingEventFactory = new HandlingEventFactory(cargoRepository, voyageRepository, locationRepository);
41
-    service = new HandlingEventServiceImpl(handlingEventRepository, domainEventNotifier, handlingEventFactory);
43
+    service = new HandlingEventServiceImpl(handlingEventRepository, systemEvents, handlingEventFactory);
42
   }
44
   }
43
 
45
 
44
   protected void tearDown() throws Exception {
46
   protected void tearDown() throws Exception {
45
-    verify(cargoRepository, voyageRepository, handlingEventRepository, domainEventNotifier);
47
+    verify(cargoRepository, voyageRepository, handlingEventRepository, systemEvents);
46
   }
48
   }
47
 
49
 
48
   public void testRegisterEvent() throws Exception {
50
   public void testRegisterEvent() throws Exception {
57
 
59
 
58
     // TODO: does not inspect the handling event instance in a sufficient way
60
     // TODO: does not inspect the handling event instance in a sufficient way
59
     handlingEventRepository.save(isA(HandlingEvent.class));
61
     handlingEventRepository.save(isA(HandlingEvent.class));
60
-    domainEventNotifier.cargoWasHandled(isA(HandlingEvent.class));
62
+    systemEvents.cargoWasHandled(isA(HandlingEvent.class));
61
 
63
 
62
-    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, domainEventNotifier);
64
+    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, systemEvents);
63
 
65
 
64
     service.register(new HandlingEventRegistrationAttempt(
66
     service.register(new HandlingEventRegistrationAttempt(
65
       new Date(), new Date(), trackingId, voyageNumber, HandlingEvent.Type.LOAD, unLocode
67
       new Date(), new Date(), trackingId, voyageNumber, HandlingEvent.Type.LOAD, unLocode
71
     expect(cargoRepository.find(trackingId)).andReturn(cargoABC);
73
     expect(cargoRepository.find(trackingId)).andReturn(cargoABC);
72
 
74
 
73
     handlingEventRepository.save(isA(HandlingEvent.class));
75
     handlingEventRepository.save(isA(HandlingEvent.class));
74
-    domainEventNotifier.cargoWasHandled(isA(HandlingEvent.class));
76
+    systemEvents.cargoWasHandled(isA(HandlingEvent.class));
75
 
77
 
76
     expect(locationRepository.find(STOCKHOLM.unLocode())).andReturn(STOCKHOLM);
78
     expect(locationRepository.find(STOCKHOLM.unLocode())).andReturn(STOCKHOLM);
77
 
79
 
78
-    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, domainEventNotifier);
80
+    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, systemEvents);
79
 
81
 
80
     service.register(new HandlingEventRegistrationAttempt(
82
     service.register(new HandlingEventRegistrationAttempt(
81
       new Date(), new Date(), trackingId, null, HandlingEvent.Type.RECEIVE, STOCKHOLM.unLocode()
83
       new Date(), new Date(), trackingId, null, HandlingEvent.Type.RECEIVE, STOCKHOLM.unLocode()
91
     expect(cargoRepository.find(trackingId)).andReturn(new Cargo(trackingId, CHICAGO, STOCKHOLM));
93
     expect(cargoRepository.find(trackingId)).andReturn(new Cargo(trackingId, CHICAGO, STOCKHOLM));
92
 
94
 
93
     expect(locationRepository.find(MELBOURNE.unLocode())).andReturn(MELBOURNE);
95
     expect(locationRepository.find(MELBOURNE.unLocode())).andReturn(MELBOURNE);
96
+
97
+    systemEvents.rejectHandlingEventRegistrationAttempt(isA(HandlingEventRegistrationAttempt.class), isA(CannotCreateHandlingEventException.class));
98
+
99
+    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, systemEvents);
94
     
100
     
95
-    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, domainEventNotifier);
96
-    
97
-    try {
98
-      service.register(new HandlingEventRegistrationAttempt(
99
-        new Date(), new Date(), trackingId, voyageNumber, HandlingEvent.Type.UNLOAD, MELBOURNE.unLocode()
100
-      ));
101
-      fail("Should not be able to register an event with non-existing carrier movement");
102
-    } catch (UnknownVoyageException expected) {}
101
+    service.register(new HandlingEventRegistrationAttempt(
102
+      new Date(), new Date(), trackingId, voyageNumber, HandlingEvent.Type.UNLOAD, MELBOURNE.unLocode()
103
+    ));
103
   }
104
   }
104
   
105
   
105
   public void testRegisterEventInvalidCargo() throws Exception {
106
   public void testRegisterEventInvalidCargo() throws Exception {
107
     expect(cargoRepository.find(trackingId)).andReturn(null);
108
     expect(cargoRepository.find(trackingId)).andReturn(null);
108
 
109
 
109
     expect(locationRepository.find(HONGKONG.unLocode())).andReturn(HONGKONG);
110
     expect(locationRepository.find(HONGKONG.unLocode())).andReturn(HONGKONG);
111
+
112
+    systemEvents.rejectHandlingEventRegistrationAttempt(isA(HandlingEventRegistrationAttempt.class), isA(CannotCreateHandlingEventException.class));
113
+
114
+    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, systemEvents);
110
     
115
     
111
-    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, domainEventNotifier);
112
-    
113
-    try {
114
       service.register(new HandlingEventRegistrationAttempt(
116
       service.register(new HandlingEventRegistrationAttempt(
115
         new Date(), new Date(), trackingId, new VoyageNumber("V001"), HandlingEvent.Type.CLAIM, HONGKONG.unLocode()
117
         new Date(), new Date(), trackingId, new VoyageNumber("V001"), HandlingEvent.Type.CLAIM, HONGKONG.unLocode()
116
       ));
118
       ));
117
-      fail("Should not be able to register an event with non-existing cargo");
118
-    } catch (UnknownCargoException expected) {}
119
   }
119
   }
120
   
120
   
121
   public void testRegisterEventInvalidLocation() throws Exception {
121
   public void testRegisterEventInvalidLocation() throws Exception {
123
     expect(cargoRepository.find(trackingId)).andReturn(cargoXYZ);
123
     expect(cargoRepository.find(trackingId)).andReturn(cargoXYZ);
124
     UnLocode wayOff = new UnLocode("XXYYY");
124
     UnLocode wayOff = new UnLocode("XXYYY");
125
     expect(locationRepository.find(wayOff)).andReturn(null);
125
     expect(locationRepository.find(wayOff)).andReturn(null);
126
+
127
+    systemEvents.rejectHandlingEventRegistrationAttempt(isA(HandlingEventRegistrationAttempt.class), isA(CannotCreateHandlingEventException.class));
128
+
129
+    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, systemEvents);
126
     
130
     
127
-    replay(cargoRepository, voyageRepository, handlingEventRepository, locationRepository, domainEventNotifier);
128
-    
129
-    try {
130
-      service.register(new HandlingEventRegistrationAttempt(
131
-        new Date(), new Date(), trackingId, null, HandlingEvent.Type.CLAIM, wayOff
132
-      ));
133
-      fail("Should not be able to register an event with non-existing Location");
134
-    } catch (UnknownLocationException expected) {}
131
+    service.register(new HandlingEventRegistrationAttempt(
132
+      new Date(), new Date(), trackingId, null, HandlingEvent.Type.CLAIM, wayOff
133
+    ));
135
   }
134
   }
136
 }
135
 }

+ 10
- 6
dddsample/src/test/java/se/citerus/dddsample/scenario/CargoHandlingScenarioTest.java View File

2
 
2
 
3
 import junit.framework.TestCase;
3
 import junit.framework.TestCase;
4
 import se.citerus.dddsample.application.HandlingEventService;
4
 import se.citerus.dddsample.application.HandlingEventService;
5
+import se.citerus.dddsample.application.SystemEvents;
5
 import se.citerus.dddsample.application.TrackingService;
6
 import se.citerus.dddsample.application.TrackingService;
6
 import se.citerus.dddsample.application.impl.HandlingEventServiceImpl;
7
 import se.citerus.dddsample.application.impl.HandlingEventServiceImpl;
7
 import se.citerus.dddsample.application.impl.TrackingServiceImpl;
8
 import se.citerus.dddsample.application.impl.TrackingServiceImpl;
17
 import se.citerus.dddsample.domain.model.location.Location;
18
 import se.citerus.dddsample.domain.model.location.Location;
18
 import se.citerus.dddsample.domain.model.location.LocationRepository;
19
 import se.citerus.dddsample.domain.model.location.LocationRepository;
19
 import static se.citerus.dddsample.domain.model.location.SampleLocations.*;
20
 import static se.citerus.dddsample.domain.model.location.SampleLocations.*;
20
-import se.citerus.dddsample.domain.service.DomainEventNotifier;
21
 import se.citerus.dddsample.domain.service.RoutingService;
21
 import se.citerus.dddsample.domain.service.RoutingService;
22
 import se.citerus.dddsample.infrastructure.persistence.inmemory.LocationRepositoryInMem;
22
 import se.citerus.dddsample.infrastructure.persistence.inmemory.LocationRepositoryInMem;
23
 import se.citerus.dddsample.infrastructure.persistence.inmemory.VoyageRepositoryInMem;
23
 import se.citerus.dddsample.infrastructure.persistence.inmemory.VoyageRepositoryInMem;
31
 
31
 
32
   HandlingEventFactory handlingEventFactory;
32
   HandlingEventFactory handlingEventFactory;
33
 
33
 
34
-  DomainEventNotifier domainEventNotifier;
34
+  SystemEvents systemEvents;
35
 
35
 
36
   HandlingEventService handlingEventService;
36
   HandlingEventService handlingEventService;
37
   TrackingService trackingService;
37
   TrackingService trackingService;
140
     };
140
     };
141
 
141
 
142
     // Synchronous stub
142
     // Synchronous stub
143
-    domainEventNotifier = new DomainEventNotifier() {
143
+    systemEvents = new SystemEvents() {
144
+      @Override
144
       public void cargoWasHandled(HandlingEvent event) {
145
       public void cargoWasHandled(HandlingEvent event) {
145
         trackingService.onCargoHandled(event.cargo().trackingId());
146
         trackingService.onCargoHandled(event.cargo().trackingId());
146
       }
147
       }
148
+      @Override
147
       public void cargoWasMisdirected(Cargo cargo) {}
149
       public void cargoWasMisdirected(Cargo cargo) {}
150
+      @Override
148
       public void cargoHasArrived(Cargo cargo) {}
151
       public void cargoHasArrived(Cargo cargo) {}
149
-      public void rejectHandlingEventRegistrationAttempt(CannotCreateHandlingEventException e) {}
152
+      @Override
153
+      public void rejectHandlingEventRegistrationAttempt(HandlingEventRegistrationAttempt attempt, CannotCreateHandlingEventException problem) {}
150
     };
154
     };
151
 
155
 
152
     // Stub
156
     // Stub
185
     voyageRepository = new VoyageRepositoryInMem();
189
     voyageRepository = new VoyageRepositoryInMem();
186
 
190
 
187
     // Domain services and factories that are implemented in the domain layer - not stubbed
191
     // Domain services and factories that are implemented in the domain layer - not stubbed
188
-    trackingService = new TrackingServiceImpl(domainEventNotifier, cargoRepository);
192
+    trackingService = new TrackingServiceImpl(systemEvents, cargoRepository);
189
     handlingEventFactory = new HandlingEventFactory(cargoRepository, this.voyageRepository, this.locationRepository);
193
     handlingEventFactory = new HandlingEventFactory(cargoRepository, this.voyageRepository, this.locationRepository);
190
-    handlingEventService = new HandlingEventServiceImpl(handlingEventRepository, domainEventNotifier, handlingEventFactory);
194
+    handlingEventService = new HandlingEventServiceImpl(handlingEventRepository, systemEvents, handlingEventFactory);
191
   }
195
   }
192
 }
196
 }