Selaa lähdekoodia

Introduced BookingServiceFacade as an application service, on top of the domain layer's BookingService and the repositories, as a DTO assembly point and remoting exposure layer (currently configured in context-remote.xml, but only used as local reference).

CargoAdminController now sits on top on this facade. If time permits, the booking part of the application can be moved to another virtual machine at this point.
peter_backlund 18 vuotta sitten
vanhempi
commit
b2726531cf

+ 30
- 0
dddsample/src/main/java/se/citerus/dddsample/service/BookingServiceFacade.java Näytä tiedosto

@@ -0,0 +1,30 @@
1
+package se.citerus.dddsample.service;
2
+
3
+import se.citerus.dddsample.service.dto.CargoRoutingDTO;
4
+import se.citerus.dddsample.service.dto.ItineraryCandidateDTO;
5
+import se.citerus.dddsample.service.dto.LocationDTO;
6
+
7
+import java.rmi.Remote;
8
+import java.rmi.RemoteException;
9
+import java.util.List;
10
+
11
+/**
12
+ * This facade shields the domain layer - model, services, repositories -
13
+ * from concerns about such things as the user interface and remoting.
14
+ * It is an application service.
15
+ */
16
+public interface BookingServiceFacade extends Remote {
17
+
18
+  String registerNewCargo(String origin, String destination) throws RemoteException;
19
+
20
+  CargoRoutingDTO loadCargoForRouting(String trackingId) throws RemoteException;
21
+
22
+  void assignCargoToRoute(String trackingId, ItineraryCandidateDTO itinerary) throws RemoteException;
23
+
24
+  List<ItineraryCandidateDTO> requestPossibleRoutesForCargo(String trackingId) throws RemoteException;
25
+
26
+  List<LocationDTO> listShippingLocations() throws RemoteException;
27
+
28
+  List<CargoRoutingDTO> listAllCargos() throws RemoteException;
29
+
30
+}

+ 92
- 0
dddsample/src/main/java/se/citerus/dddsample/service/BookingServiceFacadeImpl.java Näytä tiedosto

@@ -0,0 +1,92 @@
1
+package se.citerus.dddsample.service;
2
+
3
+import se.citerus.dddsample.domain.*;
4
+import se.citerus.dddsample.repository.CargoRepository;
5
+import se.citerus.dddsample.repository.CarrierMovementRepository;
6
+import se.citerus.dddsample.repository.LocationRepository;
7
+import se.citerus.dddsample.service.dto.CargoRoutingDTO;
8
+import se.citerus.dddsample.service.dto.ItineraryCandidateDTO;
9
+import se.citerus.dddsample.service.dto.LocationDTO;
10
+import se.citerus.dddsample.service.dto.assembler.CargoRoutingDTOAssembler;
11
+import se.citerus.dddsample.service.dto.assembler.ItineraryCandidateDTOAssembler;
12
+import se.citerus.dddsample.service.dto.assembler.LocationDTOAssembler;
13
+
14
+import java.rmi.RemoteException;
15
+import java.util.ArrayList;
16
+import java.util.List;
17
+
18
+
19
+/**
20
+ * This implementation has additional support from the infrastructure, for exposing as an RMI
21
+ * service and for keeping the OR-mapper unit-of-work open during DTO assembly,
22
+ * analogous to the view rendering for web interfaces.
23
+ *
24
+ * See context-remote.xml.  
25
+ */
26
+public class BookingServiceFacadeImpl implements BookingServiceFacade {
27
+
28
+  private BookingService bookingService;
29
+  private LocationRepository locationRepository;
30
+  private CargoRepository cargoRepository;
31
+  private CarrierMovementRepository carrierMovementRepository;
32
+
33
+  public List<LocationDTO> listShippingLocations() {
34
+    final List<Location> allLocations = locationRepository.findAll();
35
+    final LocationDTOAssembler assembler = new LocationDTOAssembler();
36
+    return assembler.toDTOList(allLocations);
37
+  }
38
+
39
+  public String registerNewCargo(String origin, String destination) {
40
+    TrackingId trackingId = bookingService.registerNewCargo(new UnLocode(origin), new UnLocode(destination));
41
+    return trackingId.idString();
42
+  }
43
+
44
+  public CargoRoutingDTO loadCargoForRouting(String trackingId) {
45
+    final Cargo cargo = bookingService.loadCargoForRouting(new TrackingId(trackingId));
46
+    final CargoRoutingDTOAssembler assembler = new CargoRoutingDTOAssembler();
47
+    return assembler.toDTO(cargo);
48
+  }
49
+
50
+  public void assignCargoToRoute(String trackingId, ItineraryCandidateDTO itineraryCandidateDTO) {
51
+    final Itinerary itinerary = new ItineraryCandidateDTOAssembler().fromDTO(itineraryCandidateDTO, carrierMovementRepository, locationRepository);
52
+    bookingService.assignCargoToRoute(new TrackingId(trackingId), itinerary);
53
+  }
54
+
55
+  public List<CargoRoutingDTO> listAllCargos() {
56
+    final List<Cargo> cargoList = cargoRepository.findAll();
57
+    final List<CargoRoutingDTO> dtoList = new ArrayList<CargoRoutingDTO>(cargoList.size());
58
+    final CargoRoutingDTOAssembler assembler = new CargoRoutingDTOAssembler();
59
+    for (Cargo cargo : cargoList) {
60
+      dtoList.add(assembler.toDTO(cargo));
61
+    }
62
+    return dtoList;
63
+  }
64
+
65
+  public List<ItineraryCandidateDTO> requestPossibleRoutesForCargo(String trackingId) throws RemoteException {
66
+    final List<Itinerary> itineraries = bookingService.requestPossibleRoutesForCargo(new TrackingId(trackingId));
67
+
68
+    final List<ItineraryCandidateDTO> itineraryCandidates = new ArrayList<ItineraryCandidateDTO>(itineraries.size());
69
+    final ItineraryCandidateDTOAssembler dtoAssembler = new ItineraryCandidateDTOAssembler();
70
+    for (Itinerary itinerary : itineraries) {
71
+      itineraryCandidates.add(dtoAssembler.toDTO(itinerary));
72
+    }
73
+
74
+    return itineraryCandidates;
75
+  }
76
+
77
+  public void setBookingService(BookingService bookingService) {
78
+    this.bookingService = bookingService;
79
+  }
80
+
81
+  public void setLocationRepository(LocationRepository locationRepository) {
82
+    this.locationRepository = locationRepository;
83
+  }
84
+
85
+  public void setCargoRepository(CargoRepository cargoRepository) {
86
+    this.cargoRepository = cargoRepository;
87
+  }
88
+
89
+  public void setCarrierMovementRepository(CarrierMovementRepository carrierMovementRepository) {
90
+    this.carrierMovementRepository = carrierMovementRepository;
91
+  }
92
+}

+ 28
- 66
dddsample/src/main/java/se/citerus/dddsample/web/CargoAdminController.java Näytä tiedosto

@@ -1,21 +1,19 @@
1 1
 package se.citerus.dddsample.web;
2 2
 
3 3
 import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
4
-import se.citerus.dddsample.domain.*;
5
-import se.citerus.dddsample.repository.CarrierMovementRepository;
6
-import se.citerus.dddsample.repository.LocationRepository;
7
-import se.citerus.dddsample.service.BookingService;
8
-import se.citerus.dddsample.service.RoutingService;
4
+import se.citerus.dddsample.service.BookingServiceFacade;
9 5
 import se.citerus.dddsample.service.dto.CargoRoutingDTO;
10 6
 import se.citerus.dddsample.service.dto.ItineraryCandidateDTO;
11 7
 import se.citerus.dddsample.service.dto.LegDTO;
12
-import se.citerus.dddsample.service.dto.assembler.CargoRoutingDTOAssembler;
13
-import se.citerus.dddsample.service.dto.assembler.ItineraryCandidateDTOAssembler;
8
+import se.citerus.dddsample.service.dto.LocationDTO;
14 9
 import se.citerus.dddsample.web.command.RegistrationCommand;
15 10
 
16 11
 import javax.servlet.http.HttpServletRequest;
17 12
 import javax.servlet.http.HttpServletResponse;
18
-import java.util.*;
13
+import java.util.ArrayList;
14
+import java.util.HashMap;
15
+import java.util.List;
16
+import java.util.Map;
19 17
 
20 18
 /**
21 19
  * Handles cargo routing and administration.
@@ -23,21 +21,16 @@ import java.util.*;
23 21
  */
24 22
 public final class CargoAdminController extends MultiActionController {
25 23
 
26
-  private BookingService bookingService;
27
-  private RoutingService routingService;
28
-  private LocationRepository locationRepository;
29
-  private CarrierMovementRepository carrierMovementRepository;
30
-
31
-  // DTO conversion is pushed out to above the service layer for the time being,
32
-  // pending a dedicated DTO remoting layer  
24
+  private BookingServiceFacade bookingServiceFacade;
33 25
 
34 26
   public Map registrationForm(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
35 27
     final Map<String, Object> map = new HashMap<String, Object>();
36
-    final List<UnLocode> unLocodes = bookingService.listShippingLocations();
28
+    final List<LocationDTO> dtoList = bookingServiceFacade.listShippingLocations();
29
+
37 30
     final List<String> unLocodeStrings = new ArrayList<String>();
38 31
 
39
-    for (UnLocode unLocode : unLocodes) {
40
-      unLocodeStrings.add(unLocode.idString());
32
+    for (LocationDTO dto : dtoList) {
33
+      unLocodeStrings.add(dto.getUnLocode());
41 34
     }
42 35
 
43 36
     map.put("unlocodes", unLocodeStrings);
@@ -47,58 +40,40 @@ public final class CargoAdminController extends MultiActionController {
47 40
   public void register(final HttpServletRequest request, final HttpServletResponse response,
48 41
                        final RegistrationCommand command) throws Exception {
49 42
 
50
-    final TrackingId trackingId = bookingService.registerNewCargo(
51
-      new UnLocode(command.getOriginUnlocode()),
52
-      new UnLocode(command.getDestinationUnlocode())
43
+    final String trackingId = bookingServiceFacade.registerNewCargo(
44
+      command.getOriginUnlocode(), command.getDestinationUnlocode()
53 45
     );
54
-    response.sendRedirect("show.html?trackingId=" + trackingId.idString());
46
+    response.sendRedirect("show.html?trackingId=" + trackingId);
55 47
   }
56 48
 
57
-  public Map list(HttpServletRequest request, HttpServletResponse response) {
49
+  public Map list(HttpServletRequest request, HttpServletResponse response) throws Exception {
58 50
     final Map<String, Object> map = new HashMap<String, Object>();
59
-    final List<Cargo> allCargos = bookingService.listAllCargos();
51
+    final List<CargoRoutingDTO> cargoList = bookingServiceFacade.listAllCargos();
60 52
 
61
-    final CargoRoutingDTOAssembler assembler = new CargoRoutingDTOAssembler();
62
-    final List<CargoRoutingDTO> dtoList = new ArrayList<CargoRoutingDTO>(allCargos.size());
63
-
64
-    for (Cargo cargo : allCargos) {
65
-      dtoList.add(assembler.toDTO(cargo));
66
-    }
67
-
68
-    map.put("cargoList", dtoList);
53
+    map.put("cargoList", cargoList);
69 54
     return map;
70 55
   }
71 56
 
72
-  public Map show(final HttpServletRequest request, final HttpServletResponse response) {
57
+  public Map show(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
73 58
     final Map<String, Object> map = new HashMap<String, Object>();
74
-    final TrackingId trackingId = new TrackingId(request.getParameter("trackingId"));
75
-    final Cargo cargo = bookingService.loadCargoForRouting(trackingId);
76
-    final CargoRoutingDTO dto = new CargoRoutingDTOAssembler().toDTO(cargo);
59
+    final String trackingId = request.getParameter("trackingId");
60
+    final CargoRoutingDTO dto = bookingServiceFacade.loadCargoForRouting(trackingId);
77 61
     map.put("cargo", dto);
78 62
     return map;
79 63
   }
80 64
 
81
-  public Map selectItinerary(final HttpServletRequest request, final HttpServletResponse response) {
65
+  public Map selectItinerary(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
82 66
     final Map<String, Object> map = new HashMap<String, Object>();
83
-    final TrackingId trackingId = new TrackingId(request.getParameter("trackingId"));
84
-
85
-    final Cargo cargo = bookingService.loadCargoForRouting(trackingId);
86
-    final RouteSpecification routeSpecification = RouteSpecification.forCargo(cargo, new Date());
87
-    final List<Itinerary> itineraries = routingService.requestPossibleRoutes(routeSpecification);
88
-
89
-    final List<ItineraryCandidateDTO> itineraryCandidates = new ArrayList<ItineraryCandidateDTO>(itineraries.size());
90
-    final ItineraryCandidateDTOAssembler dtoAssembler = new ItineraryCandidateDTOAssembler();
91
-    for (Itinerary itinerary : itineraries) {
92
-      itineraryCandidates.add(dtoAssembler.toDTO(itinerary));
93
-    }
67
+    final String trackingId = request.getParameter("trackingId");
68
+    final List<ItineraryCandidateDTO> itineraryCandidates = bookingServiceFacade.requestPossibleRoutesForCargo(trackingId);
94 69
 
95 70
     map.put("itineraryCandidates", itineraryCandidates);
96
-    map.put("trackingId", trackingId.idString());
71
+    map.put("trackingId", trackingId);
97 72
     return map;
98 73
   }
99 74
 
100 75
   public void assignItinerary(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
101
-    final TrackingId trackingId = new TrackingId(request.getParameter("trackingId"));
76
+    final String trackingId = request.getParameter("trackingId");
102 77
 
103 78
     // TODO:  gah, stuck on indexoutofbounds (legs[0].fromUnlocode etc) when trying to bind...
104 79
     // Revisit and fix this with a proper command object, this is just hideous
@@ -112,26 +87,13 @@ public final class CargoAdminController extends MultiActionController {
112 87
     }
113 88
 
114 89
     final ItineraryCandidateDTO selectedItinerary = new ItineraryCandidateDTO(legDTOs);
115
-    final Itinerary itinerary = new ItineraryCandidateDTOAssembler().fromDTO(selectedItinerary, carrierMovementRepository, locationRepository);
116 90
 
117
-    bookingService.assignCargoToRoute(trackingId, itinerary);
91
+    bookingServiceFacade.assignCargoToRoute(trackingId, selectedItinerary);
118 92
 
119 93
     response.sendRedirect("list.html");
120 94
   }
121 95
 
122
-  public void setBookingService(final BookingService bookingService) {
123
-    this.bookingService = bookingService;
124
-  }
125
-
126
-  public void setRoutingService(final RoutingService routingService) {
127
-    this.routingService = routingService;
128
-  }
129
-
130
-  public void setLocationRepository(LocationRepository locationRepository) {
131
-    this.locationRepository = locationRepository;
132
-  }
133
-
134
-  public void setCarrierMovementRepository(CarrierMovementRepository carrierMovementRepository) {
135
-    this.carrierMovementRepository = carrierMovementRepository;
96
+  public void setBookingServiceFacade(BookingServiceFacade bookingServiceFacade) {
97
+    this.bookingServiceFacade = bookingServiceFacade;
136 98
   }
137 99
 }

+ 54
- 1
dddsample/src/main/resources/context-remote.xml Näytä tiedosto

@@ -4,12 +4,17 @@
4 4
        xmlns:ws="http://jax-ws.dev.java.net/spring/core"
5 5
        xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
6 6
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
7
+       xmlns:aop="http://www.springframework.org/schema/aop"
7 8
        xsi:schemaLocation="
8 9
         http://jax-ws.dev.java.net/spring/core https://jax-ws.dev.java.net/spring/core.xsd
9 10
         http://jax-ws.dev.java.net/spring/servlet https://jax-ws.dev.java.net/spring/servlet.xsd
11
+        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
10 12
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
11 13
 
12 14
 
15
+  <!-- Handling event registration web service -->
16
+
17
+  
13 18
   <wss:bindings id="jax-ws.http">
14 19
     <wss:bindings>
15 20
       <wss:binding url="/ws/RegisterEvent">
@@ -20,9 +25,57 @@
20 25
     </wss:bindings>
21 26
   </wss:bindings>
22 27
 
23
-
24 28
   <bean id="handlingEventServiceEndpoint" class="se.citerus.dddsample.ws.HandlingEventServiceEndpointImpl">
25 29
     <property name="handlingEventService" ref="handlingEventService"/>
26 30
   </bean>
27 31
 
32
+
33
+  <!-- Booking service facade -->
34
+
35
+  
36
+  <!-- Hibernate interceptor -->
37
+  <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor">
38
+    <property name="sessionFactory" ref="sessionFactory"/>
39
+  </bean>
40
+
41
+  <!-- Facade wrapped with Hibernate interceptor -->
42
+  <bean id="bookingServiceFacade" class="org.springframework.aop.framework.ProxyFactoryBean">
43
+    <property name="interceptorNames">
44
+      <list>
45
+        <value>hibernateInterceptor</value>
46
+      </list>
47
+    </property>
48
+    <property name="target">
49
+      <bean class="se.citerus.dddsample.service.BookingServiceFacadeImpl">
50
+        <property name="bookingService" ref="bookingService"/>
51
+        <property name="cargoRepository" ref="cargoRepository"/>
52
+        <property name="locationRepository" ref="locationRepository"/>
53
+        <property name="carrierMovementRepository" ref="carrierMovementRepository"/>
54
+      </bean>
55
+    </property>
56
+  </bean>
57
+
58
+  <!-- Wrap all methods with Hibernate interceptor
59
+  TODO: add necessary aspectj deps and replace config above with this
60
+  
61
+  <bean id="bookingServiceFacade" class="se.citerus.dddsample.service.BookingServiceFacadeImpl">
62
+    <property name="bookingService" ref="bookingService"/>
63
+    <property name="cargoRepository" ref="cargoRepository"/>
64
+    <property name="locationRepository" ref="locationRepository"/>
65
+    <property name="carrierMovementRepository" ref="carrierMovementRepository"/>
66
+  </bean>
67
+
68
+  <aop:config>
69
+    <aop:advisor advice-ref="hibernateInterceptor"
70
+                 pointcut="execution (* se.citerus.dddsample.service.BookingServiceFacadeImpl(..))"/>
71
+  </aop:config>
72
+  -->
73
+
74
+  <!-- RMI exposure -->
75
+  <bean id="rmiBookingServiceFacade" class="org.springframework.remoting.rmi.RmiServiceExporter">
76
+    <property name="serviceInterface" value="se.citerus.dddsample.service.BookingServiceFacade"/>
77
+    <property name="service" ref="bookingServiceFacade"/>
78
+    <property name="serviceName" value="BookingService"/>
79
+  </bean>
80
+
28 81
 </beans>

+ 1
- 0
dddsample/src/main/resources/context-service.xml Näytä tiedosto

@@ -12,6 +12,7 @@
12 12
   <bean id="bookingService" class="se.citerus.dddsample.service.BookingServiceImpl">
13 13
     <property name="cargoRepository" ref="cargoRepository"/>
14 14
     <property name="locationRepository" ref="locationRepository"/>
15
+    <property name="routingService" ref="routingService"/>
15 16
   </bean>
16 17
 
17 18
   <bean id="trackingService" class="se.citerus.dddsample.service.TrackingServiceImpl">

+ 1
- 4
dddsample/src/main/webapp/WEB-INF/dispatch-servlet.xml Näytä tiedosto

@@ -23,10 +23,7 @@
23 23
   <bean id="trackCommandValidator" class="se.citerus.dddsample.web.command.TrackCommandValidator"/>
24 24
 
25 25
   <bean name="/admin/*" class="se.citerus.dddsample.web.CargoAdminController">
26
-    <property name="routingService" ref="routingService"/>
27
-    <property name="bookingService" ref="bookingService"/>
28
-    <property name="carrierMovementRepository" ref="carrierMovementRepository"/>
29
-    <property name="locationRepository" ref="locationRepository"/>
26
+    <property name="bookingServiceFacade" ref="bookingServiceFacade"/>
30 27
   </bean>
31 28
 
32 29
 </beans>