add new package

This commit is contained in:
2024-04-30 11:54:43 -04:00
parent 6b33c0d65d
commit 99259d231b
291 changed files with 7240 additions and 0 deletions
@@ -0,0 +1,7 @@
### Relevant Articles:
- [Service Locator Pattern and Java Implementation](https://www.baeldung.com/java-service-locator-pattern)
- [The DAO Pattern in Java](https://www.baeldung.com/java-dao-pattern)
- [DAO vs Repository Patterns](https://www.baeldung.com/java-dao-vs-repository)
- [Difference Between MVC and MVP Patterns](https://www.baeldung.com/mvc-vs-mvp-pattern)
- [The DTO Pattern (Data Transfer Object)](https://www.baeldung.com/java-dto-pattern)
- [SEDA With Spring Integration and Apache Camel](https://www.baeldung.com/spring-apache-camel-seda-integration)
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>design-patterns-architectural</artifactId>
<version>1.0</version>
<name>design-patterns-architectural</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>patterns-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>${rest-assured.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate-core.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
<version>${spring-boot-starter-integration.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-test</artifactId>
<version>${spring-integration-test.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>${camel-core.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test-junit5</artifactId>
<version>${camel-test-junit5.version}</version>
</dependency>
</dependencies>
<properties>
<hibernate-core.version>5.2.16.Final</hibernate-core.version>
<mysql-connector.version>6.0.6</mysql-connector.version>
<spring-boot.version>2.7.5</spring-boot.version>
<rest-assured.version>5.3.0</rest-assured.version>
<spring-boot-starter-integration.version>2.7.5</spring-boot-starter-integration.version>
<spring-integration-test.version>5.5.14</spring-integration-test.version>
<camel-core.version>3.20.4</camel-core.version>
<camel-test-junit5.version>3.14.0</camel-test-junit5.version>
</properties>
</project>
@@ -0,0 +1,12 @@
package com.baeldung.dtopattern;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
@@ -0,0 +1,28 @@
package com.baeldung.dtopattern.api;
import com.baeldung.dtopattern.domain.Role;
import com.baeldung.dtopattern.domain.User;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import static java.util.stream.Collectors.toList;
@Component
class Mapper {
public UserDTO toDto(User user) {
String name = user.getName();
List<String> roles = user
.getRoles()
.stream()
.map(Role::getName)
.collect(toList());
return new UserDTO(name, roles);
}
public User toUser(UserCreationDTO userDTO) {
return new User(userDTO.getName(), userDTO.getPassword(), new ArrayList<>());
}
}
@@ -0,0 +1,51 @@
package com.baeldung.dtopattern.api;
import com.baeldung.dtopattern.domain.RoleService;
import com.baeldung.dtopattern.domain.User;
import com.baeldung.dtopattern.domain.UserService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static java.util.stream.Collectors.toList;
@RestController
@RequestMapping("/users")
class UserController {
private UserService userService;
private RoleService roleService;
private Mapper mapper;
public UserController(UserService userService, RoleService roleService, Mapper mapper) {
this.userService = userService;
this.roleService = roleService;
this.mapper = mapper;
}
@GetMapping
@ResponseBody
public List<UserDTO> getUsers() {
return userService.getAll()
.stream()
.map(mapper::toDto)
.collect(toList());
}
@PostMapping
@ResponseBody
public UserIdDTO create(@RequestBody UserCreationDTO userDTO) {
User user = mapper.toUser(userDTO);
userDTO.getRoles()
.stream()
.map(role -> roleService.getOrCreate(role))
.forEach(user::addRole);
userService.save(user);
return new UserIdDTO(user.getId());
}
}
@@ -0,0 +1,36 @@
package com.baeldung.dtopattern.api;
import java.util.List;
public class UserCreationDTO {
private String name;
private String password;
private List<String> roles;
UserCreationDTO() {}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
public List<String> getRoles() {
return roles;
}
void setName(String name) {
this.name = name;
}
void setPassword(String password) {
this.password = password;
}
void setRoles(List<String> roles) {
this.roles = roles;
}
}
@@ -0,0 +1,22 @@
package com.baeldung.dtopattern.api;
import java.util.List;
public class UserDTO {
private String name;
private List<String> roles;
public UserDTO(String name, List<String> roles) {
this.name = name;
this.roles = roles;
}
public String getName() {
return name;
}
public List<String> getRoles() {
return roles;
}
}
@@ -0,0 +1,14 @@
package com.baeldung.dtopattern.api;
public class UserIdDTO {
private String id;
public UserIdDTO(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
@@ -0,0 +1,49 @@
package com.baeldung.dtopattern.domain;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
class InMemoryRepository implements UserRepository, RoleRepository {
private Map<String, User> users = new LinkedHashMap<>();
private Map<String, Role> roles = new LinkedHashMap<>();
@Override
public List<User> getAll() {
return new ArrayList<>(users.values());
}
@Override
public void save(User user) {
user.setId(UUID.randomUUID().toString());
users.put(user.getId(), user);
}
@Override
public void save(Role role) {
role.setId(UUID.randomUUID().toString());
roles.put(role.getId(), role);
}
@Override
public Role getRoleById(String id) {
return roles.get(id);
}
@Override
public Role getRoleByName(String name) {
return roles.values()
.stream()
.filter(role -> role.getName().equalsIgnoreCase(name))
.findFirst()
.orElse(null);
}
@Override
public void deleteAll() {
users.clear();
roles.clear();
}
}
@@ -0,0 +1,28 @@
package com.baeldung.dtopattern.domain;
import java.util.Objects;
public class Role {
private String id;
private String name;
public Role(String name) {
this.name = Objects.requireNonNull(name);
}
public String getId() {
return id;
}
void setId(String id) {
this.id = Objects.requireNonNull(id);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = Objects.requireNonNull(name);
}
}
@@ -0,0 +1,7 @@
package com.baeldung.dtopattern.domain;
public interface RoleRepository {
Role getRoleById(String id);
Role getRoleByName(String name);
void save(Role role);
}
@@ -0,0 +1,32 @@
package com.baeldung.dtopattern.domain;
import org.springframework.stereotype.Service;
import java.util.Objects;
@Service
public class RoleService {
private RoleRepository repository;
public RoleService(RoleRepository repository) {
this.repository = repository;
}
public Role getOrCreate(String name) {
Role role = repository.getRoleByName(name);
if (role == null) {
role = new Role(name);
repository.save(role);
}
return role;
}
public void save(Role role) {
Objects.requireNonNull(role);
repository.save(role);
}
}
@@ -0,0 +1,80 @@
package com.baeldung.dtopattern.domain;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class User {
private static SecretKeySpec KEY = initKey();
static SecretKeySpec initKey(){
try {
SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey();
return new SecretKeySpec(secretKey.getEncoded(), "AES");
} catch (NoSuchAlgorithmException ex) {
return null;
}
}
private String id;
private String name;
private String password;
private List<Role> roles;
public User(String name, String password, List<Role> roles) {
this.name = Objects.requireNonNull(name);
this.password = this.encrypt(password);
this.roles = Objects.requireNonNull(roles);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void addRole(Role role) {
roles.add(role);
}
public List<Role> getRoles() {
return Collections.unmodifiableList(roles);
}
public String getId() {
return id;
}
void setId(String id) {
this.id = id;
}
String encrypt(String password) {
Objects.requireNonNull(password);
try {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, KEY);
final byte[] encryptedBytes = cipher.doFinal(password.getBytes(StandardCharsets.UTF_8));
return new String(encryptedBytes, StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
// do nothing
return "";
}
}
}
@@ -0,0 +1,9 @@
package com.baeldung.dtopattern.domain;
import java.util.List;
public interface UserRepository {
List<User> getAll();
void save(User user);
void deleteAll();
}
@@ -0,0 +1,25 @@
package com.baeldung.dtopattern.domain;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
@Service
public class UserService {
private UserRepository repository;
public UserService(UserRepository repository) {
this.repository = repository;
}
public List<User> getAll() {
return repository.getAll();
}
public void save(User user) {
Objects.requireNonNull(user);
repository.save(user);
}
}
@@ -0,0 +1,24 @@
package com.baeldung.mvc_mvp.mvc;
public class MvcMainClass {
public static void main(String[] args) {
Product model = retrieveProductFromDatabase();
ProductView view = new ProductView();
model.setView(view);
model.showProduct();
ProductController controller = new ProductController(model);
controller.setName("SmartPhone");
model.showProduct();
}
private static Product retrieveProductFromDatabase() {
Product product = new Product();
product.setName("Mobile");
product.setDescription("New Brand");
product.setPrice(1000.0);
return product;
}
}
@@ -0,0 +1,45 @@
package com.baeldung.mvc_mvp.mvc;
public class Product {
private String name;
private String description;
private Double price;
private ProductView view;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public ProductView getView() {
return view;
}
public void setView(ProductView view) {
this.view = view;
}
public void showProduct() {
view.printProductDetails(name, description, price);
}
}
@@ -0,0 +1,34 @@
package com.baeldung.mvc_mvp.mvc;
public class ProductController {
private final Product product;
public ProductController(Product product) {
this.product = product;
}
public String getName() {
return product.getName();
}
public void setName(String name) {
product.setName(name);
}
public String getDescription() {
return product.getDescription();
}
public void setDescription(String description) {
product.setDescription(description);
}
public Double getPrice() {
return product.getPrice();
}
public void setPrice(Double price) {
product.setPrice(price);
}
}
@@ -0,0 +1,15 @@
package com.baeldung.mvc_mvp.mvc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ProductView {
private static Logger log = LoggerFactory.getLogger(ProductView.class);
public void printProductDetails(String name, String description, Double price) {
log.info("Product details:");
log.info("product Name: " + name);
log.info("product Description: " + description);
log.info("product price: " + price);
}
}
@@ -0,0 +1,22 @@
package com.baeldung.mvc_mvp.mvp;
public class MvpMainClass {
public static void main(String[] args) {
Product model = retrieveProductFromDatabase();
ProductView view = new ProductView();
ProductPresenter presenter = new ProductPresenter(model, view);
presenter.showProduct();
presenter.setName("SmartPhone");
presenter.showProduct();
}
private static Product retrieveProductFromDatabase() {
Product product = new Product();
product.setName("Mobile");
product.setDescription("New Brand");
product.setPrice(1000.0);
return product;
}
}
@@ -0,0 +1,32 @@
package com.baeldung.mvc_mvp.mvp;
public class Product {
private String name;
private String description;
private Double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
@@ -0,0 +1,40 @@
package com.baeldung.mvc_mvp.mvp;
public class ProductPresenter {
private final Product product;
private final ProductView view;
public ProductPresenter(Product product, ProductView view) {
this.product = product;
this.view = view;
}
public String getName() {
return product.getName();
}
public void setName(String name) {
product.setName(name);
}
public String getDescription() {
return product.getDescription();
}
public void setDescription(String description) {
product.setDescription(description);
}
public Double getProductPrice() {
return product.getPrice();
}
public void setPrice(Double price) {
product.setPrice(price);
}
public void showProduct() {
view.printProductDetails(product.getName(), product.getDescription(), product.getPrice());
}
}
@@ -0,0 +1,15 @@
package com.baeldung.mvc_mvp.mvp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ProductView {
private static Logger log = LoggerFactory.getLogger(ProductView.class);
public void printProductDetails(String name, String description, Double price) {
log.info("Product details:");
log.info("product Name: " + name);
log.info("product Description: " + description);
log.info("product price: " + price);
}
}
@@ -0,0 +1,37 @@
package com.baeldung.repositoryvsdaopattern;
import java.util.Date;
public class Tweet {
private String email;
private String tweetText;
private Date dateCreated;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getTweetText() {
return tweetText;
}
public void setTweetText(String tweetText) {
this.tweetText = tweetText;
}
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
}
@@ -0,0 +1,9 @@
package com.baeldung.repositoryvsdaopattern;
import java.util.List;
public interface TweetDao {
List<Tweet> fetchTweets(String email);
}
@@ -0,0 +1,17 @@
package com.baeldung.repositoryvsdaopattern;
import java.util.ArrayList;
import java.util.List;
public class TweetDaoImpl implements TweetDao {
@Override
public List<Tweet> fetchTweets(String email) {
List<Tweet> tweets = new ArrayList<Tweet>();
//call Twitter API and prepare Tweet object
return tweets;
}
}
@@ -0,0 +1,51 @@
package com.baeldung.repositoryvsdaopattern;
public class User {
private Long id;
private String userName;
private String firstName;
private String lastName;
private String email;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
@@ -0,0 +1,13 @@
package com.baeldung.repositoryvsdaopattern;
public interface UserDao {
void create(User user);
User read(Long id);
void update(User user);
void delete(String userName);
}
@@ -0,0 +1,33 @@
package com.baeldung.repositoryvsdaopattern;
import javax.persistence.EntityManager;
public class UserDaoImpl implements UserDao {
private final EntityManager entityManager;
public UserDaoImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Override
public void create(User user) {
entityManager.persist(user);
}
@Override
public User read(Long id) {
return entityManager.find(User.class, id);
}
@Override
public void update(User user) {
}
@Override
public void delete(String userName) {
}
}
@@ -0,0 +1,21 @@
package com.baeldung.repositoryvsdaopattern;
import java.util.List;
public interface UserRepository {
User get(Long id);
void add(User user);
void update(User user);
void remove(User user);
User findByUserName(String userName);
User findByEmail(String email);
List<Tweet> fetchTweets(User user);
}
@@ -0,0 +1,51 @@
package com.baeldung.repositoryvsdaopattern;
import java.util.List;
public class UserRepositoryImpl implements UserRepository {
private UserDaoImpl userDaoImpl;
private TweetDaoImpl tweetDaoImpl;
@Override
public User get(Long id) {
UserSocialMedia user = (UserSocialMedia) userDaoImpl.read(id);
List<Tweet> tweets = tweetDaoImpl.fetchTweets(user.getEmail());
user.setTweets(tweets);
return user;
}
@Override
public void add(User user) {
userDaoImpl.create(user);
}
@Override
public void remove(User user) {
}
@Override
public void update(User user) {
}
@Override
public List<Tweet> fetchTweets(User user) {
return tweetDaoImpl.fetchTweets(user.getEmail());
}
@Override
public User findByUserName(String userName) {
return null;
}
@Override
public User findByEmail(String email) {
return null;
}
}
@@ -0,0 +1,17 @@
package com.baeldung.repositoryvsdaopattern;
import java.util.List;
public class UserSocialMedia extends User {
private List<Tweet> tweets;
public List<Tweet> getTweets() {
return tweets;
}
public void setTweets(List<Tweet> tweets) {
this.tweets = tweets;
}
}
@@ -0,0 +1,48 @@
package com.baeldung.seda.apachecamel;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.camel.Exchange;
import org.apache.camel.builder.ExpressionBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.processor.aggregate.AbstractListAggregationStrategy;
public class WordCountRoute extends RouteBuilder {
public static final String receiveTextUri = "seda:receiveText?concurrentConsumers=5";
public static final String splitWordsUri = "seda:splitWords?concurrentConsumers=5";
public static final String toLowerCaseUri = "seda:toLowerCase?concurrentConsumers=5";
public static final String countWordsUri = "seda:countWords?concurrentConsumers=5";
public static final String returnResponse = "mock:result";
@Override
public void configure() throws Exception {
from(receiveTextUri).to(splitWordsUri);
from(splitWordsUri).transform(ExpressionBuilder.bodyExpression(s -> s.toString()
.split(" ")))
.to(toLowerCaseUri);
from(toLowerCaseUri).split(body(), new StringListAggregationStrategy())
.transform(ExpressionBuilder.bodyExpression(body -> body.toString()
.toLowerCase()))
.end()
.to(countWordsUri);
from(countWordsUri).transform(ExpressionBuilder.bodyExpression(List.class, body -> body.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))))
.to(returnResponse);
}
}
class StringListAggregationStrategy extends AbstractListAggregationStrategy<String> {
@Override
public String getValue(Exchange exchange) {
return exchange.getIn()
.getBody(String.class);
}
}
@@ -0,0 +1,56 @@
package com.baeldung.seda.springintegration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.integration.dsl.MessageChannels;
import org.springframework.messaging.MessageChannel;
@Configuration
public class ChannelConfiguration {
private final TaskExecutor receiveTextChannelThreadPool;
private final TaskExecutor splitWordsChannelThreadPool;
private final TaskExecutor toLowerCaseChannelThreadPool;
private final TaskExecutor countWordsChannelThreadPool;
private final TaskExecutor returnResponseChannelThreadPool;
public ChannelConfiguration(TaskExecutor receiveTextChannelThreadPool, TaskExecutor splitWordsChannelThreadPool, TaskExecutor toLowerCaseChannelThreadPool, TaskExecutor countWordsChannelThreadPool, TaskExecutor returnResponseChannelThreadPool) {
this.receiveTextChannelThreadPool = receiveTextChannelThreadPool;
this.splitWordsChannelThreadPool = splitWordsChannelThreadPool;
this.toLowerCaseChannelThreadPool = toLowerCaseChannelThreadPool;
this.countWordsChannelThreadPool = countWordsChannelThreadPool;
this.returnResponseChannelThreadPool = returnResponseChannelThreadPool;
}
@Bean(name = "receiveTextChannel")
public MessageChannel getReceiveTextChannel() {
return MessageChannels.executor("receive-text", receiveTextChannelThreadPool)
.get();
}
@Bean(name = "splitWordsChannel")
public MessageChannel getSplitWordsChannel() {
return MessageChannels.executor("split-words", splitWordsChannelThreadPool)
.get();
}
@Bean(name = "toLowerCaseChannel")
public MessageChannel getToLowerCaseChannel() {
return MessageChannels.executor("to-lower-case", toLowerCaseChannelThreadPool)
.get();
}
@Bean(name = "countWordsChannel")
public MessageChannel getCountWordsChannel() {
return MessageChannels.executor("count-words", countWordsChannelThreadPool)
.get();
}
@Bean(name = "returnResponseChannel")
public MessageChannel getReturnResponseChannel() {
return MessageChannels.executor("return-response", returnResponseChannelThreadPool)
.get();
}
}
@@ -0,0 +1,81 @@
package com.baeldung.seda.springintegration;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.aggregator.MessageGroupProcessor;
import org.springframework.integration.aggregator.ReleaseStrategy;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
@Configuration
@EnableIntegration
public class IntegrationConfiguration {
private final MessageChannel receiveTextChannel;
private final MessageChannel splitWordsChannel;
private final MessageChannel toLowerCaseChannel;
private final MessageChannel countWordsChannel;
private final MessageChannel returnResponseChannel;
private final Function<String, String[]> splitWordsFunction = sentence -> sentence.split(" ");
private final Function<List<String>, Map<String, Long>> convertArrayListToCountMap = list -> list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
private final Function<String, String> toLowerCase = String::toLowerCase;
private final MessageGroupProcessor buildMessageWithListPayload = messageGroup -> MessageBuilder.withPayload(messageGroup.streamMessages()
.map(Message::getPayload)
.collect(Collectors.toList()))
.build();
private final ReleaseStrategy listSizeReached = r -> r.size() == r.getSequenceSize();
public IntegrationConfiguration(MessageChannel receiveTextChannel, MessageChannel splitWordsChannel, MessageChannel toLowerCaseChannel, MessageChannel countWordsChannel, MessageChannel returnResponseChannel) {
this.receiveTextChannel = receiveTextChannel;
this.splitWordsChannel = splitWordsChannel;
this.toLowerCaseChannel = toLowerCaseChannel;
this.countWordsChannel = countWordsChannel;
this.returnResponseChannel = returnResponseChannel;
}
@Bean
public IntegrationFlow receiveText() {
return IntegrationFlows.from(receiveTextChannel)
.channel(splitWordsChannel)
.get();
}
@Bean
public IntegrationFlow splitWords() {
return IntegrationFlows.from(splitWordsChannel)
.transform(splitWordsFunction)
.channel(toLowerCaseChannel)
.get();
}
@Bean
public IntegrationFlow toLowerCase() {
return IntegrationFlows.from(toLowerCaseChannel)
.split()
.transform(toLowerCase)
.aggregate(aggregatorSpec -> aggregatorSpec.releaseStrategy(listSizeReached)
.outputProcessor(buildMessageWithListPayload))
.channel(countWordsChannel)
.get();
}
@Bean
public IntegrationFlow countWords() {
return IntegrationFlows.from(countWordsChannel)
.transform(convertArrayListToCountMap)
.channel(returnResponseChannel)
.get();
}
}
@@ -0,0 +1,61 @@
package com.baeldung.seda.springintegration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
public class TaskExecutorConfiguration {
@Bean("receiveTextChannelThreadPool")
public TaskExecutor receiveTextChannelThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(1);
executor.setMaxPoolSize(5);
executor.setThreadNamePrefix("receive-text-channel-thread-pool");
executor.initialize();
return executor;
}
@Bean("splitWordsChannelThreadPool")
public TaskExecutor splitWordsChannelThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(1);
executor.setMaxPoolSize(5);
executor.setThreadNamePrefix("split-words-channel-thread-pool");
executor.initialize();
return executor;
}
@Bean("toLowerCaseChannelThreadPool")
public TaskExecutor toLowerCaseChannelThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(1);
executor.setMaxPoolSize(5);
executor.setThreadNamePrefix("tto-lower-case-channel-thread-pool");
executor.initialize();
return executor;
}
@Bean("countWordsChannelThreadPool")
public TaskExecutor countWordsChannelThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(1);
executor.setMaxPoolSize(5);
executor.setThreadNamePrefix("count-words-channel-thread-pool");
executor.initialize();
return executor;
}
@Bean("returnResponseChannelThreadPool")
public TaskExecutor returnResponseChannelThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(1);
executor.setMaxPoolSize(5);
executor.setThreadNamePrefix("return-response-channel-thread-pool");
executor.initialize();
return executor;
}
}
@@ -0,0 +1,12 @@
package com.baeldung.seda.springintegration;
import java.util.Map;
import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.MessagingGateway;
@MessagingGateway
public interface TestGateway {
@Gateway(requestChannel = "receiveTextChannel", replyChannel = "returnResponseChannel")
public Map<String, Long> countWords(String test);
}
@@ -0,0 +1,56 @@
package com.baeldung.dtopattern.api;
import com.baeldung.dtopattern.domain.Role;
import com.baeldung.dtopattern.domain.User;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class MapperUnitTest {
@Test
void toDto_shouldMapFromDomainToDTO() {
String name = "Test";
String password = "test";
Role admin = new Role("admin");
List<String> expectedRoles = Collections.singletonList("admin");
List<Role> roles = new ArrayList<>();
roles.add(admin);
User user = new User(name, password, roles);
Mapper mapper = new Mapper();
UserDTO dto = mapper.toDto(user);
assertEquals(name, dto.getName());
assertEquals(expectedRoles, dto.getRoles());
}
@Test
void toUser_shouldMapFromDTOToDomain() {
String name = "Test";
String password = "test";
String role = "admin";
UserCreationDTO dto = new UserCreationDTO();
dto.setName(name);
dto.setPassword(password);
dto.setRoles(Collections.singletonList("admin"));
User expectedUser = new User(name, password, new ArrayList<>());
Mapper mapper = new Mapper();
User user = mapper.toUser(dto);
assertEquals(name, user.getName());
assertEquals(expectedUser.getPassword(), user.getPassword());
assertEquals(Collections.emptyList(), user.getRoles());
}
}
@@ -0,0 +1,80 @@
package com.baeldung.dtopattern.api;
import com.baeldung.dtopattern.domain.Role;
import com.baeldung.dtopattern.domain.RoleRepository;
import com.baeldung.dtopattern.domain.User;
import com.baeldung.dtopattern.domain.UserRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import java.util.Collections;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.*;
import static org.springframework.http.HttpStatus.OK;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserControllerIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@LocalServerPort
int port;
@Autowired
private ObjectMapper objectMapper;
@Test
void create_shouldReturnUseId() throws Exception {
UserCreationDTO request = new UserCreationDTO();
request.setName("User 1");
request.setPassword("Test@123456");
request.setRoles(Collections.singletonList("admin"));
given()
.contentType(ContentType.JSON)
.body(objectMapper.writeValueAsString(request))
.when()
.port(port)
.post("/users")
.then()
.statusCode(OK.value())
.body("id", notNullValue());
}
@Test
void getAll_shouldReturnUseDTO() {
userRepository.deleteAll();
String roleName = "admin";
Role admin = new Role(roleName);
roleRepository.save(admin);
String name = "User 1";
User user = new User(name, "Test@123456", Collections.singletonList(admin));
userRepository.save(user);
given()
.port(port)
.when()
.get("/users")
.then()
.statusCode(OK.value())
.body("size()", is(1))
.body("[0].name", equalTo(name))
.body("[0].roles", hasItem(roleName));
}
}
@@ -0,0 +1,83 @@
package com.baeldung.dtopattern.domain;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class InMemoryRepositoryUnitTest {
@Test
void getAll_shouldReturnAllUsers() {
String name = "Test";
String password = "test123";
List<Role> roles = new ArrayList<>();
User user = new User(name, password, roles);
List<User> expectedUsers = Collections.singletonList(user);
InMemoryRepository repository = new InMemoryRepository();
repository.save(user);
List<User> users = repository.getAll();
assertEquals(expectedUsers, users);
}
@Test
void save_whenSavingUser_shouldSetId() {
String name = "Test";
String password = "test123";
List<Role> roles = new ArrayList<>();
User user = new User(name, password, roles);
InMemoryRepository repository = new InMemoryRepository();
repository.save(user);
assertNotNull(user.getId());
}
@Test
void save_whenSavingRole_shouldSetId() {
String name = "Test";
Role role = new Role(name);
InMemoryRepository repository = new InMemoryRepository();
repository.save(role);
assertNotNull(role.getId());
}
@Test
void getRoleById_shouldReturnRoleById() {
String name = "Test";
Role expectedRole = new Role(name);
InMemoryRepository repository = new InMemoryRepository();
repository.save(expectedRole);
Role role = repository.getRoleById(expectedRole.getId());
assertEquals(expectedRole, role);
}
@Test
void getRoleByName_shouldReturnRoleByName() {
String name = "Test";
Role expectedRole = new Role(name);
InMemoryRepository repository = new InMemoryRepository();
repository.save(expectedRole);
Role role = repository.getRoleByName(name);
assertEquals(expectedRole, role);
}
}
@@ -0,0 +1,38 @@
package com.baeldung.dtopattern.domain;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import static org.junit.jupiter.api.Assertions.*;
class UserUnitTest {
@Test
void whenUserIsCreated_shouldEncryptPassword() {
User user = new User("Test", "test", new ArrayList<>());
assertEquals(user.encrypt("test"), user.getPassword());
assertNotEquals(user.encrypt("Test"), user.getPassword());
}
@Test
void whenUserIsCreated_shouldFailIfNameIsNull() {
assertThrows(NullPointerException.class, () ->
new User(null, "test", new ArrayList<>()));
}
@Test
void whenUserIsCreated_shouldFailIfPasswordIsNull() {
assertThrows(NullPointerException.class, () ->
new User("Test", null, new ArrayList<>()));
}
@Test
void whenUserIsCreated_shouldFailIfRolesIsNull() {
assertThrows(NullPointerException.class, () ->
new User("Test", "Test", null));
}
}
@@ -0,0 +1,48 @@
package com.baeldung.seda.apachecamel;
import java.util.HashMap;
import java.util.Map;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.test.junit5.CamelTestSupport;
import org.junit.jupiter.api.Test;
import com.baeldung.seda.apachecamel.WordCountRoute;
public class ApacheCamelSedaIntegrationTest extends CamelTestSupport {
@Test
public void givenTextWithCapitalAndSmallCaseAndWithoutDuplicateWords_whenSendingTextToInputUri_thenWordCountReturnedAsMap() throws InterruptedException {
Map<String, Long> expected = new HashMap<>();
expected.put("my", 1L);
expected.put("name", 1L);
expected.put("is", 1L);
expected.put("hesam", 1L);
getMockEndpoint(WordCountRoute.returnResponse).expectedBodiesReceived(expected);
template.sendBody(WordCountRoute.receiveTextUri, "My name is Hesam");
assertMockEndpointsSatisfied();
}
@Test
public void givenTextWithDuplicateWords_whenSendingTextToInputUri_thenWordCountReturnedAsMap() throws InterruptedException {
Map<String, Long> expected = new HashMap<>();
expected.put("the", 3L);
expected.put("dog", 1L);
expected.put("chased", 1L);
expected.put("rabbit", 1L);
expected.put("into", 1L);
expected.put("jungle", 1L);
getMockEndpoint(WordCountRoute.returnResponse).expectedBodiesReceived(expected);
template.sendBody(WordCountRoute.receiveTextUri, "the dog chased the rabbit into the jungle");
assertMockEndpointsSatisfied();
}
@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
RoutesBuilder wordCountRoute = new WordCountRoute();
return wordCountRoute;
}
}
@@ -0,0 +1,50 @@
package com.baeldung.seda.springintegration;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = { TaskExecutorConfiguration.class, ChannelConfiguration.class, IntegrationConfiguration.class })
@EnableIntegration
@IntegrationComponentScan(basePackages = { "com.baeldung.seda.springintegration" })
public class SpringIntegrationSedaIntegrationTest {
@Autowired
TestGateway testGateway;
@Test
void givenTextWithCapitalAndSmallCaseAndWithoutDuplicateWords_whenCallingCountWordOnGateway_thenWordCountReturnedAsMap() {
Map<String, Long> actual = testGateway.countWords("My name is Hesam");
Map<String, Long> expected = new HashMap<>();
expected.put("my", 1L);
expected.put("name", 1L);
expected.put("is", 1L);
expected.put("hesam", 1L);
org.junit.Assert.assertEquals(expected, actual);
}
@Test
void givenTextWithDuplicateWords_whenCallingCountWordOnGateway_thenWordCountReturnedAsMap() {
Map<String, Long> actual = testGateway.countWords("the dog chased the rabbit into the jungle");
Map<String, Long> expected = new HashMap<>();
expected.put("the", 3L);
expected.put("dog", 1L);
expected.put("chased", 1L);
expected.put("rabbit", 1L);
expected.put("into", 1L);
expected.put("jungle", 1L);
org.junit.Assert.assertEquals(expected, actual);
}
}