├── README.md ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── pluralsight │ │ └── orderfulfillment │ │ ├── catalog │ │ ├── CatalogItem.java │ │ ├── CatalogItemEntity.java │ │ └── CatalogItemRepository.java │ │ ├── config │ │ ├── Application.java │ │ ├── DataConfig.java │ │ ├── WebConfig.java │ │ └── WebContextInitializer.java │ │ ├── customer │ │ ├── Customer.java │ │ ├── CustomerEntity.java │ │ └── CustomerRepository.java │ │ └── order │ │ ├── DefaultOrderService.java │ │ ├── Order.java │ │ ├── OrderController.java │ │ ├── OrderEntity.java │ │ ├── OrderItem.java │ │ ├── OrderItemEntity.java │ │ ├── OrderItemRepository.java │ │ ├── OrderRepository.java │ │ ├── OrderService.java │ │ ├── OrderStatus.java │ │ └── fulfillment │ │ ├── FulfillmentCommand.java │ │ ├── FulfillmentContext.java │ │ ├── FulfillmentProcessor.java │ │ ├── NewOrderRetrievalCommand.java │ │ └── NewOrderSendToFulfillmentCenterOneCommand.java ├── resources │ ├── log4j.dtd │ ├── log4j.xml │ └── order-fulfillment.properties ├── sql │ ├── hibernate.reveng.xml │ └── postgresql │ │ ├── ddl │ │ ├── create-orders-db.sql │ │ ├── create-orders.sql │ │ └── drop-orders-db.sql │ │ └── dml │ │ └── load-orders.sql └── webapp │ ├── WEB-INF │ ├── jsp │ │ ├── footer.jsp │ │ ├── header.jsp │ │ ├── orderHome.jsp │ │ ├── page.jsp │ │ ├── processOrders.jsp │ │ ├── resetOrders.jsp │ │ ├── tiles.xml │ │ └── viewOrders.jsp │ └── web.xml │ └── resources │ ├── css │ ├── app.css │ ├── bootstrap-theme.css │ └── bootstrap.css │ ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff │ ├── img │ ├── glyphicons-halflings-white.png │ └── glyphicons-halflings.png │ └── js │ ├── bootstrap.js │ ├── jquery-1.11.0.min.js │ ├── jquery-ui-1.10.4.js │ └── underscore-min.js └── test └── java └── com └── pluralsight └── orderfulfillment ├── catalog └── CatalogItemRepositoryTest.java ├── customer └── CustomerRepositoryTest.java ├── order ├── OrderItemRepositoryTest.java └── OrderRepositoryTest.java └── test └── BaseJpaRepositoryTest.java /README.md: -------------------------------------------------------------------------------- 1 | # Order Fulfillment Processor 2 | 3 | ## Installation Overview 4 | 5 | This is the installation guide for setting up the order fulfillment processor application that acts as the case study for 6 | Pluralsight's Introduction to Integration with Apache Camel. The case study is a custom implementation of a mediator. You 7 | will be able to follow along with the course using this case study project as the base for demonstrations. The case study 8 | was developed using the following: 9 | 10 | ..* Implemented on Windows 8.1, 64-bit 11 | ..* Eclipse 12 | ..* JDK 1.7.0_45 13 | ..* Maven 3 14 | ..* Spring 4 15 | ..* PostgreSQL 9.3 16 | ..* Apache Tomcat 7.0.54 17 | ..* Apache ActiveMQ 5.10.0 18 | ..* Apache Camel 2.13.2 19 | ..* Hawt.io 1.4.14 20 | 21 | ## Component Installation 22 | 23 | Below are the instructions on a per-component basis. The installation assumes Windows, so you will need to follow the instructions 24 | that pertain to your OS if you are not using Windows. 25 | 26 | ### Java 27 | 28 | The case study depends on Java. The course makes use of Java SDK 1.7.0_45. The SDK can be downloaded here: 29 | 30 | http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html 31 | 32 | Following installation, you will need to configure your environment variables based on your OS 33 | 34 | ### Eclipse 35 | 36 | My preference for an integrated development environment is Eclipse. I am currently developing using Eclipse Kepler. You can 37 | find the download for Eclipse here: 38 | 39 | http://www.eclipse.org/kepler/ 40 | 41 | ### Maven 42 | 43 | I use Apache Maven for build and dependency management. You can download Maven here: 44 | 45 | http://maven.apache.org/download.cgi 46 | 47 | After installation, you will need to configure your environment variables based on your OS. You can also skip installation of 48 | Maven and use the Eclipse Maven plug-in if you are developing with Eclipse as your IDE. 49 | 50 | ### PostgreSQL 51 | 52 | I chose to use PostgreSQL for the project's database. PostgreSQL is a free, open-source database. PostgreSQL can be 53 | downloaded from the following URL: 54 | 55 | http://www.postgresql.org/download/windows/ 56 | 57 | The installation should include PGAdmin III, which is a graphical editor for PostgreSQL. 58 | 59 | The scripts to create the database for the case study project can be found in the project directory: 60 | 61 | order-fulfillment-processor\src\main\sql\postgresql\ddl 62 | 63 | Scripts include: 64 | 65 | ..* create-orders-db.sql = Creates the login, database and schema for the project. 66 | ..* create-orders.sql = Drops and re-creates the database table schema 67 | ..* drop-orders-db.sql = Drops the orders database 68 | 69 | The script to load initial data can be found in the project directory: 70 | 71 | order-fulfillment-processor\src\main\sql\postgresql\dml\load-orders.sql 72 | 73 | To initially create the database: 74 | 75 | 1. Log in to PGAdmin III and connect using the postgres user 76 | 2. Create the login for orders using the create statement found in create-orders-db.sql 77 | 3. Create the database for orders using the create statement found in create-orders-db.sql 78 | 4. Disconnect from the server, then right click the database, select properties and enter the user name as orders. 79 | 5. Connect to the server using the orders user name. 80 | 6. Open the query tool and run the create-orders.sql file, then run the load-orders.sql file. 81 | 82 | To re-load the database: 83 | 84 | 1. Log in to PGAdmin III and connect using the orders user 85 | 2. Open the query tool and run the create-orders.sql file, then run the load-orders.sql file. 86 | 87 | ### Apache Tomcat 88 | 89 | I used Apache Tomcat 7.0.54 as a server runtime in Eclipse. Below are instructions for adding the runtime in Eclipse: 90 | 91 | 1. Download Tomcat 7 from http://tomcat.apache.org/ 92 | 2. Unzip the file to a directory on your hard drive 93 | 3. In Eclipse, click the Window -> Preference menu and then select Server -> Runtime Environments from the Preferences popup 94 | 4. Click the Add button. 95 | 5. Select Tomcat 7 and click next 96 | 6. Enter the installation directory you unzipped Tomcat to and click Finish 97 | 98 | ### Apache ActiveMQ 99 | 100 | I used Apache ActiveMQ 5.10.0 for messaging. Below are instructions for installation: 101 | 102 | 1. Download ActiveMQ 5.10 from http://activemq.apache.org/ 103 | 2. Unzip the file to a directory on your hard drivev 104 | 3. Open a command prompt and navigate to the bin directory of the activemq installation you unzipped 105 | 4. Run the command activemq.bat start 106 | 5. Verify the broker started by navigating to http://localhost:8161/ and logging in with admin/admin 107 | 108 | ### Hawt.io 109 | 110 | I used Hawt.io version 1.4.14. Below are instructions for installation: 111 | 112 | 1. Downloaded Hawt.io 1.4.14 WAR file from http://hawt.io/ 113 | 2. In Eclipse, I selected the File -> import menu, then selected Web -> WAR 114 | 3. I selected the hawt.io WAR file I downloaded and then selected next 115 | 4. I kept all the selections unchecked and clicked finish to import the WAR. 116 | 5. I added the project to Tomcat in Eclipse 117 | 6. You can then verify the installation from http://localhost:8080/hawtio-default-1.4.14 118 | 119 | ### Order Fulfillment Project Installation 120 | 121 | Below are instructions for getting the Order Fulfillment Processor running in Eclipse: 122 | 123 | 1. In Eclipse, select File -> Import and select Maven -> Existing Maven Projects 124 | 2. Enter the root directory of the project then make sure the pom.xml file is checked. Click Next and then click Finish 125 | 3. Make sure the project is faceted as a Maven project 126 | 4. Right click the project and select Properties 127 | 5. Click Project Facets in the pop-up and then click the convert to faceted project link if not already in faceted form. 128 | 6. Make sure Dynamic Web Module 3.0 is checked 129 | 7. Make sure Java 1.7 is checked 130 | 8. Click OK to close the properties popup, then right-click the project and select Properties again. 131 | 9. There should now be a Deployment Assembly selection, which you should select. 132 | 10. Make sure that /src/main/java/ and /src/main/resources are deployed to WEB-INF/classes 133 | 11. Remove the /WebContent to / entry 134 | 12. Add the java build path entry Maven Dependencies and make sure it deploys to WEB-INF/lib 135 | 13. Add the /src/main/webapp folder and make sure it deploys to / 136 | 14. Click OK to close the properties window 137 | 15. Add the project to the Tomcat 7 server and start the server. 138 | 16. Once the server is started, open a browser to http://localhost:8080/order-fulfillment-processor/orderHome 139 | 140 | If you want to run order processing, click Orders -> Process Orders 141 | 142 | If you want to reset the orders back to new status, click Orders -> Reset Orders 143 | 144 | ## Contact Information 145 | 146 | If you have any questions, please feel free to contact me: 147 | 148 | Michael Hoffman 149 | mike@michaelhoffmaninc.com 150 | @mhi_inc -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | 9 | central 10 | http://central.maven.org/maven2/ 11 | 12 | 13 | 14 | com.pluralsight.camel 15 | order-fulfillment-processor 16 | 1.0-SNAPSHOT 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | org.springframework 25 | spring-core 26 | 4.0.4.RELEASE 27 | 28 | 29 | commons-logging 30 | commons-logging 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.springframework 38 | spring-aspects 39 | 4.0.4.RELEASE 40 | 41 | 42 | 43 | 44 | org.springframework 45 | spring-web 46 | 4.0.4.RELEASE 47 | 48 | 49 | 50 | 51 | org.springframework 52 | spring-webmvc 53 | 4.0.4.RELEASE 54 | 55 | 56 | 57 | 58 | org.springframework 59 | spring-jdbc 60 | 4.0.4.RELEASE 61 | 62 | 63 | 64 | 65 | org.springframework.data 66 | spring-data-jpa 67 | 1.5.2.RELEASE 68 | 69 | 70 | spring-aop 71 | org.springframework 72 | 73 | 74 | 75 | 76 | 77 | 78 | javax.validation 79 | validation-api 80 | 1.0.0.GA 81 | compile 82 | 83 | 84 | org.hibernate 85 | hibernate-validator 86 | 4.3.1.Final 87 | compile 88 | 89 | 90 | org.hibernate 91 | hibernate-core 92 | 4.3.5.Final 93 | compile 94 | 95 | 96 | org.hibernate 97 | hibernate-entitymanager 98 | 4.3.5.Final 99 | compile 100 | 101 | 102 | org.hibernate.javax.persistence 103 | hibernate-jpa-2.1-api 104 | 1.0.0.Final 105 | 106 | 107 | 108 | 109 | org.springframework 110 | spring-orm 111 | 4.0.4.RELEASE 112 | 113 | 114 | 115 | 116 | org.slf4j 117 | jcl-over-slf4j 118 | 1.5.8 119 | 120 | 121 | org.slf4j 122 | slf4j-api 123 | 1.5.8 124 | 125 | 126 | org.slf4j 127 | slf4j-log4j12 128 | 1.5.8 129 | 130 | 131 | log4j 132 | log4j 133 | 1.2.14 134 | 135 | 136 | 137 | 138 | org.aspectj 139 | aspectjrt 140 | 1.7.4 141 | 142 | 143 | 144 | 145 | cglib 146 | cglib-nodep 147 | 2.2 148 | 149 | 150 | 151 | 152 | javax.inject 153 | javax.inject 154 | 1 155 | 156 | 157 | 158 | 159 | postgresql 160 | postgresql 161 | 9.1-901.jdbc4 162 | 163 | 164 | 165 | commons-dbcp 166 | commons-dbcp 167 | 1.4 168 | 169 | 170 | 171 | 172 | javax.servlet 173 | javax.servlet-api 174 | 3.0.1 175 | provided 176 | 177 | 178 | javax.servlet.jsp 179 | jsp-api 180 | 2.2 181 | provided 182 | 183 | 184 | jstl 185 | jstl 186 | 1.2 187 | 188 | 189 | 190 | org.codehaus.jackson 191 | jackson-mapper-asl 192 | 1.9.9 193 | 194 | 195 | 196 | 197 | org.apache.tiles 198 | tiles-jsp 199 | 2.2.2 200 | 201 | 202 | org.apache.tiles 203 | tiles-el 204 | 2.2.2 205 | 206 | 207 | org.apache.commons 208 | commons-lang3 209 | 3.3.2 210 | 211 | 212 | 213 | 214 | net.sf.opencsv 215 | opencsv 216 | 2.3 217 | 218 | 219 | 220 | 221 | org.springframework 222 | spring-test 223 | 4.0.4.RELEASE 224 | test 225 | 226 | 227 | junit 228 | junit-dep 229 | 4.10 230 | test 231 | 232 | 233 | org.hamcrest 234 | hamcrest-core 235 | 236 | 237 | 238 | 239 | org.hamcrest 240 | hamcrest-library 241 | 1.3 242 | test 243 | 244 | 245 | org.mockito 246 | mockito-core 247 | 1.9.0 248 | test 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | src/main/resources 257 | 258 | 259 | 260 | 261 | src/test/resources 262 | 263 | 264 | 265 | 266 | org.apache.maven.plugins 267 | maven-compiler-plugin 268 | 3.1 269 | 270 | 1.7 271 | 1.7 272 | 273 | 274 | 275 | org.codehaus.mojo 276 | aspectj-maven-plugin 277 | 1.5 278 | 279 | 280 | org.aspectj 281 | aspectjrt 282 | 1.7.4 283 | 284 | 285 | org.aspectj 286 | aspectjtools 287 | 1.7.4 288 | 289 | 290 | 291 | 292 | 293 | compile 294 | test-compile 295 | 296 | 297 | 298 | 299 | true 300 | 301 | 302 | org.springframework 303 | spring-aspects 304 | 305 | 306 | 1.7 307 | 1.7 308 | 1.7 309 | 310 | 311 | 312 | org.apache.maven.plugins 313 | maven-dependency-plugin 314 | 315 | 316 | install 317 | install 318 | 319 | sources 320 | 321 | 322 | 323 | 324 | 325 | org.apache.maven.plugins 326 | maven-war-plugin 327 | 2.4 328 | 329 | 330 | org.apache.maven.plugins 331 | maven-eclipse-plugin 332 | 2.9 333 | 334 | false 335 | true 336 | true 337 | 2.0 338 | 339 | 340 | 341 | 342 | 343 | 345 | 346 | org.eclipse.m2e 347 | lifecycle-mapping 348 | 1.0.0 349 | 350 | 351 | 352 | 353 | 354 | 355 | org.codehaus.mojo 356 | 357 | 358 | properties-maven-plugin 359 | 360 | 361 | [1.0-alpha-2,) 362 | 363 | 364 | 365 | write-active-profile-properties 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | org.codehaus.mojo 377 | 378 | 379 | aspectj-maven-plugin 380 | 381 | 382 | [1.5,) 383 | 384 | 385 | compile 386 | test-compile 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | ofp 400 | 401 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/catalog/CatalogItem.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.catalog; 2 | 3 | import java.io.*; 4 | 5 | public class CatalogItem implements Serializable { 6 | 7 | private static final long serialVersionUID = -3048858539620507612L; 8 | 9 | private long id; 10 | private String itemNumber; 11 | private String itemName; 12 | private String itemType; 13 | 14 | public CatalogItem() { 15 | 16 | } 17 | 18 | public CatalogItem(long id, String itemNumber, String itemName, String itemType) { 19 | this.id = id; 20 | this.itemNumber = itemNumber; 21 | this.itemName = itemName; 22 | this.itemType = itemType; 23 | } 24 | 25 | /** 26 | * @return the id 27 | */ 28 | public long getId() { 29 | return id; 30 | } 31 | 32 | /** 33 | * @param id 34 | * the id to set 35 | */ 36 | public void setId(long id) { 37 | this.id = id; 38 | } 39 | 40 | /** 41 | * @return the itemNumber 42 | */ 43 | public String getItemNumber() { 44 | return itemNumber; 45 | } 46 | 47 | /** 48 | * @param itemNumber 49 | * the itemNumber to set 50 | */ 51 | public void setItemNumber(String itemNumber) { 52 | this.itemNumber = itemNumber; 53 | } 54 | 55 | /** 56 | * @return the itemName 57 | */ 58 | public String getItemName() { 59 | return itemName; 60 | } 61 | 62 | /** 63 | * @param itemName 64 | * the itemName to set 65 | */ 66 | public void setItemName(String itemName) { 67 | this.itemName = itemName; 68 | } 69 | 70 | /** 71 | * @return the itemType 72 | */ 73 | public String getItemType() { 74 | return itemType; 75 | } 76 | 77 | /** 78 | * @param itemType 79 | * the itemType to set 80 | */ 81 | public void setItemType(String itemType) { 82 | this.itemType = itemType; 83 | } 84 | 85 | /* 86 | * (non-Javadoc) 87 | * 88 | * @see java.lang.Object#toString() 89 | */ 90 | @Override 91 | public String toString() { 92 | StringBuilder builder = new StringBuilder(); 93 | builder.append("CatalogItem [id="); 94 | builder.append(id); 95 | builder.append(", "); 96 | if (itemNumber != null) { 97 | builder.append("itemNumber="); 98 | builder.append(itemNumber); 99 | builder.append(", "); 100 | } 101 | if (itemName != null) { 102 | builder.append("itemName="); 103 | builder.append(itemName); 104 | builder.append(", "); 105 | } 106 | if (itemType != null) { 107 | builder.append("itemType="); 108 | builder.append(itemType); 109 | } 110 | builder.append("]"); 111 | return builder.toString(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/catalog/CatalogItemEntity.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.catalog; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | 6 | import javax.persistence.*; 7 | 8 | import com.pluralsight.orderfulfillment.order.*; 9 | 10 | /** 11 | * Customer entity. 12 | * 13 | * @author Michael Hoffman 14 | * 15 | */ 16 | @Entity 17 | @Table(name = "catalogItem") 18 | @SequenceGenerator(name = "catalogitem_id_seq", sequenceName = "catalogitem_id_seq") 19 | public class CatalogItemEntity implements Serializable { 20 | 21 | private static final long serialVersionUID = 4868640483823944904L; 22 | 23 | private long id; 24 | private String itemNumber; 25 | private String itemName; 26 | private String itemType; 27 | private Set orderItems = new HashSet(0); 28 | 29 | public CatalogItemEntity() { 30 | 31 | } 32 | 33 | public CatalogItemEntity(long id, String itemNumber, String itemName, String itemType) { 34 | this.id = id; 35 | this.itemNumber = itemNumber; 36 | this.itemName = itemName; 37 | this.itemType = itemType; 38 | } 39 | 40 | public CatalogItemEntity(long id, String itemNumber, String itemName, String itemType, 41 | Set orderItems) { 42 | this.id = id; 43 | this.itemNumber = itemNumber; 44 | this.itemName = itemName; 45 | this.itemType = itemType; 46 | this.orderItems = orderItems; 47 | } 48 | 49 | /** 50 | * @return the id 51 | */ 52 | @Id 53 | @Column(name = "id") 54 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "catalogitem_id_seq") 55 | public long getId() { 56 | return id; 57 | } 58 | 59 | /** 60 | * @param id 61 | * the id to set 62 | */ 63 | public void setId(long id) { 64 | this.id = id; 65 | } 66 | 67 | /** 68 | * @return the itemNumber 69 | */ 70 | @Column(name = "itemNumber", nullable = false) 71 | public String getItemNumber() { 72 | return itemNumber; 73 | } 74 | 75 | /** 76 | * @param itemNumber 77 | * the itemNumber to set 78 | */ 79 | public void setItemNumber(String itemNumber) { 80 | this.itemNumber = itemNumber; 81 | } 82 | 83 | /** 84 | * @return the itemName 85 | */ 86 | @Column(name = "itemName", nullable = false) 87 | public String getItemName() { 88 | return itemName; 89 | } 90 | 91 | /** 92 | * @param itemName 93 | * the itemName to set 94 | */ 95 | public void setItemName(String itemName) { 96 | this.itemName = itemName; 97 | } 98 | 99 | /** 100 | * @return the itemType 101 | */ 102 | @Column(name = "itemType", nullable = false) 103 | public String getItemType() { 104 | return itemType; 105 | } 106 | 107 | /** 108 | * @param itemType 109 | * the itemType to set 110 | */ 111 | public void setItemType(String itemType) { 112 | this.itemType = itemType; 113 | } 114 | 115 | @OneToMany(fetch = FetchType.LAZY, mappedBy = "catalogItem") 116 | public Set getOrderItems() { 117 | return this.orderItems; 118 | } 119 | 120 | public void setOrderItems(Set orderItems) { 121 | this.orderItems = orderItems; 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/catalog/CatalogItemRepository.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.catalog; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | /** 6 | * Repository access for CatalogItemEntity data. 7 | * 8 | * @author Michael Hoffman, Pluralsight 9 | * 10 | */ 11 | public interface CatalogItemRepository extends JpaRepository { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/config/Application.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.config; 2 | 3 | import org.springframework.context.annotation.*; 4 | 5 | /** 6 | * Main application configuration for the order fulfillment processor. 7 | * 8 | * @author Michael Hoffman, Pluralsight 9 | * 10 | */ 11 | @Configuration 12 | @ComponentScan(basePackages = "com.pluralsight.orderfulfillment") 13 | @PropertySource("classpath:order-fulfillment.properties") 14 | public class Application { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/config/DataConfig.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.config; 2 | 3 | import java.util.*; 4 | 5 | import javax.inject.*; 6 | import javax.persistence.*; 7 | import javax.sql.*; 8 | 9 | import org.apache.commons.dbcp.*; 10 | import org.springframework.context.annotation.*; 11 | import org.springframework.core.env.*; 12 | import org.springframework.data.jpa.repository.config.*; 13 | import org.springframework.orm.hibernate4.*; 14 | import org.springframework.orm.jpa.*; 15 | import org.springframework.orm.jpa.vendor.*; 16 | import org.springframework.transaction.*; 17 | import org.springframework.transaction.annotation.*; 18 | 19 | /** 20 | * Data configuration for repositories. 21 | * 22 | * @author Michael Hoffman 23 | * 24 | */ 25 | @Configuration 26 | @EnableJpaRepositories(basePackages = { "com.pluralsight.orderfulfillment" }) 27 | @EnableTransactionManagement 28 | public class DataConfig { 29 | 30 | @Inject 31 | private Environment environment; 32 | 33 | @Bean 34 | public DataSource dataSource() { 35 | BasicDataSource dataSource = new BasicDataSource(); 36 | dataSource.setDriverClassName(environment.getProperty("db.driver")); 37 | dataSource.setUrl(environment.getProperty("db.url")); 38 | dataSource.setUsername(environment.getProperty("db.user")); 39 | dataSource.setPassword(environment.getProperty("db.password")); 40 | return dataSource; 41 | } 42 | 43 | @Bean 44 | public EntityManagerFactory entityManagerFactory() { 45 | final HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter(); 46 | jpaVendorAdapter.setDatabasePlatform(environment.getProperty("hibernate.dialect")); 47 | jpaVendorAdapter.setShowSql(false); 48 | final Map jpaProperties = new HashMap(); 49 | jpaProperties.put("hibernate.jdbc.batch_size", 50 | environment.getProperty("hibernate.jdbc.batch_size")); 51 | jpaProperties.put("hibernate.default_schema", 52 | environment.getProperty("hibernate.default_schema")); 53 | LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); 54 | factory.setPackagesToScan("com.pluralsight.orderfulfillment"); 55 | factory.setJpaVendorAdapter(jpaVendorAdapter); 56 | factory.setDataSource(dataSource()); 57 | factory.setJpaPropertyMap(jpaProperties); 58 | factory.afterPropertiesSet(); 59 | return factory.getObject(); 60 | } 61 | 62 | @Bean 63 | public PlatformTransactionManager transactionManager() { 64 | JpaTransactionManager transactionManager = new JpaTransactionManager(); 65 | transactionManager.setEntityManagerFactory(entityManagerFactory()); 66 | return transactionManager; 67 | } 68 | 69 | @Bean 70 | public HibernateExceptionTranslator hibernateExceptionTranslator() { 71 | return new HibernateExceptionTranslator(); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.config; 2 | 3 | import org.springframework.context.annotation.*; 4 | import org.springframework.web.servlet.*; 5 | import org.springframework.web.servlet.config.annotation.*; 6 | import org.springframework.web.servlet.view.*; 7 | import org.springframework.web.servlet.view.tiles2.*; 8 | 9 | /** 10 | * Web configuration 11 | * 12 | * @author Michael Hoffman, Pluralsight 13 | * 14 | */ 15 | @Configuration 16 | @ComponentScan("com.pluralsight.orderfulfillment") 17 | @EnableWebMvc 18 | public class WebConfig extends WebMvcConfigurerAdapter { 19 | 20 | @Bean 21 | public ViewResolver viewResolver() { 22 | UrlBasedViewResolver viewResolver = new UrlBasedViewResolver(); 23 | viewResolver.setViewClass(TilesView.class); 24 | return viewResolver; 25 | } 26 | 27 | /** 28 | * Configures Tiles at application startup. 29 | */ 30 | @Bean 31 | public TilesConfigurer tilesConfigurer() { 32 | TilesConfigurer configurer = new TilesConfigurer(); 33 | configurer.setDefinitions(new String[] { "/WEB-INF/jsp/tiles.xml" }); 34 | configurer.setCheckRefresh(true); 35 | return configurer; 36 | } 37 | 38 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 39 | registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/config/WebContextInitializer.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.config; 2 | 3 | import javax.servlet.*; 4 | 5 | import org.springframework.web.*; 6 | import org.springframework.web.context.support.*; 7 | import org.springframework.web.servlet.*; 8 | 9 | /** 10 | * Initializes the web application in place of a descriptor. 11 | * 12 | * @author Michael Hoffman, Pluralsight 13 | * 14 | */ 15 | public class WebContextInitializer implements WebApplicationInitializer { 16 | 17 | @Override 18 | public void onStartup(ServletContext servletContext) throws ServletException { 19 | AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); 20 | rootContext.register(Application.class); 21 | rootContext.setServletContext(servletContext); 22 | ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", 23 | new DispatcherServlet(rootContext)); 24 | dispatcher.setLoadOnStartup(1); 25 | dispatcher.addMapping("/"); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/customer/Customer.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.customer; 2 | 3 | /** 4 | * Domain object for a Customer 5 | * 6 | * @author Michael Hoffman, Pluralsight 7 | * 8 | */ 9 | public class Customer { 10 | private long id; 11 | private String firstName; 12 | private String lastName; 13 | private String email; 14 | 15 | public Customer() { 16 | 17 | } 18 | 19 | public Customer(long id, String firstName, String lastName, String email) { 20 | super(); 21 | this.id = id; 22 | this.firstName = firstName; 23 | this.lastName = lastName; 24 | this.email = email; 25 | } 26 | 27 | /** 28 | * @return the id 29 | */ 30 | public long getId() { 31 | return id; 32 | } 33 | 34 | /** 35 | * @param id 36 | * the id to set 37 | */ 38 | public void setId(long id) { 39 | this.id = id; 40 | } 41 | 42 | /** 43 | * @return the firstName 44 | */ 45 | public String getFirstName() { 46 | return firstName; 47 | } 48 | 49 | /** 50 | * @param firstName 51 | * the firstName to set 52 | */ 53 | public void setFirstName(String firstName) { 54 | this.firstName = firstName; 55 | } 56 | 57 | /** 58 | * @return the lastName 59 | */ 60 | public String getLastName() { 61 | return lastName; 62 | } 63 | 64 | /** 65 | * @param lastName 66 | * the lastName to set 67 | */ 68 | public void setLastName(String lastName) { 69 | this.lastName = lastName; 70 | } 71 | 72 | /** 73 | * @return the email 74 | */ 75 | public String getEmail() { 76 | return email; 77 | } 78 | 79 | /** 80 | * @param email 81 | * the email to set 82 | */ 83 | public void setEmail(String email) { 84 | this.email = email; 85 | } 86 | 87 | /* 88 | * (non-Javadoc) 89 | * 90 | * @see java.lang.Object#toString() 91 | */ 92 | @Override 93 | public String toString() { 94 | StringBuilder builder = new StringBuilder(); 95 | builder.append("Customer [id="); 96 | builder.append(id); 97 | builder.append(", "); 98 | if (firstName != null) { 99 | builder.append("firstName="); 100 | builder.append(firstName); 101 | builder.append(", "); 102 | } 103 | if (lastName != null) { 104 | builder.append("lastName="); 105 | builder.append(lastName); 106 | builder.append(", "); 107 | } 108 | if (email != null) { 109 | builder.append("email="); 110 | builder.append(email); 111 | } 112 | builder.append("]"); 113 | return builder.toString(); 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/customer/CustomerEntity.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.customer; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | 6 | import javax.persistence.*; 7 | 8 | import com.pluralsight.orderfulfillment.order.*; 9 | 10 | /** 11 | * Customer entity 12 | * 13 | * @author Michael Hoffman 14 | * 15 | */ 16 | @Entity 17 | @Table(name = "customer") 18 | @SequenceGenerator(name = "customer_id_seq", sequenceName = "customer_id_seq") 19 | public class CustomerEntity implements Serializable { 20 | 21 | private static final long serialVersionUID = -7602916426025960936L; 22 | 23 | private long id; 24 | private String firstName; 25 | private String lastName; 26 | private String email; 27 | private Set orders = new HashSet(0); 28 | 29 | public CustomerEntity() { 30 | 31 | } 32 | 33 | public CustomerEntity(long id, String firstName, String lastName, String email) { 34 | super(); 35 | this.id = id; 36 | this.firstName = firstName; 37 | this.lastName = lastName; 38 | this.email = email; 39 | } 40 | 41 | public CustomerEntity(long id, String firstName, String lastName, String email, 42 | Set orders) { 43 | super(); 44 | this.id = id; 45 | this.firstName = firstName; 46 | this.lastName = lastName; 47 | this.email = email; 48 | this.orders = orders; 49 | } 50 | 51 | /** 52 | * @return the id 53 | */ 54 | @Id 55 | @Column(name = "id") 56 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "customer_id_seq") 57 | public long getId() { 58 | return id; 59 | } 60 | 61 | /** 62 | * @param id 63 | * the id to set 64 | */ 65 | public void setId(long id) { 66 | this.id = id; 67 | } 68 | 69 | /** 70 | * @return the firstName 71 | */ 72 | @Column(name = "firstName", nullable = false) 73 | public String getFirstName() { 74 | return firstName; 75 | } 76 | 77 | /** 78 | * @param firstName 79 | * the firstName to set 80 | */ 81 | public void setFirstName(String firstName) { 82 | this.firstName = firstName; 83 | } 84 | 85 | /** 86 | * @return the lastName 87 | */ 88 | @Column(name = "lastName", nullable = false) 89 | public String getLastName() { 90 | return lastName; 91 | } 92 | 93 | /** 94 | * @param lastName 95 | * the lastName to set 96 | */ 97 | public void setLastName(String lastName) { 98 | this.lastName = lastName; 99 | } 100 | 101 | /** 102 | * @return the email 103 | */ 104 | @Column(name = "email", nullable = false) 105 | public String getEmail() { 106 | return email; 107 | } 108 | 109 | /** 110 | * @param email 111 | * the email to set 112 | */ 113 | public void setEmail(String email) { 114 | this.email = email; 115 | } 116 | 117 | @OneToMany(fetch = FetchType.LAZY, mappedBy = "customer") 118 | public Set getOrders() { 119 | return this.orders; 120 | } 121 | 122 | public void setOrders(Set orders) { 123 | this.orders = orders; 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/customer/CustomerRepository.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.customer; 2 | 3 | import org.springframework.data.jpa.repository.*; 4 | 5 | public interface CustomerRepository extends JpaRepository { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/DefaultOrderService.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order; 2 | 3 | import java.util.*; 4 | 5 | import javax.inject.*; 6 | import javax.transaction.*; 7 | 8 | import org.slf4j.*; 9 | import org.springframework.data.domain.*; 10 | import org.springframework.stereotype.*; 11 | 12 | import com.pluralsight.orderfulfillment.catalog.*; 13 | import com.pluralsight.orderfulfillment.customer.*; 14 | import com.pluralsight.orderfulfillment.order.fulfillment.*; 15 | 16 | /** 17 | * Services related to orders 18 | * 19 | * @author Michael Hoffman, Pluralsight 20 | * 21 | */ 22 | @Transactional 23 | @Service 24 | public class DefaultOrderService implements OrderService { 25 | private static final Logger log = LoggerFactory 26 | .getLogger(DefaultOrderService.class); 27 | 28 | @Inject 29 | private OrderRepository orderRepository; 30 | 31 | @Inject 32 | private OrderItemRepository orderItemRepository; 33 | 34 | @Inject 35 | private FulfillmentProcessor fulfillmentProcessor; 36 | 37 | @Override 38 | public List getOrderDetails() { 39 | List orders = new ArrayList(); 40 | 41 | try { 42 | populateOrderDetails(orders, orderRepository.findAll()); 43 | } catch (Exception e) { 44 | log.error( 45 | "An error occurred while retrieving all orders: " 46 | + e.getMessage(), e); 47 | } 48 | 49 | return orders; 50 | } 51 | 52 | @Override 53 | public void processOrderFulfillment() { 54 | try { 55 | fulfillmentProcessor.run(); 56 | } catch (Exception e) { 57 | log.error( 58 | "An error occurred during the execution of order fulfillment processing: " 59 | + e.getMessage(), e); 60 | } 61 | } 62 | 63 | @Override 64 | public List getOrderDetails(OrderStatus orderStatus, int fetchSize) { 65 | List orders = new ArrayList(); 66 | 67 | try { 68 | populateOrderDetails(orders, orderRepository.findByStatus( 69 | orderStatus.getCode(), new PageRequest(0, fetchSize))); 70 | } catch (Exception e) { 71 | log.error("An error occurred while getting orders by order status: " 72 | + e.getMessage(), e); 73 | } 74 | 75 | return orders; 76 | } 77 | 78 | @Transactional(rollbackOn = Exception.class) 79 | @Override 80 | public void processOrderStatusUpdate(List orders, 81 | OrderStatus orderStatus) throws Exception { 82 | List orderIds = new ArrayList(); 83 | for (Order order : orders) { 84 | orderIds.add(order.getId()); 85 | } 86 | orderRepository.updateStatus(orderStatus.getCode(), 87 | new Date(System.currentTimeMillis()), orderIds); 88 | orderItemRepository.updateStatus(orderStatus.getCode(), 89 | new Date(System.currentTimeMillis()), orderIds); 90 | for (Order order : orders) { 91 | order.setStatus(orderStatus.getCode()); 92 | } 93 | } 94 | 95 | @Override 96 | public List getOrderItems(long id) { 97 | List orderItems = new ArrayList(); 98 | 99 | try { 100 | List orderItemEntities = orderItemRepository 101 | .findByOrderId(id); 102 | populateOrderItems(orderItems, orderItemEntities); 103 | } catch (Exception e) { 104 | log.error( 105 | "An error occurred while retrieving order items for the order id |" 106 | + id + "|: " + e.getMessage(), e); 107 | } 108 | return orderItems; 109 | } 110 | 111 | /** 112 | * Populate the list of orders based on order entity details. 113 | * 114 | * @param orders 115 | * @param orderEntities 116 | */ 117 | private void populateOrderDetails(List orders, 118 | Iterable orderEntities) { 119 | for (Iterator iterator = orderEntities.iterator(); iterator 120 | .hasNext();) { 121 | OrderEntity entity = iterator.next(); 122 | CustomerEntity customerEntity = entity.getCustomer(); 123 | Customer customer = new Customer(customerEntity.getId(), 124 | customerEntity.getFirstName(), customerEntity.getLastName(), 125 | customerEntity.getEmail()); 126 | orders.add(new Order(entity.getId(), customer, 127 | entity.getOrderNumber(), entity.getTimeOrderPlaced(), entity 128 | .getLastUpdate(), OrderStatus.getOrderStatusByCode( 129 | entity.getStatus()).getDescription())); 130 | } 131 | } 132 | 133 | private void populateOrderItems(List orderItems, 134 | Iterable orderItemEntities) { 135 | for (Iterator iterator = orderItemEntities.iterator(); iterator 136 | .hasNext();) { 137 | OrderItemEntity entity = iterator.next(); 138 | CatalogItemEntity catalogItemEntity = entity.getCatalogItem(); 139 | CatalogItem catalogItem = new CatalogItem(catalogItemEntity.getId(), 140 | catalogItemEntity.getItemNumber(), 141 | catalogItemEntity.getItemName(), catalogItemEntity.getItemType()); 142 | orderItems.add(new OrderItem(entity.getId(), catalogItem, entity 143 | .getStatus(), entity.getPrice(), entity.getLastUpdate(), entity 144 | .getQuantity())); 145 | } 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/Order.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order; 2 | 3 | import java.util.*; 4 | 5 | import com.pluralsight.orderfulfillment.customer.*; 6 | 7 | /** 8 | * Domain object for an Order 9 | * 10 | * @author Michael Hoffman, Pluralsight 11 | * 12 | */ 13 | public class Order { 14 | private long id; 15 | private Customer customer; 16 | private String orderNumber; 17 | private Date timeOrderPlaced; 18 | private Date lastUpdate; 19 | private String status; 20 | 21 | public Order() { 22 | 23 | } 24 | 25 | public Order(long id, Customer customer, String orderNumber, 26 | Date timeOrderPlaced, Date lastUpdate, String status) { 27 | super(); 28 | this.id = id; 29 | this.customer = customer; 30 | this.orderNumber = orderNumber; 31 | this.timeOrderPlaced = timeOrderPlaced; 32 | this.lastUpdate = lastUpdate; 33 | this.status = status; 34 | } 35 | 36 | /** 37 | * @return the id 38 | */ 39 | public long getId() { 40 | return id; 41 | } 42 | 43 | /** 44 | * @param id 45 | * the id to set 46 | */ 47 | public void setId(long id) { 48 | this.id = id; 49 | } 50 | 51 | /** 52 | * @return the customer 53 | */ 54 | public Customer getCustomer() { 55 | return customer; 56 | } 57 | 58 | /** 59 | * @param customer 60 | * the customer to set 61 | */ 62 | public void setCustomer(Customer customer) { 63 | this.customer = customer; 64 | } 65 | 66 | /** 67 | * @return the orderNumber 68 | */ 69 | public String getOrderNumber() { 70 | return orderNumber; 71 | } 72 | 73 | /** 74 | * @param orderNumber 75 | * the orderNumber to set 76 | */ 77 | public void setOrderNumber(String orderNumber) { 78 | this.orderNumber = orderNumber; 79 | } 80 | 81 | /** 82 | * @return the timeOrderPlaced 83 | */ 84 | public Date getTimeOrderPlaced() { 85 | return timeOrderPlaced; 86 | } 87 | 88 | /** 89 | * @param timeOrderPlaced 90 | * the timeOrderPlaced to set 91 | */ 92 | public void setTimeOrderPlaced(Date timeOrderPlaced) { 93 | this.timeOrderPlaced = timeOrderPlaced; 94 | } 95 | 96 | /** 97 | * @return the lastUpdate 98 | */ 99 | public Date getLastUpdate() { 100 | return lastUpdate; 101 | } 102 | 103 | /** 104 | * @param lastUpdate 105 | * the lastUpdate to set 106 | */ 107 | public void setLastUpdate(Date lastUpdate) { 108 | this.lastUpdate = lastUpdate; 109 | } 110 | 111 | /** 112 | * @return the status 113 | */ 114 | public String getStatus() { 115 | return status; 116 | } 117 | 118 | /** 119 | * @param status 120 | * the status to set 121 | */ 122 | public void setStatus(String status) { 123 | this.status = status; 124 | } 125 | 126 | /* 127 | * (non-Javadoc) 128 | * 129 | * @see java.lang.Object#toString() 130 | */ 131 | @Override 132 | public String toString() { 133 | StringBuilder builder = new StringBuilder(); 134 | builder.append("Order [id="); 135 | builder.append(id); 136 | builder.append(", "); 137 | if (customer != null) { 138 | builder.append("customer="); 139 | builder.append(customer); 140 | builder.append(", "); 141 | } 142 | if (orderNumber != null) { 143 | builder.append("orderNumber="); 144 | builder.append(orderNumber); 145 | builder.append(", "); 146 | } 147 | if (timeOrderPlaced != null) { 148 | builder.append("timeOrderPlaced="); 149 | builder.append(timeOrderPlaced); 150 | builder.append(", "); 151 | } 152 | if (lastUpdate != null) { 153 | builder.append("lastUpdate="); 154 | builder.append(lastUpdate); 155 | builder.append(", "); 156 | } 157 | if (status != null) { 158 | builder.append("status="); 159 | builder.append(status); 160 | builder.append(", "); 161 | } 162 | builder.append("]"); 163 | return builder.toString(); 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/OrderController.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order; 2 | 3 | import java.util.*; 4 | 5 | import javax.inject.*; 6 | 7 | import org.slf4j.*; 8 | import org.springframework.stereotype.*; 9 | import org.springframework.ui.*; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | /** 13 | * Controller for order-related requests 14 | * 15 | * @author Michael Hoffman, Pluralsight 16 | * 17 | */ 18 | @Controller 19 | public class OrderController { 20 | 21 | private static final Logger log = LoggerFactory 22 | .getLogger(OrderController.class); 23 | 24 | @Inject 25 | private OrderService orderService; 26 | 27 | /** 28 | * Render the home page for order fulfillment. 29 | * 30 | * @return String 31 | */ 32 | @RequestMapping(value = "/orderHome") 33 | public String orderHome() { 34 | return "orderHome"; 35 | } 36 | 37 | /** 38 | * Render the page that supports running the order fulfillment processor 39 | * 40 | * @return String 41 | */ 42 | @RequestMapping(value = "/processOrders", method = RequestMethod.GET) 43 | public String processOrdersRender() { 44 | return "processOrders"; 45 | } 46 | 47 | /** 48 | * Execute order processing, than show the list of orders on the view orders 49 | * page. 50 | * 51 | * @param model 52 | * @return String 53 | */ 54 | @RequestMapping(value = "/processOrders", method = RequestMethod.POST) 55 | public String processOrders(Model model) { 56 | orderService.processOrderFulfillment(); 57 | model.addAttribute("orders", orderService.getOrderDetails()); 58 | return "viewOrders"; 59 | } 60 | 61 | /** 62 | * Render the page that supports resetting the order status of orders that 63 | * ran through fulfillment. 64 | * 65 | * @return String 66 | */ 67 | @RequestMapping(value = "/resetOrders", method = RequestMethod.GET) 68 | public String resetOrdersRender() { 69 | return "resetOrders"; 70 | } 71 | 72 | /** 73 | * Processes the resetting of orders fulfilled by order fulfillment. 74 | * 75 | * @param model 76 | * @return 77 | */ 78 | @RequestMapping(value = "/resetOrders", method = RequestMethod.POST) 79 | public String resetOrders(Model model) { 80 | List orders = orderService.getOrderDetails(OrderStatus.PROCESSING, 81 | 100); 82 | try { 83 | orderService.processOrderStatusUpdate(orders, OrderStatus.NEW); 84 | } catch (Exception e) { 85 | log.error( 86 | "An error occurred while resetting orders: " + e.getMessage(), e); 87 | } 88 | model.addAttribute("orders", orderService.getOrderDetails()); 89 | return "viewOrders"; 90 | } 91 | 92 | /** 93 | * Builds the list of order details in the database to present in the view. 94 | * 95 | * @param model 96 | * @return String 97 | */ 98 | @RequestMapping(value = "/viewOrders", method = RequestMethod.GET) 99 | public String viewOrders(Model model) { 100 | model.addAttribute("orders", orderService.getOrderDetails()); 101 | return "viewOrders"; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/OrderEntity.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | 6 | import javax.persistence.*; 7 | 8 | import com.pluralsight.orderfulfillment.customer.*; 9 | 10 | /** 11 | * Order entity 12 | * 13 | * @author Michael Hoffman, Pluralsight 14 | * 15 | */ 16 | @Entity 17 | @Table(name = "order") 18 | @SequenceGenerator(name = "order_id_seq", sequenceName = "order_id_seq") 19 | public class OrderEntity implements Serializable { 20 | 21 | private static final long serialVersionUID = -8239299025198163223L; 22 | 23 | private long id; 24 | private CustomerEntity customer; 25 | private String orderNumber; 26 | private Date timeOrderPlaced; 27 | private Date lastUpdate; 28 | private String status; 29 | private Set orderItems = new HashSet(0); 30 | 31 | public OrderEntity() { 32 | 33 | } 34 | 35 | public OrderEntity(long id, CustomerEntity customer, String orderNumber, 36 | Date timeOrderPlaced, Date lastUpdate, String status) { 37 | this.id = id; 38 | this.customer = customer; 39 | this.orderNumber = orderNumber; 40 | this.timeOrderPlaced = timeOrderPlaced; 41 | this.lastUpdate = lastUpdate; 42 | this.status = status; 43 | } 44 | 45 | public OrderEntity(long id, CustomerEntity customer, String orderNumber, 46 | Date timeOrderPlaced, Date lastUpdate, String status, Set orderItems) { 47 | this.id = id; 48 | this.customer = customer; 49 | this.orderNumber = orderNumber; 50 | this.timeOrderPlaced = timeOrderPlaced; 51 | this.lastUpdate = lastUpdate; 52 | this.status = status; 53 | this.orderItems = orderItems; 54 | } 55 | 56 | /** 57 | * @return the id 58 | */ 59 | @Id 60 | @Column(name = "id") 61 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "order_id_seq") 62 | public long getId() { 63 | return id; 64 | } 65 | 66 | /** 67 | * @param id 68 | * the id to set 69 | */ 70 | public void setId(long id) { 71 | this.id = id; 72 | } 73 | 74 | /** 75 | * @return the customer 76 | */ 77 | @ManyToOne(fetch = FetchType.LAZY) 78 | @JoinColumn(name = "customer_id", nullable = false) 79 | public CustomerEntity getCustomer() { 80 | return customer; 81 | } 82 | 83 | /** 84 | * @param customer 85 | * the customer to set 86 | */ 87 | public void setCustomer(CustomerEntity customer) { 88 | this.customer = customer; 89 | } 90 | 91 | /** 92 | * @return the orderNumber 93 | */ 94 | @Column(name = "orderNumber", nullable = false) 95 | public String getOrderNumber() { 96 | return orderNumber; 97 | } 98 | 99 | /** 100 | * @param orderNumber 101 | * the orderNumber to set 102 | */ 103 | public void setOrderNumber(String orderNumber) { 104 | this.orderNumber = orderNumber; 105 | } 106 | 107 | /** 108 | * @return the timeOrderPlaced 109 | */ 110 | @Temporal(TemporalType.TIMESTAMP) 111 | @Column(name = "timeOrderPlaced", nullable = false, length = 29) 112 | public Date getTimeOrderPlaced() { 113 | return timeOrderPlaced; 114 | } 115 | 116 | /** 117 | * @param timeOrderPlaced 118 | * the timeOrderPlaced to set 119 | */ 120 | public void setTimeOrderPlaced(Date timeOrderPlaced) { 121 | this.timeOrderPlaced = timeOrderPlaced; 122 | } 123 | 124 | /** 125 | * @return the lastUpdate 126 | */ 127 | @Temporal(TemporalType.TIMESTAMP) 128 | @Column(name = "lastUpdate", nullable = false, length = 29) 129 | public Date getLastUpdate() { 130 | return lastUpdate; 131 | } 132 | 133 | /** 134 | * @param lastUpdate 135 | * the lastUpdate to set 136 | */ 137 | public void setLastUpdate(Date lastUpdate) { 138 | this.lastUpdate = lastUpdate; 139 | } 140 | 141 | /** 142 | * @return the status 143 | */ 144 | @Column(name = "status", nullable = false) 145 | public String getStatus() { 146 | return status; 147 | } 148 | 149 | /** 150 | * @param status 151 | * the status to set 152 | */ 153 | public void setStatus(String status) { 154 | this.status = status; 155 | } 156 | 157 | /** 158 | * @return the orderItems 159 | */ 160 | @OneToMany(fetch = FetchType.LAZY, mappedBy = "order") 161 | public Set getOrderItems() { 162 | return orderItems; 163 | } 164 | 165 | /** 166 | * @param orderItems 167 | * the orderItems to set 168 | */ 169 | public void setOrderItems(Set orderItems) { 170 | this.orderItems = orderItems; 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/OrderItem.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order; 2 | 3 | import java.io.*; 4 | import java.math.*; 5 | import java.util.*; 6 | 7 | import com.pluralsight.orderfulfillment.catalog.*; 8 | 9 | public class OrderItem implements Serializable { 10 | 11 | private static final long serialVersionUID = 8218385047375857766L; 12 | 13 | private long id; 14 | private CatalogItem catalogItem; 15 | private String status; 16 | private BigDecimal price; 17 | private Date lastUpdate; 18 | private int quantity; 19 | 20 | public OrderItem() { 21 | 22 | } 23 | 24 | public OrderItem(long id, CatalogItem catalogItem, String status, BigDecimal price, 25 | Date lastUpdate, int quantity) { 26 | super(); 27 | this.id = id; 28 | this.catalogItem = catalogItem; 29 | this.status = status; 30 | this.price = price; 31 | this.lastUpdate = lastUpdate; 32 | this.quantity = quantity; 33 | } 34 | 35 | /** 36 | * @return the id 37 | */ 38 | public long getId() { 39 | return id; 40 | } 41 | 42 | /** 43 | * @param id 44 | * the id to set 45 | */ 46 | public void setId(long id) { 47 | this.id = id; 48 | } 49 | 50 | /** 51 | * @return the catalogItem 52 | */ 53 | public CatalogItem getCatalogItem() { 54 | return catalogItem; 55 | } 56 | 57 | /** 58 | * @param catalogItem 59 | * the catalogItem to set 60 | */ 61 | public void setCatalogItem(CatalogItem catalogItem) { 62 | this.catalogItem = catalogItem; 63 | } 64 | 65 | /** 66 | * @return the status 67 | */ 68 | public String getStatus() { 69 | return status; 70 | } 71 | 72 | /** 73 | * @param status 74 | * the status to set 75 | */ 76 | public void setStatus(String status) { 77 | this.status = status; 78 | } 79 | 80 | /** 81 | * @return the price 82 | */ 83 | public BigDecimal getPrice() { 84 | return price; 85 | } 86 | 87 | /** 88 | * @param price 89 | * the price to set 90 | */ 91 | public void setPrice(BigDecimal price) { 92 | this.price = price; 93 | } 94 | 95 | /** 96 | * @return the lastUpdate 97 | */ 98 | public Date getLastUpdate() { 99 | return lastUpdate; 100 | } 101 | 102 | /** 103 | * @param lastUpdate 104 | * the lastUpdate to set 105 | */ 106 | public void setLastUpdate(Date lastUpdate) { 107 | this.lastUpdate = lastUpdate; 108 | } 109 | 110 | /** 111 | * @return the quantity 112 | */ 113 | public int getQuantity() { 114 | return quantity; 115 | } 116 | 117 | /** 118 | * @param quantity 119 | * the quantity to set 120 | */ 121 | public void setQuantity(int quantity) { 122 | this.quantity = quantity; 123 | } 124 | 125 | /* 126 | * (non-Javadoc) 127 | * 128 | * @see java.lang.Object#toString() 129 | */ 130 | @Override 131 | public String toString() { 132 | StringBuilder builder = new StringBuilder(); 133 | builder.append("OrderItem [id="); 134 | builder.append(id); 135 | builder.append(", "); 136 | if (catalogItem != null) { 137 | builder.append("catalogItem="); 138 | builder.append(catalogItem); 139 | builder.append(", "); 140 | } 141 | if (status != null) { 142 | builder.append("status="); 143 | builder.append(status); 144 | builder.append(", "); 145 | } 146 | if (price != null) { 147 | builder.append("price="); 148 | builder.append(price); 149 | builder.append(", "); 150 | } 151 | if (lastUpdate != null) { 152 | builder.append("lastUpdate="); 153 | builder.append(lastUpdate); 154 | builder.append(", "); 155 | } 156 | builder.append("quantity="); 157 | builder.append(quantity); 158 | builder.append("]"); 159 | return builder.toString(); 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/OrderItemEntity.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order; 2 | 3 | import java.io.*; 4 | import java.math.*; 5 | import java.util.*; 6 | 7 | import javax.persistence.*; 8 | 9 | import com.pluralsight.orderfulfillment.catalog.*; 10 | 11 | /** 12 | * Order item entity 13 | * 14 | * @author Michael Hoffman 15 | * 16 | */ 17 | @Entity 18 | @Table(name = "orderItem") 19 | @SequenceGenerator(name = "orderitem_id_seq", sequenceName = "orderitem_id_seq") 20 | public class OrderItemEntity implements Serializable { 21 | 22 | private static final long serialVersionUID = -3950813201243788920L; 23 | 24 | private long id; 25 | private OrderEntity order; 26 | private CatalogItemEntity catalogItem; 27 | private String status; 28 | private BigDecimal price; 29 | private Date lastUpdate; 30 | private int quantity; 31 | 32 | public OrderItemEntity() { 33 | 34 | } 35 | 36 | public OrderItemEntity(long id, OrderEntity order, CatalogItemEntity catalogItem, 37 | String status, Date lastUpdate, int quantity) { 38 | this.id = id; 39 | this.order = order; 40 | this.catalogItem = catalogItem; 41 | this.status = status; 42 | this.lastUpdate = lastUpdate; 43 | this.quantity = quantity; 44 | } 45 | 46 | public OrderItemEntity(long id, OrderEntity order, CatalogItemEntity catalogItem, 47 | String status, Date lastUpdate, int quantity, BigDecimal price) { 48 | this.id = id; 49 | this.order = order; 50 | this.catalogItem = catalogItem; 51 | this.status = status; 52 | this.lastUpdate = lastUpdate; 53 | this.quantity = quantity; 54 | this.price = price; 55 | } 56 | 57 | /** 58 | * @return the id 59 | */ 60 | @Id 61 | @Column(name = "id") 62 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "orderitem_id_seq") 63 | public long getId() { 64 | return id; 65 | } 66 | 67 | /** 68 | * @param id 69 | * the id to set 70 | */ 71 | public void setId(long id) { 72 | this.id = id; 73 | } 74 | 75 | /** 76 | * @return the order 77 | */ 78 | @ManyToOne(fetch = FetchType.LAZY) 79 | @JoinColumn(name = "order_id", nullable = false) 80 | public OrderEntity getOrder() { 81 | return order; 82 | } 83 | 84 | /** 85 | * @param order 86 | * the order to set 87 | */ 88 | public void setOrder(OrderEntity order) { 89 | this.order = order; 90 | } 91 | 92 | /** 93 | * @return the catalogItem 94 | */ 95 | @ManyToOne(fetch = FetchType.LAZY) 96 | @JoinColumn(name = "catalogItem_id", nullable = false) 97 | public CatalogItemEntity getCatalogItem() { 98 | return catalogItem; 99 | } 100 | 101 | /** 102 | * @param catalogItem 103 | * the catalogItem to set 104 | */ 105 | public void setCatalogItem(CatalogItemEntity catalogItem) { 106 | this.catalogItem = catalogItem; 107 | } 108 | 109 | /** 110 | * @return the status 111 | */ 112 | @Column(name = "status", nullable = false) 113 | public String getStatus() { 114 | return status; 115 | } 116 | 117 | /** 118 | * @param status 119 | * the status to set 120 | */ 121 | public void setStatus(String status) { 122 | this.status = status; 123 | } 124 | 125 | /** 126 | * @return the price 127 | */ 128 | @Column(name = "price", precision = 20, scale = 5) 129 | public BigDecimal getPrice() { 130 | return price; 131 | } 132 | 133 | /** 134 | * @param price 135 | * the price to set 136 | */ 137 | public void setPrice(BigDecimal price) { 138 | this.price = price; 139 | } 140 | 141 | /** 142 | * @return the lastUpdate 143 | */ 144 | @Temporal(TemporalType.TIMESTAMP) 145 | @Column(name = "lastUpdate", nullable = false, length = 29) 146 | public Date getLastUpdate() { 147 | return lastUpdate; 148 | } 149 | 150 | /** 151 | * @param lastUpdate 152 | * the lastUpdate to set 153 | */ 154 | public void setLastUpdate(Date lastUpdate) { 155 | this.lastUpdate = lastUpdate; 156 | } 157 | 158 | /** 159 | * @return the quantity 160 | */ 161 | @Column(name = "quantity", nullable = false) 162 | public int getQuantity() { 163 | return quantity; 164 | } 165 | 166 | /** 167 | * @param quantity 168 | * the quantity to set 169 | */ 170 | public void setQuantity(int quantity) { 171 | this.quantity = quantity; 172 | } 173 | 174 | } 175 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/OrderItemRepository.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order; 2 | 3 | import java.util.*; 4 | 5 | import org.springframework.data.jpa.repository.*; 6 | 7 | /** 8 | * Repository for OrderItemEntity data. 9 | * 10 | * @author Michael Hoffman, Pluralsight 11 | * 12 | */ 13 | public interface OrderItemRepository extends 14 | JpaRepository { 15 | 16 | @Query("select oi from OrderItemEntity oi where oi.order.id = ?1") 17 | List findByOrderId(long orderId); 18 | 19 | @Modifying 20 | @Query("update OrderItemEntity oi set oi.status = ?1, oi.lastUpdate = ?2 where oi.order.id in (?3)") 21 | int updateStatus(String code, Date lastUpdate, List orderIds); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/OrderRepository.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order; 2 | 3 | import java.util.*; 4 | 5 | import org.springframework.data.domain.*; 6 | import org.springframework.data.jpa.repository.*; 7 | import org.springframework.data.repository.*; 8 | 9 | /** 10 | * Repository for OrderEntity data. 11 | * 12 | * @author Michael Hoffman, Pluralsight 13 | * 14 | */ 15 | public interface OrderRepository extends 16 | PagingAndSortingRepository { 17 | 18 | /** 19 | * Select all orders for the page ordered by the timeOrderPlaced value in 20 | * ascending order. 21 | * 22 | * @param status 23 | * @param pageable 24 | * @return 25 | */ 26 | @Query(value = "select o from OrderEntity o where o.status = ?1 order by o.timeOrderPlaced") 27 | Page findByStatus(String status, Pageable pageable); 28 | 29 | /** 30 | * Update the status of all order IDs passed. 31 | * 32 | * @param code 33 | * @param orderIds 34 | * @return 35 | */ 36 | @Modifying 37 | @Query("update OrderEntity o set o.status = ?1, o.lastUpdate = ?2 where o.id in (?3)") 38 | int updateStatus(String code, Date lastUpdate, List orderIds); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * Interface for order functionality 7 | * 8 | * @author Michael Hoffman, Pluralsight 9 | * 10 | */ 11 | public interface OrderService { 12 | 13 | /** 14 | * Returns the details of the order without the order items. 15 | * 16 | * @return List 17 | */ 18 | List getOrderDetails(); 19 | 20 | /** 21 | * Returns the order details of the order without the order item for the 22 | * status passed. The result size is limited based on the fetch size passed. 23 | * 24 | * @param OrderStatus 25 | * orderStatus 26 | * @param int fetchSize 27 | * @return List 28 | */ 29 | List getOrderDetails(OrderStatus orderStatus, int fetchSize); 30 | 31 | /** 32 | * Executes the business task of order fulfillment 33 | */ 34 | void processOrderFulfillment(); 35 | 36 | /** 37 | * Updates the order status of one or more orders. Also will update the list 38 | * of orders passed to match the status passed. 39 | * 40 | * @param orders 41 | * @param orderStatus 42 | */ 43 | void processOrderStatusUpdate(List orders, OrderStatus orderStatus) 44 | throws Exception; 45 | 46 | /** 47 | * Retrieves the order items for an order. 48 | * 49 | * @param id 50 | * @return List 51 | */ 52 | List getOrderItems(long id); 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/OrderStatus.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order; 2 | 3 | import org.apache.commons.lang3.*; 4 | 5 | /** 6 | * Key and value for order statuses. 7 | * 8 | * @author Michael Hoffman, Pluralsight 9 | * 10 | */ 11 | public enum OrderStatus { 12 | 13 | NEW("N", "New"), PROCESSING("P", "Processing"); 14 | 15 | private String code; 16 | private String description; 17 | 18 | private OrderStatus(String code, String description) { 19 | this.code = code; 20 | this.description = description; 21 | } 22 | 23 | /** 24 | * @return the code 25 | */ 26 | public String getCode() { 27 | return code; 28 | } 29 | 30 | /** 31 | * @return the description 32 | */ 33 | public String getDescription() { 34 | return description; 35 | } 36 | 37 | public static OrderStatus getOrderStatusByCode(String code) { 38 | OrderStatus orderStatus = null; 39 | if (StringUtils.isNotBlank(code)) { 40 | for (OrderStatus status : OrderStatus.values()) { 41 | if (status.getCode().equals(code)) { 42 | orderStatus = status; 43 | break; 44 | } 45 | } 46 | } 47 | return orderStatus; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/fulfillment/FulfillmentCommand.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order.fulfillment; 2 | 3 | /** 4 | * Interface for all commands that handle order fulfillment processing. 5 | * 6 | * @author Michael Hoffman, Pluralsight 7 | */ 8 | public interface FulfillmentCommand { 9 | 10 | void execute(FulfillmentContext context); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/fulfillment/FulfillmentContext.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order.fulfillment; 2 | 3 | import java.util.*; 4 | 5 | import com.pluralsight.orderfulfillment.order.*; 6 | 7 | /** 8 | * Context object that will be passed to various commands for processing order 9 | * fulfillment. 10 | * 11 | * @author Michael Hoffman, Pluralsight 12 | * 13 | */ 14 | public class FulfillmentContext { 15 | 16 | private String fulfillmentCenter1FileName; 17 | private String fulfillmentCenter1OutboundFolder; 18 | private List orderDetails; 19 | 20 | /** 21 | * Default constructor 22 | */ 23 | public FulfillmentContext() { 24 | 25 | } 26 | 27 | /** 28 | * @return the orderDetails 29 | */ 30 | public List getOrderDetails() { 31 | return orderDetails; 32 | } 33 | 34 | /** 35 | * @param orderDetails 36 | * the orderDetails to set 37 | */ 38 | public void setOrderDetails(List orderDetails) { 39 | this.orderDetails = orderDetails; 40 | } 41 | 42 | /** 43 | * @return the fulfillmentCenter1OutboundFolder 44 | */ 45 | public String getFulfillmentCenter1OutboundFolder() { 46 | return fulfillmentCenter1OutboundFolder; 47 | } 48 | 49 | /** 50 | * @param fulfillmentCenter1OutboundFolder 51 | * the fulfillmentCenter1OutboundFolder to set 52 | */ 53 | public void setFulfillmentCenter1OutboundFolder( 54 | String fulfillmentCenter1OutboundFolder) { 55 | this.fulfillmentCenter1OutboundFolder = fulfillmentCenter1OutboundFolder; 56 | } 57 | 58 | /** 59 | * @return the fulfillmentCenter1FileName 60 | */ 61 | public String getFulfillmentCenter1FileName() { 62 | return fulfillmentCenter1FileName; 63 | } 64 | 65 | /** 66 | * @param fulfillmentCenter1FileName 67 | * the fulfillmentCenter1FileName to set 68 | */ 69 | public void setFulfillmentCenter1FileName(String fulfillmentCenter1FileName) { 70 | this.fulfillmentCenter1FileName = fulfillmentCenter1FileName; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/fulfillment/FulfillmentProcessor.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order.fulfillment; 2 | 3 | import javax.inject.Inject; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Qualifier; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * This is the entry point for order fulfillment processing. It provides a 12 | * single method for orchestrating the fulfillment process. Execution is started 13 | * by a scheduler or direct calls. 14 | * 15 | * @author Michael Hoffman, Pluralsight 16 | * 17 | */ 18 | @Component 19 | public class FulfillmentProcessor { 20 | 21 | private static final Logger log = LoggerFactory 22 | .getLogger(FulfillmentProcessor.class); 23 | 24 | @Inject 25 | @Qualifier("newOrderRetrievalCommand") 26 | private FulfillmentCommand newOrderRetrievalCommand; 27 | 28 | @Inject 29 | @Qualifier("newOrderSendToFulfillmentCenterOneCommand") 30 | private FulfillmentCommand newOrderSendToFulfillmentCenterOneCommand; 31 | 32 | /** 33 | * Orchestrates order fulfillment. 34 | */ 35 | public void run() { 36 | // 1 - Build a context to be passed into each of the commands 37 | FulfillmentContext context = new FulfillmentContext(); 38 | 39 | // 2 - Call the order retrieval command to discover what orders need to be 40 | // fulfilled. New orders will be added to the context. 41 | newOrderRetrievalCommand.execute(context); 42 | 43 | // 3 - Call the order fulfill command to fulfill new orders through 44 | // fulfillment center 1. 45 | newOrderSendToFulfillmentCenterOneCommand.execute(context); 46 | } 47 | 48 | /** 49 | * @param newOrderRetrievalCommand 50 | * the newOrderRetrievalCommand to set 51 | */ 52 | public void setNewOrderRetrievalCommand( 53 | FulfillmentCommand newOrderRetrievalCommand) { 54 | this.newOrderRetrievalCommand = newOrderRetrievalCommand; 55 | } 56 | 57 | /** 58 | * @param newOrderSendToFulfillmentCenterOneCommand 59 | * the newOrderSendToFulfillmentCenterOneCommand to set 60 | */ 61 | public void setNewOrderSendToFulfillmentCenterOneCommand( 62 | FulfillmentCommand newOrderSendToFulfillmentCenterOneCommand) { 63 | this.newOrderSendToFulfillmentCenterOneCommand = newOrderSendToFulfillmentCenterOneCommand; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/fulfillment/NewOrderRetrievalCommand.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order.fulfillment; 2 | 3 | import java.util.*; 4 | 5 | import javax.inject.*; 6 | 7 | import org.slf4j.*; 8 | import org.springframework.core.env.*; 9 | import org.springframework.stereotype.*; 10 | 11 | import com.pluralsight.orderfulfillment.order.*; 12 | 13 | /** 14 | * Command to retrieve the next set of orders for processing. This includes 15 | * selecting the orders, updating their status and putting them into the 16 | * context. 17 | * 18 | * @author Michael Hoffman, Pluralsight 19 | * 20 | */ 21 | @Component("newOrderRetrievalCommand") 22 | public class NewOrderRetrievalCommand implements FulfillmentCommand { 23 | 24 | private static final Logger log = LoggerFactory 25 | .getLogger(NewOrderRetrievalCommand.class); 26 | 27 | @Inject 28 | private Environment environment; 29 | 30 | @Inject 31 | private OrderService orderService; 32 | 33 | /* 34 | * (non-Javadoc) 35 | * 36 | * @see 37 | * com.pluralsight.orderfulfillment.order.FulfillmentCommand#execute(com. 38 | * pluralsight.orderfulfillment.order.FulfillmentContext) 39 | */ 40 | @Override 41 | public void execute(FulfillmentContext context) { 42 | // 1 - Load the context 43 | try { 44 | loadContext(context); 45 | } catch (Exception e) { 46 | log.error( 47 | "An error occurred while retrieving new orders: " 48 | + e.getMessage(), e); 49 | } 50 | } 51 | 52 | /** 53 | * Populate the context for this run of order fulfillment 54 | * 55 | * @param context 56 | */ 57 | private void loadContext(FulfillmentContext context) throws Exception { 58 | // 1 - Determine how many orders we process at a time 59 | int fetchSize = Integer.parseInt(environment 60 | .getProperty("neworderretrievalcommand.fetchsize")); 61 | 62 | // 2 - Get the order details for new orders. This will retrieve the next 63 | // five order entries in order of the time it was placed. 64 | List newOrders = orderService.getOrderDetails(OrderStatus.NEW, 65 | fetchSize); 66 | 67 | // 3 - Mark the orders as in progress so they are not retrieved again by a 68 | // new processor. 69 | orderService.processOrderStatusUpdate(newOrders, OrderStatus.PROCESSING); 70 | 71 | // 4 - Now update the context 72 | context.setOrderDetails(newOrders); 73 | context.setFulfillmentCenter1OutboundFolder(environment 74 | .getProperty("order.fulfillment.center.1.outbound.folder")); 75 | context.setFulfillmentCenter1FileName(environment 76 | .getProperty("order.fulfillment.center.1.filename")); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/pluralsight/orderfulfillment/order/fulfillment/NewOrderSendToFulfillmentCenterOneCommand.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order.fulfillment; 2 | 3 | import java.io.*; 4 | import java.text.*; 5 | import java.util.*; 6 | 7 | import javax.inject.*; 8 | 9 | import org.slf4j.*; 10 | import org.springframework.stereotype.*; 11 | 12 | import au.com.bytecode.opencsv.*; 13 | 14 | import com.pluralsight.orderfulfillment.order.*; 15 | 16 | /** 17 | * Command that fulfills the new orders in context by sending them as an SSH 18 | * file. 19 | * 20 | * @author Michael Hoffman 21 | * 22 | */ 23 | @Component("newOrderSendToFulfillmentCenterOneCommand") 24 | public class NewOrderSendToFulfillmentCenterOneCommand implements 25 | FulfillmentCommand { 26 | 27 | private static final Logger log = LoggerFactory 28 | .getLogger(NewOrderSendToFulfillmentCenterOneCommand.class); 29 | 30 | @Inject 31 | private OrderService orderService; 32 | 33 | @Override 34 | public void execute(FulfillmentContext context) { 35 | final List orderFulfillmentLines = new ArrayList(); 36 | 37 | // 1 - Build the content to send for fulfillment using the orders in 38 | // context 39 | buildOrderFulfillmentLines(orderFulfillmentLines, 40 | context.getOrderDetails()); 41 | 42 | // 2 - Write the lines out to the file 43 | writeOrderFulfillmentLines(orderFulfillmentLines, 44 | context.getFulfillmentCenter1OutboundFolder(), 45 | context.getFulfillmentCenter1FileName()); 46 | } 47 | 48 | private void buildOrderFulfillmentLines( 49 | List orderFulfillmentLines, List orderDetails) { 50 | // 1 - Iterate the orders 51 | for (Order order : orderDetails) { 52 | // 2 - Get the order items for the order 53 | List orderItems = orderService.getOrderItems(order.getId()); 54 | 55 | // 3 - Build the order fulfillment line 56 | for (OrderItem orderItem : orderItems) { 57 | orderFulfillmentLines.add(buildOrderFulfillmentLine(order, 58 | orderItem)); 59 | } 60 | } 61 | } 62 | 63 | /** 64 | * Builds a string array of the contents for an order fulfillment line. The 65 | * schema is as follows: 66 | * 67 | *
    68 | *
  • [0] = order number from order (not unique ID from database)
  • 69 | *
  • [1] = time the order was placed in the format yyyy.MM.dd HH:mm:ss z
  • 70 | *
  • [2] = the catalog item number, usually the SKU
  • 71 | *
  • [3] = the price
  • 72 | *
  • [4] = the quantity
  • 73 | * 74 | * @param order 75 | * @param orderItem 76 | * @return 77 | */ 78 | private String[] buildOrderFulfillmentLine(Order order, OrderItem orderItem) { 79 | // 1 - Build the array of data needed for the fulfillment center 1 schema 80 | final String[] line = new String[5]; 81 | line[0] = order.getOrderNumber(); 82 | line[1] = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z").format(order 83 | .getTimeOrderPlaced()); 84 | line[2] = orderItem.getCatalogItem().getItemNumber(); 85 | line[3] = NumberFormat.getCurrencyInstance(Locale.US).format( 86 | orderItem.getPrice().doubleValue()); 87 | line[4] = Integer.toString(orderItem.getQuantity()); 88 | return line; 89 | } 90 | 91 | /** 92 | * Writes the orders out to a file. 93 | * 94 | * @param orderFulfillmentLines 95 | * @param fulfillmentCenter1OutboundFolder 96 | * @param fulfillmentCenter1FileName 97 | */ 98 | private void writeOrderFulfillmentLines( 99 | List orderFulfillmentLines, 100 | String fulfillmentCenter1OutboundFolder, 101 | String fulfillmentCenter1FileName) { 102 | CSVWriter writer = null; 103 | try { 104 | String filePath = fulfillmentCenter1OutboundFolder 105 | + "/" 106 | + fulfillmentCenter1FileName 107 | + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date(System 108 | .currentTimeMillis())) + ".csv"; 109 | File file = new File(filePath); 110 | if (!file.exists()) { 111 | file.createNewFile(); 112 | } 113 | writer = new CSVWriter(new FileWriter(file)); 114 | writer.writeAll(orderFulfillmentLines); 115 | } catch (Exception e) { 116 | log.error( 117 | "An error occurred while writing out to a file for fulfillment center 1: " 118 | + e.getMessage(), e); 119 | } finally { 120 | if (writer != null) { 121 | try { 122 | writer.close(); 123 | } catch (Exception e) { 124 | } 125 | } 126 | } 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/main/resources/log4j.dtd: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 58 | 59 | 60 | 61 | 62 | 65 | 69 | 70 | 71 | 74 | 75 | 76 | 79 | 80 | 81 | 82 | 83 | 84 | 87 | 88 | 89 | 90 | 91 | 94 | 95 | 96 | 100 | 101 | 102 | 103 | 104 | 108 | 109 | 110 | 111 | 115 | 116 | 117 | 118 | 119 | 120 | 125 | 126 | 127 | 128 | 129 | 133 | 134 | 135 | 136 | 138 | 139 | 140 | 142 | 143 | 144 | 147 | 148 | 149 | 150 | 154 | 155 | 156 | 159 | 160 | 161 | 164 | 165 | 166 | 170 | 171 | 172 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 193 | 194 | 195 | 196 | 198 | 199 | 200 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 220 | 221 | 222 | 223 | 224 | 228 | -------------------------------------------------------------------------------- /src/main/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/resources/order-fulfillment.properties: -------------------------------------------------------------------------------- 1 | #### ORDER FULFILLMENT APP PROPERTIES #### 2 | 3 | # Database 4 | db.driver=org.postgresql.Driver 5 | db.url=jdbc:postgresql://localhost:5432/orders 6 | db.user=orders 7 | db.password=orders 8 | hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect 9 | hibernate.jdbc.batch_size=10 10 | hibernate.default_schema=orders 11 | 12 | # Order retrieval settings 13 | neworderretrievalcommand.fetchsize=5 14 | 15 | # Order fulfillment center 1 16 | order.fulfillment.center.1.outbound.folder=c:/dev/fulfillmentcenter1/out 17 | order.fulfillment.center.1.inbound.folder=c:/dev/fulfillmentcenter1/in 18 | order.fulfillment.center.1.filename=fulfillmentcenter1 19 | -------------------------------------------------------------------------------- /src/main/sql/hibernate.reveng.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/sql/postgresql/ddl/create-orders-db.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * PostgreSQL DML for creating the role and database for Pluralsight's 3 | * course Apache Camel Introduction to Integration. This should be run 4 | * for initial setup or when the database needs to be re-loaded. 5 | */ 6 | 7 | -- Role: orders 8 | -- Password: orders 9 | CREATE ROLE orders LOGIN 10 | ENCRYPTED PASSWORD 'md55f038b5aa5a392661ff3a8494829bd9e' 11 | NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION; 12 | COMMENT ON ROLE orders IS 'Orders role'; 13 | 14 | -- Database: orders 15 | CREATE DATABASE orders 16 | WITH OWNER = orders 17 | ENCODING = 'UTF8' 18 | TABLESPACE = pg_default 19 | LC_COLLATE = 'English_United States.1252' 20 | LC_CTYPE = 'English_United States.1252' 21 | CONNECTION LIMIT = -1; 22 | 23 | -- Schema: orders 24 | CREATE SCHEMA orders AUTHORIZATION orders; 25 | -------------------------------------------------------------------------------- /src/main/sql/postgresql/ddl/create-orders.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * PostgreSQL DML for creating the orders database objects for Pluralsight's 3 | * course Apache Camel Introduction to Integration. This should be run 4 | * for initial setup or when the database needs to be re-loaded. 5 | */ 6 | 7 | drop table if exists orders.orderItem; 8 | drop table if exists orders.order; 9 | drop table if exists orders.catalogitem; 10 | drop table if exists orders.customer; 11 | 12 | /* 13 | * Table: Customer 14 | * Description: Contains the customer information 15 | */ 16 | create table orders.customer ( 17 | id bigserial not null, 18 | firstName text not null, 19 | lastName text not null, 20 | email text not null, 21 | primary key (id) 22 | ) tablespace pg_default; 23 | 24 | /* 25 | * Table: CatalogItem 26 | * Description: Contains the catalog item 27 | */ 28 | create table orders.catalogitem ( 29 | id bigserial not null, 30 | itemNumber text not null, 31 | itemName text not null, 32 | itemType text not null, 33 | primary key (id) 34 | ) tablespace pg_default; 35 | 36 | 37 | /* 38 | * Table: Order 39 | * Description: Contains base order details 40 | */ 41 | create table orders.order ( 42 | id bigserial not null, 43 | customer_id bigint not null, 44 | orderNumber text not null, 45 | timeOrderPlaced timestamp not null, 46 | lastUpdate timestamp not null, 47 | status text not null, 48 | primary key (id) 49 | ) tablespace pg_default; 50 | 51 | alter table orders.order add constraint orders_fk_1 foreign key (customer_id) references orders.customer (id); 52 | 53 | create table orders.orderItem ( 54 | id bigserial not null, 55 | order_id bigint not null, 56 | catalogitem_id bigint not null, 57 | status text not null, 58 | price decimal(20,5), 59 | lastUpdate timestamp not null, 60 | quantity integer not null, 61 | primary key (id) 62 | ) tablespace pg_default; 63 | 64 | alter table orders.orderItem add constraint orderItem_fk_1 foreign key (order_id) references orders.order (id); 65 | alter table orders.orderItem add constraint orderItem_fk_2 foreign key (catalogitem_id) references orders.catalogitem (id); -------------------------------------------------------------------------------- /src/main/sql/postgresql/ddl/drop-orders-db.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * PostgreSQL DML for dropping the role and database for Pluralsight's 3 | * course Apache Camel Introduction to Integration. This should be run 4 | * when the database needs to be re-loaded. 5 | */ 6 | 7 | DROP SCHEMA orders; 8 | DROP DATABASE orders; 9 | DROP ROLE orders; 10 | -------------------------------------------------------------------------------- /src/main/sql/postgresql/dml/load-orders.sql: -------------------------------------------------------------------------------- 1 | -- Load catalog items 2 | insert into orders.catalogitem (itemnumber, itemname, itemtype) 3 | values ('078-1344200444', 'Build Your Own JavaScript Framework Framework in Just 24 Hours', 'Book'); 4 | insert into orders.catalogitem (itemnumber, itemname, itemtype) 5 | values ('222-5452210433', 'Object-Oriented Cobol - The Future of Programming', 'Book'); 6 | insert into orders.catalogitem (itemnumber, itemname, itemtype) 7 | values ('516-5982748121', 'There is a Thunderstorm in My Private Cloud', 'Book'); 8 | insert into orders.catalogitem (itemnumber, itemname, itemtype) 9 | values ('048-8273591782', '5,428,101 Things Every Programmer Must Know', 'Book'); 10 | insert into orders.catalogitem (itemnumber, itemname, itemtype) 11 | values ('091-7282346816', 'Java Applets: Through the Eyes of the Criminally Insane', 'Book'); 12 | insert into orders.catalogitem (itemnumber, itemname, itemtype) 13 | values ('329918349', 'Yellow Notepad', 'Office Product'); 14 | insert into orders.catalogitem (itemnumber, itemname, itemtype) 15 | values ('44910432221', 'Number 2 Pencil', 'Office Product'); 16 | insert into orders.catalogitem (itemnumber, itemname, itemtype) 17 | values ('28342227', 'Generic Eraser', 'Office Product'); 18 | insert into orders.catalogitem (itemnumber, itemname, itemtype) 19 | values ('0128381', 'Headphones', 'Audio'); 20 | insert into orders.catalogitem (itemnumber, itemname, itemtype) 21 | values ('4818', 'Microphone', 'Audio'); 22 | insert into orders.catalogitem (itemnumber, itemname, itemtype) 23 | values ('69191882', 'Speakers', 'Audio'); 24 | 25 | -- Load customers 26 | insert into orders.customer (firstname, lastname, email) values ('Michael', 'Hoffman', 'mike@michaelhoffmaninc.com'); 27 | insert into orders.customer (firstname, lastname, email) values ('John', 'Smith', 'john@somewhere.com'); 28 | insert into orders.customer (firstname, lastname, email) values ('Jane', 'Smith', 'jane@somehow.com'); 29 | insert into orders.customer (firstname, lastname, email) values ('Jeff', 'Chan', 'john@someway.com'); 30 | insert into orders.customer (firstname, lastname, email) values ('Ron', 'River', 'ron@goodbye.com'); 31 | insert into orders.customer (firstname, lastname, email) values ('Larry', 'Horse', 'larry@hello.com'); 32 | 33 | -- Load orders 34 | insert into orders.order (customer_id, orderNumber, timeorderplaced, lastupdate, status) 35 | values ((select id from orders.customer where email = 'mike@michaelhoffmaninc.com'), 36 | '1001', CURRENT_TIMESTAMP - INTERVAL '1 day', CURRENT_TIMESTAMP - INTERVAL '1 day', 'N'); 37 | insert into orders.order (customer_id, orderNumber, timeorderplaced, lastupdate, status) 38 | values ((select id from orders.customer where email = 'john@somewhere.com'), 39 | '1002', CURRENT_TIMESTAMP - INTERVAL '1 day', CURRENT_TIMESTAMP - INTERVAL '1 day', 'N'); 40 | insert into orders.order (customer_id, orderNumber, timeorderplaced, lastupdate, status) 41 | values ((select id from orders.customer where email = 'jane@somehow.com'), 42 | '1003', CURRENT_TIMESTAMP - INTERVAL '1 day', CURRENT_TIMESTAMP - INTERVAL '1 day', 'N'); 43 | insert into orders.order (customer_id, orderNumber, timeorderplaced, lastupdate, status) 44 | values ((select id from orders.customer where email = 'john@someway.com'), 45 | '1004', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'N'); 46 | insert into orders.order (customer_id, orderNumber, timeorderplaced, lastupdate, status) 47 | values ((select id from orders.customer where email = 'ron@goodbye.com'), 48 | '1005', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'N'); 49 | insert into orders.order (customer_id, orderNumber, timeorderplaced, lastupdate, status) 50 | values ((select id from orders.customer where email = 'larry@hello.com'), 51 | '1006', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'N'); 52 | insert into orders.order (customer_id, orderNumber, timeorderplaced, lastupdate, status) 53 | values ((select id from orders.customer where email = 'mike@michaelhoffmaninc.com'), 54 | '1007', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'N'); 55 | 56 | -- Load order items 57 | insert into orders.orderitem (order_id, catalogitem_id, status, price, quantity, lastupdate) 58 | values ((select id from orders.order where orderNumber = '1001'), 59 | (select id from orders.catalogitem where itemnumber = '078-1344200444'), 'N', 20.00, 1, CURRENT_TIMESTAMP); 60 | insert into orders.orderitem (order_id, catalogitem_id, status, price, quantity, lastupdate) 61 | values ((select id from orders.order where orderNumber = '1001'), 62 | (select id from orders.catalogitem where itemnumber = '44910432221'), 'N', 1.25, 10, CURRENT_TIMESTAMP); 63 | insert into orders.orderitem (order_id, catalogitem_id, status, price, quantity, lastupdate) 64 | values ((select id from orders.order where orderNumber = '1002'), 65 | (select id from orders.catalogitem where itemnumber = '078-1344200444'), 'N', 20.00, 1, CURRENT_TIMESTAMP); 66 | insert into orders.orderitem (order_id, catalogitem_id, status, price, quantity, lastupdate) 67 | values ((select id from orders.order where orderNumber = '1003'), 68 | (select id from orders.catalogitem where itemnumber = '078-1344200444'), 'N', 20.00, 1, CURRENT_TIMESTAMP); 69 | insert into orders.orderitem (order_id, catalogitem_id, status, price, quantity, lastupdate) 70 | values ((select id from orders.order where orderNumber = '1004'), 71 | (select id from orders.catalogitem where itemnumber = '222-5452210433'), 'N', 40.00, 1, CURRENT_TIMESTAMP); 72 | insert into orders.orderitem (order_id, catalogitem_id, status, price, quantity, lastupdate) 73 | values ((select id from orders.order where orderNumber = '1004'), 74 | (select id from orders.catalogitem where itemnumber = '329918349'), 'N', 2.50, 15, CURRENT_TIMESTAMP); 75 | insert into orders.orderitem (order_id, catalogitem_id, status, price, quantity, lastupdate) 76 | values ((select id from orders.order where orderNumber = '1004'), 77 | (select id from orders.catalogitem where itemnumber = '69191882'), 'N', 101.10, 1, CURRENT_TIMESTAMP); 78 | insert into orders.orderitem (order_id, catalogitem_id, status, price, quantity, lastupdate) 79 | values ((select id from orders.order where orderNumber = '1005'), 80 | (select id from orders.catalogitem where itemnumber = '078-1344200444'), 'N', 20.00, 3, CURRENT_TIMESTAMP); 81 | insert into orders.orderitem (order_id, catalogitem_id, status, price, quantity, lastupdate) 82 | values ((select id from orders.order where orderNumber = '1006'), 83 | (select id from orders.catalogitem where itemnumber = '329918349'), 'N', 2.50, 1, CURRENT_TIMESTAMP); 84 | insert into orders.orderitem (order_id, catalogitem_id, status, price, quantity, lastupdate) 85 | values ((select id from orders.order where orderNumber = '1007'), 86 | (select id from orders.catalogitem where itemnumber = '0128381'), 'N', 65.99, 2, CURRENT_TIMESTAMP); 87 | insert into orders.orderitem (order_id, catalogitem_id, status, price, quantity, lastupdate) 88 | values ((select id from orders.order where orderNumber = '1004'), 89 | (select id from orders.catalogitem where itemnumber = '69191882'), 'N', 101.10, 1, CURRENT_TIMESTAMP); 90 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/footer.jsp: -------------------------------------------------------------------------------- 1 | <%@ page session="false" %> 2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 3 | 4 |
    5 |

    Order Fulfillment Management sample app for 6 | Pluralsight.com course 7 | Introduction to Integration with Apache Camel by Michael Hoffman. 8 |

    9 |
    -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/header.jsp: -------------------------------------------------------------------------------- 1 | <%@ page session="false" %> 2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 3 | 4 |
    5 | 15 | 29 |
    30 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/orderHome.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" 2 | contentType="text/html; charset=utf-8" 3 | pageEncoding="utf-8"%> 4 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 5 |
    6 |
    7 |

    Order Fulfillment Management

    8 |

    9 | Supporting various pages devoted to order fulfillment management. 10 |

    11 |
    12 |
    13 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/page.jsp: -------------------------------------------------------------------------------- 1 | <%@ page session="false" %> 2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 3 | <%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %> 4 | 5 | 6 | 7 | 8 | <tiles:insertAttribute name="title" defaultValue="Order Fulfillment Management" /> 9 | 10 | 11 | "> 12 | "> 13 | "> 14 | 15 | 16 | 17 | 18 | 19 | 20 |
    21 | 24 |
    25 | 26 |
    27 |
    28 |
    29 | 32 | 33 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/processOrders.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" 2 | contentType="text/html; charset=utf-8" 3 | pageEncoding="utf-8"%> 4 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 5 |
    6 |
    7 |
    8 |

    Process Orders

    9 |

    10 | Click the button below to run order fulfillment processing. 11 |

    12 |

    13 |
    14 |
    15 |
    16 | 17 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/resetOrders.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" 2 | contentType="text/html; charset=utf-8" 3 | pageEncoding="utf-8"%> 4 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 5 |
    6 |
    7 |
    8 |

    Reset Orders

    9 |

    10 | Clicking the button below will reset the order statuses of all orders to new. 11 |

    12 |

    13 |
    14 |
    15 |
    16 | 17 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/tiles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/viewOrders.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" 2 | contentType="text/html; charset=utf-8" 3 | pageEncoding="utf-8"%> 4 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 5 |
    6 |
    7 |

    View Orders

    8 |

    9 | Below are the current list of orders in the system. 10 |

    11 |
    12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
    Order IDOrder #CustomerTime Order PlacedStatus
    ${order.id}${order.orderNumber}${order.customer.firstName} ${order.customer.lastName}${order.timeOrderPlaced}${order.status}
    34 |
    35 |
    36 |
    37 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /src/main/webapp/resources/css/app.css: -------------------------------------------------------------------------------- 1 | /* app css stylesheet */ 2 | 3 | body { 4 | padding-top: 50px; 5 | height: 100%; 6 | } 7 | 8 | .starter-template { 9 | padding: 40px 15px; 10 | } 11 | 12 | .theme-dropdown .dropdown-menu { 13 | position: static; 14 | display: block; 15 | margin-bottom: 20px; 16 | } 17 | 18 | /* Wrapper for page content to push down footer */ 19 | #wrap { 20 | min-height: 100%; 21 | height: auto !important; 22 | height: 100%; 23 | /* Negative indent footer by it's height */ 24 | margin: 0 auto -60px; 25 | } 26 | 27 | /* Set the fixed height of the footer here */ 28 | #push, #footer { 29 | height: 60px; 30 | } 31 | #footer { 32 | background-color: #f5f5f5; 33 | } 34 | 35 | /* Lastly, apply responsive CSS fixes as necessary */ 36 | @media (max-width: 767px) { 37 | #footer { 38 | margin-left: -20px; 39 | margin-right: -20px; 40 | padding-left: 20px; 41 | padding-right: 20px; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/webapp/resources/css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.1.1 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | .btn-default, 8 | .btn-primary, 9 | .btn-success, 10 | .btn-info, 11 | .btn-warning, 12 | .btn-danger { 13 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); 14 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 15 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 16 | } 17 | .btn-default:active, 18 | .btn-primary:active, 19 | .btn-success:active, 20 | .btn-info:active, 21 | .btn-warning:active, 22 | .btn-danger:active, 23 | .btn-default.active, 24 | .btn-primary.active, 25 | .btn-success.active, 26 | .btn-info.active, 27 | .btn-warning.active, 28 | .btn-danger.active { 29 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 30 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 31 | } 32 | .btn:active, 33 | .btn.active { 34 | background-image: none; 35 | } 36 | .btn-default { 37 | text-shadow: 0 1px 0 #fff; 38 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); 39 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); 40 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); 41 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 42 | background-repeat: repeat-x; 43 | border-color: #dbdbdb; 44 | border-color: #ccc; 45 | } 46 | .btn-default:hover, 47 | .btn-default:focus { 48 | background-color: #e0e0e0; 49 | background-position: 0 -15px; 50 | } 51 | .btn-default:active, 52 | .btn-default.active { 53 | background-color: #e0e0e0; 54 | border-color: #dbdbdb; 55 | } 56 | .btn-primary { 57 | background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); 58 | background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); 59 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); 60 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 61 | background-repeat: repeat-x; 62 | border-color: #2b669a; 63 | } 64 | .btn-primary:hover, 65 | .btn-primary:focus { 66 | background-color: #2d6ca2; 67 | background-position: 0 -15px; 68 | } 69 | .btn-primary:active, 70 | .btn-primary.active { 71 | background-color: #2d6ca2; 72 | border-color: #2b669a; 73 | } 74 | .btn-success { 75 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); 76 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); 77 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); 78 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 79 | background-repeat: repeat-x; 80 | border-color: #3e8f3e; 81 | } 82 | .btn-success:hover, 83 | .btn-success:focus { 84 | background-color: #419641; 85 | background-position: 0 -15px; 86 | } 87 | .btn-success:active, 88 | .btn-success.active { 89 | background-color: #419641; 90 | border-color: #3e8f3e; 91 | } 92 | .btn-info { 93 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 94 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); 95 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); 96 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 97 | background-repeat: repeat-x; 98 | border-color: #28a4c9; 99 | } 100 | .btn-info:hover, 101 | .btn-info:focus { 102 | background-color: #2aabd2; 103 | background-position: 0 -15px; 104 | } 105 | .btn-info:active, 106 | .btn-info.active { 107 | background-color: #2aabd2; 108 | border-color: #28a4c9; 109 | } 110 | .btn-warning { 111 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 112 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); 113 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); 114 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 115 | background-repeat: repeat-x; 116 | border-color: #e38d13; 117 | } 118 | .btn-warning:hover, 119 | .btn-warning:focus { 120 | background-color: #eb9316; 121 | background-position: 0 -15px; 122 | } 123 | .btn-warning:active, 124 | .btn-warning.active { 125 | background-color: #eb9316; 126 | border-color: #e38d13; 127 | } 128 | .btn-danger { 129 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 130 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); 131 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); 132 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 133 | background-repeat: repeat-x; 134 | border-color: #b92c28; 135 | } 136 | .btn-danger:hover, 137 | .btn-danger:focus { 138 | background-color: #c12e2a; 139 | background-position: 0 -15px; 140 | } 141 | .btn-danger:active, 142 | .btn-danger.active { 143 | background-color: #c12e2a; 144 | border-color: #b92c28; 145 | } 146 | .thumbnail, 147 | .img-thumbnail { 148 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 149 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 150 | } 151 | .dropdown-menu > li > a:hover, 152 | .dropdown-menu > li > a:focus { 153 | background-color: #e8e8e8; 154 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 155 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 156 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 157 | background-repeat: repeat-x; 158 | } 159 | .dropdown-menu > .active > a, 160 | .dropdown-menu > .active > a:hover, 161 | .dropdown-menu > .active > a:focus { 162 | background-color: #357ebd; 163 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 164 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 165 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 166 | background-repeat: repeat-x; 167 | } 168 | .navbar-default { 169 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); 170 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); 171 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 172 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 173 | background-repeat: repeat-x; 174 | border-radius: 4px; 175 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 176 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 177 | } 178 | .navbar-default .navbar-nav > .active > a { 179 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); 180 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); 181 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); 182 | background-repeat: repeat-x; 183 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 184 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 185 | } 186 | .navbar-brand, 187 | .navbar-nav > li > a { 188 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25); 189 | } 190 | .navbar-inverse { 191 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); 192 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); 193 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 194 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 195 | background-repeat: repeat-x; 196 | } 197 | .navbar-inverse .navbar-nav > .active > a { 198 | background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%); 199 | background-image: linear-gradient(to bottom, #222 0%, #282828 100%); 200 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); 201 | background-repeat: repeat-x; 202 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 203 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 204 | } 205 | .navbar-inverse .navbar-brand, 206 | .navbar-inverse .navbar-nav > li > a { 207 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); 208 | } 209 | .navbar-static-top, 210 | .navbar-fixed-top, 211 | .navbar-fixed-bottom { 212 | border-radius: 0; 213 | } 214 | .alert { 215 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2); 216 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 217 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 218 | } 219 | .alert-success { 220 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 221 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 222 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 223 | background-repeat: repeat-x; 224 | border-color: #b2dba1; 225 | } 226 | .alert-info { 227 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 228 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 229 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 230 | background-repeat: repeat-x; 231 | border-color: #9acfea; 232 | } 233 | .alert-warning { 234 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 235 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 236 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 237 | background-repeat: repeat-x; 238 | border-color: #f5e79e; 239 | } 240 | .alert-danger { 241 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 242 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 243 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 244 | background-repeat: repeat-x; 245 | border-color: #dca7a7; 246 | } 247 | .progress { 248 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 249 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 250 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 251 | background-repeat: repeat-x; 252 | } 253 | .progress-bar { 254 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); 255 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 256 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 257 | background-repeat: repeat-x; 258 | } 259 | .progress-bar-success { 260 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); 261 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 262 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 263 | background-repeat: repeat-x; 264 | } 265 | .progress-bar-info { 266 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 267 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 268 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 269 | background-repeat: repeat-x; 270 | } 271 | .progress-bar-warning { 272 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 273 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 274 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 275 | background-repeat: repeat-x; 276 | } 277 | .progress-bar-danger { 278 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); 279 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 280 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 281 | background-repeat: repeat-x; 282 | } 283 | .list-group { 284 | border-radius: 4px; 285 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 286 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 287 | } 288 | .list-group-item.active, 289 | .list-group-item.active:hover, 290 | .list-group-item.active:focus { 291 | text-shadow: 0 -1px 0 #3071a9; 292 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); 293 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); 294 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); 295 | background-repeat: repeat-x; 296 | border-color: #3278b3; 297 | } 298 | .panel { 299 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 300 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 301 | } 302 | .panel-default > .panel-heading { 303 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 304 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 305 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 306 | background-repeat: repeat-x; 307 | } 308 | .panel-primary > .panel-heading { 309 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 310 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 311 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 312 | background-repeat: repeat-x; 313 | } 314 | .panel-success > .panel-heading { 315 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 316 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 317 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 318 | background-repeat: repeat-x; 319 | } 320 | .panel-info > .panel-heading { 321 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 322 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 323 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 324 | background-repeat: repeat-x; 325 | } 326 | .panel-warning > .panel-heading { 327 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 328 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 329 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 330 | background-repeat: repeat-x; 331 | } 332 | .panel-danger > .panel-heading { 333 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 334 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 335 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 336 | background-repeat: repeat-x; 337 | } 338 | .well { 339 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 340 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 341 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 342 | background-repeat: repeat-x; 343 | border-color: #dcdcdc; 344 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 345 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 346 | } 347 | /*# sourceMappingURL=bootstrap-theme.css.map */ 348 | -------------------------------------------------------------------------------- /src/main/webapp/resources/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikevoxcap/pluralsight-camel-intro/9c5e1985f43017ab4fe2d0b6647c9516a74ebd32/src/main/webapp/resources/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/main/webapp/resources/fonts/glyphicons-halflings-regular.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /src/main/webapp/resources/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikevoxcap/pluralsight-camel-intro/9c5e1985f43017ab4fe2d0b6647c9516a74ebd32/src/main/webapp/resources/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/main/webapp/resources/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikevoxcap/pluralsight-camel-intro/9c5e1985f43017ab4fe2d0b6647c9516a74ebd32/src/main/webapp/resources/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/main/webapp/resources/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikevoxcap/pluralsight-camel-intro/9c5e1985f43017ab4fe2d0b6647c9516a74ebd32/src/main/webapp/resources/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /src/main/webapp/resources/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikevoxcap/pluralsight-camel-intro/9c5e1985f43017ab4fe2d0b6647c9516a74ebd32/src/main/webapp/resources/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /src/main/webapp/resources/js/underscore-min.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.6.0 2 | // http://underscorejs.org 3 | // (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 4 | // Underscore may be freely distributed under the MIT license. 5 | (function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,w=Object.keys,_=i.bind,j=function(n){return n instanceof j?n:this instanceof j?void(this._wrapped=n):new j(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=j),exports._=j):n._=j,j.VERSION="1.6.0";var A=j.each=j.forEach=function(n,t,e){if(null==n)return n;if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a=j.keys(n),u=0,i=a.length;i>u;u++)if(t.call(e,n[a[u]],a[u],n)===r)return;return n};j.map=j.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var O="Reduce of empty array with no initial value";j.reduce=j.foldl=j.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=j.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},j.reduceRight=j.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=j.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=j.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},j.find=j.detect=function(n,t,r){var e;return k(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},j.filter=j.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},j.reject=function(n,t,r){return j.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},j.every=j.all=function(n,t,e){t||(t=j.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var k=j.some=j.any=function(n,t,e){t||(t=j.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};j.contains=j.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:k(n,function(n){return n===t})},j.invoke=function(n,t){var r=o.call(arguments,2),e=j.isFunction(t);return j.map(n,function(n){return(e?t:n[t]).apply(n,r)})},j.pluck=function(n,t){return j.map(n,j.property(t))},j.where=function(n,t){return j.filter(n,j.matches(t))},j.findWhere=function(n,t){return j.find(n,j.matches(t))},j.max=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);var e=-1/0,u=-1/0;return A(n,function(n,i,a){var o=t?t.call(r,n,i,a):n;o>u&&(e=n,u=o)}),e},j.min=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);var e=1/0,u=1/0;return A(n,function(n,i,a){var o=t?t.call(r,n,i,a):n;u>o&&(e=n,u=o)}),e},j.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=j.random(r++),e[r-1]=e[t],e[t]=n}),e},j.sample=function(n,t,r){return null==t||r?(n.length!==+n.length&&(n=j.values(n)),n[j.random(n.length-1)]):j.shuffle(n).slice(0,Math.max(0,t))};var E=function(n){return null==n?j.identity:j.isFunction(n)?n:j.property(n)};j.sortBy=function(n,t,r){return t=E(t),j.pluck(j.map(n,function(n,e,u){return{value:n,index:e,criteria:t.call(r,n,e,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=E(r),A(t,function(i,a){var o=r.call(e,i,a,t);n(u,o,i)}),u}};j.groupBy=F(function(n,t,r){j.has(n,t)?n[t].push(r):n[t]=[r]}),j.indexBy=F(function(n,t,r){n[t]=r}),j.countBy=F(function(n,t){j.has(n,t)?n[t]++:n[t]=1}),j.sortedIndex=function(n,t,r,e){r=E(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;r.call(e,n[o])t?[]:o.call(n,0,t)},j.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},j.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},j.rest=j.tail=j.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},j.compact=function(n){return j.filter(n,j.identity)};var M=function(n,t,r){return t&&j.every(n,j.isArray)?c.apply(r,n):(A(n,function(n){j.isArray(n)||j.isArguments(n)?t?a.apply(r,n):M(n,t,r):r.push(n)}),r)};j.flatten=function(n,t){return M(n,t,[])},j.without=function(n){return j.difference(n,o.call(arguments,1))},j.partition=function(n,t){var r=[],e=[];return A(n,function(n){(t(n)?r:e).push(n)}),[r,e]},j.uniq=j.unique=function(n,t,r,e){j.isFunction(t)&&(e=r,r=t,t=!1);var u=r?j.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:j.contains(a,r))||(a.push(r),i.push(n[e]))}),i},j.union=function(){return j.uniq(j.flatten(arguments,!0))},j.intersection=function(n){var t=o.call(arguments,1);return j.filter(j.uniq(n),function(n){return j.every(t,function(t){return j.contains(t,n)})})},j.difference=function(n){var t=c.apply(e,o.call(arguments,1));return j.filter(n,function(n){return!j.contains(t,n)})},j.zip=function(){for(var n=j.max(j.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=j.pluck(arguments,""+r);return t},j.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},j.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=j.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},j.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},j.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var R=function(){};j.bind=function(n,t){var r,e;if(_&&n.bind===_)return _.apply(n,o.call(arguments,1));if(!j.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));R.prototype=n.prototype;var u=new R;R.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},j.partial=function(n){var t=o.call(arguments,1);return function(){for(var r=0,e=t.slice(),u=0,i=e.length;i>u;u++)e[u]===j&&(e[u]=arguments[r++]);for(;r=f?(clearTimeout(a),a=null,o=l,i=n.apply(e,u),e=u=null):a||r.trailing===!1||(a=setTimeout(c,f)),i}},j.debounce=function(n,t,r){var e,u,i,a,o,c=function(){var l=j.now()-a;t>l?e=setTimeout(c,t-l):(e=null,r||(o=n.apply(i,u),i=u=null))};return function(){i=this,u=arguments,a=j.now();var l=r&&!e;return e||(e=setTimeout(c,t)),l&&(o=n.apply(i,u),i=u=null),o}},j.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},j.wrap=function(n,t){return j.partial(t,n)},j.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},j.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},j.keys=function(n){if(!j.isObject(n))return[];if(w)return w(n);var t=[];for(var r in n)j.has(n,r)&&t.push(r);return t},j.values=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},j.pairs=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},j.invert=function(n){for(var t={},r=j.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},j.functions=j.methods=function(n){var t=[];for(var r in n)j.isFunction(n[r])&&t.push(r);return t.sort()},j.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},j.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},j.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)j.contains(r,u)||(t[u]=n[u]);return t},j.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]===void 0&&(n[r]=t[r])}),n},j.clone=function(n){return j.isObject(n)?j.isArray(n)?n.slice():j.extend({},n):n},j.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof j&&(n=n._wrapped),t instanceof j&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==String(t);case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;var a=n.constructor,o=t.constructor;if(a!==o&&!(j.isFunction(a)&&a instanceof a&&j.isFunction(o)&&o instanceof o)&&"constructor"in n&&"constructor"in t)return!1;r.push(n),e.push(t);var c=0,f=!0;if("[object Array]"==u){if(c=n.length,f=c==t.length)for(;c--&&(f=S(n[c],t[c],r,e)););}else{for(var s in n)if(j.has(n,s)&&(c++,!(f=j.has(t,s)&&S(n[s],t[s],r,e))))break;if(f){for(s in t)if(j.has(t,s)&&!c--)break;f=!c}}return r.pop(),e.pop(),f};j.isEqual=function(n,t){return S(n,t,[],[])},j.isEmpty=function(n){if(null==n)return!0;if(j.isArray(n)||j.isString(n))return 0===n.length;for(var t in n)if(j.has(n,t))return!1;return!0},j.isElement=function(n){return!(!n||1!==n.nodeType)},j.isArray=x||function(n){return"[object Array]"==l.call(n)},j.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){j["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),j.isArguments(arguments)||(j.isArguments=function(n){return!(!n||!j.has(n,"callee"))}),"function"!=typeof/./&&(j.isFunction=function(n){return"function"==typeof n}),j.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},j.isNaN=function(n){return j.isNumber(n)&&n!=+n},j.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},j.isNull=function(n){return null===n},j.isUndefined=function(n){return n===void 0},j.has=function(n,t){return f.call(n,t)},j.noConflict=function(){return n._=t,this},j.identity=function(n){return n},j.constant=function(n){return function(){return n}},j.property=function(n){return function(t){return t[n]}},j.matches=function(n){return function(t){if(t===n)return!0;for(var r in n)if(n[r]!==t[r])return!1;return!0}},j.times=function(n,t,r){for(var e=Array(Math.max(0,n)),u=0;n>u;u++)e[u]=t.call(r,u);return e},j.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},j.now=Date.now||function(){return(new Date).getTime()};var T={escape:{"&":"&","<":"<",">":">",'"':""","'":"'"}};T.unescape=j.invert(T.escape);var I={escape:new RegExp("["+j.keys(T.escape).join("")+"]","g"),unescape:new RegExp("("+j.keys(T.unescape).join("|")+")","g")};j.each(["escape","unescape"],function(n){j[n]=function(t){return null==t?"":(""+t).replace(I[n],function(t){return T[n][t]})}}),j.result=function(n,t){if(null==n)return void 0;var r=n[t];return j.isFunction(r)?r.call(n):r},j.mixin=function(n){A(j.functions(n),function(t){var r=j[t]=n[t];j.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(j,n))}})};var N=0;j.uniqueId=function(n){var t=++N+"";return n?n+t:t},j.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;j.template=function(n,t,r){var e;r=j.defaults({},r,j.templateSettings);var u=new RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(D,function(n){return"\\"+B[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=new Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,j);var c=function(n){return e.call(this,n,j)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},j.chain=function(n){return j(n).chain()};var z=function(n){return this._chain?j(n).chain():n};j.mixin(j),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];j.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];j.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),j.extend(j.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}}),"function"==typeof define&&define.amd&&define("underscore",[],function(){return j})}).call(this); 6 | //# sourceMappingURL=underscore-min.map -------------------------------------------------------------------------------- /src/test/java/com/pluralsight/orderfulfillment/catalog/CatalogItemRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.catalog; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | import javax.inject.Inject; 9 | 10 | import org.junit.After; 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | 14 | import com.pluralsight.orderfulfillment.order.OrderItemEntity; 15 | import com.pluralsight.orderfulfillment.test.BaseJpaRepositoryTest; 16 | 17 | public class CatalogItemRepositoryTest extends BaseJpaRepositoryTest { 18 | 19 | @Inject 20 | private CatalogItemRepository catalogItemRepository; 21 | 22 | @Before 23 | public void setUp() throws Exception { 24 | } 25 | 26 | @After 27 | public void tearDown() throws Exception { 28 | } 29 | 30 | @Test 31 | public void testFindAllSuccess() { 32 | List catalogItems = catalogItemRepository.findAll(); 33 | assertNotNull(catalogItems); 34 | assertFalse(catalogItems.isEmpty()); 35 | } 36 | 37 | @Test 38 | public void testOrderOrderItemsSuccess() { 39 | List catalogItems = catalogItemRepository.findAll(); 40 | assertNotNull(catalogItems); 41 | assertFalse(catalogItems.isEmpty()); 42 | CatalogItemEntity catalogItem = catalogItems.get(0); 43 | Set orderItems = catalogItem.getOrderItems(); 44 | assertNotNull(orderItems); 45 | assertFalse(orderItems.isEmpty()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/com/pluralsight/orderfulfillment/customer/CustomerRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.customer; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.util.*; 6 | 7 | import javax.inject.*; 8 | 9 | import org.junit.*; 10 | 11 | import com.pluralsight.orderfulfillment.order.OrderEntity; 12 | import com.pluralsight.orderfulfillment.test.*; 13 | 14 | public class CustomerRepositoryTest extends BaseJpaRepositoryTest { 15 | 16 | @Inject 17 | private CustomerRepository customerRepository; 18 | 19 | @Before 20 | public void setUp() throws Exception { 21 | } 22 | 23 | @After 24 | public void tearDown() throws Exception { 25 | } 26 | 27 | @Test 28 | public void test_findAllCustomersSuccess() throws Exception { 29 | List customers = customerRepository.findAll(); 30 | assertNotNull(customers); 31 | assertFalse(customers.isEmpty()); 32 | } 33 | 34 | @Test 35 | public void test_findCustomerOrdersSuccess() throws Exception { 36 | List customers = customerRepository.findAll(); 37 | assertNotNull(customers); 38 | assertFalse(customers.isEmpty()); 39 | CustomerEntity customer = customers.get(0); 40 | Set orders = customer.getOrders(); 41 | assertNotNull(orders); 42 | assertFalse(orders.isEmpty()); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/com/pluralsight/orderfulfillment/order/OrderItemRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.util.*; 6 | 7 | import javax.inject.*; 8 | 9 | import org.junit.*; 10 | 11 | import com.pluralsight.orderfulfillment.test.*; 12 | 13 | public class OrderItemRepositoryTest extends BaseJpaRepositoryTest { 14 | 15 | @Inject 16 | private OrderItemRepository orderItemRepository; 17 | 18 | @Before 19 | public void setUp() throws Exception { 20 | } 21 | 22 | @After 23 | public void tearDown() throws Exception { 24 | } 25 | 26 | @Test 27 | public void test_findAllOrderItemsSuccess() throws Exception { 28 | List orderItems = orderItemRepository.findAll(); 29 | assertNotNull(orderItems); 30 | assertFalse(orderItems.isEmpty()); 31 | } 32 | 33 | @Test 34 | public void test_findOrderItemOrderCatalogItemSuccess() throws Exception { 35 | List orderItems = orderItemRepository.findAll(); 36 | assertNotNull(orderItems); 37 | assertFalse(orderItems.isEmpty()); 38 | OrderItemEntity orderItem = orderItems.get(0); 39 | assertNotNull(orderItem.getOrder()); 40 | assertNotNull(orderItem.getCatalogItem()); 41 | } 42 | 43 | @Test 44 | public void test_findByOrderIdSuccess() throws Exception { 45 | List orderItems = orderItemRepository.findByOrderId(1L); 46 | assertNotNull(orderItems); 47 | assertFalse(orderItems.isEmpty()); 48 | } 49 | 50 | @Test 51 | public void test_() throws Exception { 52 | List orderIds = new ArrayList(); 53 | orderIds.add(1L); 54 | orderIds.add(2L); 55 | orderIds.add(3L); 56 | orderIds.add(4L); 57 | int updateCount = orderItemRepository.updateStatus( 58 | OrderStatus.PROCESSING.getCode(), 59 | new Date(System.currentTimeMillis()), orderIds); 60 | assertTrue(updateCount == 8); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/com/pluralsight/orderfulfillment/order/OrderRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.order; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.util.*; 6 | 7 | import javax.inject.*; 8 | 9 | import org.junit.*; 10 | import org.springframework.data.domain.*; 11 | 12 | import com.pluralsight.orderfulfillment.test.*; 13 | 14 | public class OrderRepositoryTest extends BaseJpaRepositoryTest { 15 | 16 | @Inject 17 | private OrderRepository orderRepository; 18 | 19 | @Before 20 | public void setUp() throws Exception { 21 | } 22 | 23 | @After 24 | public void tearDown() throws Exception { 25 | } 26 | 27 | @Test 28 | public void test_findAllOrdersSuccess() throws Exception { 29 | Iterable orders = orderRepository.findAll(); 30 | assertNotNull(orders); 31 | assertTrue(orders.iterator().hasNext()); 32 | } 33 | 34 | @Test 35 | public void test_findOrderCustomerAndOrderItemsSuccess() throws Exception { 36 | Iterable orders = orderRepository.findAll(); 37 | assertNotNull(orders); 38 | Iterator iterator = orders.iterator(); 39 | assertTrue(iterator.hasNext()); 40 | OrderEntity order = iterator.next(); 41 | assertNotNull(order.getCustomer()); 42 | Set orderItems = order.getOrderItems(); 43 | assertNotNull(orderItems); 44 | assertFalse(orderItems.isEmpty()); 45 | } 46 | 47 | @Test 48 | public void test_findOrdersByOrderStatusOrderByTimeOrderPlacedAscSuccess() 49 | throws Exception { 50 | Iterable orders = orderRepository.findByStatus( 51 | OrderStatus.NEW.getCode(), new PageRequest(0, 5)); 52 | assertNotNull(orders); 53 | assertTrue(orders.iterator().hasNext()); 54 | } 55 | 56 | @Test 57 | public void test_findOrdersByOrderStatusOrderByTimeOrderPlacedAscFailInvalidStatus() 58 | throws Exception { 59 | Iterable orders = orderRepository.findByStatus("whefiehwi", 60 | new PageRequest(0, 5)); 61 | assertNotNull(orders); 62 | assertFalse(orders.iterator().hasNext()); 63 | } 64 | 65 | @Test 66 | public void test_updateStatusSuccess() throws Exception { 67 | List orderIds = new ArrayList(); 68 | orderIds.add(1L); 69 | orderIds.add(2L); 70 | orderIds.add(3L); 71 | orderIds.add(4L); 72 | int count = orderRepository.updateStatus( 73 | OrderStatus.PROCESSING.getCode(), 74 | new Date(System.currentTimeMillis()), orderIds); 75 | assertTrue(count == 4); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/test/java/com/pluralsight/orderfulfillment/test/BaseJpaRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.pluralsight.orderfulfillment.test; 2 | 3 | import javax.persistence.*; 4 | 5 | import org.junit.*; 6 | import org.junit.runner.*; 7 | import org.springframework.test.context.*; 8 | import org.springframework.test.context.junit4.*; 9 | import org.springframework.test.context.support.*; 10 | import org.springframework.test.context.transaction.*; 11 | import org.springframework.test.context.web.WebAppConfiguration; 12 | import org.springframework.transaction.annotation.*; 13 | 14 | import com.pluralsight.orderfulfillment.config.*; 15 | 16 | @RunWith(SpringJUnit4ClassRunner.class) 17 | @ContextConfiguration(classes = { Application.class }) 18 | @WebAppConfiguration 19 | @TransactionConfiguration(transactionManager = "transactionManager") 20 | @TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class, 21 | DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class }) 22 | @Transactional 23 | @Ignore 24 | public class BaseJpaRepositoryTest { 25 | 26 | @PersistenceContext 27 | protected EntityManager entityManager; 28 | 29 | } 30 | --------------------------------------------------------------------------------