Skip to content

Commit

Permalink
Merge pull request #32 from seyedali-dev/feature/event-project-kafka
Browse files Browse the repository at this point in the history
Feature/event project kafka done! (Close #14)
  • Loading branch information
seyedali-dev authored Jun 4, 2024
2 parents 611490a + befc24a commit 448f92c
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 3 deletions.
11 changes: 11 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

<!-- Message Broker -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>

<!-- Caching -->
<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down Expand Up @@ -106,6 +112,11 @@
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<dependencyManagement>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.seyed.ali.timeentryservice.event;

import com.seyed.ali.timeentryservice.model.enums.OperationType;
import com.seyed.ali.timeentryservice.model.payload.ProjectDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class ProjectEventListener {

private final ProjectEventService projectEventService;

@KafkaListener(
topics = "${spring.kafka.topic.name}",
groupId = "${spring.kafka.consumer.group-id}" // if we change the group-id name, the events from the previous data will also be logged, otherwise, only the new events will be logged!
)
public void handleProjectEvent(@Payload ConsumerRecord<String, ProjectDTO> record, @Header("OperationType") String operationType) {
ProjectDTO projectDTO = record.value();
switch (OperationType.valueOf(operationType)) {
case DELETE -> this.projectEventService.handleDeleteOperation(projectDTO);
case DETACH -> this.projectEventService.handleDetachOperation(projectDTO);
default -> log.warn("\"{}\" operation type not supported.", operationType);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.seyed.ali.timeentryservice.event;

import com.seyed.ali.timeentryservice.model.payload.ProjectDTO;
import com.seyed.ali.timeentryservice.repository.TimeEntryRepository;
import com.seyed.ali.timeentryservice.service.interfaces.TimeEntryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Slf4j
@Service
@RequiredArgsConstructor
public class ProjectEventService {

private final TimeEntryService timeEntryService;
private final TimeEntryRepository timeEntryRepository;

public void handleDeleteOperation(ProjectDTO projectDTO) {
log.info("\"Delete\" project, associated tasks & time entries: {}", projectDTO);
this.timeEntryRepository.findByProjectId(projectDTO.getProjectId())
.forEach(this.timeEntryService::deleteTimeEntry);
}

public void handleDetachOperation(ProjectDTO projectDTO) {
log.info("\"Detach\" project, associated tasks & time entries: {}", projectDTO);
this.timeEntryRepository.findByProjectId(projectDTO.getProjectId())
.forEach(timeEntry -> {
timeEntry.setProjectId(null);
timeEntry.setTaskId(null);
this.timeEntryRepository.save(timeEntry);
});
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.seyed.ali.timeentryservice.model.enums;

public enum OperationType {

DELETE, DETACH

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.seyed.ali.timeentryservice.model.payload;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
* DTO for {@link com.seyed.ali.projectservice.model.domain.Project}
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProjectDTO implements Serializable {

@Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED, description = "Unique identifier for the project", example = "12345")
private String projectId;

@Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED, description = "The project name", example = "Microservices-Springboot")
private String projectName;

@Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED, description = "The project name", example = "Learning microservices is really exciting and HARD ;)")
private String projectDescription;

@Schema(requiredMode = Schema.RequiredMode.NOT_REQUIRED, description = "The task associated with the project", implementation = TaskDTO.class)
private List<TaskDTO> taskDTO = new ArrayList<>();

public ProjectDTO(String projectId, String projectName, String projectDescription) {
this.projectId = projectId;
this.projectName = projectName;
this.projectDescription = projectDescription;
this.taskDTO = new ArrayList<>();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.seyed.ali.timeentryservice.model.domain.TimeEntry;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;

public interface TimeEntryRepository extends JpaRepository<TimeEntry, String> {
Expand All @@ -11,4 +12,8 @@ public interface TimeEntryRepository extends JpaRepository<TimeEntry, String> {

TimeEntry findByUserIdAndTimeEntryId(String userId, String timeEntryId);

List<TimeEntry> findByProjectId(String projectId);

List<TimeEntry> findByTaskId(String taskId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,19 @@ public void deleteTimeEntry(String timeEntryId) {
this.timeEntryRepository.deleteById(timeEntryId);
}

/**
* {@inheritDoc}
*/
@Override
@Transactional
@CacheEvict(
cacheNames = TimeEntryCacheManager.TIME_ENTRY_CACHE,
key = "#timeEntry.timeEntryId"
)
public void deleteTimeEntry(TimeEntry timeEntry) {
TimeEntry foundTimeEntry = this.timeEntryRepository.findById(timeEntry.getTimeEntryId())
.orElseThrow(() -> new ResourceNotFoundException("The provided timeEntryId does not exist"));
this.timeEntryRepository.delete(foundTimeEntry);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,17 @@ public interface TimeEntryService {
TimeEntry updateTimeEntryManually(String id, TimeEntryDTO timeEntryDTO);

/**
* Deletes a time entry.
* Deletes a time entry by ID.
*
* @param timeEntryId The ID of the time entry to be deleted.
*/
void deleteTimeEntry(String timeEntryId);

/**
* Deletes a time entry.
*
* @param timeEntry The time entry to be deleted.
*/
void deleteTimeEntry(TimeEntry timeEntry);

}
21 changes: 20 additions & 1 deletion src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,23 @@ authentication:
service:
user-persistence-controller:
base-url: http://${AUTHENTICATION_SERVICE_HANDLE_USER_BASE_URL:localhost:8081}/keycloak-user
handle-user-url: /handle-user
handle-user-url: /handle-user

--- # Kafka
spring:
kafka:
consumer:
bootstrap-servers: localhost:9092
group-id: project_group_timeentry
auto-offset-reset: earliest

#configure deserialize classes for key & value pair
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
properties:
spring.json.trusted.packages: "*"
spring.json.type.mapping: ProjectEvent:com.seyed.ali.timeentryservice.model.payload.ProjectDTO

#custom
topic:
name: project_name
21 changes: 20 additions & 1 deletion src/test/resources/application-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,23 @@ authentication:
service:
user-persistence-controller:
base-url: http://${AUTHENTICATION_SERVICE_HANDLE_USER_BASE_URL:localhost:8081}/keycloak-user
handle-user-url: /handle-user
handle-user-url: /handle-user

--- # Kafka
spring:
kafka:
consumer:
bootstrap-servers: localhost:9092
group-id: project_group_timeentry
auto-offset-reset: earliest

#configure deserialize classes for key & value pair
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
properties:
spring.json.trusted.packages: "*"
spring.json.type.mapping: ProjectEvent:com.seyed.ali.timeentryservice.model.payload.ProjectDTO

#custom
topic:
name: project_name

0 comments on commit 448f92c

Please sign in to comment.