29
									
								
								cqrs/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								cqrs/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| --- | ||||
| layout: pattern | ||||
| title: CQRS | ||||
| folder: cqrs | ||||
| permalink: /patterns/cqrs/ | ||||
| pumlid: 7SPR4a0m3030gt00pR_RH6I8QQFouFgC_TfHb6gkd5Q7FQBx363ub4rYpoMTZKuDrYXqDX37HIuuyCPfPPTDfuuHREhGqBy0NUR0GNzAMYizMtq1 | ||||
| categories: Architectural | ||||
| tags: | ||||
|  - Java | ||||
|  - Difficulty-Intermediate | ||||
| --- | ||||
|  | ||||
| ## Intent | ||||
| CQRS Command Query Responsibility Segregation - Separate the query side from the command side. | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Applicability | ||||
| Use the CQRS pattern when | ||||
|  | ||||
| * you want to scale the queries and commands independently. | ||||
| * you want to use different data models for queries and commands. Useful when dealing with complex domains. | ||||
| * you want to use architectures like event sourcing or task based UI. | ||||
|  | ||||
| ## Credits | ||||
|  | ||||
| * [Greg Young - CQRS, Task Based UIs, Event Sourcing agh!](http://codebetter.com/gregyoung/2010/02/16/cqrs-task-based-uis-event-sourcing-agh/) | ||||
| * [Martin Fowler - CQRS](https://martinfowler.com/bliki/CQRS.html) | ||||
| * [Oliver Wolf - CQRS for Great Good](https://www.youtube.com/watch?v=Ge53swja9Dw) | ||||
							
								
								
									
										
											BIN
										
									
								
								cqrs/etc/cqrs.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								cqrs/etc/cqrs.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 103 KiB | 
							
								
								
									
										115
									
								
								cqrs/etc/cqrs.ucls
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								cqrs/etc/cqrs.ucls
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <class-diagram version="1.2.0" icons="true" always-add-relationships="false" generalizations="true" realizations="true"  | ||||
|   associations="true" dependencies="false" nesting-relationships="true" router="FAN">   | ||||
|   <interface id="1" language="java" name="com.iluwatar.cqrs.commandes.ICommandService" project="cqrs"  | ||||
|     file="/cqrs/src/main/java/com/iluwatar/cqrs/commandes/ICommandService.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="-1" width="-1" x="291" y="-49"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </interface>   | ||||
|   <class id="2" language="java" name="com.iluwatar.cqrs.commandes.CommandServiceImpl" project="cqrs"  | ||||
|     file="/cqrs/src/main/java/com/iluwatar/cqrs/commandes/CommandServiceImpl.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="263" width="256" x="170" y="87"/>     | ||||
|     <display autosize="false" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <interface id="3" language="java" name="com.iluwatar.cqrs.queries.IQueryService" project="cqrs"  | ||||
|     file="/cqrs/src/main/java/com/iluwatar/cqrs/queries/IQueryService.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="182" width="248" x="176" y="428"/>     | ||||
|     <display autosize="false" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </interface>   | ||||
|   <class id="4" language="java" name="com.iluwatar.cqrs.queries.QueryServiceImpl" project="cqrs"  | ||||
|     file="/cqrs/src/main/java/com/iluwatar/cqrs/queries/QueryServiceImpl.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="258" width="253" x="169" y="665"/>     | ||||
|     <display autosize="false" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="5" language="java" name="com.iluwatar.cqrs.domain.model.Book" project="cqrs"  | ||||
|     file="/cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Book.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="326" width="158" x="778" y="-93"/>     | ||||
|     <display autosize="false" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="6" language="java" name="com.iluwatar.cqrs.dto.Book" project="cqrs"  | ||||
|     file="/cqrs/src/main/java/com/iluwatar/cqrs/dto/Book.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="219" width="150" x="541" y="607"/>     | ||||
|     <display autosize="false" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="7" language="java" name="com.iluwatar.cqrs.domain.model.Author" project="cqrs"  | ||||
|     file="/cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Author.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="-1" width="-1" x="608" y="70"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="8" language="java" name="com.iluwatar.cqrs.dto.Author" project="cqrs"  | ||||
|     file="/cqrs/src/main/java/com/iluwatar/cqrs/dto/Author.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="-1" width="-1" x="834" y="719"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <class id="9" language="java" name="com.iluwatar.cqrs.util.HibernateUtil" project="cqrs"  | ||||
|     file="/cqrs/src/main/java/com/iluwatar/cqrs/util/HibernateUtil.java" binary="false" corner="BOTTOM_RIGHT">     | ||||
|     <position height="-1" width="-1" x="662" y="412"/>     | ||||
|     <display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|       sort-features="false" accessors="true" visibility="true">       | ||||
|       <attributes public="true" package="true" protected="true" private="true" static="true"/>       | ||||
|       <operations public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     </display>   | ||||
|   </class>   | ||||
|   <dependency id="10">     | ||||
|     <end type="SOURCE" refId="4"/>     | ||||
|     <end type="TARGET" refId="9"/>   | ||||
|   </dependency>   | ||||
|   <dependency id="11">     | ||||
|     <end type="SOURCE" refId="2"/>     | ||||
|     <end type="TARGET" refId="9"/>   | ||||
|   </dependency>   | ||||
|   <realization id="12">     | ||||
|     <end type="SOURCE" refId="4"/>     | ||||
|     <end type="TARGET" refId="3"/>   | ||||
|   </realization>   | ||||
|   <association id="13">     | ||||
|     <end type="SOURCE" refId="5" navigable="false">       | ||||
|       <attribute id="14" name="author"/>       | ||||
|       <multiplicity id="15" minimum="0" maximum="1"/>     | ||||
|     </end>     | ||||
|     <end type="TARGET" refId="7" navigable="true"/>     | ||||
|     <display labels="true" multiplicity="true"/>   | ||||
|   </association>   | ||||
|   <realization id="16">     | ||||
|     <end type="SOURCE" refId="2"/>     | ||||
|     <end type="TARGET" refId="1"/>   | ||||
|   </realization>   | ||||
|   <classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"  | ||||
|     sort-features="false" accessors="true" visibility="true">     | ||||
|     <attributes public="true" package="true" protected="true" private="true" static="true"/>     | ||||
|     <operations public="true" package="true" protected="true" private="true" static="true"/>   | ||||
|   </classifier-display>   | ||||
|   <association-display labels="true" multiplicity="true"/> | ||||
| </class-diagram> | ||||
							
								
								
									
										124
									
								
								cqrs/etc/cqrs.urm.puml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								cqrs/etc/cqrs.urm.puml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | ||||
| @startuml | ||||
| package com.iluwatar.cqrs.util { | ||||
|   class HibernateUtil { | ||||
|     - LOGGER : Logger {static} | ||||
|     - SESSIONFACTORY : SessionFactory {static} | ||||
|     + HibernateUtil() | ||||
|     - buildSessionFactory() : SessionFactory {static} | ||||
|     + getSessionFactory() : SessionFactory {static} | ||||
|   } | ||||
| } | ||||
| package com.iluwatar.cqrs.app { | ||||
|   class App { | ||||
|     + App() | ||||
|     + main(args : String[]) {static} | ||||
|   } | ||||
| } | ||||
| package com.iluwatar.cqrs.dto { | ||||
|   class Author { | ||||
|     - email : String | ||||
|     - name : String | ||||
|     - username : String | ||||
|     + Author() | ||||
|     + Author(name : String, email : String, username : String) | ||||
|     + equals(obj : Object) : boolean | ||||
|     + getEmail() : String | ||||
|     + getName() : String | ||||
|     + getUsername() : String | ||||
|     + hashCode() : int | ||||
|     + toString() : String | ||||
|   } | ||||
|   class Book { | ||||
|     - price : double | ||||
|     - title : String | ||||
|     + Book() | ||||
|     + Book(title : String, price : double) | ||||
|     + equals(obj : Object) : boolean | ||||
|     + getPrice() : double | ||||
|     + getTitle() : String | ||||
|     + hashCode() : int | ||||
|     + toString() : String | ||||
|   } | ||||
| } | ||||
| package com.iluwatar.cqrs.commandes { | ||||
|   class CommandServiceImpl { | ||||
|     - sessionFactory : SessionFactory | ||||
|     + CommandServiceImpl() | ||||
|     + authorCreated(username : String, name : String, email : String) | ||||
|     + authorEmailUpdated(username : String, email : String) | ||||
|     + authorNameUpdated(username : String, name : String) | ||||
|     + authorUsernameUpdated(oldUsername : String, newUsername : String) | ||||
|     + bookAddedToAuthor(title : String, price : double, username : String) | ||||
|     + bookPriceUpdated(title : String, price : double) | ||||
|     + bookTitleUpdated(oldTitle : String, newTitle : String) | ||||
|     - getAuthorByUsername(username : String) : Author | ||||
|     - getBookByTitle(title : String) : Book | ||||
|   } | ||||
|   interface ICommandService { | ||||
|     + authorCreated(String, String, String) {abstract} | ||||
|     + authorEmailUpdated(String, String) {abstract} | ||||
|     + authorNameUpdated(String, String) {abstract} | ||||
|     + authorUsernameUpdated(String, String) {abstract} | ||||
|     + bookAddedToAuthor(String, double, String) {abstract} | ||||
|     + bookPriceUpdated(String, double) {abstract} | ||||
|     + bookTitleUpdated(String, String) {abstract} | ||||
|   } | ||||
| } | ||||
| package com.iluwatar.cqrs.queries { | ||||
|   interface IQueryService { | ||||
|     + getAuthorBooks(String) : List<Book> {abstract} | ||||
|     + getAuthorBooksCount(String) : BigInteger {abstract} | ||||
|     + getAuthorByUsername(String) : Author {abstract} | ||||
|     + getAuthorsCount() : BigInteger {abstract} | ||||
|     + getBook(String) : Book {abstract} | ||||
|   } | ||||
|   class QueryServiceImpl { | ||||
|     - sessionFactory : SessionFactory | ||||
|     + QueryServiceImpl() | ||||
|     + getAuthorBooks(username : String) : List<Book> | ||||
|     + getAuthorBooksCount(username : String) : BigInteger | ||||
|     + getAuthorByUsername(username : String) : Author | ||||
|     + getAuthorsCount() : BigInteger | ||||
|     + getBook(title : String) : Book | ||||
|   } | ||||
| } | ||||
| package com.iluwatar.cqrs.domain.model { | ||||
|   class Author { | ||||
|     - email : String | ||||
|     - id : long | ||||
|     - name : String | ||||
|     - username : String | ||||
|     # Author() | ||||
|     + Author(username : String, name : String, email : String) | ||||
|     + getEmail() : String | ||||
|     + getId() : long | ||||
|     + getName() : String | ||||
|     + getUsername() : String | ||||
|     + setEmail(email : String) | ||||
|     + setId(id : long) | ||||
|     + setName(name : String) | ||||
|     + setUsername(username : String) | ||||
|     + toString() : String | ||||
|   } | ||||
|   class Book { | ||||
|     - author : Author | ||||
|     - id : long | ||||
|     - price : double | ||||
|     - title : String | ||||
|     # Book() | ||||
|     + Book(title : String, price : double, author : Author) | ||||
|     + getAuthor() : Author | ||||
|     + getId() : long | ||||
|     + getPrice() : double | ||||
|     + getTitle() : String | ||||
|     + setAuthor(author : Author) | ||||
|     + setId(id : long) | ||||
|     + setPrice(price : double) | ||||
|     + setTitle(title : String) | ||||
|     + toString() : String | ||||
|   } | ||||
| } | ||||
| Book -->  "-author" Author | ||||
| CommandServiceImpl ..|> ICommandService  | ||||
| QueryServiceImpl ..|> IQueryService  | ||||
| @enduml | ||||
							
								
								
									
										42
									
								
								cqrs/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								cqrs/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| <?xml version="1.0"?> | ||||
| <!-- The MIT License Copyright (c) 2014-2016 Ilkka Seppälä Permission is  | ||||
| 	hereby granted, free of charge, to any person obtaining a copy of this software  | ||||
| 	and associated documentation files (the "Software"), to deal in the Software  | ||||
| 	without restriction, including without limitation the rights to use, copy,  | ||||
| 	modify, merge, publish, distribute, sublicense, and/or sell copies of the  | ||||
| 	Software, and to permit persons to whom the Software is furnished to do so,  | ||||
| 	subject to the following conditions: The above copyright notice and this  | ||||
| 	permission notice shall be included in all copies or substantial portions  | ||||
| 	of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY  | ||||
| 	KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  | ||||
| 	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN  | ||||
| 	NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,  | ||||
| 	DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,  | ||||
| 	ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER  | ||||
| 	DEALINGS IN THE SOFTWARE. --> | ||||
| <project | ||||
| 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" | ||||
| 	xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | ||||
| 	<modelVersion>4.0.0</modelVersion> | ||||
| 	<parent> | ||||
| 		<groupId>com.iluwatar</groupId> | ||||
| 		<artifactId>java-design-patterns</artifactId> | ||||
| 		<version>1.17.0-SNAPSHOT</version> | ||||
| 	</parent> | ||||
| 	<artifactId>cqrs</artifactId> | ||||
| 	<dependencies> | ||||
| 		<dependency> | ||||
| 			<groupId>junit</groupId> | ||||
| 			<artifactId>junit</artifactId> | ||||
| 			<scope>test</scope> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>com.h2database</groupId> | ||||
| 			<artifactId>h2</artifactId> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.hibernate</groupId> | ||||
| 			<artifactId>hibernate-core</artifactId> | ||||
| 		</dependency> | ||||
| 	</dependencies> | ||||
| </project> | ||||
							
								
								
									
										95
									
								
								cqrs/src/main/java/com/iluwatar/cqrs/app/App.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								cqrs/src/main/java/com/iluwatar/cqrs/app/App.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| /** | ||||
|  * The MIT License | ||||
|  * Copyright (c) 2014-2016 Ilkka Seppälä | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
| package com.iluwatar.cqrs.app; | ||||
|  | ||||
| import java.math.BigInteger; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| import com.iluwatar.cqrs.commandes.CommandServiceImpl; | ||||
| import com.iluwatar.cqrs.commandes.ICommandService; | ||||
| import com.iluwatar.cqrs.dto.Author; | ||||
| import com.iluwatar.cqrs.dto.Book; | ||||
| import com.iluwatar.cqrs.queries.IQueryService; | ||||
| import com.iluwatar.cqrs.queries.QueryServiceImpl; | ||||
| import com.iluwatar.cqrs.util.HibernateUtil; | ||||
|  | ||||
| /** | ||||
|  * CQRS : Command Query Responsibility Segregation. A pattern used to separate query services from commands or writes | ||||
|  * services. The pattern is very simple but it has many consequences. For example, it can be used to tackle down a | ||||
|  * complex domain, or to use other architectures that were hard to implement with the classical way. | ||||
|  *  | ||||
|  * This implementation is an example of managing books and authors in a library. The persistence of books and authors is | ||||
|  * done according to the CQRS architecture. A command side that deals with a data model to persist(insert,update,delete) | ||||
|  * objects to a database. And a query side that uses native queries to get data from the database and return objects as | ||||
|  * DTOs (Data transfer Objects). | ||||
|  * | ||||
|  */ | ||||
| public class App { | ||||
|   private static final Logger LOGGER = LoggerFactory.getLogger(App.class); | ||||
|  | ||||
|   /** | ||||
|    * Program entry point | ||||
|    *  | ||||
|    * @param args | ||||
|    *          command line args | ||||
|    */ | ||||
|   public static void main(String[] args) { | ||||
|     ICommandService commands = new CommandServiceImpl(); | ||||
|  | ||||
|     // Create Authors and Books using CommandService | ||||
|     commands.authorCreated("eEvans", "Eric Evans", "eEvans@email.com"); | ||||
|     commands.authorCreated("jBloch", "Joshua Bloch", "jBloch@email.com"); | ||||
|     commands.authorCreated("mFowler", "Martin Fowler", "mFowler@email.com"); | ||||
|  | ||||
|     commands.bookAddedToAuthor("Domain-Driven Design", 60.08, "eEvans"); | ||||
|     commands.bookAddedToAuthor("Effective Java", 40.54, "jBloch"); | ||||
|     commands.bookAddedToAuthor("Java Puzzlers", 39.99, "jBloch"); | ||||
|     commands.bookAddedToAuthor("Java Concurrency in Practice", 29.40, "jBloch"); | ||||
|     commands.bookAddedToAuthor("Patterns of Enterprise Application Architecture", 54.01, "mFowler"); | ||||
|     commands.bookAddedToAuthor("Domain Specific Languages", 48.89, "mFowler"); | ||||
|     commands.authorNameUpdated("eEvans", "Eric J. Evans"); | ||||
|  | ||||
|     IQueryService queries = new QueryServiceImpl(); | ||||
|  | ||||
|     // Query the database using QueryService | ||||
|     Author nullAuthor = queries.getAuthorByUsername("username"); | ||||
|     Author eEvans = queries.getAuthorByUsername("eEvans"); | ||||
|     BigInteger jBlochBooksCount = queries.getAuthorBooksCount("jBloch"); | ||||
|     BigInteger authorsCount = queries.getAuthorsCount(); | ||||
|     Book dddBook = queries.getBook("Domain-Driven Design"); | ||||
|     List<Book> jBlochBooks = queries.getAuthorBooks("jBloch"); | ||||
|  | ||||
|     LOGGER.info("Author username : {}", nullAuthor); | ||||
|     LOGGER.info("Author eEvans : {}", eEvans); | ||||
|     LOGGER.info("jBloch number of books : {}", jBlochBooksCount); | ||||
|     LOGGER.info("Number of authors : {}", authorsCount); | ||||
|     LOGGER.info("DDD book : {}", dddBook); | ||||
|     LOGGER.info("jBloch books : {}", jBlochBooks); | ||||
|  | ||||
|     HibernateUtil.getSessionFactory().close(); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,123 @@ | ||||
| package com.iluwatar.cqrs.commandes; | ||||
|  | ||||
| import org.hibernate.Query; | ||||
| import org.hibernate.Session; | ||||
| import org.hibernate.SessionFactory; | ||||
|  | ||||
| import com.iluwatar.cqrs.domain.model.Author; | ||||
| import com.iluwatar.cqrs.domain.model.Book; | ||||
| import com.iluwatar.cqrs.util.HibernateUtil; | ||||
|  | ||||
| /** | ||||
|  * This class is an implementation of {@link ICommandService} interface. It uses Hibernate as an api for persistence. | ||||
|  * | ||||
|  */ | ||||
| public class CommandServiceImpl implements ICommandService { | ||||
|  | ||||
|   private SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); | ||||
|  | ||||
|   private Author getAuthorByUsername(String username) { | ||||
|     Author author = null; | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       Query query = session.createQuery("from Author where username=:username"); | ||||
|       query.setParameter("username", username); | ||||
|       author = (Author) query.uniqueResult(); | ||||
|     } | ||||
|     if (author == null) { | ||||
|       HibernateUtil.getSessionFactory().close(); | ||||
|       throw new NullPointerException("Author " + username + " doesn't exist!"); | ||||
|     } | ||||
|     return author; | ||||
|   } | ||||
|  | ||||
|   private Book getBookByTitle(String title) { | ||||
|     Book book = null; | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       Query query = session.createQuery("from Book where title=:title"); | ||||
|       query.setParameter("title", title); | ||||
|       book = (Book) query.uniqueResult(); | ||||
|     } | ||||
|     if (book == null) { | ||||
|       HibernateUtil.getSessionFactory().close(); | ||||
|       throw new NullPointerException("Book " + title + " doesn't exist!"); | ||||
|     } | ||||
|     return book; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void authorCreated(String username, String name, String email) { | ||||
|     Author author = new Author(username, name, email); | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       session.beginTransaction(); | ||||
|       session.save(author); | ||||
|       session.getTransaction().commit(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void bookAddedToAuthor(String title, double price, String username) { | ||||
|     Author author = getAuthorByUsername(username); | ||||
|     Book book = new Book(title, price, author); | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       session.beginTransaction(); | ||||
|       session.save(book); | ||||
|       session.getTransaction().commit(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void authorNameUpdated(String username, String name) { | ||||
|     Author author = getAuthorByUsername(username); | ||||
|     author.setName(name); | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       session.beginTransaction(); | ||||
|       session.update(author); | ||||
|       session.getTransaction().commit(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void authorUsernameUpdated(String oldUsername, String newUsername) { | ||||
|     Author author = getAuthorByUsername(oldUsername); | ||||
|     author.setUsername(newUsername); | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       session.beginTransaction(); | ||||
|       session.update(author); | ||||
|       session.getTransaction().commit(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void authorEmailUpdated(String username, String email) { | ||||
|     Author author = getAuthorByUsername(username); | ||||
|     author.setEmail(email); | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       session.beginTransaction(); | ||||
|       session.update(author); | ||||
|       session.getTransaction().commit(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void bookTitleUpdated(String oldTitle, String newTitle) { | ||||
|     Book book = getBookByTitle(oldTitle); | ||||
|     book.setTitle(newTitle); | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       session.beginTransaction(); | ||||
|       session.update(book); | ||||
|       session.getTransaction().commit(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void bookPriceUpdated(String title, double price) { | ||||
|     Book book = getBookByTitle(title); | ||||
|     book.setPrice(price); | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       session.beginTransaction(); | ||||
|       session.update(book); | ||||
|       session.getTransaction().commit(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,23 @@ | ||||
| package com.iluwatar.cqrs.commandes; | ||||
|  | ||||
| /** | ||||
|  * This interface represents the commands of the CQRS pattern | ||||
|  * | ||||
|  */ | ||||
| public interface ICommandService { | ||||
|  | ||||
|   void authorCreated(String username, String name, String email); | ||||
|  | ||||
|   void bookAddedToAuthor(String title, double price, String username); | ||||
|  | ||||
|   void authorNameUpdated(String username, String name); | ||||
|  | ||||
|   void authorUsernameUpdated(String oldUsername, String newUsername); | ||||
|  | ||||
|   void authorEmailUpdated(String username, String email); | ||||
|  | ||||
|   void bookTitleUpdated(String oldTitle, String newTitle); | ||||
|  | ||||
|   void bookPriceUpdated(String title, double price); | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,78 @@ | ||||
| package com.iluwatar.cqrs.domain.model; | ||||
|  | ||||
| import javax.persistence.Entity; | ||||
| import javax.persistence.GeneratedValue; | ||||
| import javax.persistence.GenerationType; | ||||
| import javax.persistence.Id; | ||||
|  | ||||
| /** | ||||
|  * This is an Author entity. It is used by Hibernate for persistence. | ||||
|  * | ||||
|  */ | ||||
| @Entity | ||||
| public class Author { | ||||
|   @Id | ||||
|   @GeneratedValue(strategy = GenerationType.IDENTITY) | ||||
|   private long id; | ||||
|   private String username; | ||||
|   private String name; | ||||
|   private String email; | ||||
|  | ||||
|   /** | ||||
|    *  | ||||
|    * @param username | ||||
|    *          username of the author | ||||
|    * @param name | ||||
|    *          name of the author | ||||
|    * @param email | ||||
|    *          email of the author | ||||
|    */ | ||||
|   public Author(String username, String name, String email) { | ||||
|     super(); | ||||
|     this.username = username; | ||||
|     this.name = name; | ||||
|     this.email = email; | ||||
|   } | ||||
|  | ||||
|   protected Author() { | ||||
|     super(); | ||||
|   } | ||||
|  | ||||
|   public long getId() { | ||||
|     return id; | ||||
|   } | ||||
|  | ||||
|   public void setId(long id) { | ||||
|     this.id = id; | ||||
|   } | ||||
|  | ||||
|   public String getUsername() { | ||||
|     return username; | ||||
|   } | ||||
|  | ||||
|   public void setUsername(String username) { | ||||
|     this.username = username; | ||||
|   } | ||||
|  | ||||
|   public String getName() { | ||||
|     return name; | ||||
|   } | ||||
|  | ||||
|   public void setName(String name) { | ||||
|     this.name = name; | ||||
|   } | ||||
|  | ||||
|   public String getEmail() { | ||||
|     return email; | ||||
|   } | ||||
|  | ||||
|   public void setEmail(String email) { | ||||
|     this.email = email; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String toString() { | ||||
|     return "Author [name=" + name + ", email=" + email + "]"; | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										80
									
								
								cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Book.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Book.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| package com.iluwatar.cqrs.domain.model; | ||||
|  | ||||
| import javax.persistence.Entity; | ||||
| import javax.persistence.GeneratedValue; | ||||
| import javax.persistence.GenerationType; | ||||
| import javax.persistence.Id; | ||||
| import javax.persistence.ManyToOne; | ||||
|  | ||||
| /** | ||||
|  * This is a Book entity. It is used by Hibernate for persistence. Many books can be written by one {@link Author} | ||||
|  * | ||||
|  */ | ||||
| @Entity | ||||
| public class Book { | ||||
|   @Id | ||||
|   @GeneratedValue(strategy = GenerationType.IDENTITY) | ||||
|   private long id; | ||||
|   private String title; | ||||
|   private double price; | ||||
|   @ManyToOne | ||||
|   private Author author; | ||||
|  | ||||
|   /** | ||||
|    *  | ||||
|    * @param title | ||||
|    *          title of the book | ||||
|    * @param price | ||||
|    *          price of the book | ||||
|    * @param author | ||||
|    *          author of the book | ||||
|    */ | ||||
|   public Book(String title, double price, Author author) { | ||||
|     super(); | ||||
|     this.title = title; | ||||
|     this.price = price; | ||||
|     this.author = author; | ||||
|   } | ||||
|  | ||||
|   protected Book() { | ||||
|     super(); | ||||
|   } | ||||
|  | ||||
|   public long getId() { | ||||
|     return id; | ||||
|   } | ||||
|  | ||||
|   public void setId(long id) { | ||||
|     this.id = id; | ||||
|   } | ||||
|  | ||||
|   public String getTitle() { | ||||
|     return title; | ||||
|   } | ||||
|  | ||||
|   public void setTitle(String title) { | ||||
|     this.title = title; | ||||
|   } | ||||
|  | ||||
|   public double getPrice() { | ||||
|     return price; | ||||
|   } | ||||
|  | ||||
|   public void setPrice(double price) { | ||||
|     this.price = price; | ||||
|   } | ||||
|  | ||||
|   public Author getAuthor() { | ||||
|     return author; | ||||
|   } | ||||
|  | ||||
|   public void setAuthor(Author author) { | ||||
|     this.author = author; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String toString() { | ||||
|     return "Book [title=" + title + ", price=" + price + ", author=" + author + "]"; | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										71
									
								
								cqrs/src/main/java/com/iluwatar/cqrs/dto/Author.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								cqrs/src/main/java/com/iluwatar/cqrs/dto/Author.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| package com.iluwatar.cqrs.dto; | ||||
|  | ||||
| import java.util.Objects; | ||||
|  | ||||
| /** | ||||
|  *  | ||||
|  * This is a DTO (Data Transfer Object) author, contains only useful information to be returned | ||||
|  * | ||||
|  */ | ||||
| public class Author { | ||||
|  | ||||
|   private String name; | ||||
|   private String email; | ||||
|   private String username; | ||||
|  | ||||
|   /** | ||||
|    *  | ||||
|    * @param name | ||||
|    *          name of the author | ||||
|    * @param email | ||||
|    *          email of the author | ||||
|    * @param username | ||||
|    *          username of the author | ||||
|    */ | ||||
|   public Author(String name, String email, String username) { | ||||
|     super(); | ||||
|     this.name = name; | ||||
|     this.email = email; | ||||
|     this.username = username; | ||||
|   } | ||||
|  | ||||
|   public Author() { | ||||
|     super(); | ||||
|   } | ||||
|  | ||||
|   public String getName() { | ||||
|     return name; | ||||
|   } | ||||
|  | ||||
|   public String getEmail() { | ||||
|     return email; | ||||
|   } | ||||
|  | ||||
|   public String getUsername() { | ||||
|     return username; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String toString() { | ||||
|     return "AuthorDTO [name=" + name + ", email=" + email + ", username=" + username + "]"; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public int hashCode() { | ||||
|     return Objects.hash(username, name, email); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public boolean equals(Object obj) { | ||||
|     if (this == obj) { | ||||
|       return true; | ||||
|     } | ||||
|     if (!(obj instanceof Author)) { | ||||
|       return false; | ||||
|     } | ||||
|     Author other = (Author) obj; | ||||
|     return username.equals(other.getUsername()) && email.equals(other.getEmail()) && name.equals(other.getName()); | ||||
|  | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										62
									
								
								cqrs/src/main/java/com/iluwatar/cqrs/dto/Book.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								cqrs/src/main/java/com/iluwatar/cqrs/dto/Book.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| package com.iluwatar.cqrs.dto; | ||||
|  | ||||
| import java.util.Objects; | ||||
|  | ||||
| /** | ||||
|  *  | ||||
|  * This is a DTO (Data Transfer Object) book, contains only useful information to be returned | ||||
|  * | ||||
|  */ | ||||
| public class Book { | ||||
|  | ||||
|   private String title; | ||||
|   private double price; | ||||
|  | ||||
|   /** | ||||
|    *  | ||||
|    * @param title | ||||
|    *          title of the book | ||||
|    * @param price | ||||
|    *          price of the book | ||||
|    */ | ||||
|   public Book(String title, double price) { | ||||
|     super(); | ||||
|     this.title = title; | ||||
|     this.price = price; | ||||
|   } | ||||
|  | ||||
|   public Book() { | ||||
|     super(); | ||||
|   } | ||||
|  | ||||
|   public String getTitle() { | ||||
|     return title; | ||||
|   } | ||||
|  | ||||
|   public double getPrice() { | ||||
|     return price; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String toString() { | ||||
|     return "BookDTO [title=" + title + ", price=" + price + "]"; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public int hashCode() { | ||||
|     return Objects.hash(title, price); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public boolean equals(Object obj) { | ||||
|     if (this == obj) { | ||||
|       return true; | ||||
|     } | ||||
|     if (!(obj instanceof Book)) { | ||||
|       return false; | ||||
|     } | ||||
|     Book book = (Book) obj; | ||||
|     return title.equals(book.getTitle()) && price == book.getPrice(); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,26 @@ | ||||
| package com.iluwatar.cqrs.queries; | ||||
|  | ||||
| import java.math.BigInteger; | ||||
| import java.util.List; | ||||
|  | ||||
| import com.iluwatar.cqrs.dto.Author; | ||||
| import com.iluwatar.cqrs.dto.Book; | ||||
|  | ||||
| /** | ||||
|  *  | ||||
|  * This interface represents the query methods of the CQRS pattern | ||||
|  * | ||||
|  */ | ||||
| public interface IQueryService { | ||||
|  | ||||
|   Author getAuthorByUsername(String username); | ||||
|  | ||||
|   Book getBook(String title); | ||||
|  | ||||
|   List<Book> getAuthorBooks(String username); | ||||
|  | ||||
|   BigInteger getAuthorBooksCount(String username); | ||||
|  | ||||
|   BigInteger getAuthorsCount(); | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,83 @@ | ||||
| package com.iluwatar.cqrs.queries; | ||||
|  | ||||
| import java.math.BigInteger; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.hibernate.SQLQuery; | ||||
| import org.hibernate.Session; | ||||
| import org.hibernate.SessionFactory; | ||||
| import org.hibernate.transform.Transformers; | ||||
|  | ||||
| import com.iluwatar.cqrs.dto.Author; | ||||
| import com.iluwatar.cqrs.dto.Book; | ||||
| import com.iluwatar.cqrs.util.HibernateUtil; | ||||
|  | ||||
| /** | ||||
|  * This class is an implementation of {@link IQueryService}. It uses Hibernate native queries to return DTOs from the | ||||
|  * database. | ||||
|  * | ||||
|  */ | ||||
| public class QueryServiceImpl implements IQueryService { | ||||
|  | ||||
|   private SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); | ||||
|  | ||||
|   @Override | ||||
|   public Author getAuthorByUsername(String username) { | ||||
|     Author authorDTo = null; | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       SQLQuery sqlQuery = session | ||||
|           .createSQLQuery("SELECT a.username as \"username\", a.name as \"name\", a.email as \"email\"" | ||||
|               + "FROM Author a where a.username=:username"); | ||||
|       sqlQuery.setParameter("username", username); | ||||
|       authorDTo = (Author) sqlQuery.setResultTransformer(Transformers.aliasToBean(Author.class)).uniqueResult(); | ||||
|     } | ||||
|     return authorDTo; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public Book getBook(String title) { | ||||
|     Book bookDTo = null; | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       SQLQuery sqlQuery = session | ||||
|           .createSQLQuery("SELECT b.title as \"title\", b.price as \"price\"" + " FROM Book b where b.title=:title"); | ||||
|       sqlQuery.setParameter("title", title); | ||||
|       bookDTo = (Book) sqlQuery.setResultTransformer(Transformers.aliasToBean(Book.class)).uniqueResult(); | ||||
|     } | ||||
|     return bookDTo; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public List<Book> getAuthorBooks(String username) { | ||||
|     List<Book> bookDTos = null; | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       SQLQuery sqlQuery = session.createSQLQuery("SELECT b.title as \"title\", b.price as \"price\"" | ||||
|           + " FROM Author a , Book b where b.author_id = a.id and a.username=:username"); | ||||
|       sqlQuery.setParameter("username", username); | ||||
|       bookDTos = sqlQuery.setResultTransformer(Transformers.aliasToBean(Book.class)).list(); | ||||
|     } | ||||
|     return bookDTos; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public BigInteger getAuthorBooksCount(String username) { | ||||
|     BigInteger bookcount = null; | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       SQLQuery sqlQuery = session.createSQLQuery( | ||||
|           "SELECT count(b.title)" + " FROM  Book b, Author a where b.author_id = a.id and a.username=:username"); | ||||
|       sqlQuery.setParameter("username", username); | ||||
|       bookcount = (BigInteger) sqlQuery.uniqueResult(); | ||||
|     } | ||||
|     return bookcount; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public BigInteger getAuthorsCount() { | ||||
|     BigInteger authorcount = null; | ||||
|     try (Session session = sessionFactory.openSession()) { | ||||
|       SQLQuery sqlQuery = session.createSQLQuery("SELECT count(id) from Author"); | ||||
|       authorcount = (BigInteger) sqlQuery.uniqueResult(); | ||||
|     } | ||||
|     return authorcount; | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										36
									
								
								cqrs/src/main/java/com/iluwatar/cqrs/util/HibernateUtil.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								cqrs/src/main/java/com/iluwatar/cqrs/util/HibernateUtil.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| package com.iluwatar.cqrs.util; | ||||
|  | ||||
| import org.hibernate.SessionFactory; | ||||
| import org.hibernate.boot.MetadataSources; | ||||
| import org.hibernate.boot.registry.StandardServiceRegistry; | ||||
| import org.hibernate.boot.registry.StandardServiceRegistryBuilder; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| /** | ||||
|  * This class simply returns one instance of {@link SessionFactory} initialized when the application is started | ||||
|  * | ||||
|  */ | ||||
| public class HibernateUtil { | ||||
|  | ||||
|   private static final SessionFactory SESSIONFACTORY = buildSessionFactory(); | ||||
|   private static final Logger LOGGER = LoggerFactory.getLogger(HibernateUtil.class); | ||||
|  | ||||
|   private static SessionFactory buildSessionFactory() { | ||||
|  | ||||
|     // configures settings from hibernate.cfg.xml | ||||
|     final StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build(); | ||||
|     try { | ||||
|       return new MetadataSources(registry).buildMetadata().buildSessionFactory(); | ||||
|     } catch (Exception ex) { | ||||
|       StandardServiceRegistryBuilder.destroy(registry); | ||||
|       LOGGER.error("Initial SessionFactory creation failed." + ex); | ||||
|       throw new ExceptionInInitializerError(ex); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public static SessionFactory getSessionFactory() { | ||||
|     return SESSIONFACTORY; | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										15
									
								
								cqrs/src/main/resources/hibernate.cfg.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								cqrs/src/main/resources/hibernate.cfg.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!DOCTYPE hibernate-configuration SYSTEM | ||||
| "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> | ||||
|  | ||||
| <hibernate-configuration> | ||||
|     <session-factory> | ||||
|         <property name="dialect">org.hibernate.dialect.H2Dialect</property> | ||||
|         <property name="connection.driver_class">org.h2.Driver</property> | ||||
|         <property name="connection.url">jdbc:h2:mem:test</property> | ||||
|         <property name="connection.username">sa</property> | ||||
|         <property name="hbm2ddl.auto">create</property> | ||||
|         <mapping class="com.iluwatar.cqrs.domain.model.Author" /> | ||||
|         <mapping class="com.iluwatar.cqrs.domain.model.Book" /> | ||||
|     </session-factory> | ||||
| </hibernate-configuration> | ||||
							
								
								
									
										13
									
								
								cqrs/src/main/resources/logback.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								cqrs/src/main/resources/logback.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <configuration> | ||||
|     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | ||||
|         <encoder> | ||||
|             <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n | ||||
|             </pattern> | ||||
|         </encoder> | ||||
|     </appender> | ||||
|  | ||||
|     <root level="info"> | ||||
|         <appender-ref ref="STDOUT" /> | ||||
|     </root> | ||||
| </configuration> | ||||
							
								
								
									
										98
									
								
								cqrs/src/test/java/com/iluwatar/cqrs/IntegrationTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								cqrs/src/test/java/com/iluwatar/cqrs/IntegrationTest.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| package com.iluwatar.cqrs; | ||||
|  | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertTrue; | ||||
|  | ||||
| import java.math.BigInteger; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.junit.BeforeClass; | ||||
| import org.junit.Test; | ||||
|  | ||||
| import com.iluwatar.cqrs.commandes.CommandServiceImpl; | ||||
| import com.iluwatar.cqrs.commandes.ICommandService; | ||||
| import com.iluwatar.cqrs.dto.Author; | ||||
| import com.iluwatar.cqrs.dto.Book; | ||||
| import com.iluwatar.cqrs.queries.IQueryService; | ||||
| import com.iluwatar.cqrs.queries.QueryServiceImpl; | ||||
|  | ||||
| /** | ||||
|  * Integration test of IQueryService and ICommandService with h2 data | ||||
|  * | ||||
|  */ | ||||
| public class IntegrationTest { | ||||
|  | ||||
|   private static IQueryService queryService; | ||||
|   private static ICommandService commandService; | ||||
|  | ||||
|   @BeforeClass | ||||
|   public static void initialize() { | ||||
|     commandService = new CommandServiceImpl(); | ||||
|     queryService = new QueryServiceImpl(); | ||||
|   } | ||||
|  | ||||
|   @BeforeClass | ||||
|   public static void populateDatabase() { | ||||
|     // create first author1 | ||||
|     commandService.authorCreated("username1", "name1", "email1"); | ||||
|  | ||||
|     // create author1 and update all its data | ||||
|     commandService.authorCreated("username2", "name2", "email2"); | ||||
|     commandService.authorEmailUpdated("username2", "new_email2"); | ||||
|     commandService.authorNameUpdated("username2", "new_name2"); | ||||
|     commandService.authorUsernameUpdated("username2", "new_username2"); | ||||
|  | ||||
|     // add book1 to author1 | ||||
|     commandService.bookAddedToAuthor("title1", 10, "username1"); | ||||
|  | ||||
|     // add book2 to author1 and update all its data | ||||
|     commandService.bookAddedToAuthor("title2", 20, "username1"); | ||||
|     commandService.bookPriceUpdated("title2", 30); | ||||
|     commandService.bookTitleUpdated("title2", "new_title2"); | ||||
|  | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void testGetAuthorByUsername() { | ||||
|     Author author = queryService.getAuthorByUsername("username1"); | ||||
|     assertEquals("username1", author.getUsername()); | ||||
|     assertEquals("name1", author.getName()); | ||||
|     assertEquals("email1", author.getEmail()); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void testGetUpdatedAuthorByUsername() { | ||||
|     Author author = queryService.getAuthorByUsername("new_username2"); | ||||
|     Author expectedAuthor = new Author("new_name2", "new_email2", "new_username2"); | ||||
|     assertEquals(expectedAuthor, author); | ||||
|  | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void testGetBook() { | ||||
|     Book book = queryService.getBook("title1"); | ||||
|     assertEquals("title1", book.getTitle()); | ||||
|     assertEquals(10, book.getPrice(), 0); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void testGetAuthorBooks() { | ||||
|     List<Book> books = queryService.getAuthorBooks("username1"); | ||||
|     assertTrue(books.size() == 2); | ||||
|     assertTrue(books.contains(new Book("title1", 10))); | ||||
|     assertTrue(books.contains(new Book("new_title2", 30))); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void testGetAuthorBooksCount() { | ||||
|     BigInteger bookCount = queryService.getAuthorBooksCount("username1"); | ||||
|     assertEquals(new BigInteger("2"), bookCount); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void testGetAuthorsCount() { | ||||
|     BigInteger authorCount = queryService.getAuthorsCount(); | ||||
|     assertEquals(new BigInteger("2"), authorCount); | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										15
									
								
								cqrs/src/test/resources/hibernate.cfg.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								cqrs/src/test/resources/hibernate.cfg.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!DOCTYPE hibernate-configuration SYSTEM | ||||
| "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> | ||||
|  | ||||
| <hibernate-configuration> | ||||
|     <session-factory> | ||||
|         <property name="dialect">org.hibernate.dialect.H2Dialect</property> | ||||
|         <property name="connection.driver_class">org.h2.Driver</property> | ||||
|         <property name="connection.url">jdbc:h2:mem:test</property> | ||||
|         <property name="connection.username">sa</property> | ||||
|         <property name="hbm2ddl.auto">create</property> | ||||
|         <mapping class="com.iluwatar.cqrs.domain.model.Author" /> | ||||
|         <mapping class="com.iluwatar.cqrs.domain.model.Book" /> | ||||
|     </session-factory> | ||||
| </hibernate-configuration> | ||||
							
								
								
									
										13
									
								
								cqrs/src/test/resources/logback.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								cqrs/src/test/resources/logback.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <configuration> | ||||
|     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | ||||
|         <encoder> | ||||
|             <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n | ||||
|             </pattern> | ||||
|         </encoder> | ||||
|     </appender> | ||||
|  | ||||
|     <root level="info"> | ||||
|         <appender-ref ref="STDOUT" /> | ||||
|     </root> | ||||
| </configuration> | ||||
		Reference in New Issue
	
	Block a user