From c462b79e9853fdb5ea91a28be8126d2394d7b1c8 Mon Sep 17 00:00:00 2001 From: esmailian Date: Mon, 28 Apr 2025 15:54:16 +0330 Subject: [PATCH] add order command query for test in project and add consumer kfka for test event driven read model design pattern dont forget change implementation of kafka consumer to list of values --- .../testapp/Listner/UserEventListener.java | 7 ++-- .../testapp/command/CreateOrderCommand.java | 13 ++++++++ .../testapp/command/CreateUserCommand.java | 13 -------- .../testapp/command/OrderCommandHandler.java | 33 +++++++++++++++++++ .../testapp/command/UserCommandHandler.java | 33 ------------------- .../testapp/controller/UserController.java | 10 +++--- .../mmad/testapp/entity/OrderEntity.java | 25 ++++++++++++++ .../mmad/testapp/event/OrderCreatedEvent.java | 25 ++++++++++++++ .../mmad/testapp/event/UserCreatedEvent.java | 29 +++++----------- .../KafkaConsumerConfig.java | 21 +++++------- .../mmad/testapp/query/UserQueryHandler.java | 6 ++-- .../testapp/repository/UserRepository.java | 4 +-- src/main/resources/application.properties | 2 +- 13 files changed, 129 insertions(+), 92 deletions(-) create mode 100644 src/main/java/com/example/mmad/testapp/command/CreateOrderCommand.java delete mode 100644 src/main/java/com/example/mmad/testapp/command/CreateUserCommand.java create mode 100644 src/main/java/com/example/mmad/testapp/command/OrderCommandHandler.java delete mode 100644 src/main/java/com/example/mmad/testapp/command/UserCommandHandler.java create mode 100755 src/main/java/com/example/mmad/testapp/entity/OrderEntity.java create mode 100644 src/main/java/com/example/mmad/testapp/event/OrderCreatedEvent.java diff --git a/src/main/java/com/example/mmad/testapp/Listner/UserEventListener.java b/src/main/java/com/example/mmad/testapp/Listner/UserEventListener.java index e35a873..edf6136 100644 --- a/src/main/java/com/example/mmad/testapp/Listner/UserEventListener.java +++ b/src/main/java/com/example/mmad/testapp/Listner/UserEventListener.java @@ -14,14 +14,15 @@ public class UserEventListener { this.userSnapshotRepository = userSnapshotRepository; } - @KafkaListener(topics = "user-commanded", groupId = "") + @KafkaListener(topics = "user-created", containerFactory = "kafkaListenerContainerFactory", groupId = "test") public void updatedUserSnapshot(UserCreatedEvent user) { UserEntity userSnapshot = new UserEntity(); //Todo write an mapper - userSnapshot.setId(userSnapshot.getId()); + userSnapshot.setId(user.getUserId()); userSnapshot.setUserName(user.getUsername()); userSnapshot.setEmail(user.getEmail()); - userSnapshotRepository.save(userSnapshot); + System.out.println("snapshot is updated" + user.getUserId()); +// userSnapshotRepository.save(userSnapshot); } } diff --git a/src/main/java/com/example/mmad/testapp/command/CreateOrderCommand.java b/src/main/java/com/example/mmad/testapp/command/CreateOrderCommand.java new file mode 100644 index 0000000..0ebacf5 --- /dev/null +++ b/src/main/java/com/example/mmad/testapp/command/CreateOrderCommand.java @@ -0,0 +1,13 @@ +package com.example.mmad.testapp.command; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CreateOrderCommand { + + private Long orderId; + private String orderName; + private String description; +} diff --git a/src/main/java/com/example/mmad/testapp/command/CreateUserCommand.java b/src/main/java/com/example/mmad/testapp/command/CreateUserCommand.java deleted file mode 100644 index bbb69b8..0000000 --- a/src/main/java/com/example/mmad/testapp/command/CreateUserCommand.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.mmad.testapp.command; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class CreateUserCommand { - - private Long userId; - private String userName; - private String email; -} diff --git a/src/main/java/com/example/mmad/testapp/command/OrderCommandHandler.java b/src/main/java/com/example/mmad/testapp/command/OrderCommandHandler.java new file mode 100644 index 0000000..cefa400 --- /dev/null +++ b/src/main/java/com/example/mmad/testapp/command/OrderCommandHandler.java @@ -0,0 +1,33 @@ +package com.example.mmad.testapp.command; + +import com.example.mmad.testapp.entity.OrderEntity; +import com.example.mmad.testapp.event.OrderCreatedEvent; +import com.example.mmad.testapp.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +@Service +public class OrderCommandHandler { + @Autowired + private ApplicationEventPublisher applicationEventPublisher; + private final UserRepository userRepository; + + public OrderCommandHandler(UserRepository userRepository) { + this.userRepository = userRepository; + } + + public void createUser(CreateOrderCommand createUserCommand) { + OrderEntity orderEntity = new OrderEntity(); + orderEntity.setId(createUserCommand.getOrderId()); + orderEntity.setOrderName(createUserCommand.getOrderName()); + orderEntity.setDescription(createUserCommand.getDescription()); +// userRepository.save(orderEntity); + OrderCreatedEvent event = new OrderCreatedEvent( + orderEntity.getId(), + orderEntity.getOrderName(), + orderEntity.getDescription() + ); + applicationEventPublisher.publishEvent(event); + } +} diff --git a/src/main/java/com/example/mmad/testapp/command/UserCommandHandler.java b/src/main/java/com/example/mmad/testapp/command/UserCommandHandler.java deleted file mode 100644 index a882cbd..0000000 --- a/src/main/java/com/example/mmad/testapp/command/UserCommandHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.example.mmad.testapp.command; - -import com.example.mmad.testapp.entity.UserEntity; -import com.example.mmad.testapp.event.UserCreatedEvent; -import com.example.mmad.testapp.repository.UserRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.stereotype.Service; - -@Service -public class UserCommandHandler { - @Autowired - private ApplicationEventPublisher applicationEventPublisher; - private final UserRepository userRepository; - - public UserCommandHandler(UserRepository userRepository) { - this.userRepository = userRepository; - } - - public void createUser(CreateUserCommand createUserCommand) { - UserEntity userEntity = new UserEntity(); - userEntity.setId(createUserCommand.getUserId()); - userEntity.setUserName(createUserCommand.getUserName()); - userEntity.setEmail(createUserCommand.getEmail()); -// userRepository.save(userEntity); - UserCreatedEvent event = new UserCreatedEvent( - userEntity.getId(), - userEntity.getUserName(), - userEntity.getEmail() - ); - applicationEventPublisher.publishEvent(event); - } -} diff --git a/src/main/java/com/example/mmad/testapp/controller/UserController.java b/src/main/java/com/example/mmad/testapp/controller/UserController.java index fe56821..dfb8346 100755 --- a/src/main/java/com/example/mmad/testapp/controller/UserController.java +++ b/src/main/java/com/example/mmad/testapp/controller/UserController.java @@ -1,7 +1,7 @@ package com.example.mmad.testapp.controller; -import com.example.mmad.testapp.command.CreateUserCommand; -import com.example.mmad.testapp.command.UserCommandHandler; +import com.example.mmad.testapp.command.CreateOrderCommand; +import com.example.mmad.testapp.command.OrderCommandHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -13,10 +13,10 @@ import javax.validation.Valid; @RequestMapping("/user") public class UserController { - private UserCommandHandler userCommandHandler; + private OrderCommandHandler userCommandHandler; @Autowired - public void setPersonService(UserCommandHandler userCommandHandler) { + public void setPersonService(OrderCommandHandler userCommandHandler) { this.userCommandHandler = userCommandHandler; } @@ -28,7 +28,7 @@ public class UserController { @CrossOrigin(origins = "http://localhost:3001") @PostMapping("/create") - public ResponseEntity create(@Valid @RequestBody CreateUserCommand userCommand) { + public ResponseEntity create(@Valid @RequestBody CreateOrderCommand userCommand) { userCommandHandler.createUser(userCommand); return ResponseEntity.ok(200); } diff --git a/src/main/java/com/example/mmad/testapp/entity/OrderEntity.java b/src/main/java/com/example/mmad/testapp/entity/OrderEntity.java new file mode 100755 index 0000000..c6aefc4 --- /dev/null +++ b/src/main/java/com/example/mmad/testapp/entity/OrderEntity.java @@ -0,0 +1,25 @@ +package com.example.mmad.testapp.entity; + +import jakarta.persistence.*; +import lombok.*; + +import static jakarta.persistence.GenerationType.SEQUENCE; + +@Entity +@Getter +@Setter +@Table(schema = "testapp", name = "order") +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class OrderEntity { + + @Id + @SequenceGenerator(name = "seqTest", sequenceName = "testapp.order_seq", allocationSize = 1) + @GeneratedValue(strategy = SEQUENCE, generator = "seqTest") + private Long id; + @Column(name = "order_name") + private String orderName; + @Column(name = "description") + private String description; +} diff --git a/src/main/java/com/example/mmad/testapp/event/OrderCreatedEvent.java b/src/main/java/com/example/mmad/testapp/event/OrderCreatedEvent.java new file mode 100644 index 0000000..f768cef --- /dev/null +++ b/src/main/java/com/example/mmad/testapp/event/OrderCreatedEvent.java @@ -0,0 +1,25 @@ +package com.example.mmad.testapp.event; + +public class OrderCreatedEvent { + private final Long orderId; + private final String orderName; + private final String description; + + public OrderCreatedEvent(Long orderId, String orderName, String description) { + this.orderId = orderId; + this.orderName = orderName; + this.description = description; + } + + public Long getOrderId() { + return orderId; + } + + public String getOrderName() { + return orderName; + } + + public String getDescription() { + return description; + } +} diff --git a/src/main/java/com/example/mmad/testapp/event/UserCreatedEvent.java b/src/main/java/com/example/mmad/testapp/event/UserCreatedEvent.java index 3202eaf..27542b2 100644 --- a/src/main/java/com/example/mmad/testapp/event/UserCreatedEvent.java +++ b/src/main/java/com/example/mmad/testapp/event/UserCreatedEvent.java @@ -1,25 +1,14 @@ package com.example.mmad.testapp.event; -public class UserCreatedEvent { - private final Long userId; - private final String username; - private final String email; +import lombok.Getter; +import lombok.Setter; - public UserCreatedEvent(Long userId, String username, String email) { - this.userId = userId; - this.username = username; - this.email = email; - } +import java.io.Serializable; - public Long getUserId() { - return userId; - } - - public String getUsername() { - return username; - } - - public String getEmail() { - return email; - } +@Getter +@Setter +public class UserCreatedEvent implements Serializable { + private Long userId; + private String username; + private String email; } diff --git a/src/main/java/com/example/mmad/testapp/kafkaConsumerConfig/KafkaConsumerConfig.java b/src/main/java/com/example/mmad/testapp/kafkaConsumerConfig/KafkaConsumerConfig.java index a774f7c..82ec579 100755 --- a/src/main/java/com/example/mmad/testapp/kafkaConsumerConfig/KafkaConsumerConfig.java +++ b/src/main/java/com/example/mmad/testapp/kafkaConsumerConfig/KafkaConsumerConfig.java @@ -1,8 +1,9 @@ package com.example.mmad.testapp.kafkaConsumerConfig; -import com.fasterxml.jackson.core.type.TypeReference; +import com.example.mmad.testapp.event.UserCreatedEvent; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.common.serialization.StringDeserializer; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -12,7 +13,6 @@ import org.springframework.kafka.core.DefaultKafkaConsumerFactory; import org.springframework.kafka.support.serializer.JsonDeserializer; import java.util.HashMap; -import java.util.List; import java.util.Map; @EnableKafka @@ -20,32 +20,29 @@ import java.util.Map; @ConfigurationProperties(prefix = "spring.kafka.consumer") public class KafkaConsumerConfig { + @Value("${spring.kafka.consumer.bootstrap-servers}") private String bootstrapServers; + @Value("${spring.kafka.consumer.group-id}") private String groupId; - @Bean - public DefaultKafkaConsumerFactory> consumerFactory() { - JsonDeserializer> deserializer = - new JsonDeserializer<>(new TypeReference>() { - }); - deserializer.setRemoveTypeHeaders(false); + public DefaultKafkaConsumerFactory consumerFactory() { + JsonDeserializer deserializer = new JsonDeserializer<>(UserCreatedEvent.class); deserializer.addTrustedPackages("*"); - deserializer.setUseTypeMapperForKey(true); Map config = new HashMap<>(); config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers); config.put(ConsumerConfig.GROUP_ID_CONFIG, groupId); config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); - config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, deserializer); + config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class); return new DefaultKafkaConsumerFactory<>(config, new StringDeserializer(), deserializer); } @Bean - public ConcurrentKafkaListenerContainerFactory> kafkaListenerContainerFactory() { - ConcurrentKafkaListenerContainerFactory> factory = new ConcurrentKafkaListenerContainerFactory<>(); + public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory() { + ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); factory.setConsumerFactory(consumerFactory()); return factory; } diff --git a/src/main/java/com/example/mmad/testapp/query/UserQueryHandler.java b/src/main/java/com/example/mmad/testapp/query/UserQueryHandler.java index a01f7bb..6127533 100644 --- a/src/main/java/com/example/mmad/testapp/query/UserQueryHandler.java +++ b/src/main/java/com/example/mmad/testapp/query/UserQueryHandler.java @@ -1,6 +1,6 @@ package com.example.mmad.testapp.query; -import com.example.mmad.testapp.event.UserCreatedEvent; +import com.example.mmad.testapp.event.OrderCreatedEvent; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; @@ -9,7 +9,7 @@ import org.springframework.stereotype.Component; public class UserQueryHandler { @Async("taskExecutor") @EventListener - public void handelUserCreated(UserCreatedEvent event) { - System.out.println("Received user created event" + event.getUserId()); + public void handelUserCreated(OrderCreatedEvent event) { + System.out.println("Received user created event" + event.getOrderId()); } } diff --git a/src/main/java/com/example/mmad/testapp/repository/UserRepository.java b/src/main/java/com/example/mmad/testapp/repository/UserRepository.java index 9c6b0f5..e0a23ae 100755 --- a/src/main/java/com/example/mmad/testapp/repository/UserRepository.java +++ b/src/main/java/com/example/mmad/testapp/repository/UserRepository.java @@ -1,10 +1,10 @@ package com.example.mmad.testapp.repository; -import com.example.mmad.testapp.entity.UserEntity; +import com.example.mmad.testapp.entity.OrderEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository -public interface UserRepository extends JpaRepository { +public interface UserRepository extends JpaRepository { } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e33f2d0..6bda357 100755 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,4 +1,4 @@ -spring.application.name=service-a +spring.application.name=service-b eureka.client.service-url.defaultZone=http://localhost:8761/eureka spring.config.import=configserver:http://localhost:8888/ eureka.client.register-with-eureka=true