소스 검색

Tightened the CargoTrackingController a bit, treating "no cargo found" same way as a binding error

Introduced a Spring context for the web layer, where all web support components go.

Introduced the RequestContext attribute as "rc" in views.

Removed unneeded "unknown cargo" JSP.

c:out not needed anymore.
peter_backlund 18 년 전
부모
커밋
feb0a349ca

+ 1
- 0
dddsample/src/main/java/se/citerus/dddsample/domain/HandlingEvent.java 파일 보기

@@ -56,6 +56,7 @@ public class HandlingEvent implements Comparable<HandlingEvent> {
56 56
     return HashCodeBuilder.reflectionHashCode(this);
57 57
   }
58 58
 
59
+  @Override
59 60
   public int compareTo(HandlingEvent o) {
60 61
     return time.compareTo(o.getTime());
61 62
   }

+ 0
- 2
dddsample/src/main/java/se/citerus/dddsample/domain/Location.java 파일 보기

@@ -28,7 +28,5 @@ public class Location {
28 28
   public String toString() {
29 29
     return unlocode;
30 30
   }
31
-  
32
-  
33 31
 
34 32
 }

+ 9
- 43
dddsample/src/main/java/se/citerus/dddsample/web/CargoTrackingController.java 파일 보기

@@ -1,20 +1,17 @@
1 1
 package se.citerus.dddsample.web;
2 2
 
3
-import java.util.HashMap;
4
-import java.util.Map;
5
-
6
-import javax.servlet.http.HttpServletRequest;
7
-import javax.servlet.http.HttpServletResponse;
8
-
9 3
 import org.springframework.validation.BindException;
10 4
 import org.springframework.web.servlet.ModelAndView;
11 5
 import org.springframework.web.servlet.mvc.SimpleFormController;
12
-
13 6
 import se.citerus.dddsample.domain.Cargo;
14
-import se.citerus.dddsample.domain.Location;
15 7
 import se.citerus.dddsample.service.CargoService;
16 8
 import se.citerus.dddsample.web.command.TrackCommand;
17 9
 
10
+import javax.servlet.http.HttpServletRequest;
11
+import javax.servlet.http.HttpServletResponse;
12
+import java.util.HashMap;
13
+import java.util.Map;
14
+
18 15
 /**
19 16
  * Controller for tracking cargo.
20 17
  */
@@ -24,34 +21,23 @@ public class CargoTrackingController extends SimpleFormController {
24 21
    * Service instance.
25 22
    */
26 23
   private CargoService cargoService;
27
-  private String unknownCargoView;
28 24
 
29 25
   public CargoTrackingController() {
30 26
     setCommandClass(TrackCommand.class);
31 27
   }
32 28
 
33
-  
34 29
   @Override
35 30
   protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
36
-    ModelAndView mav = null;
37
-    final Map<String, Object> model = new HashMap<String, Object>();
38
-
39
-    final TrackCommand trackCommand = (TrackCommand) command;   
40
-    logger.debug("Finding cargo by trackingId: " + trackCommand.getTrackingId());
31
+    final TrackCommand trackCommand = (TrackCommand) command;
41 32
     final Cargo cargo = cargoService.find(trackCommand.getTrackingId());
42 33
 
34
+    final Map<String, Cargo> model = new HashMap<String, Cargo>();
43 35
     if (cargo != null) {
44 36
       model.put("cargo", cargo);
45
-      
46
-      // Can't just return a new MaV instance when successView and FormView is the same. Binding will fail.
47
-      // showForm will append our command and model to the request so that the form will bind successfully.
48
-      mav = showForm(request, errors, getSuccessView(), model);
49 37
     } else {
50
-      model.put("trackingId", trackCommand.getTrackingId());
51
-      mav = new ModelAndView(getUnknownCargoView(), model);
38
+      errors.rejectValue("trackingId", "cargo.unknown_id", new Object[] {trackCommand.getTrackingId()}, "Unknown cargo id");
52 39
     }
53
-    
54
-    return mav;
40
+    return showForm(request, response, errors, model);
55 41
   }
56 42
    
57 43
 
@@ -64,24 +50,4 @@ public class CargoTrackingController extends SimpleFormController {
64 50
     this.cargoService = cargoService;
65 51
   }
66 52
   
67
-  /**
68
-   * Sets the view to show when an unknown tracking id is submitted.
69
-   *
70
-   * @param unknownCargoView The view.
71
-   */
72
-  public void setUnknownCargoView(final String unkownCargoView) {
73
-    this.unknownCargoView = unkownCargoView;
74
-  }
75
-
76
-  /**
77
-   * Gets the view to show when an unknown tracking id is submitted
78
-   * 
79
-   * @return The View
80
-   */
81
-  public String getUnknownCargoView() {
82
-    return unknownCargoView;
83
-  }
84
-
85
-
86
-  
87 53
 }

+ 28
- 0
dddsample/src/main/resources/context-web.xml 파일 보기

@@ -0,0 +1,28 @@
1
+<?xml version="1.0"?>
2
+
3
+<beans xmlns="http://www.springframework.org/schema/beans"
4
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
6
+
7
+  <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
8
+    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
9
+    <property name="prefix" value="/WEB-INF/jsp/"/>
10
+    <property name="suffix" value=".jsp"/>
11
+    <property name="requestContextAttribute" value="rc"/>
12
+  </bean>
13
+
14
+  <!--
15
+    - This bean resolves specific types of exceptions to corresponding logical
16
+    - view names for error views. The default behaviour of DispatcherServlet
17
+    - is to propagate all exceptions to the servlet container: this will happen
18
+    - here with all other types of exceptions.
19
+  -->
20
+  <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
21
+    <property name="exceptionMappings">
22
+      <props>
23
+        <prop key="org.springframework.dao.DataAccessException">dataAccessFailure</prop>
24
+      </props>
25
+    </property>
26
+  </bean>
27
+
28
+</beans>

+ 0
- 21
dddsample/src/main/webapp/WEB-INF/dispatch-servlet.xml 파일 보기

@@ -10,29 +10,8 @@
10 10
     <property name="successView" value="start"/>
11 11
     <property name="cargoService" ref="cargoService"/>
12 12
     <property name="validator" ref="trackCommandValidator"/>
13
-    <property name="unknownCargoView" value="unknownCargo"/>
14 13
   </bean>
15 14
 
16 15
   <bean id="trackCommandValidator" class="se.citerus.dddsample.web.command.TrackCommandValidator"/>
17 16
 
18
-  <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
19
-    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
20
-    <property name="prefix" value="/WEB-INF/jsp/"/>
21
-    <property name="suffix" value=".jsp"/>
22
-  </bean>
23
-  
24
-  <!--
25
-    - This bean resolves specific types of exceptions to corresponding logical 
26
-    - view names for error views. The default behaviour of DispatcherServlet 
27
-    - is to propagate all exceptions to the servlet container: this will happen 
28
-    - here with all other types of exceptions.
29
-  -->
30
-  <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
31
-    <property name="exceptionMappings">
32
-      <props>
33
-        <prop key="org.springframework.dao.DataAccessException">dataAccessFailure</prop>
34
-      </props>
35
-    </property>
36
-  </bean>
37
-
38 17
 </beans>

+ 1
- 1
dddsample/src/main/webapp/WEB-INF/jsp/dataAccessFailure.jsp 파일 보기

@@ -5,7 +5,7 @@
5 5
 	<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
6 6
 	<script type="text/javascript"></script>
7 7
 	<style type="text/css" title="style" media="screen">
8
-		@import "/dddsample/style.css";
8
+		@import "${rc.contextPath}/style.css";
9 9
 	</style>
10 10
 </head>
11 11
 <body>

+ 29
- 18
dddsample/src/main/webapp/WEB-INF/jsp/start.jsp 파일 보기

@@ -2,11 +2,11 @@
2 2
 
3 3
 <html>
4 4
 <head>
5
-	<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
6
-	<script type="text/javascript"></script>
7
-	<style type="text/css" title="style" media="screen">
8
-		@import "/dddsample/style.css";
9
-	</style>
5
+  <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>
6
+  <script type="text/javascript"></script>
7
+  <style type="text/css" title="style" media="screen">
8
+    @import "${rc.contextPath}/style.css";
9
+  </style>
10 10
 </head>
11 11
 <body>
12 12
 <div id="form">
@@ -29,20 +29,31 @@
29 29
     </table>
30 30
   </form:form>
31 31
 </div>
32
-<div id="result">
33
-<c:choose>
34
-  <c:when test="${cargo ne null}">
35
-  	
32
+<c:if test="${cargo ne null}">
33
+  <div id="result">
34
+
36 35
     <p>Your cargo is currently at: <span id="currentLocation">${cargo.currentLocation}</span></p>
37
-    
38
-    <table>
39
-      <c:forEach var="event" items="${cargo.deliveryHistory.events}">
40
-        <tr><td><c:out value="${event.type}"/> &nbsp; on &nbsp;</td><td><c:out value="${event.location}"/>&nbsp; at &nbsp;</td><td><c:out value="${event.time}"/></td></tr>
41
-      </c:forEach>
36
+
37
+    <table cellspacing="4">
38
+      <thead>
39
+        <tr>
40
+          <td>Event</td>
41
+          <td>Location</td>
42
+          <td>Time</td>
43
+        </tr>
44
+      </thead>
45
+      <tbody>
46
+        <c:forEach var="event" items="${cargo.deliveryHistory.events}">
47
+          <tr>
48
+            <td>${event.type}</td>
49
+            <td>${event.location}</td>
50
+            <td>${event.time}</td>
51
+          </tr>
52
+        </c:forEach>
53
+      </tbody>
42 54
     </table>
43
-    
44
-  </c:when>
45
-</c:choose>
46
-</div>
55
+
56
+  </div>
57
+</c:if>
47 58
 </body>
48 59
 </html>

+ 0
- 19
dddsample/src/main/webapp/WEB-INF/jsp/unknownCargo.jsp 파일 보기

@@ -1,19 +0,0 @@
1
-<%@ include file="/WEB-INF/jspf/include.jspf" %>
2
-
3
-<html>
4
-<head>
5
-	<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
6
-	<script type="text/javascript"></script>
7
-	<style type="text/css" title="style" media="screen">
8
-		@import "/dddsample/style.css";
9
-	</style>
10
-</head>
11
-<body>
12
-
13
-<p>Unknown tracking id ${trackingId}</p>
14
-
15
-<br/>
16
-<a href="start.html">Start page</a>
17
-
18
-</body>
19
-</html>

+ 21
- 25
dddsample/src/test/java/se/citerus/dddsample/web/CargoTrackingControllerTest.java 파일 보기

@@ -1,13 +1,14 @@
1 1
 package se.citerus.dddsample.web;
2 2
 
3 3
 import junit.framework.TestCase;
4
-
5 4
 import org.springframework.mock.web.MockHttpServletRequest;
6 5
 import org.springframework.mock.web.MockHttpServletResponse;
7 6
 import org.springframework.mock.web.MockHttpSession;
8 7
 import org.springframework.mock.web.MockServletContext;
8
+import org.springframework.validation.BindingResult;
9
+import org.springframework.validation.Errors;
10
+import org.springframework.validation.FieldError;
9 11
 import org.springframework.web.servlet.ModelAndView;
10
-
11 12
 import se.citerus.dddsample.domain.Cargo;
12 13
 import se.citerus.dddsample.domain.Location;
13 14
 import se.citerus.dddsample.domain.TrackingId;
@@ -31,9 +32,7 @@ public class CargoTrackingControllerTest extends TestCase {
31 32
     controller = new CargoTrackingController();
32 33
     controller.setFormView("test-form");
33 34
     controller.setSuccessView("test-success");
34
-    controller.setUnknownCargoView("test-unkownCargo");
35 35
     controller.setCommandName("test-command-name");
36
-    controller.setCargoService(getCargoServiceMock());
37 36
   }
38 37
 
39 38
   private CargoService getCargoServiceMock() {
@@ -57,6 +56,7 @@ public class CargoTrackingControllerTest extends TestCase {
57 56
   }
58 57
 
59 58
   public void testHandleGet() throws Exception {
59
+    controller.setCargoService(getCargoServiceMock());
60 60
     request.setMethod("GET");
61 61
 
62 62
     ModelAndView mav = controller.handleRequest(request, response);
@@ -67,11 +67,13 @@ public class CargoTrackingControllerTest extends TestCase {
67 67
   }
68 68
 
69 69
   public void testHandlePost() throws Exception {
70
+    controller.setCargoService(getCargoServiceMock());
70 71
     request.setMethod("POST");
71 72
 
72 73
     ModelAndView mav = controller.handleRequest(request, response);
73 74
 
74
-    assertEquals("test-success", mav.getViewName());
75
+    assertEquals("test-form", mav.getViewName());
76
+    // Errors, command are two standard map attributes, the third should be the cargo object
75 77
     assertEquals(3, mav.getModel().size());
76 78
     Cargo cargo = (Cargo) mav.getModel().get("cargo");
77 79
     assertEquals("AAA", cargo.getCurrentLocation().unlocode());
@@ -79,28 +81,22 @@ public class CargoTrackingControllerTest extends TestCase {
79 81
 
80 82
   public void testUnknownCargo() throws Exception {
81 83
     controller.setCargoService(getCargoServiceNullMock());
82
-    controller.setCommandClass(TrackCommandMock.class);
83 84
     request.setMethod("POST");
84
-
85
+    request.setParameter("trackingId", "unknown-id");
86
+    
85 87
     ModelAndView mav = controller.handleRequest(request, response);
86 88
 
87
-    assertEquals("test-unkownCargo", mav.getViewName());
88
-    assertEquals(1, mav.getModel().size());
89
-    String trackId = (String) mav.getModel().get("trackingId");
90
-    assertEquals("MOCK", trackId);
91
-  }
92
-  
93
-  
94
-  
95
-  
96
-  /**
97
-   * Mock track command.
98
-   * 
99
-   * Sets a default track id when constructed.
100
-   */
101
-  private static class TrackCommandMock extends TrackCommand {
102
-    public TrackCommandMock() {
103
-      setTrackingId("MOCK");
104
-    }
89
+    assertEquals("test-form", mav.getViewName());
90
+    assertEquals(2, mav.getModel().size());
91
+
92
+    TrackCommand command = (TrackCommand) mav.getModel().get(controller.getCommandName());
93
+    assertEquals("unknown-id", command.getTrackingId());
94
+
95
+    Errors errors = (Errors) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + controller.getCommandName());
96
+    FieldError fe = errors.getFieldError("trackingId");
97
+    assertEquals("cargo.unknown_id", fe.getCode());
98
+    assertEquals(1, fe.getArguments().length);
99
+    assertEquals(command.getTrackingId(), fe.getArguments()[0]);
105 100
   }
101
+
106 102
 }