├── LICENSE.txt ├── README.md ├── contributing.md └── ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master ├── README.md ├── docker-compose └── dependencies.yml ├── ebook-chat ├── pom.xml └── src │ ├── main │ ├── java │ │ └── br │ │ │ └── com │ │ │ └── jorgeacetozi │ │ │ └── ebookChat │ │ │ ├── Application.java │ │ │ ├── authentication │ │ │ ├── api │ │ │ │ └── AuthenticationController.java │ │ │ └── domain │ │ │ │ ├── model │ │ │ │ ├── Role.java │ │ │ │ └── User.java │ │ │ │ ├── repository │ │ │ │ ├── RoleRepository.java │ │ │ │ └── UserRepository.java │ │ │ │ ├── service │ │ │ │ ├── DefaultUserService.java │ │ │ │ ├── UserDetailsServiceImpl.java │ │ │ │ └── UserService.java │ │ │ │ └── validator │ │ │ │ └── NewUserValidator.java │ │ │ ├── chat │ │ │ └── api │ │ │ │ └── ChatController.java │ │ │ ├── chatroom │ │ │ ├── api │ │ │ │ └── ChatRoomController.java │ │ │ ├── domain │ │ │ │ ├── model │ │ │ │ │ ├── ChatRoom.java │ │ │ │ │ ├── ChatRoomUser.java │ │ │ │ │ ├── InstantMessage.java │ │ │ │ │ └── InstantMessageBuilder.java │ │ │ │ ├── repository │ │ │ │ │ ├── ChatRoomRepository.java │ │ │ │ │ └── InstantMessageRepository.java │ │ │ │ └── service │ │ │ │ │ ├── CassandraInstantMessageService.java │ │ │ │ │ ├── ChatRoomService.java │ │ │ │ │ ├── InstantMessageService.java │ │ │ │ │ └── RedisChatRoomService.java │ │ │ └── websocket │ │ │ │ └── WebSocketEvents.java │ │ │ ├── configuration │ │ │ ├── CassandraConfig.java │ │ │ ├── WebConfig.java │ │ │ ├── WebSecurityConfig.java │ │ │ └── WebSocketConfigSpringSession.java │ │ │ └── utils │ │ │ ├── Destinations.java │ │ │ ├── SystemMessages.java │ │ │ └── SystemUsers.java │ └── resources │ │ ├── application.yml │ │ ├── db │ │ ├── create_database_mysql.sql │ │ ├── create_keyspace_cassandra.cql │ │ └── migration │ │ │ └── V1__init.sql │ │ ├── messages.properties │ │ ├── messages_pt.properties │ │ └── templates │ │ ├── chat.html │ │ ├── chatroom.html │ │ ├── layout │ │ └── default.html │ │ ├── login.html │ │ └── new-account.html │ └── test │ └── java │ └── br │ └── com │ └── jorgeacetozi │ └── ebookChat │ ├── integrationTests │ ├── IntegrationTestsSuite.java │ ├── authentication │ │ ├── api │ │ │ └── AuthenticationControllerTest.java │ │ └── domain │ │ │ └── service │ │ │ └── DefaultUserServiceTest.java │ ├── chatroom │ │ ├── api │ │ │ └── ChatRoomControllerTest.java │ │ └── domain │ │ │ └── service │ │ │ ├── CassandraInstantMessageServiceTest.java │ │ │ └── RedisChatRoomServiceTest.java │ └── test │ │ ├── AbstractIntegrationTest.java │ │ └── EbookChatTest.java │ └── unitTests │ ├── UnitTestsSuite.java │ ├── chatroom │ └── domain │ │ ├── model │ │ └── InstantMessageBuilderTest.java │ │ └── service │ │ └── RedisChatRoomServiceTest.java │ └── utils │ ├── DestinationsTest.java │ └── SystemMessagesTest.java └── images ├── ebook-chat-application.png └── title_page.png /LICENSE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-java-clustering-scalability/b3cbfbda4d6a1fa7c3a3b2c3f3c537310dd767a6/LICENSE.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apress Source Code 2 | 3 | This repository accompanies [*Pro Java Clustering and Scalability*](http://www.apress.com/9781484229842) by Jorge Acetozi (Apress, 2017). 4 | 5 | [comment]: #cover 6 | 7 | 8 | Download the files as a zip using the green button, or clone the repository to your machine using Git. 9 | 10 | ## Releases 11 | 12 | Release v1.0 corresponds to the code in the published book, without corrections or updates. 13 | 14 | ## Contributions 15 | 16 | See the file Contributing.md for more information on how you can contribute to this repository. 17 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apress Source Code 2 | 3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/README.md: -------------------------------------------------------------------------------- 1 | # Building a Real-Time Chat Application with Spring Boot, WebSocket, Cassandra, Redis and RabbitMQ 2 | 3 | ![Chat Application](/images/ebook-chat-application.png) 4 | 5 | ## Check my eBook for a step-by-step code guide for the `ebook-chat` project: 6 | - https://leanpub.com/building-a-real-time-chat-application-with-spring-boot-websocket-cassandra-redis-and-rabbitmq 7 | 8 | **There is a sample book version available for download on the above link as well. It has 80 pages and brings many interesting topics like Introduction to NoSQL, Cassandra, Redis, Spring Boot, Spring Data and Introduction to WebSockets and STOMP protocol**. 9 | 10 | ![eBook Chat Application](/images/title_page.png) 11 | 12 | # Technologies used in this project 13 | 14 | - Spring Boot 15 | - Spring Data (JPA / Cassandra / Redis) 16 | - Spring Security 17 | - Spring WebSocket 18 | - Spring Session 19 | - Cassandra 20 | - Redis 21 | - RabbitMQ 22 | - MySQL 23 | - JUnit, Mockito and TestContainers (spin up Docker containers for Integration Tests) 24 | - Thymeleaf, JQuery and Bootstrap 25 | - Apache Maven (Surefire and Failsafe plugins) 26 | 27 | # Setting up this project locally 28 | 29 | > **Note:** 30 | The fastest way to get this application up and running locally is using **Docker** and **Docker Compose**. Be sure that you have at least **Docker 1.13.0** and **Docker Compose 1.11.2** installed on your machine. 31 | 32 | 1. Clone this repository 33 | ```shell 34 | $ git clone git@github.com:jorgeacetozi/ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq.git 35 | ``` 36 | 2. Setup the dependencies (Cassandra, Redis, MySQL and RabbitMQ with STOMP support) 37 | 38 | ```shell 39 | $ docker-compose -f docker-compose/dependencies.yml up 40 | ``` 41 | 42 | 3. Start the application 43 | 44 | ```shell 45 | $ wget https://github.com/jorgeacetozi/ebook-chat-app-spring-websocket-cassandra-redis/releases/download/ebook-chat-1.0.0/ebook-chat-1.0.0.jar && java -jar ebook-chat-1.0.0.jar 46 | ``` 47 | 48 | # Basic Usage 49 | 50 | 1. Sign in with username **admin** and password **admin** 51 | 2. Create a **New Chat Room** and logout 52 | 3. Create your private account 53 | 4. Sign in with your account credentials 54 | 5. Join the chat room 55 | 6. Open a new incognito window and create another account 56 | 7. Sign in with this another account 57 | 8. Join the chat room 58 | 9. Send some messages 59 | 10. Open the other browser window and see the messages coming 60 | 11. Click the username to send private messages 61 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/docker-compose/dependencies.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | redis: 4 | image: "redis:3.0.6" 5 | ports: 6 | - "6379:6379" 7 | cassandra: 8 | image: "cassandra:3.0" 9 | ports: 10 | - "9042:9042" 11 | mysql: 12 | image: "mysql:5.7" 13 | ports: 14 | - "3306:3306" 15 | environment: 16 | MYSQL_ROOT_PASSWORD: root 17 | MYSQL_DATABASE: ebook_chat 18 | rabbitmq-stomp: 19 | image: "jorgeacetozi/rabbitmq-stomp:3.6" 20 | ports: 21 | - "5672:5672" 22 | - "15672:15672" 23 | - "61613:61613" 24 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | br.com.jorgeacetozi 7 | ebook-chat 8 | 1.0.1-SNAPSHOT 9 | jar 10 | 11 | Jorge Acetozi - eBook Chat Application 12 | Final project for my free ebook on LeanPub 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.5.2.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-websocket 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-security 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-data-jpa 43 | 44 | 45 | mysql 46 | mysql-connector-java 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-starter-data-redis 51 | 52 | 53 | org.springframework.boot 54 | spring-boot-starter-data-cassandra 55 | 56 | 57 | org.springframework.session 58 | spring-session 59 | 60 | 61 | org.webjars 62 | jquery 63 | 3.1.1 64 | 65 | 66 | org.webjars 67 | sockjs-client 68 | 1.1.2 69 | 70 | 71 | org.webjars.bower 72 | stomp-websocket 73 | 2.3.4 74 | 75 | 76 | org.webjars 77 | bootstrap 78 | 3.3.7 79 | 80 | 81 | org.springframework.boot 82 | spring-boot-starter-thymeleaf 83 | 84 | 85 | org.thymeleaf.extras 86 | thymeleaf-extras-springsecurity4 87 | 88 | 89 | org.springframework.boot 90 | spring-boot-starter-test 91 | test 92 | 93 | 94 | org.flywaydb 95 | flyway-core 96 | 97 | 98 | org.testcontainers 99 | testcontainers 100 | 1.1.9 101 | 102 | 103 | org.springframework.security 104 | spring-security-test 105 | 106 | 107 | org.webjars 108 | noty 109 | 2.2.4 110 | 111 | 112 | io.projectreactor 113 | reactor-core 114 | 115 | 116 | io.projectreactor 117 | reactor-net 118 | 119 | 120 | io.netty 121 | netty-all 122 | 4.1.7.Final 123 | 124 | 125 | io.netty 126 | netty-transport-native-epoll 127 | 4.1.7.Final 128 | 129 | 130 | 131 | 132 | 133 | 134 | org.springframework.boot 135 | spring-boot-maven-plugin 136 | 137 | 138 | 139 | org.apache.maven.plugins 140 | maven-surefire-plugin 141 | 142 | 143 | **/UnitTestsSuite.java 144 | 145 | 146 | 147 | 148 | 149 | org.apache.maven.plugins 150 | maven-failsafe-plugin 151 | 152 | 153 | **/UnitTestsSuite.java 154 | **/IntegrationTestsSuite.java 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/Application.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/authentication/api/AuthenticationController.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.authentication.api; 2 | 3 | import javax.validation.Valid; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.Model; 8 | import org.springframework.validation.BindingResult; 9 | import org.springframework.web.bind.WebDataBinder; 10 | import org.springframework.web.bind.annotation.InitBinder; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestMethod; 13 | 14 | import br.com.jorgeacetozi.ebookChat.authentication.domain.model.User; 15 | import br.com.jorgeacetozi.ebookChat.authentication.domain.service.UserService; 16 | import br.com.jorgeacetozi.ebookChat.authentication.domain.validator.NewUserValidator; 17 | 18 | @Controller 19 | public class AuthenticationController { 20 | 21 | @Autowired 22 | private UserService userService; 23 | 24 | @Autowired 25 | private NewUserValidator newUserValidator; 26 | 27 | @InitBinder 28 | protected void initBinder(WebDataBinder binder) { 29 | binder.addValidators(newUserValidator); 30 | } 31 | 32 | @RequestMapping("/") 33 | public String login() { 34 | return "login"; 35 | } 36 | 37 | @RequestMapping("/new-account") 38 | public String newAccount(Model model) { 39 | model.addAttribute("user", new User()); 40 | return "new-account"; 41 | } 42 | 43 | @RequestMapping(path = "/new-account", method = RequestMethod.POST) 44 | public String createAccount(@Valid User user, BindingResult bindingResult) { 45 | if (bindingResult.hasErrors()) { 46 | return "new-account"; 47 | } 48 | userService.createUser(user); 49 | return "redirect:/"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/authentication/domain/model/Role.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.authentication.domain.model; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | import javax.persistence.Table; 9 | 10 | @Entity 11 | @Table(name = "role") 12 | public class Role { 13 | 14 | @Id 15 | @GeneratedValue(strategy = GenerationType.AUTO) 16 | @Column(name="role_id") 17 | private Integer id; 18 | private String name; 19 | 20 | public Integer getId() { 21 | return id; 22 | } 23 | public void setId(Integer id) { 24 | this.id = id; 25 | } 26 | public String getName() { 27 | return name; 28 | } 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | @Override 34 | public int hashCode() { 35 | final int prime = 31; 36 | int result = 1; 37 | result = prime * result + ((id == null) ? 0 : id.hashCode()); 38 | return result; 39 | } 40 | @Override 41 | public boolean equals(Object obj) { 42 | if (this == obj) 43 | return true; 44 | if (obj == null) 45 | return false; 46 | if (getClass() != obj.getClass()) 47 | return false; 48 | Role other = (Role) obj; 49 | if (id == null) { 50 | if (other.id != null) 51 | return false; 52 | } else if (!id.equals(other.id)) 53 | return false; 54 | return true; 55 | } 56 | } -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/authentication/domain/model/User.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.authentication.domain.model; 2 | 3 | import java.util.Collection; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | import javax.persistence.Entity; 7 | import javax.persistence.FetchType; 8 | import javax.persistence.Id; 9 | import javax.persistence.JoinColumn; 10 | import javax.persistence.JoinTable; 11 | import javax.persistence.ManyToMany; 12 | import javax.persistence.Table; 13 | import javax.validation.constraints.Size; 14 | import org.hibernate.validator.constraints.Email; 15 | import org.hibernate.validator.constraints.NotEmpty; 16 | 17 | @Entity 18 | @Table(name = "user") 19 | public class User { 20 | 21 | @Id 22 | @NotEmpty 23 | @Size(min = 5, max = 15) 24 | private String username; 25 | 26 | @NotEmpty 27 | @Size(min = 5) 28 | private String password; 29 | 30 | @NotEmpty 31 | private String name; 32 | 33 | @Email 34 | @NotEmpty 35 | private String email; 36 | 37 | @ManyToMany(fetch=FetchType.EAGER) 38 | @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "username"), inverseJoinColumns = @JoinColumn(name = "role_id")) 39 | private Set roles = new HashSet<>(); 40 | 41 | public User () { 42 | 43 | } 44 | 45 | public User(String username, String password, String name, String email) { 46 | this.username = username; 47 | this.password = password; 48 | this.name = name; 49 | this.email = email; 50 | } 51 | 52 | public String getUsername() { 53 | return username; 54 | } 55 | public void setUsername(String username) { 56 | this.username = username; 57 | } 58 | public String getPassword() { 59 | return password; 60 | } 61 | public void setPassword(String password) { 62 | this.password = password; 63 | } 64 | public String getName() { 65 | return name; 66 | } 67 | public void setName(String name) { 68 | this.name = name; 69 | } 70 | public String getEmail() { 71 | return email; 72 | } 73 | public void setEmail(String email) { 74 | this.email = email; 75 | } 76 | public Set getRoles() { 77 | return roles; 78 | } 79 | public void addRoles(Collection roles) { 80 | this.roles.addAll(roles); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/authentication/domain/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.authentication.domain.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import br.com.jorgeacetozi.ebookChat.authentication.domain.model.Role; 6 | 7 | public interface RoleRepository extends JpaRepository { 8 | 9 | Role findByName(String name); 10 | } 11 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/authentication/domain/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.authentication.domain.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import br.com.jorgeacetozi.ebookChat.authentication.domain.model.User; 6 | 7 | public interface UserRepository extends JpaRepository { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/authentication/domain/service/DefaultUserService.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.authentication.domain.service; 2 | 3 | import java.util.Arrays; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.transaction.annotation.Transactional; 9 | 10 | import br.com.jorgeacetozi.ebookChat.authentication.domain.model.Role; 11 | import br.com.jorgeacetozi.ebookChat.authentication.domain.model.User; 12 | import br.com.jorgeacetozi.ebookChat.authentication.domain.repository.RoleRepository; 13 | import br.com.jorgeacetozi.ebookChat.authentication.domain.repository.UserRepository; 14 | 15 | @Service 16 | public class DefaultUserService implements UserService { 17 | 18 | @Autowired 19 | private UserRepository userRepository; 20 | 21 | @Autowired 22 | private RoleRepository roleRepository; 23 | 24 | @Autowired 25 | private BCryptPasswordEncoder bCryptPasswordEncoder; 26 | 27 | @Override 28 | @Transactional 29 | public User createUser(User user) { 30 | user.setPassword(bCryptPasswordEncoder.encode(user.getPassword())); 31 | Role userRole = roleRepository.findByName("ROLE_USER"); 32 | user.addRoles(Arrays.asList(userRole)); 33 | return userRepository.save(user); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/authentication/domain/service/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.authentication.domain.service; 2 | 3 | import java.util.Set; 4 | import java.util.stream.Collectors; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 11 | import org.springframework.stereotype.Service; 12 | 13 | import br.com.jorgeacetozi.ebookChat.authentication.domain.model.User; 14 | import br.com.jorgeacetozi.ebookChat.authentication.domain.repository.UserRepository; 15 | 16 | @Service 17 | public class UserDetailsServiceImpl implements UserDetailsService{ 18 | 19 | @Autowired 20 | private UserRepository userRepository; 21 | 22 | @Override 23 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 24 | User user = userRepository.findOne(username); 25 | 26 | if (user == null) { 27 | throw new UsernameNotFoundException("User not found"); 28 | } else { 29 | Set grantedAuthorities = user.getRoles().stream() 30 | .map(role -> new SimpleGrantedAuthority(role.getName())) 31 | .collect(Collectors.toSet()); 32 | 33 | return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/authentication/domain/service/UserService.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.authentication.domain.service; 2 | 3 | import br.com.jorgeacetozi.ebookChat.authentication.domain.model.User; 4 | 5 | public interface UserService { 6 | 7 | User createUser(User user); 8 | } 9 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/authentication/domain/validator/NewUserValidator.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.authentication.domain.validator; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Component; 5 | import org.springframework.validation.Errors; 6 | import org.springframework.validation.Validator; 7 | 8 | import br.com.jorgeacetozi.ebookChat.authentication.domain.model.User; 9 | import br.com.jorgeacetozi.ebookChat.authentication.domain.repository.UserRepository; 10 | 11 | @Component 12 | public class NewUserValidator implements Validator { 13 | 14 | @Autowired 15 | private UserRepository userRepository; 16 | 17 | @Override 18 | public boolean supports(Class clazz) { 19 | return User.class.isAssignableFrom(clazz); 20 | } 21 | 22 | @Override 23 | public void validate(Object target, Errors errors) { 24 | User newUser = (User) target; 25 | if (userRepository.exists(newUser.getUsername())) { 26 | errors.rejectValue("username", "new.account.username.already.exists"); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chat/api/ChatController.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chat.api; 2 | 3 | import java.util.List; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.servlet.ModelAndView; 8 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoom; 9 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.service.ChatRoomService; 10 | 11 | @Controller 12 | public class ChatController { 13 | 14 | @Autowired 15 | private ChatRoomService chatRoomService; 16 | 17 | @RequestMapping("/chat") 18 | public ModelAndView getRooms() { 19 | ModelAndView modelAndView = new ModelAndView("chat"); 20 | List chatRooms = chatRoomService.findAll(); 21 | modelAndView.addObject("chatRooms", chatRooms); 22 | return modelAndView; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chatroom/api/ChatRoomController.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chatroom.api; 2 | 3 | import java.security.Principal; 4 | import java.util.List; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.messaging.handler.annotation.MessageMapping; 9 | import org.springframework.messaging.handler.annotation.Payload; 10 | import org.springframework.messaging.simp.SimpMessageHeaderAccessor; 11 | import org.springframework.messaging.simp.annotation.SubscribeMapping; 12 | import org.springframework.security.access.annotation.Secured; 13 | import org.springframework.stereotype.Controller; 14 | import org.springframework.web.bind.annotation.PathVariable; 15 | import org.springframework.web.bind.annotation.RequestBody; 16 | import org.springframework.web.bind.annotation.RequestMapping; 17 | import org.springframework.web.bind.annotation.RequestMethod; 18 | import org.springframework.web.bind.annotation.ResponseBody; 19 | import org.springframework.web.bind.annotation.ResponseStatus; 20 | import org.springframework.web.servlet.ModelAndView; 21 | 22 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoom; 23 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoomUser; 24 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessage; 25 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.service.ChatRoomService; 26 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.service.InstantMessageService; 27 | 28 | @Controller 29 | public class ChatRoomController { 30 | 31 | @Autowired 32 | private ChatRoomService chatRoomService; 33 | 34 | @Autowired 35 | private InstantMessageService instantMessageService; 36 | 37 | @Secured("ROLE_ADMIN") 38 | @RequestMapping(path = "/chatroom", method = RequestMethod.POST) 39 | @ResponseBody 40 | @ResponseStatus(code = HttpStatus.CREATED) 41 | public ChatRoom createChatRoom(@RequestBody ChatRoom chatRoom) { 42 | return chatRoomService.save(chatRoom); 43 | } 44 | 45 | @RequestMapping("/chatroom/{chatRoomId}") 46 | public ModelAndView join(@PathVariable String chatRoomId, Principal principal) { 47 | ModelAndView modelAndView = new ModelAndView("chatroom"); 48 | modelAndView.addObject("chatRoom", chatRoomService.findById(chatRoomId)); 49 | return modelAndView; 50 | } 51 | 52 | @SubscribeMapping("/connected.users") 53 | public List listChatRoomConnectedUsersOnSubscribe(SimpMessageHeaderAccessor headerAccessor) { 54 | String chatRoomId = headerAccessor.getSessionAttributes().get("chatRoomId").toString(); 55 | return chatRoomService.findById(chatRoomId).getConnectedUsers(); 56 | } 57 | 58 | @SubscribeMapping("/old.messages") 59 | public List listOldMessagesFromUserOnSubscribe(Principal principal, 60 | SimpMessageHeaderAccessor headerAccessor) { 61 | String chatRoomId = headerAccessor.getSessionAttributes().get("chatRoomId").toString(); 62 | return instantMessageService.findAllInstantMessagesFor(principal.getName(), chatRoomId); 63 | } 64 | 65 | @MessageMapping("/send.message") 66 | public void sendMessage(@Payload InstantMessage instantMessage, Principal principal, 67 | SimpMessageHeaderAccessor headerAccessor) { 68 | String chatRoomId = headerAccessor.getSessionAttributes().get("chatRoomId").toString(); 69 | instantMessage.setFromUser(principal.getName()); 70 | instantMessage.setChatRoomId(chatRoomId); 71 | 72 | if (instantMessage.isPublic()) { 73 | chatRoomService.sendPublicMessage(instantMessage); 74 | } else { 75 | chatRoomService.sendPrivateMessage(instantMessage); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chatroom/domain/model/ChatRoom.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chatroom.domain.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.springframework.data.annotation.Id; 7 | import org.springframework.data.redis.core.RedisHash; 8 | 9 | import com.google.common.annotations.VisibleForTesting; 10 | 11 | @RedisHash("chatrooms") 12 | public class ChatRoom { 13 | 14 | @Id 15 | private String id; 16 | private String name; 17 | private String description; 18 | private List connectedUsers = new ArrayList<>(); 19 | 20 | public ChatRoom() { 21 | 22 | } 23 | 24 | @VisibleForTesting 25 | public ChatRoom(String id, String name, String description) { 26 | this.id = id; 27 | this.name = name; 28 | this.description = description; 29 | } 30 | 31 | public String getId() { 32 | return id; 33 | } 34 | public void setId(String id) { 35 | this.id = id; 36 | } 37 | public String getName() { 38 | return name; 39 | } 40 | public void setName(String name) { 41 | this.name = name; 42 | } 43 | public String getDescription() { 44 | return description; 45 | } 46 | public void setDescription(String description) { 47 | this.description = description; 48 | } 49 | public List getConnectedUsers() { 50 | return connectedUsers; 51 | } 52 | public void addUser(ChatRoomUser user) { 53 | this.connectedUsers.add(user); 54 | } 55 | public void removeUser(ChatRoomUser user) { 56 | this.connectedUsers.remove(user); 57 | } 58 | public int getNumberOfConnectedUsers(){ 59 | return this.connectedUsers.size(); 60 | } 61 | 62 | @Override 63 | public int hashCode() { 64 | final int prime = 31; 65 | int result = 1; 66 | result = prime * result + ((description == null) ? 0 : description.hashCode()); 67 | result = prime * result + ((id == null) ? 0 : id.hashCode()); 68 | result = prime * result + ((name == null) ? 0 : name.hashCode()); 69 | return result; 70 | } 71 | 72 | @Override 73 | public boolean equals(Object obj) { 74 | if (this == obj) 75 | return true; 76 | if (obj == null) 77 | return false; 78 | if (getClass() != obj.getClass()) 79 | return false; 80 | ChatRoom other = (ChatRoom) obj; 81 | if (description == null) { 82 | if (other.description != null) 83 | return false; 84 | } else if (!description.equals(other.description)) 85 | return false; 86 | if (id == null) { 87 | if (other.id != null) 88 | return false; 89 | } else if (!id.equals(other.id)) 90 | return false; 91 | if (name == null) { 92 | if (other.name != null) 93 | return false; 94 | } else if (!name.equals(other.name)) 95 | return false; 96 | return true; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chatroom/domain/model/ChatRoomUser.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chatroom.domain.model; 2 | 3 | import java.util.Date; 4 | 5 | public class ChatRoomUser implements Comparable { 6 | 7 | private String username; 8 | private Date joinedAt = new Date(); 9 | 10 | public ChatRoomUser() { 11 | 12 | } 13 | 14 | public ChatRoomUser(String username) { 15 | this.username = username; 16 | } 17 | public String getUsername() { 18 | return username; 19 | } 20 | public void setUsername(String username) { 21 | this.username = username; 22 | } 23 | public Date getJoinedAt() { 24 | return joinedAt; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return this.username; 30 | } 31 | 32 | @Override 33 | public int compareTo(ChatRoomUser chatRoomUser) { 34 | return this.username.compareTo(chatRoomUser.getUsername()); 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | final int prime = 31; 40 | int result = 1; 41 | result = prime * result + ((username == null) ? 0 : username.hashCode()); 42 | return result; 43 | } 44 | 45 | @Override 46 | public boolean equals(Object obj) { 47 | if (this == obj) 48 | return true; 49 | if (obj == null) 50 | return false; 51 | if (getClass() != obj.getClass()) 52 | return false; 53 | ChatRoomUser other = (ChatRoomUser) obj; 54 | if (username == null) { 55 | if (other.username != null) 56 | return false; 57 | } else if (!username.equals(other.username)) 58 | return false; 59 | return true; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chatroom/domain/model/InstantMessage.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chatroom.domain.model; 2 | 3 | import java.util.Date; 4 | import org.springframework.cassandra.core.Ordering; 5 | import org.springframework.cassandra.core.PrimaryKeyType; 6 | import org.springframework.data.cassandra.mapping.PrimaryKeyColumn; 7 | import org.springframework.data.cassandra.mapping.Table; 8 | import com.fasterxml.jackson.annotation.JsonIgnore; 9 | import com.google.common.base.Strings; 10 | import br.com.jorgeacetozi.ebookChat.utils.SystemUsers; 11 | 12 | @Table("messages") 13 | public class InstantMessage { 14 | 15 | @JsonIgnore 16 | @PrimaryKeyColumn(name = "username", ordinal = 0, type = PrimaryKeyType.PARTITIONED) 17 | private String username; 18 | 19 | @PrimaryKeyColumn(name = "chatRoomId", ordinal = 1, type = PrimaryKeyType.PARTITIONED) 20 | private String chatRoomId; 21 | 22 | @PrimaryKeyColumn(name = "date", ordinal = 2, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.ASCENDING) 23 | private Date date; 24 | 25 | private String fromUser; 26 | private String toUser; 27 | private String text; 28 | 29 | public InstantMessage() { 30 | this.date = new Date(); 31 | } 32 | 33 | public boolean isPublic() { 34 | return Strings.isNullOrEmpty(this.toUser); 35 | } 36 | public boolean isFromAdmin() { 37 | return this.fromUser.equals(SystemUsers.ADMIN.getUsername()); 38 | } 39 | public void appendToUserConversation(String username) { 40 | this.username = username; 41 | } 42 | public String getUsername() { 43 | return username; 44 | } 45 | public void setUsername(String username) { 46 | this.username = username; 47 | } 48 | public String getChatRoomId() { 49 | return chatRoomId; 50 | } 51 | public void setChatRoomId(String chatRoomId) { 52 | this.chatRoomId = chatRoomId; 53 | } 54 | public Date getDate() { 55 | return date; 56 | } 57 | public void setDate(Date date) { 58 | this.date = date; 59 | } 60 | public String getFromUser() { 61 | return fromUser; 62 | } 63 | public void setFromUser(String fromUser) { 64 | this.fromUser = fromUser; 65 | } 66 | public String getToUser() { 67 | return toUser; 68 | } 69 | public void setToUser(String toUser) { 70 | this.toUser = toUser; 71 | } 72 | public String getText() { 73 | return text; 74 | } 75 | public void setText(String text) { 76 | this.text = text; 77 | } 78 | 79 | @Override 80 | public int hashCode() { 81 | final int prime = 31; 82 | int result = 1; 83 | result = prime * result + ((chatRoomId == null) ? 0 : chatRoomId.hashCode()); 84 | result = prime * result + ((fromUser == null) ? 0 : fromUser.hashCode()); 85 | result = prime * result + ((text == null) ? 0 : text.hashCode()); 86 | result = prime * result + ((toUser == null) ? 0 : toUser.hashCode()); 87 | result = prime * result + ((username == null) ? 0 : username.hashCode()); 88 | return result; 89 | } 90 | 91 | @Override 92 | public boolean equals(Object obj) { 93 | if (this == obj) 94 | return true; 95 | if (obj == null) 96 | return false; 97 | if (getClass() != obj.getClass()) 98 | return false; 99 | InstantMessage other = (InstantMessage) obj; 100 | if (chatRoomId == null) { 101 | if (other.chatRoomId != null) 102 | return false; 103 | } else if (!chatRoomId.equals(other.chatRoomId)) 104 | return false; 105 | if (fromUser == null) { 106 | if (other.fromUser != null) 107 | return false; 108 | } else if (!fromUser.equals(other.fromUser)) 109 | return false; 110 | if (text == null) { 111 | if (other.text != null) 112 | return false; 113 | } else if (!text.equals(other.text)) 114 | return false; 115 | if (toUser == null) { 116 | if (other.toUser != null) 117 | return false; 118 | } else if (!toUser.equals(other.toUser)) 119 | return false; 120 | if (username == null) { 121 | if (other.username != null) 122 | return false; 123 | } else if (!username.equals(other.username)) 124 | return false; 125 | return true; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chatroom/domain/model/InstantMessageBuilder.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chatroom.domain.model; 2 | 3 | import br.com.jorgeacetozi.ebookChat.utils.SystemUsers; 4 | 5 | public class InstantMessageBuilder { 6 | 7 | private InstantMessage instantMessage; 8 | private InstantMessageChatRoom instantMessageChatRoom; 9 | private InstantMessageType instantMessageType; 10 | private InstantMessageText instantMessageText; 11 | private InstantMessageFromUser instantMessageFromUser; 12 | private InstantMessageToUser instantMessageToUser; 13 | 14 | public InstantMessageBuilder() { 15 | 16 | } 17 | 18 | public InstantMessageChatRoom newMessage() { 19 | instantMessage = new InstantMessage(); 20 | instantMessageChatRoom = new InstantMessageChatRoom(); 21 | return instantMessageChatRoom; 22 | } 23 | 24 | public class InstantMessageChatRoom { 25 | public InstantMessageType withChatRoomId(String chatRoomId) { 26 | instantMessage.setChatRoomId(chatRoomId); 27 | instantMessageType = new InstantMessageType(); 28 | return instantMessageType; 29 | } 30 | } 31 | 32 | public class InstantMessageType { 33 | public InstantMessageText systemMessage(){ 34 | instantMessage.setFromUser(SystemUsers.ADMIN.getUsername()); 35 | instantMessageText = new InstantMessageText(); 36 | return instantMessageText; 37 | } 38 | 39 | public InstantMessageFromUser publicMessage() { 40 | instantMessage.setToUser(null); 41 | instantMessageFromUser = new InstantMessageFromUser(); 42 | return instantMessageFromUser; 43 | } 44 | 45 | public InstantMessageToUser privateMessage(){ 46 | instantMessageToUser = new InstantMessageToUser(); 47 | return instantMessageToUser; 48 | } 49 | } 50 | 51 | public class InstantMessageToUser { 52 | public InstantMessageFromUser toUser(String username) { 53 | instantMessage.setToUser(username); 54 | instantMessageFromUser = new InstantMessageFromUser(); 55 | return instantMessageFromUser; 56 | } 57 | } 58 | 59 | public class InstantMessageFromUser { 60 | public InstantMessageText fromUser(String username) { 61 | instantMessage.setFromUser(username); 62 | instantMessageText = new InstantMessageText(); 63 | return instantMessageText; 64 | } 65 | } 66 | 67 | public class InstantMessageText { 68 | public InstantMessage withText(String text) { 69 | instantMessage.setText(text); 70 | return instantMessage; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chatroom/domain/repository/ChatRoomRepository.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chatroom.domain.repository; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoom; 6 | 7 | public interface ChatRoomRepository extends CrudRepository { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chatroom/domain/repository/InstantMessageRepository.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chatroom.domain.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.cassandra.repository.CassandraRepository; 6 | 7 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessage; 8 | 9 | public interface InstantMessageRepository extends CassandraRepository { 10 | 11 | List findInstantMessagesByUsernameAndChatRoomId(String username, String chatRoomId); 12 | } 13 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chatroom/domain/service/CassandraInstantMessageService.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chatroom.domain.service; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoom; 9 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessage; 10 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.repository.InstantMessageRepository; 11 | 12 | @Service 13 | public class CassandraInstantMessageService implements InstantMessageService { 14 | 15 | @Autowired 16 | private InstantMessageRepository instantMessageRepository; 17 | 18 | @Autowired 19 | private ChatRoomService chatRoomService; 20 | 21 | @Override 22 | public void appendInstantMessageToConversations(InstantMessage instantMessage) { 23 | if (instantMessage.isFromAdmin() || instantMessage.isPublic()) { 24 | ChatRoom chatRoom = chatRoomService.findById(instantMessage.getChatRoomId()); 25 | 26 | chatRoom.getConnectedUsers().forEach(connectedUser -> { 27 | instantMessage.appendToUserConversation(connectedUser.getUsername()); 28 | instantMessageRepository.save(instantMessage); 29 | }); 30 | } else { 31 | instantMessage.appendToUserConversation(instantMessage.getFromUser()); 32 | instantMessageRepository.save(instantMessage); 33 | 34 | instantMessage.appendToUserConversation(instantMessage.getToUser()); 35 | instantMessageRepository.save(instantMessage); 36 | } 37 | } 38 | 39 | @Override 40 | public List findAllInstantMessagesFor(String username, String chatRoomId) { 41 | return instantMessageRepository.findInstantMessagesByUsernameAndChatRoomId(username, chatRoomId); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chatroom/domain/service/ChatRoomService.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chatroom.domain.service; 2 | 3 | import java.util.List; 4 | 5 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoom; 6 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoomUser; 7 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessage; 8 | 9 | public interface ChatRoomService { 10 | 11 | ChatRoom save(ChatRoom chatRoom); 12 | ChatRoom findById(String chatRoomId); 13 | ChatRoom join(ChatRoomUser joiningUser, ChatRoom chatRoom); 14 | ChatRoom leave(ChatRoomUser leavingUser, ChatRoom chatRoom); 15 | void sendPublicMessage(InstantMessage instantMessage); 16 | void sendPrivateMessage(InstantMessage instantMessage); 17 | List findAll(); 18 | } 19 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chatroom/domain/service/InstantMessageService.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chatroom.domain.service; 2 | 3 | import java.util.List; 4 | 5 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessage; 6 | 7 | public interface InstantMessageService { 8 | 9 | void appendInstantMessageToConversations(InstantMessage instantMessage); 10 | List findAllInstantMessagesFor(String username, String chatRoomId); 11 | } 12 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chatroom/domain/service/RedisChatRoomService.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chatroom.domain.service; 2 | 3 | import java.util.List; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.messaging.simp.SimpMessagingTemplate; 6 | import org.springframework.stereotype.Service; 7 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoom; 8 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoomUser; 9 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessage; 10 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.repository.ChatRoomRepository; 11 | import br.com.jorgeacetozi.ebookChat.utils.Destinations; 12 | import br.com.jorgeacetozi.ebookChat.utils.SystemMessages; 13 | 14 | @Service 15 | public class RedisChatRoomService implements ChatRoomService { 16 | 17 | @Autowired 18 | private SimpMessagingTemplate webSocketMessagingTemplate; 19 | 20 | @Autowired 21 | private ChatRoomRepository chatRoomRepository; 22 | 23 | @Autowired 24 | private InstantMessageService instantMessageService; 25 | 26 | @Override 27 | public ChatRoom save(ChatRoom chatRoom) { 28 | return chatRoomRepository.save(chatRoom); 29 | } 30 | 31 | @Override 32 | public ChatRoom findById(String chatRoomId) { 33 | return chatRoomRepository.findOne(chatRoomId); 34 | } 35 | 36 | @Override 37 | public ChatRoom join(ChatRoomUser joiningUser, ChatRoom chatRoom) { 38 | chatRoom.addUser(joiningUser); 39 | chatRoomRepository.save(chatRoom); 40 | 41 | sendPublicMessage(SystemMessages.welcome(chatRoom.getId(), joiningUser.getUsername())); 42 | updateConnectedUsersViaWebSocket(chatRoom); 43 | return chatRoom; 44 | } 45 | 46 | @Override 47 | public ChatRoom leave(ChatRoomUser leavingUser, ChatRoom chatRoom) { 48 | sendPublicMessage(SystemMessages.goodbye(chatRoom.getId(), leavingUser.getUsername())); 49 | 50 | chatRoom.removeUser(leavingUser); 51 | chatRoomRepository.save(chatRoom); 52 | 53 | updateConnectedUsersViaWebSocket(chatRoom); 54 | return chatRoom; 55 | } 56 | 57 | @Override 58 | public void sendPublicMessage(InstantMessage instantMessage) { 59 | webSocketMessagingTemplate.convertAndSend( 60 | Destinations.ChatRoom.publicMessages(instantMessage.getChatRoomId()), 61 | instantMessage); 62 | 63 | instantMessageService.appendInstantMessageToConversations(instantMessage); 64 | } 65 | 66 | @Override 67 | public void sendPrivateMessage(InstantMessage instantMessage) { 68 | webSocketMessagingTemplate.convertAndSendToUser( 69 | instantMessage.getToUser(), 70 | Destinations.ChatRoom.privateMessages(instantMessage.getChatRoomId()), 71 | instantMessage); 72 | 73 | webSocketMessagingTemplate.convertAndSendToUser( 74 | instantMessage.getFromUser(), 75 | Destinations.ChatRoom.privateMessages(instantMessage.getChatRoomId()), 76 | instantMessage); 77 | 78 | instantMessageService.appendInstantMessageToConversations(instantMessage); 79 | } 80 | 81 | @Override 82 | public List findAll() { 83 | return (List) chatRoomRepository.findAll(); 84 | } 85 | 86 | private void updateConnectedUsersViaWebSocket(ChatRoom chatRoom) { 87 | webSocketMessagingTemplate.convertAndSend( 88 | Destinations.ChatRoom.connectedUsers(chatRoom.getId()), 89 | chatRoom.getConnectedUsers()); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/chatroom/websocket/WebSocketEvents.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.chatroom.websocket; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.event.EventListener; 5 | import org.springframework.messaging.simp.SimpMessageHeaderAccessor; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.socket.messaging.SessionConnectEvent; 8 | import org.springframework.web.socket.messaging.SessionDisconnectEvent; 9 | 10 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoomUser; 11 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.service.ChatRoomService; 12 | 13 | @Component 14 | public class WebSocketEvents { 15 | 16 | @Autowired 17 | private ChatRoomService chatRoomService; 18 | 19 | @EventListener 20 | private void handleSessionConnected(SessionConnectEvent event) { 21 | SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(event.getMessage()); 22 | String chatRoomId = headers.getNativeHeader("chatRoomId").get(0); 23 | headers.getSessionAttributes().put("chatRoomId", chatRoomId); 24 | ChatRoomUser joiningUser = new ChatRoomUser(event.getUser().getName()); 25 | 26 | chatRoomService.join(joiningUser, chatRoomService.findById(chatRoomId)); 27 | } 28 | 29 | @EventListener 30 | private void handleSessionDisconnect(SessionDisconnectEvent event) { 31 | SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(event.getMessage()); 32 | String chatRoomId = headers.getSessionAttributes().get("chatRoomId").toString(); 33 | ChatRoomUser leavingUser = new ChatRoomUser(event.getUser().getName()); 34 | 35 | chatRoomService.leave(leavingUser, chatRoomService.findById(chatRoomId)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/configuration/CassandraConfig.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.configuration; 2 | 3 | import java.util.Arrays; 4 | import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.context.annotation.Profile; 8 | import org.springframework.data.cassandra.config.CassandraClusterFactoryBean; 9 | import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration; 10 | import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext; 11 | import org.springframework.data.cassandra.mapping.CassandraMappingContext; 12 | 13 | @Profile({"dev","test"}) 14 | @Configuration 15 | public class CassandraConfig extends AbstractCassandraConfiguration { 16 | 17 | @Override 18 | protected String getKeyspaceName() { 19 | return "ebook_chat"; 20 | } 21 | 22 | @Bean 23 | @Override 24 | public CassandraClusterFactoryBean cluster() { 25 | CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean(); 26 | cluster.setContactPoints("localhost"); 27 | cluster.setPort(9042); 28 | cluster.setKeyspaceCreations( 29 | Arrays.asList( 30 | new CreateKeyspaceSpecification("ebook_chat") 31 | .ifNotExists() 32 | .withSimpleReplication(1)) 33 | ); 34 | cluster.setStartupScripts(Arrays.asList( 35 | "USE ebook_chat", 36 | "CREATE TABLE IF NOT EXISTS messages (" + 37 | "username text," + 38 | "chatRoomId text," + 39 | "date timestamp," + 40 | "fromUser text," + 41 | "toUser text," + 42 | "text text," + 43 | "PRIMARY KEY ((username, chatRoomId), date)" + 44 | ") WITH CLUSTERING ORDER BY (date ASC)" 45 | ) 46 | ); 47 | return cluster; 48 | } 49 | 50 | @Bean 51 | @Override 52 | public CassandraMappingContext cassandraMapping() 53 | throws ClassNotFoundException { 54 | return new BasicCassandraMappingContext(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/configuration/WebConfig.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.configuration; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.servlet.LocaleResolver; 6 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 7 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 8 | import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; 9 | import org.springframework.web.servlet.i18n.SessionLocaleResolver; 10 | 11 | @Configuration 12 | public class WebConfig extends WebMvcConfigurerAdapter { 13 | 14 | @Bean 15 | public LocaleResolver localeResolver() { 16 | return new SessionLocaleResolver(); 17 | } 18 | 19 | @Bean 20 | public LocaleChangeInterceptor localeChangeInterceptor() { 21 | LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); 22 | localeChangeInterceptor.setParamName("lang"); 23 | return localeChangeInterceptor; 24 | } 25 | 26 | @Override 27 | public void addInterceptors(InterceptorRegistry registry) { 28 | registry.addInterceptor(localeChangeInterceptor()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/configuration/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.configuration; 2 | 3 | 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.http.HttpMethod; 8 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 9 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 12 | import org.springframework.security.core.userdetails.UserDetailsService; 13 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 14 | 15 | @Configuration 16 | @EnableGlobalMethodSecurity(prePostEnabled = true) 17 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 18 | 19 | @Autowired 20 | private UserDetailsService userDetailsService; 21 | 22 | @Override 23 | protected void configure(HttpSecurity http) throws Exception { 24 | http 25 | .csrf().disable() 26 | .formLogin() 27 | .loginProcessingUrl("/login") 28 | .loginPage("/") 29 | .defaultSuccessUrl("/chat") 30 | .and() 31 | .logout() 32 | .logoutSuccessUrl("/") 33 | .and() 34 | .authorizeRequests() 35 | .antMatchers("/login", "/new-account", "/").permitAll() 36 | .antMatchers(HttpMethod.POST, "/chatroom").hasRole("ADMIN") 37 | .anyRequest().authenticated(); 38 | } 39 | 40 | @Autowired 41 | public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 42 | auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); 43 | } 44 | 45 | @Bean 46 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 47 | return new BCryptPasswordEncoder(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/configuration/WebSocketConfigSpringSession.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.configuration; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.messaging.simp.config.MessageBrokerRegistry; 6 | import org.springframework.scheduling.annotation.EnableScheduling; 7 | import org.springframework.session.ExpiringSession; 8 | import org.springframework.session.web.socket.config.annotation.AbstractSessionWebSocketMessageBrokerConfigurer; 9 | import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; 10 | import org.springframework.web.socket.config.annotation.StompEndpointRegistry; 11 | 12 | @Configuration 13 | @EnableScheduling 14 | @EnableWebSocketMessageBroker 15 | public class WebSocketConfigSpringSession extends AbstractSessionWebSocketMessageBrokerConfigurer { 16 | 17 | @Value("${ebook.chat.relay.host}") 18 | private String relayHost; 19 | 20 | @Value("${ebook.chat.relay.port}") 21 | private Integer relayPort; 22 | 23 | protected void configureStompEndpoints(StompEndpointRegistry registry) { 24 | registry.addEndpoint("/ws").withSockJS(); 25 | } 26 | 27 | public void configureMessageBroker(MessageBrokerRegistry registry) { 28 | registry.enableStompBrokerRelay("/queue/", "/topic/") 29 | .setUserDestinationBroadcast("/topic/unresolved.user.dest") 30 | .setUserRegistryBroadcast("/topic/registry.broadcast") 31 | .setRelayHost(relayHost) 32 | .setRelayPort(relayPort); 33 | 34 | registry.setApplicationDestinationPrefixes("/chatroom"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/utils/Destinations.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.utils; 2 | 3 | public class Destinations { 4 | 5 | public static class ChatRoom { 6 | 7 | public static String publicMessages(String chatRoomId) { 8 | return "/topic/" + chatRoomId + ".public.messages"; 9 | } 10 | 11 | public static String privateMessages(String chatRoomId) { 12 | return "/queue/" + chatRoomId + ".private.messages"; 13 | } 14 | 15 | public static String connectedUsers(String chatRoomId) { 16 | return "/topic/" + chatRoomId + ".connected.users"; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/utils/SystemMessages.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.utils; 2 | 3 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessage; 4 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessageBuilder; 5 | 6 | public class SystemMessages { 7 | 8 | public static final InstantMessage welcome(String chatRoomId, String username) { 9 | return new InstantMessageBuilder() 10 | .newMessage() 11 | .withChatRoomId(chatRoomId) 12 | .systemMessage() 13 | .withText(username + " joined us :)"); 14 | } 15 | 16 | public static final InstantMessage goodbye(String chatRoomId, String username) { 17 | return new InstantMessageBuilder() 18 | .newMessage() 19 | .withChatRoomId(chatRoomId) 20 | .systemMessage() 21 | .withText(username + " left us :("); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/java/br/com/jorgeacetozi/ebookChat/utils/SystemUsers.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.utils; 2 | 3 | public enum SystemUsers { 4 | 5 | ADMIN("admin"); 6 | 7 | SystemUsers(String username) { 8 | this.username = username; 9 | } 10 | 11 | private String username; 12 | 13 | public String getUsername() { 14 | return this.username; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring.profiles.active: dev 2 | 3 | --- 4 | 5 | spring: 6 | profiles: dev 7 | datasource: 8 | url: jdbc:mysql://localhost:3306/ebook_chat 9 | username: root 10 | password: root 11 | testWhileIdle: true 12 | validationQuery: SELECT 1 13 | jpa: 14 | show-sql: true 15 | hibernate: 16 | ddl-auto: validate 17 | naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy 18 | properties: 19 | hibernate: 20 | dialect: org.hibernate.dialect.MySQL5Dialect 21 | session: 22 | store-type: redis 23 | thymeleaf: 24 | cache: false 25 | messages: 26 | cache-seconds: 0 27 | redis: 28 | host: localhost 29 | port: 6379 30 | data: 31 | redis: 32 | repositories: 33 | enabled: true 34 | 35 | flyway.enabled: true 36 | security.headers.cache: false 37 | server.session.timeout: 600 38 | 39 | ebook: 40 | chat: 41 | relay: 42 | host: localhost 43 | port: 61613 44 | 45 | --- 46 | 47 | spring: 48 | profiles: test 49 | datasource: 50 | url: jdbc:mysql://localhost:3306/ebook_chat 51 | username: root 52 | password: root 53 | testWhileIdle: true 54 | validationQuery: SELECT 1 55 | jpa: 56 | show-sql: true 57 | hibernate: 58 | ddl-auto: validate 59 | naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy 60 | properties: 61 | hibernate: 62 | dialect: org.hibernate.dialect.MySQL5Dialect 63 | session: 64 | store-type: redis 65 | redis: 66 | host: localhost 67 | port: 6379 68 | data: 69 | redis: 70 | repositories: 71 | enabled: true 72 | 73 | flyway.enabled: true 74 | 75 | ebook: 76 | chat: 77 | relay: 78 | host: localhost 79 | port: 61613 -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/resources/db/create_database_mysql.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE ebook_chat; 2 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/resources/db/create_keyspace_cassandra.cql: -------------------------------------------------------------------------------- 1 | CREATE KEYSPACE ebook_chat WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; 2 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/resources/db/migration/V1__init.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE role ( 2 | role_id INTEGER NOT NULL AUTO_INCREMENT, 3 | name VARCHAR(255), 4 | PRIMARY KEY (role_id) 5 | ); 6 | 7 | CREATE TABLE user ( 8 | username VARCHAR(15) NOT NULL, 9 | email VARCHAR(255) NOT NULL, 10 | name VARCHAR(255) NOT NULL, 11 | password VARCHAR(255) NOT NULL, 12 | PRIMARY KEY (username) 13 | ); 14 | 15 | CREATE TABLE user_role ( 16 | username VARCHAR(255) NOT NULL, 17 | role_id INTEGER NOT NULL, 18 | PRIMARY KEY (username, role_id) 19 | ); 20 | 21 | ALTER TABLE user_role ADD CONSTRAINT fk_user_role_role_id FOREIGN KEY (role_id) REFERENCES role (role_id); 22 | ALTER TABLE user_role ADD CONSTRAINT fk_user_role_username FOREIGN KEY (username) REFERENCES user (username); 23 | 24 | INSERT INTO ebook_chat.role VALUES (1,'ROLE_ADMIN'); 25 | INSERT INTO ebook_chat.role VALUES (2,'ROLE_USER'); 26 | INSERT INTO ebook_chat.user VALUES ('admin', 'admin@jorgeacetozi.com.br', 'Jorge Acetozi', '$2a$06$WfXHoFhYT/cXcyNOZQsjMuXRyydgcUTMJcMweF0m8RMub2HS1rCHu'); 27 | INSERT INTO ebook_chat.user_role VALUES ('admin', 1); 28 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/resources/messages.properties: -------------------------------------------------------------------------------- 1 | menu.language=Language 2 | menu.language.english=English 3 | menu.language.portuguese=Portuguese 4 | menu.chatrooms=Chat Rooms 5 | menu.new.chatrooms=New Chat Room 6 | menu.logout=Logout 7 | menu.leave.chatroom=Leave Chat Room 8 | 9 | login.title=Login 10 | login.your.username=Your username 11 | login.your.password=Your password 12 | login.username=Username 13 | login.password=Password 14 | login.signin=Sign In 15 | login.create.account=Or create an account 16 | login.badCredentials=Invalid username or password 17 | 18 | new.account.title=New Account 19 | new.account.name=Name 20 | new.account.email=Email 21 | new.account.username=Username 22 | new.account.password=Password 23 | new.account.your.name=Your name 24 | new.account.your.email=Your email 25 | new.account.your.username=Your username 26 | new.account.your.password=Your password 27 | new.account.create=Create 28 | new.account.username.already.exists=Username already exists 29 | 30 | chat.available.chatrooms=Available Chat Rooms 31 | chat.chatrooms.name=Name 32 | chat.chatrooms.description=Description 33 | chat.chatrooms.connectedUsers=Connected Users 34 | chat.chatrooms.join=Join 35 | chat.new.chatroom.title=New Chat Room 36 | chat.new.chatroom.name=Name 37 | chat.new.chatroom.description=Description 38 | chat.new.chatroom.close=Close 39 | chat.new.chatroom.create=Create 40 | 41 | chatroom.title=Chat Room 42 | chatroom.users=Users 43 | chatroom.public.messages=I want to send public messages 44 | chatroom.message.placeholder=Type your message... 45 | chatroom.send=Send 46 | 47 | NotEmpty=May not be empty 48 | Size.user.username=Must have between 5 and 15 characters 49 | Size.user.password=Must have at least 5 characters 50 | Email=Specify a valid email address 51 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/resources/messages_pt.properties: -------------------------------------------------------------------------------- 1 | menu.language=Idioma 2 | menu.language.english=Inglês 3 | menu.language.portuguese=Português 4 | menu.chatrooms=Salas de Bate-Papo 5 | menu.new.chatrooms=Nova Sala de Bate-Papo 6 | menu.logout=Sair 7 | menu.leave.chatroom=Sair da Sala de Bate-Papo 8 | 9 | login.title=Entrar 10 | login.your.username=Seu nome de usuário 11 | login.your.password=sua senha 12 | login.username=Nome de Usuário 13 | login.password=Senha 14 | login.signin=Entrar 15 | login.create.account=Ou crie sua conta 16 | login.badCredentials=Nome de usuário ou senha inválidos 17 | 18 | new.account.title=Nova Conta 19 | new.account.name=Nome 20 | new.account.email=Email 21 | new.account.username=Nome de Usuário 22 | new.account.password=Senha 23 | new.account.your.name=Seu nome 24 | new.account.your.email=Seu email 25 | new.account.your.username=Seu nome de usuário 26 | new.account.your.password=Sua senha 27 | new.account.create=Criar 28 | new.account.username.already.exists=Nome de usuário já cadastrado 29 | 30 | chat.available.chatrooms=Salas de Bate-Papo Disponíveis 31 | chat.chatrooms.name=Nome 32 | chat.chatrooms.description=Descrição 33 | chat.chatrooms.connectedUsers=Usuários Conectados 34 | chat.chatrooms.join=Entrar 35 | chat.new.chatroom.title=Nova Sala de Bate Papo 36 | chat.new.chatroom.name=Nome 37 | chat.new.chatroom.description=Descrição 38 | chat.new.chatroom.close=Fechar 39 | chat.new.chatroom.create=Criar 40 | 41 | chatroom.title=Sala de Bate Papo 42 | chatroom.users=Usuários 43 | chatroom.public.messages=Quero enviar mensagens públicas 44 | chatroom.message.placeholder=Escreva sua mensagem... 45 | chatroom.send=Enviar 46 | 47 | NotEmpty=Não deve estar vazio 48 | Size.user.username=Deve ter entre 5 e 15 caracteres 49 | Size.user.password=Deve ter pelo menos 5 caracteres 50 | Email=Especifique um endereço de email válido 51 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/resources/templates/chat.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 |
9 | 10 |

Available Chat Rooms

11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 | 31 |
NameDescriptionConnected Users
BrazilMeet brazilian people 26 | here0Join
32 | 33 | 63 |
64 | 65 | 66 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/resources/templates/chatroom.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | Jorge Acetozi - Ebook Chat App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 46 | 47 |
48 |

Awesome Chat Room

49 |
50 |
51 |
52 |
53 |
54 |

Users

55 |
56 |
58 | 59 | 60 | 61 | 62 |
63 |
64 | 65 | 68 |
69 |
70 | 71 |
72 |
73 |
74 | 75 |
76 |
77 |
78 |
79 |
80 | public 81 | 82 | 83 | 84 | 85 |
86 |
87 |
88 |
89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 290 | 291 | 292 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/resources/templates/layout/default.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | Jorge Acetozi - Ebook Chat App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 49 | 50 |
51 |

Page content here

52 |
53 | 54 | 55 | 56 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/resources/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 |
9 | 10 |
11 |

Login

12 |
13 |
14 |

15 |
16 |
17 |
18 | 19 |
20 | 21 |
22 |
23 |
24 | 25 |
26 | 27 |
28 |
29 |
30 |
31 | 32 | Or create an account 33 |
34 |
35 |
36 |
37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/main/resources/templates/new-account.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 |
9 | 10 |
11 |

New Account

12 |
13 |
14 |
15 | 16 |
17 | 18 |
Error
19 |
20 |
21 |
22 | 23 |
24 | 25 |
Error
26 |
27 |
28 |
29 | 30 |
31 | 32 |
Error
33 |
34 |
35 |
36 | 37 |
38 | 39 |
Error
40 |
41 |
42 |
43 |
44 | 45 |
46 |
47 |
48 |
49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/integrationTests/IntegrationTestsSuite.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.integrationTests; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.junit.runners.Suite; 5 | 6 | import br.com.jorgeacetozi.ebookChat.integrationTests.authentication.api.AuthenticationControllerTest; 7 | import br.com.jorgeacetozi.ebookChat.integrationTests.authentication.domain.service.DefaultUserServiceTest; 8 | import br.com.jorgeacetozi.ebookChat.integrationTests.chatroom.api.ChatRoomControllerTest; 9 | import br.com.jorgeacetozi.ebookChat.integrationTests.chatroom.domain.service.CassandraInstantMessageServiceTest; 10 | import br.com.jorgeacetozi.ebookChat.integrationTests.chatroom.domain.service.RedisChatRoomServiceTest; 11 | import br.com.jorgeacetozi.ebookChat.integrationTests.test.AbstractIntegrationTest; 12 | 13 | @RunWith(Suite.class) 14 | @Suite.SuiteClasses({ 15 | CassandraInstantMessageServiceTest.class, 16 | RedisChatRoomServiceTest.class, 17 | DefaultUserServiceTest.class, 18 | AuthenticationControllerTest.class, 19 | ChatRoomControllerTest.class 20 | }) 21 | public class IntegrationTestsSuite extends AbstractIntegrationTest { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/integrationTests/authentication/api/AuthenticationControllerTest.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.integrationTests.authentication.api; 2 | 3 | import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; 4 | import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; 5 | import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated; 6 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 8 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 9 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | import org.junit.runner.RunWith; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.security.web.FilterChainProxy; 15 | import org.springframework.test.context.junit4.SpringRunner; 16 | import org.springframework.test.context.web.WebAppConfiguration; 17 | import org.springframework.test.web.servlet.MockMvc; 18 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 19 | import org.springframework.web.context.WebApplicationContext; 20 | import br.com.jorgeacetozi.ebookChat.authentication.domain.model.User; 21 | import br.com.jorgeacetozi.ebookChat.authentication.domain.repository.UserRepository; 22 | import br.com.jorgeacetozi.ebookChat.authentication.domain.service.UserService; 23 | import br.com.jorgeacetozi.ebookChat.integrationTests.test.EbookChatTest; 24 | 25 | @RunWith(SpringRunner.class) 26 | @EbookChatTest 27 | @WebAppConfiguration 28 | public class AuthenticationControllerTest { 29 | 30 | @Autowired 31 | private UserService userService; 32 | 33 | @Autowired 34 | private UserRepository userRepository; 35 | 36 | @Autowired 37 | private WebApplicationContext wac; 38 | 39 | @Autowired 40 | private FilterChainProxy springSecurityFilter; 41 | 42 | private MockMvc mockMvc; 43 | 44 | @Before 45 | public void setup() { 46 | this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).addFilter(springSecurityFilter).build(); 47 | } 48 | 49 | @Test 50 | public void shouldNavigateToLoginPage() throws Exception { 51 | this.mockMvc.perform(get("/")) 52 | .andDo(print()) 53 | .andExpect(status().isOk()) 54 | .andExpect(view().name("login")); 55 | } 56 | 57 | @Test 58 | public void shouldNavigateToNewAccountPage() throws Exception { 59 | this.mockMvc.perform(get("/new-account")) 60 | .andDo(print()) 61 | .andExpect(status().isOk()) 62 | .andExpect(view().name("new-account")); 63 | } 64 | 65 | @Test 66 | public void shouldAuthenticateAdminWithRoleAdmin() throws Exception { 67 | this.mockMvc.perform(formLogin("/login").user("admin").password("admin")) 68 | .andExpect(authenticated().withRoles("ADMIN")); 69 | } 70 | 71 | @Test 72 | public void shouldAuthenticateUserWithRoleUser() throws Exception { 73 | User user = new User("jorge_acetozi", "123456", "Jorge Acetozi", "jorge.acetozi@ebookchat.com.br"); 74 | userService.createUser(user); 75 | 76 | this.mockMvc.perform(formLogin("/login").user(user.getUsername()).password("123456")) 77 | .andExpect(authenticated().withRoles("USER")); 78 | 79 | userRepository.delete(user); 80 | } 81 | 82 | @Test 83 | public void shouldNotAuthenticateNonExistingUser() throws Exception { 84 | this.mockMvc.perform(formLogin("/login").user("ghost").password("ghost")) 85 | .andExpect(unauthenticated()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/integrationTests/authentication/domain/service/DefaultUserServiceTest.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.integrationTests.authentication.domain.service; 2 | 3 | import static org.hamcrest.MatcherAssert.assertThat; 4 | import static org.hamcrest.core.Is.is; 5 | import org.hamcrest.Matchers; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | import br.com.jorgeacetozi.ebookChat.authentication.domain.model.Role; 11 | import br.com.jorgeacetozi.ebookChat.authentication.domain.model.User; 12 | import br.com.jorgeacetozi.ebookChat.authentication.domain.repository.RoleRepository; 13 | import br.com.jorgeacetozi.ebookChat.authentication.domain.repository.UserRepository; 14 | import br.com.jorgeacetozi.ebookChat.authentication.domain.service.UserService; 15 | import br.com.jorgeacetozi.ebookChat.integrationTests.test.EbookChatTest; 16 | 17 | @RunWith(SpringRunner.class) 18 | @EbookChatTest 19 | public class DefaultUserServiceTest { 20 | 21 | @Autowired 22 | private UserService userService; 23 | 24 | @Autowired 25 | private UserRepository userRepository; 26 | 27 | @Autowired 28 | private RoleRepository roleRepository; 29 | 30 | @Test 31 | public void shouldCreateNewUserWithRoleUser() { 32 | User user = new User("jorge_acetozi", "123456", "Jorge Acetozi", "jorge.acetozi@ebookchat.com.br"); 33 | Role userRole = roleRepository.findByName("ROLE_USER"); 34 | User createdUser = userService.createUser(user); 35 | 36 | assertThat(createdUser.getRoles(), Matchers.contains(userRole)); 37 | assertThat(createdUser.getName(), is(user.getName())); 38 | assertThat(createdUser.getUsername(), is(user.getUsername())); 39 | assertThat(createdUser.getEmail(), is(user.getEmail())); 40 | 41 | userRepository.delete(createdUser); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/integrationTests/chatroom/api/ChatRoomControllerTest.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.integrationTests.chatroom.api; 2 | 3 | import static org.hamcrest.core.Is.is; 4 | import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; 5 | import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated; 6 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 8 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; 9 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 10 | 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | import org.junit.runner.RunWith; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.http.MediaType; 16 | import org.springframework.security.web.FilterChainProxy; 17 | import org.springframework.test.context.junit4.SpringRunner; 18 | import org.springframework.test.context.web.WebAppConfiguration; 19 | import org.springframework.test.web.servlet.MockMvc; 20 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 21 | import org.springframework.web.context.WebApplicationContext; 22 | 23 | import com.fasterxml.jackson.databind.ObjectMapper; 24 | 25 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoom; 26 | import br.com.jorgeacetozi.ebookChat.integrationTests.test.EbookChatTest; 27 | 28 | @RunWith(SpringRunner.class) 29 | @EbookChatTest 30 | @WebAppConfiguration 31 | public class ChatRoomControllerTest { 32 | 33 | @Autowired 34 | private WebApplicationContext wac; 35 | 36 | @Autowired 37 | private FilterChainProxy springSecurityFilter; 38 | 39 | private MockMvc mockMvc; 40 | 41 | @Before 42 | public void setup() { 43 | this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).addFilter(springSecurityFilter).build(); 44 | } 45 | 46 | @Test 47 | public void shouldNotCreateChatRoomWhenThereIsNoAuthentication() throws Exception { 48 | ChatRoom chatRoom = new ChatRoom("123", "Dream Theater", "Discuss about best band ever!"); 49 | 50 | this.mockMvc.perform(post("/chatroom") 51 | .content(new ObjectMapper().writeValueAsString(chatRoom))) 52 | .andDo(print()) 53 | .andExpect(unauthenticated()); 54 | } 55 | 56 | @Test 57 | public void shouldCreateChatRoomWhenUserHasRoleAdmin() throws Exception { 58 | ChatRoom chatRoom = new ChatRoom("123", "Dream Theater", "Discuss about best band ever!"); 59 | 60 | this.mockMvc.perform( 61 | post("/chatroom") 62 | .with(user("admin").roles("ADMIN")) 63 | .contentType(MediaType.APPLICATION_JSON) 64 | .content(new ObjectMapper().writeValueAsString(chatRoom)) 65 | ) 66 | .andDo(print()) 67 | .andExpect(status().isCreated()) 68 | .andExpect(jsonPath("$.id", is(chatRoom.getId()))) 69 | .andExpect(jsonPath("$.name", is(chatRoom.getName()))) 70 | .andExpect(jsonPath("$.description", is(chatRoom.getDescription()))); 71 | } 72 | 73 | @Test 74 | public void shouldNotCreateChatRoomWhenUserDoesntHaveRoleAdmin() throws Exception { 75 | ChatRoom chatRoom = new ChatRoom("123", "Dream Theater", "Discuss about best band ever!"); 76 | 77 | this.mockMvc.perform( 78 | post("/chatroom") 79 | .with(user("xuxa").roles("USER")) 80 | .contentType(MediaType.APPLICATION_JSON) 81 | .content(new ObjectMapper().writeValueAsString(chatRoom)) 82 | ) 83 | .andDo(print()) 84 | .andExpect(status().isForbidden()); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/integrationTests/chatroom/domain/service/CassandraInstantMessageServiceTest.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.integrationTests.chatroom.domain.service; 2 | 3 | import static org.hamcrest.MatcherAssert.assertThat; 4 | import static org.hamcrest.Matchers.nullValue; 5 | import static org.hamcrest.core.Is.is; 6 | import java.util.List; 7 | import org.junit.After; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.test.context.junit4.SpringRunner; 13 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoom; 14 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoomUser; 15 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessage; 16 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessageBuilder; 17 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.repository.ChatRoomRepository; 18 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.repository.InstantMessageRepository; 19 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.service.ChatRoomService; 20 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.service.InstantMessageService; 21 | import br.com.jorgeacetozi.ebookChat.integrationTests.test.EbookChatTest; 22 | import br.com.jorgeacetozi.ebookChat.utils.SystemMessages; 23 | import br.com.jorgeacetozi.ebookChat.utils.SystemUsers; 24 | 25 | @RunWith(SpringRunner.class) 26 | @EbookChatTest 27 | public class CassandraInstantMessageServiceTest { 28 | 29 | @Autowired 30 | private ChatRoomService chatRoomService; 31 | 32 | @Autowired 33 | private InstantMessageService instantMessageService; 34 | 35 | @Autowired 36 | private ChatRoomRepository chatRoomRepository; 37 | 38 | @Autowired 39 | private InstantMessageRepository instantMessageRepository; 40 | 41 | private ChatRoom chatRoom; 42 | 43 | @Before 44 | public void setup() { 45 | chatRoom = new ChatRoom("123", "Dream Theater", "Discuss about best band ever!"); 46 | chatRoomService.save(chatRoom); 47 | } 48 | 49 | @After 50 | public void destroy() { 51 | chatRoomRepository.delete(chatRoom); 52 | instantMessageRepository.deleteAll(); 53 | } 54 | 55 | @Test 56 | public void shouldReceiveWelcomeAndGoodByeMessagesFromAdmin() { 57 | final ChatRoomUser jorgeAcetozi = new ChatRoomUser("jorge_acetozi"); 58 | List jorgeAcetoziMessages; 59 | 60 | chatRoomService.join(jorgeAcetozi, chatRoom); 61 | 62 | jorgeAcetoziMessages = instantMessageService.findAllInstantMessagesFor("jorge_acetozi", "123"); 63 | assertThat(jorgeAcetoziMessages.size(), is((1))); 64 | 65 | InstantMessage welcomeMessage = jorgeAcetoziMessages.get(0); 66 | 67 | assertThat(welcomeMessage.getUsername(), is(jorgeAcetozi.getUsername())); 68 | assertThat(welcomeMessage.getChatRoomId(), is(chatRoom.getId())); 69 | assertThat(welcomeMessage.getFromUser(), is(SystemUsers.ADMIN.getUsername())); 70 | assertThat(welcomeMessage.getToUser(), is(nullValue())); 71 | assertThat(welcomeMessage.getText(), is(SystemMessages.welcome(chatRoom.getId(), jorgeAcetozi.getUsername()).getText())); 72 | 73 | chatRoomService.leave(jorgeAcetozi, chatRoom); 74 | 75 | jorgeAcetoziMessages = instantMessageService.findAllInstantMessagesFor(jorgeAcetozi.getUsername(), chatRoom.getId()); 76 | assertThat(jorgeAcetoziMessages.size(), is((2))); 77 | 78 | InstantMessage goodbyeMessage = jorgeAcetoziMessages.get(1); 79 | 80 | assertThat(goodbyeMessage.getUsername(), is(jorgeAcetozi.getUsername())); 81 | assertThat(goodbyeMessage.getChatRoomId(), is(chatRoom.getId())); 82 | assertThat(goodbyeMessage.getFromUser(), is(SystemUsers.ADMIN.getUsername())); 83 | assertThat(goodbyeMessage.getToUser(), is(nullValue())); 84 | assertThat(goodbyeMessage.getText(), is(SystemMessages.goodbye(chatRoom.getId(), jorgeAcetozi.getUsername()).getText())); 85 | } 86 | 87 | @Test 88 | public void shouldStoreEntireConversationWithPublicMessage() { 89 | final ChatRoomUser jorgeAcetozi = new ChatRoomUser("jorge_acetozi"); 90 | List jorgeAcetoziMessages; 91 | 92 | chatRoomService.join(jorgeAcetozi, chatRoom); 93 | 94 | InstantMessage publicMessage = new InstantMessageBuilder() 95 | .newMessage() 96 | .withChatRoomId(chatRoom.getId()) 97 | .publicMessage() 98 | .fromUser(jorgeAcetozi.getUsername()) 99 | .withText("There's no people to chat with me here... I'm leaving now :("); 100 | 101 | chatRoomService.sendPublicMessage(publicMessage); 102 | chatRoomService.leave(jorgeAcetozi, chatRoom); 103 | 104 | jorgeAcetoziMessages = instantMessageService.findAllInstantMessagesFor(jorgeAcetozi.getUsername(), chatRoom.getId()); 105 | assertThat(jorgeAcetoziMessages.size(), is((3))); 106 | 107 | InstantMessage messageOne = jorgeAcetoziMessages.get(0); 108 | InstantMessage messageTwo = jorgeAcetoziMessages.get(1); 109 | InstantMessage messageThree = jorgeAcetoziMessages.get(2); 110 | 111 | assertThat(messageOne.getText(), is(SystemMessages.welcome(chatRoom.getId(), jorgeAcetozi.getUsername()).getText())); 112 | 113 | assertThat(messageTwo.getUsername(), is(jorgeAcetozi.getUsername())); 114 | assertThat(messageTwo.getChatRoomId(), is(chatRoom.getId())); 115 | assertThat(messageTwo.getFromUser(), is(jorgeAcetozi.getUsername())); 116 | assertThat(messageTwo.getToUser(), is(nullValue())); 117 | assertThat(messageTwo.getText(), is(publicMessage.getText())); 118 | 119 | assertThat(messageThree.getText(), is(SystemMessages.goodbye(chatRoom.getId(), jorgeAcetozi.getUsername()).getText())); 120 | } 121 | 122 | @Test 123 | public void shouldStoreEntireConversationWithPrivateMessages() { 124 | final ChatRoomUser jorgeAcetozi = new ChatRoomUser("jorge_acetozi"); 125 | final ChatRoomUser johnPetrucci = new ChatRoomUser("john_petrucci"); 126 | List jorgeAcetoziMessages, johnPetrucciMessages; 127 | 128 | chatRoomService.join(jorgeAcetozi, chatRoom); 129 | chatRoomService.join(johnPetrucci, chatRoom); 130 | 131 | InstantMessage privateMessageOne = new InstantMessageBuilder() 132 | .newMessage() 133 | .withChatRoomId(chatRoom.getId()) 134 | .privateMessage() 135 | .toUser(johnPetrucci.getUsername()) 136 | .fromUser(jorgeAcetozi.getUsername()) 137 | .withText("Hey John, can you play 30 notes per second?"); 138 | chatRoomService.sendPrivateMessage(privateMessageOne); 139 | 140 | InstantMessage privateMessageTwo = new InstantMessageBuilder() 141 | .newMessage() 142 | .withChatRoomId(chatRoom.getId()) 143 | .privateMessage() 144 | .toUser(jorgeAcetozi.getUsername()) 145 | .fromUser(johnPetrucci.getUsername()) 146 | .withText("Of course! That's so easy..."); 147 | chatRoomService.sendPrivateMessage(privateMessageTwo); 148 | 149 | chatRoomService.leave(jorgeAcetozi, chatRoom); 150 | chatRoomService.leave(johnPetrucci, chatRoom); 151 | 152 | jorgeAcetoziMessages = instantMessageService.findAllInstantMessagesFor(jorgeAcetozi.getUsername(), chatRoom.getId()); 153 | assertThat(jorgeAcetoziMessages.size(), is((5))); 154 | 155 | InstantMessage jorgeAcetoziMessageOne = jorgeAcetoziMessages.get(0); 156 | InstantMessage jorgeAcetoziMessageTwo = jorgeAcetoziMessages.get(1); 157 | InstantMessage jorgeAcetoziMessageThree = jorgeAcetoziMessages.get(2); 158 | InstantMessage jorgeAcetoziMessageFour = jorgeAcetoziMessages.get(3); 159 | InstantMessage jorgeAcetoziMessageFive = jorgeAcetoziMessages.get(4); 160 | 161 | assertThat(jorgeAcetoziMessageOne.getText(), is(SystemMessages.welcome(chatRoom.getId(), jorgeAcetozi.getUsername()).getText())); 162 | assertThat(jorgeAcetoziMessageTwo.getText(), is(SystemMessages.welcome(chatRoom.getId(), johnPetrucci.getUsername()).getText())); 163 | 164 | assertThat(jorgeAcetoziMessageThree.getUsername(), is(jorgeAcetozi.getUsername())); 165 | assertThat(jorgeAcetoziMessageThree.getChatRoomId(), is(chatRoom.getId())); 166 | assertThat(jorgeAcetoziMessageThree.getFromUser(), is(jorgeAcetozi.getUsername())); 167 | assertThat(jorgeAcetoziMessageThree.getToUser(), is(johnPetrucci.getUsername())); 168 | assertThat(jorgeAcetoziMessageThree.getText(), is(privateMessageOne.getText())); 169 | 170 | assertThat(jorgeAcetoziMessageFour.getUsername(), is(jorgeAcetozi.getUsername())); 171 | assertThat(jorgeAcetoziMessageFour.getChatRoomId(), is(chatRoom.getId())); 172 | assertThat(jorgeAcetoziMessageFour.getFromUser(), is(johnPetrucci.getUsername())); 173 | assertThat(jorgeAcetoziMessageFour.getToUser(), is(jorgeAcetozi.getUsername())); 174 | assertThat(jorgeAcetoziMessageFour.getText(), is(privateMessageTwo.getText())); 175 | 176 | assertThat(jorgeAcetoziMessageFive.getText(), is(SystemMessages.goodbye(chatRoom.getId(), jorgeAcetozi.getUsername()).getText())); 177 | 178 | johnPetrucciMessages = instantMessageService.findAllInstantMessagesFor(johnPetrucci.getUsername(), chatRoom.getId()); 179 | assertThat(johnPetrucciMessages.size(), is((5))); 180 | 181 | InstantMessage johnPetrucciMessageOne = johnPetrucciMessages.get(0); 182 | InstantMessage johnPetrucciMessageTwo = johnPetrucciMessages.get(1); 183 | InstantMessage johnPetrucciMessageThree = johnPetrucciMessages.get(2); 184 | InstantMessage johnPetrucciMessageFour = johnPetrucciMessages.get(3); 185 | InstantMessage johnPetrucciMessageFive = johnPetrucciMessages.get(4); 186 | 187 | assertThat(johnPetrucciMessageOne.getText(), is(SystemMessages.welcome(chatRoom.getId(), johnPetrucci.getUsername()).getText())); 188 | 189 | assertThat(johnPetrucciMessageTwo.getUsername(), is(johnPetrucci.getUsername())); 190 | assertThat(johnPetrucciMessageTwo.getChatRoomId(), is(chatRoom.getId())); 191 | assertThat(johnPetrucciMessageTwo.getFromUser(), is(jorgeAcetozi.getUsername())); 192 | assertThat(johnPetrucciMessageTwo.getToUser(), is(johnPetrucci.getUsername())); 193 | assertThat(johnPetrucciMessageTwo.getText(), is(privateMessageOne.getText())); 194 | 195 | assertThat(johnPetrucciMessageThree.getUsername(), is(johnPetrucci.getUsername())); 196 | assertThat(johnPetrucciMessageThree.getChatRoomId(), is(chatRoom.getId())); 197 | assertThat(johnPetrucciMessageThree.getFromUser(), is(johnPetrucci.getUsername())); 198 | assertThat(johnPetrucciMessageThree.getToUser(), is(jorgeAcetozi.getUsername())); 199 | assertThat(johnPetrucciMessageThree.getText(), is(privateMessageTwo.getText())); 200 | 201 | assertThat(johnPetrucciMessageFour.getText(), is(SystemMessages.goodbye(chatRoom.getId(), jorgeAcetozi.getUsername()).getText())); 202 | assertThat(johnPetrucciMessageFive.getText(), is(SystemMessages.goodbye(chatRoom.getId(), johnPetrucci.getUsername()).getText())); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/integrationTests/chatroom/domain/service/RedisChatRoomServiceTest.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.integrationTests.chatroom.domain.service; 2 | 3 | import static org.hamcrest.MatcherAssert.assertThat; 4 | import static org.hamcrest.core.Is.is; 5 | import java.util.List; 6 | import org.junit.After; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoom; 13 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoomUser; 14 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.repository.ChatRoomRepository; 15 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.repository.InstantMessageRepository; 16 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.service.ChatRoomService; 17 | import br.com.jorgeacetozi.ebookChat.integrationTests.test.EbookChatTest; 18 | 19 | @RunWith(SpringRunner.class) 20 | @EbookChatTest 21 | public class RedisChatRoomServiceTest { 22 | 23 | @Autowired 24 | private ChatRoomService chatRoomService; 25 | 26 | @Autowired 27 | private ChatRoomRepository chatRoomRepository; 28 | 29 | @Autowired 30 | private InstantMessageRepository instantMessageRepository; 31 | 32 | private ChatRoom chatRoom; 33 | 34 | @Before 35 | public void setup() { 36 | chatRoom = new ChatRoom("123", "Dream Theater", "Discuss about best band ever!"); 37 | chatRoomService.save(chatRoom); 38 | } 39 | 40 | @After 41 | public void destroy() { 42 | chatRoomRepository.delete(chatRoom); 43 | instantMessageRepository.deleteAll(); 44 | } 45 | 46 | @Test 47 | public void shouldJoinUsersToChatRoom() { 48 | assertThat(chatRoom.getNumberOfConnectedUsers(), is(0)); 49 | 50 | ChatRoomUser jorgeAcetozi = new ChatRoomUser("jorge_acetozi"); 51 | ChatRoomUser johnPetrucci = new ChatRoomUser("john_petrucci"); 52 | 53 | chatRoomService.join(jorgeAcetozi, chatRoom); 54 | assertThat(chatRoom.getNumberOfConnectedUsers(), is(1)); 55 | 56 | chatRoomService.join(johnPetrucci, chatRoom); 57 | assertThat(chatRoom.getNumberOfConnectedUsers(), is(2)); 58 | 59 | ChatRoom dreamTheaterChatRoom = chatRoomService.findById(chatRoom.getId()); 60 | List connectedUsers = dreamTheaterChatRoom.getConnectedUsers(); 61 | 62 | assertThat(connectedUsers.contains(jorgeAcetozi), is(true)); 63 | assertThat(connectedUsers.contains(johnPetrucci), is(true)); 64 | } 65 | 66 | @Test 67 | public void shouldLeaveUsersFromChatRoom() { 68 | ChatRoomUser jorgeAcetozi = new ChatRoomUser("jorge_acetozi"); 69 | ChatRoomUser johnPetrucci = new ChatRoomUser("john_petrucci"); 70 | 71 | chatRoomService.join(jorgeAcetozi, chatRoom); 72 | chatRoomService.join(johnPetrucci, chatRoom); 73 | assertThat(chatRoom.getNumberOfConnectedUsers(), is(2)); 74 | 75 | chatRoomService.leave(jorgeAcetozi, chatRoom); 76 | chatRoomService.leave(johnPetrucci, chatRoom); 77 | assertThat(chatRoom.getNumberOfConnectedUsers(), is(0)); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/integrationTests/test/AbstractIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.integrationTests.test; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | import java.util.concurrent.TimeoutException; 5 | 6 | import org.junit.BeforeClass; 7 | import org.junit.ClassRule; 8 | import org.testcontainers.containers.FixedHostPortGenericContainer; 9 | import org.testcontainers.containers.GenericContainer; 10 | import org.testcontainers.containers.output.WaitingConsumer; 11 | 12 | public class AbstractIntegrationTest { 13 | 14 | @ClassRule 15 | public static final GenericContainer cassandra = new FixedHostPortGenericContainer("cassandra:3.0") 16 | .withFixedExposedPort(9042, 9042); 17 | 18 | @ClassRule 19 | public static final GenericContainer mysql = new FixedHostPortGenericContainer("mysql:5.7") 20 | .withFixedExposedPort(3306, 3306) 21 | .withEnv("MYSQL_DATABASE", "ebook_chat") 22 | .withEnv("MYSQL_ROOT_PASSWORD", "root"); 23 | 24 | @ClassRule 25 | public static final GenericContainer redis = new FixedHostPortGenericContainer("redis:3.0.6") 26 | .withFixedExposedPort(6379, 6379); 27 | 28 | @ClassRule 29 | public static final GenericContainer rabbitmq = new FixedHostPortGenericContainer("jorgeacetozi/rabbitmq-stomp:3.6") 30 | .withFixedExposedPort(61613, 61613) 31 | .withExposedPorts(61613); 32 | 33 | @BeforeClass 34 | public static void waitForMysqlContainerStartup() throws InterruptedException, TimeoutException { 35 | WaitingConsumer consumer = new WaitingConsumer(); 36 | mysql.followOutput(consumer); 37 | consumer.waitUntil(frame -> 38 | frame.getUtf8String().contains("mysqld: ready for connections."), 90, TimeUnit.SECONDS); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/integrationTests/test/EbookChatTest.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.integrationTests.test; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.test.context.ActiveProfiles; 10 | 11 | @Target(ElementType.TYPE) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @SpringBootTest 14 | @ActiveProfiles("test") 15 | public @interface EbookChatTest { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/unitTests/UnitTestsSuite.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.unitTests; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.junit.runners.Suite; 5 | 6 | import br.com.jorgeacetozi.ebookChat.unitTests.chatroom.domain.service.RedisChatRoomServiceTest; 7 | import br.com.jorgeacetozi.ebookChat.unitTests.chatroom.domain.model.InstantMessageBuilderTest; 8 | import br.com.jorgeacetozi.ebookChat.unitTests.utils.DestinationsTest; 9 | import br.com.jorgeacetozi.ebookChat.unitTests.utils.SystemMessagesTest; 10 | 11 | @RunWith(Suite.class) 12 | @Suite.SuiteClasses({ 13 | InstantMessageBuilderTest.class, 14 | DestinationsTest.class, 15 | SystemMessagesTest.class, 16 | RedisChatRoomServiceTest.class 17 | }) 18 | public class UnitTestsSuite { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/unitTests/chatroom/domain/model/InstantMessageBuilderTest.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.unitTests.chatroom.domain.model; 2 | 3 | import static org.hamcrest.MatcherAssert.assertThat; 4 | import static org.hamcrest.Matchers.nullValue; 5 | import static org.hamcrest.core.Is.is; 6 | 7 | import org.junit.Test; 8 | 9 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessage; 10 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessageBuilder; 11 | import br.com.jorgeacetozi.ebookChat.utils.SystemUsers; 12 | 13 | public class InstantMessageBuilderTest { 14 | 15 | private final String chatRoomId = "123"; 16 | private final String fromUser = "jorge_acetozi"; 17 | private final String toUser = "michael_romeo"; 18 | private final String publicMessageText = "Hello guys... I hope you are enjoying my eBook!"; 19 | private final String privateMessageText = "I'm listening to Symphony X right now!"; 20 | private final String systemMessageText = "This is a system message from admin user!"; 21 | 22 | @Test 23 | public void shouldCreatePublicInstantMessage() { 24 | InstantMessage publicMessage = new InstantMessageBuilder() 25 | .newMessage() 26 | .withChatRoomId(chatRoomId) 27 | .publicMessage() 28 | .fromUser(fromUser) 29 | .withText(publicMessageText); 30 | 31 | assertThat(publicMessage.isPublic(), is(true)); 32 | assertThat(publicMessage.isFromAdmin(), is(false)); 33 | assertThat(publicMessage.getChatRoomId(), is(chatRoomId)); 34 | assertThat(publicMessage.getFromUser(), is(fromUser)); 35 | assertThat(publicMessage.getToUser(), is(nullValue())); 36 | assertThat(publicMessage.getText(), is(publicMessageText)); 37 | } 38 | 39 | @Test 40 | public void shouldCreatePrivateInstantMessage() { 41 | InstantMessage privateMessage = new InstantMessageBuilder() 42 | .newMessage() 43 | .withChatRoomId(chatRoomId) 44 | .privateMessage() 45 | .toUser(toUser) 46 | .fromUser(fromUser). 47 | withText(privateMessageText); 48 | 49 | assertThat(privateMessage.isPublic(), is(false)); 50 | assertThat(privateMessage.isFromAdmin(), is(false)); 51 | assertThat(privateMessage.getChatRoomId(), is(chatRoomId)); 52 | assertThat(privateMessage.getFromUser(), is(fromUser)); 53 | assertThat(privateMessage.getToUser(), is(toUser)); 54 | assertThat(privateMessage.getText(), is(privateMessageText)); 55 | } 56 | 57 | @Test 58 | public void shouldCreateSystemInstantMessage() { 59 | InstantMessage systemMessage = new InstantMessageBuilder() 60 | .newMessage() 61 | .withChatRoomId(chatRoomId) 62 | .systemMessage() 63 | .withText(systemMessageText); 64 | 65 | assertThat(systemMessage.isPublic(), is(true)); 66 | assertThat(systemMessage.isFromAdmin(), is(true)); 67 | assertThat(systemMessage.getChatRoomId(), is(chatRoomId)); 68 | assertThat(systemMessage.getFromUser(), is(SystemUsers.ADMIN.getUsername())); 69 | assertThat(systemMessage.getToUser(), is(nullValue())); 70 | assertThat(systemMessage.getText(), is(systemMessageText)); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/unitTests/chatroom/domain/service/RedisChatRoomServiceTest.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.unitTests.chatroom.domain.service; 2 | 3 | import static org.hamcrest.MatcherAssert.assertThat; 4 | import static org.hamcrest.core.Is.is; 5 | import static org.junit.Assert.assertEquals; 6 | import static org.mockito.Mockito.times; 7 | import static org.mockito.Mockito.verify; 8 | 9 | import java.util.List; 10 | 11 | import org.junit.Test; 12 | import org.junit.runner.RunWith; 13 | import org.mockito.ArgumentCaptor; 14 | import org.mockito.Captor; 15 | import org.mockito.InjectMocks; 16 | import org.mockito.Mock; 17 | import org.mockito.runners.MockitoJUnitRunner; 18 | import org.springframework.messaging.simp.SimpMessagingTemplate; 19 | 20 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoom; 21 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.ChatRoomUser; 22 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessage; 23 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessageBuilder; 24 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.repository.ChatRoomRepository; 25 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.service.ChatRoomService; 26 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.service.InstantMessageService; 27 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.service.RedisChatRoomService; 28 | import br.com.jorgeacetozi.ebookChat.utils.Destinations; 29 | import br.com.jorgeacetozi.ebookChat.utils.SystemMessages; 30 | 31 | @RunWith(MockitoJUnitRunner.class) 32 | public class RedisChatRoomServiceTest { 33 | 34 | @InjectMocks 35 | private ChatRoomService chatRoomService = new RedisChatRoomService(); 36 | 37 | @Mock 38 | private SimpMessagingTemplate webSocketMessagingTemplate; 39 | 40 | @Mock 41 | private ChatRoomRepository chatRoomRepository; 42 | 43 | @Mock 44 | private InstantMessageService instantMessageService; 45 | 46 | @Captor 47 | private ArgumentCaptor chatRoomCaptor; 48 | 49 | @Captor 50 | private ArgumentCaptor toUserCaptor; 51 | 52 | @Captor 53 | private ArgumentCaptor destinationCaptor; 54 | 55 | @Captor 56 | private ArgumentCaptor instantMessageCaptor; 57 | 58 | @Captor 59 | private ArgumentCaptor messageObjectCaptor; 60 | 61 | @Test 62 | public void shouldJoinUserToChatRoom() { 63 | ChatRoom chatRoom = new ChatRoom("123", "Dream Theater", "Discuss about best band ever!"); 64 | 65 | assertThat(chatRoom.getNumberOfConnectedUsers(), is(0)); 66 | 67 | ChatRoomUser user = new ChatRoomUser("jorge_acetozi"); 68 | chatRoomService.join(user, chatRoom); 69 | 70 | assertThat(chatRoom.getNumberOfConnectedUsers(), is(1)); 71 | 72 | verify(chatRoomRepository, times(1)).save(chatRoom); 73 | verify(webSocketMessagingTemplate, times(2)).convertAndSend(destinationCaptor.capture(), 74 | messageObjectCaptor.capture()); 75 | verify(instantMessageService, times(1)).appendInstantMessageToConversations(instantMessageCaptor.capture()); 76 | 77 | List destinations = destinationCaptor.getAllValues(); 78 | List messageObjects = messageObjectCaptor.getAllValues(); 79 | InstantMessage instantMessageToBeAppendedToConversations = instantMessageCaptor.getValue(); 80 | 81 | String publicMessagesDestination = destinations.get(0); 82 | String connectedUsersDestination = destinations.get(1); 83 | InstantMessage welcomeMessage = (InstantMessage) messageObjects.get(0); 84 | List connectedUsers = (List) messageObjects.get(1); 85 | 86 | assertThat(publicMessagesDestination, is(Destinations.ChatRoom.publicMessages(chatRoom.getId()))); 87 | assertThat(connectedUsersDestination, is(Destinations.ChatRoom.connectedUsers(chatRoom.getId()))); 88 | assertEquals(SystemMessages.welcome(chatRoom.getId(), user.getUsername()), welcomeMessage); 89 | assertEquals(SystemMessages.welcome(chatRoom.getId(), user.getUsername()), 90 | instantMessageToBeAppendedToConversations); 91 | assertThat(connectedUsers.contains(user), is(true)); 92 | } 93 | 94 | @Test 95 | public void shouldLeaveUserFromChatRoom() { 96 | ChatRoom chatRoom = new ChatRoom("123", "Dream Theater", "Discuss about best band ever!"); 97 | ChatRoomUser user = new ChatRoomUser("jorge_acetozi"); 98 | chatRoom.addUser(user); 99 | 100 | assertThat(chatRoom.getNumberOfConnectedUsers(), is(1)); 101 | 102 | chatRoomService.leave(user, chatRoom); 103 | 104 | assertThat(chatRoom.getNumberOfConnectedUsers(), is(0)); 105 | 106 | verify(chatRoomRepository, times(1)).save(chatRoom); 107 | verify(webSocketMessagingTemplate, times(2)).convertAndSend(destinationCaptor.capture(), 108 | messageObjectCaptor.capture()); 109 | verify(instantMessageService, times(1)).appendInstantMessageToConversations(instantMessageCaptor.capture()); 110 | 111 | List destinations = destinationCaptor.getAllValues(); 112 | List messageObjects = messageObjectCaptor.getAllValues(); 113 | InstantMessage instantMessageToBeAppendedToConversations = instantMessageCaptor.getValue(); 114 | 115 | String publicMessagesDestination = destinations.get(0); 116 | String connectedUsersDestination = destinations.get(1); 117 | InstantMessage goodbyeMessage = (InstantMessage) messageObjects.get(0); 118 | List connectedUsers = (List) messageObjects.get(1); 119 | 120 | assertThat(publicMessagesDestination, is(Destinations.ChatRoom.publicMessages(chatRoom.getId()))); 121 | assertThat(connectedUsersDestination, is(Destinations.ChatRoom.connectedUsers(chatRoom.getId()))); 122 | assertEquals(SystemMessages.goodbye(chatRoom.getId(), user.getUsername()), goodbyeMessage); 123 | assertEquals(SystemMessages.goodbye(chatRoom.getId(), user.getUsername()), 124 | instantMessageToBeAppendedToConversations); 125 | assertThat(connectedUsers.contains(user), is(false)); 126 | } 127 | 128 | @Test 129 | public void shouldSendPublicMessage() { 130 | ChatRoom chatRoom = new ChatRoom("123", "Dream Theater", "Discuss about best band ever!"); 131 | ChatRoomUser user = new ChatRoomUser("jorge_acetozi"); 132 | chatRoom.addUser(user); 133 | 134 | assertThat(chatRoom.getNumberOfConnectedUsers(), is(1)); 135 | 136 | InstantMessage publicMessage = new InstantMessageBuilder().newMessage().withChatRoomId(chatRoom.getId()) 137 | .publicMessage().fromUser(user.getUsername()).withText("This is a public message!"); 138 | 139 | chatRoomService.sendPublicMessage(publicMessage); 140 | 141 | verify(webSocketMessagingTemplate, times(1)).convertAndSend(destinationCaptor.capture(), 142 | messageObjectCaptor.capture()); 143 | verify(instantMessageService, times(1)).appendInstantMessageToConversations(instantMessageCaptor.capture()); 144 | 145 | String sentDestination = destinationCaptor.getValue(); 146 | InstantMessage sentMessage = (InstantMessage) messageObjectCaptor.getValue(); 147 | InstantMessage instantMessageToBeAppendedToConversations = instantMessageCaptor.getValue(); 148 | 149 | assertThat(sentDestination, is(Destinations.ChatRoom.publicMessages(chatRoom.getId()))); 150 | assertEquals(publicMessage, sentMessage); 151 | assertEquals(publicMessage, instantMessageToBeAppendedToConversations); 152 | } 153 | 154 | @Test 155 | public void shouldSendPrivateMessage() { 156 | ChatRoom chatRoom = new ChatRoom("123", "Dream Theater", "Discuss about best band ever!"); 157 | ChatRoomUser jorgeAcetozi = new ChatRoomUser("jorge_acetozi"); 158 | ChatRoomUser johnPetrucci = new ChatRoomUser("john_petrucci"); 159 | chatRoom.addUser(jorgeAcetozi); 160 | chatRoom.addUser(johnPetrucci); 161 | 162 | assertThat(chatRoom.getNumberOfConnectedUsers(), is(2)); 163 | 164 | InstantMessage privateMessage = new InstantMessageBuilder().newMessage().withChatRoomId(chatRoom.getId()) 165 | .privateMessage().toUser(johnPetrucci.getUsername()).fromUser(jorgeAcetozi.getUsername()) 166 | .withText("Hello John, can you teach me how to play guitar?"); 167 | 168 | chatRoomService.sendPrivateMessage(privateMessage); 169 | 170 | verify(webSocketMessagingTemplate, times(2)).convertAndSendToUser(toUserCaptor.capture(), 171 | destinationCaptor.capture(), messageObjectCaptor.capture()); 172 | verify(instantMessageService, times(1)).appendInstantMessageToConversations(instantMessageCaptor.capture()); 173 | 174 | List toUsers = toUserCaptor.getAllValues(); 175 | List destinations = destinationCaptor.getAllValues(); 176 | List messageObjects = messageObjectCaptor.getAllValues(); 177 | InstantMessage instantMessageToBeAppendedToConversations = instantMessageCaptor.getValue(); 178 | 179 | String messageOneSentToUser = toUsers.get(0); 180 | String messageTwoSentToUser = toUsers.get(1); 181 | 182 | String messageOneDestination = destinations.get(0); 183 | String messageTwoDestination = destinations.get(1); 184 | 185 | InstantMessage messageOne = (InstantMessage) messageObjects.get(0); 186 | InstantMessage messageTwo = (InstantMessage) messageObjects.get(1); 187 | 188 | assertThat(messageOneDestination, is(Destinations.ChatRoom.privateMessages(chatRoom.getId()))); 189 | assertEquals(privateMessage, messageOne); 190 | assertThat(messageOneSentToUser, is(johnPetrucci.getUsername())); 191 | 192 | assertThat(messageTwoDestination, is(Destinations.ChatRoom.privateMessages(chatRoom.getId()))); 193 | assertEquals(privateMessage, messageTwo); 194 | assertThat(messageTwoSentToUser, is(jorgeAcetozi.getUsername())); 195 | 196 | assertEquals(privateMessage, instantMessageToBeAppendedToConversations); 197 | } 198 | 199 | @Test 200 | public void shouldSaveNewChatRoom() { 201 | ChatRoom chatRoom = new ChatRoom("123", "Dream Theater", "Discuss about best band ever!"); 202 | chatRoomService.save(chatRoom); 203 | verify(chatRoomRepository, times(1)).save(chatRoom); 204 | } 205 | 206 | @Test 207 | public void shouldFindChatRoomById() { 208 | String chatRoomId = "123"; 209 | chatRoomService.findById(chatRoomId); 210 | verify(chatRoomRepository, times(1)).findOne(chatRoomId); 211 | } 212 | 213 | @Test 214 | public void shouldFindAllChatRooms() { 215 | chatRoomService.findAll(); 216 | verify(chatRoomRepository, times(1)).findAll(); 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/unitTests/utils/DestinationsTest.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.unitTests.utils; 2 | 3 | import static org.hamcrest.MatcherAssert.assertThat; 4 | import static org.hamcrest.core.Is.is; 5 | 6 | import org.junit.Test; 7 | 8 | import br.com.jorgeacetozi.ebookChat.utils.Destinations; 9 | 10 | public class DestinationsTest { 11 | 12 | private final String chatRoomId = "123"; 13 | 14 | @Test 15 | public void shouldGetPublicMessagesDestination() { 16 | assertThat(Destinations.ChatRoom.publicMessages("123"), is("/topic/" + chatRoomId + ".public.messages")); 17 | } 18 | 19 | @Test 20 | public void shouldGetPrivateMessagesDestination() { 21 | assertThat(Destinations.ChatRoom.privateMessages("123"), is("/queue/" + chatRoomId + ".private.messages")); 22 | } 23 | 24 | @Test 25 | public void shouldGetConnectedUsersDestination() { 26 | assertThat(Destinations.ChatRoom.connectedUsers("123"), is("/topic/" + chatRoomId + ".connected.users")); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/ebook-chat/src/test/java/br/com/jorgeacetozi/ebookChat/unitTests/utils/SystemMessagesTest.java: -------------------------------------------------------------------------------- 1 | package br.com.jorgeacetozi.ebookChat.unitTests.utils; 2 | 3 | import static org.hamcrest.MatcherAssert.assertThat; 4 | import static org.hamcrest.Matchers.nullValue; 5 | import static org.hamcrest.core.Is.is; 6 | 7 | import org.junit.Test; 8 | 9 | import br.com.jorgeacetozi.ebookChat.chatroom.domain.model.InstantMessage; 10 | import br.com.jorgeacetozi.ebookChat.utils.SystemMessages; 11 | import br.com.jorgeacetozi.ebookChat.utils.SystemUsers; 12 | 13 | public class SystemMessagesTest { 14 | 15 | private final String chatRoomId = "123"; 16 | private final String username = "jorge_acetozi"; 17 | 18 | @Test 19 | public void shouldGetWelcomeInstantMessage() { 20 | InstantMessage welcomeMessage = SystemMessages.welcome(chatRoomId, username); 21 | 22 | assertThat(welcomeMessage.isPublic(), is(true)); 23 | assertThat(welcomeMessage.isFromAdmin(), is(true)); 24 | assertThat(welcomeMessage.getChatRoomId(), is(chatRoomId)); 25 | assertThat(welcomeMessage.getFromUser(), is(SystemUsers.ADMIN.getUsername())); 26 | assertThat(welcomeMessage.getToUser(), is(nullValue())); 27 | assertThat(welcomeMessage.getText(), is(username + " joined us :)")); 28 | } 29 | 30 | @Test 31 | public void shouldGetGoodbyeInstantMessage() { 32 | InstantMessage goodbyeMessage = SystemMessages.goodbye(chatRoomId, username); 33 | 34 | assertThat(goodbyeMessage.isPublic(), is(true)); 35 | assertThat(goodbyeMessage.isFromAdmin(), is(true)); 36 | assertThat(goodbyeMessage.getChatRoomId(), is(chatRoomId)); 37 | assertThat(goodbyeMessage.getFromUser(), is(SystemUsers.ADMIN.getUsername())); 38 | assertThat(goodbyeMessage.getToUser(), is(nullValue())); 39 | assertThat(goodbyeMessage.getText(), is(username + " left us :(")); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/images/ebook-chat-application.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-java-clustering-scalability/b3cbfbda4d6a1fa7c3a3b2c3f3c537310dd767a6/ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/images/ebook-chat-application.png -------------------------------------------------------------------------------- /ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/images/title_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/pro-java-clustering-scalability/b3cbfbda4d6a1fa7c3a3b2c3f3c537310dd767a6/ebook-chat-app-spring-websocket-cassandra-redis-rabbitmq-master/images/title_page.png --------------------------------------------------------------------------------