commit
1b409a3a6e
|
@ -3,16 +3,21 @@
|
|||
This application exists as an example for the Lightrun series of articles.
|
||||
|
||||
## Building
|
||||
|
||||
This application requires [Apache Maven](https://maven.apache.org/) and [Java 17+](https://www.oracle.com/java/technologies/downloads/).
|
||||
|
||||
Building the code is done by executing:
|
||||
|
||||
```
|
||||
$ mvn install
|
||||
```
|
||||
|
||||
from the top level.
|
||||
|
||||
## Running
|
||||
|
||||
The application consists of three services:
|
||||
|
||||
* Tasks
|
||||
* Users
|
||||
* API
|
||||
|
@ -23,7 +28,9 @@ The Tasks and Users services exist as microservices for managing one facet of da
|
|||
|
||||
This does mean that the startup order is important. The JMS queue exists within the Tasks service and is connected to from the Users service. As such, the Tasks service must be started before the others.
|
||||
|
||||
Each service can be started either by executing `mvn spring-boot:run` from within the appropriate directory. Alternatively, as Spring Boot applications, the build will produce an executable JAR file within the `target` directory that can be executed as, for example:
|
||||
Each service can be started either by executing `mvn spring-boot:run` from within the appropriate directory. Alternatively, as Spring Boot applications, the build will produce an executable JAR file within the `target` directory that can be executed as, for
|
||||
example:
|
||||
|
||||
```
|
||||
$ java -jar ./target/tasks-service-0.0.1-SNAPSHOT.jar
|
||||
```
|
||||
|
|
|
@ -1,45 +1,45 @@
|
|||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.6.7</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>api-service</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>api-service</name>
|
||||
<description>Aggregator Service for LightRun Article</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.6.7</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>api-service</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>api-service</name>
|
||||
<description>Aggregator Service for LightRun Article</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -6,8 +6,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||
@SpringBootApplication
|
||||
public class ApiServiceApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ApiServiceApplication.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ApiServiceApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
package com.baeldung.apiservice;
|
||||
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
@Component
|
||||
public class RequestIdGenerator implements HandlerInterceptor {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
String requestId = UUID.randomUUID().toString();
|
||||
String requestId = UUID.randomUUID()
|
||||
.toString();
|
||||
|
||||
MDC.put(RequestIdGenerator.class.getCanonicalName(), requestId);
|
||||
response.addHeader("X-Request-Id", requestId);
|
||||
|
|
|
@ -9,12 +9,12 @@ import org.springframework.web.client.RestTemplate;
|
|||
public class RestTemplateConfig {
|
||||
@Bean
|
||||
public RestTemplate restTemplate(RestTemplateBuilder builder) {
|
||||
return builder
|
||||
.additionalInterceptors((request, body, execution) -> {
|
||||
request.getHeaders().add("X-Request-Id", RequestIdGenerator.getRequestId());
|
||||
return builder.additionalInterceptors((request, body, execution) -> {
|
||||
request.getHeaders()
|
||||
.add("X-Request-Id", RequestIdGenerator.getRequestId());
|
||||
|
||||
return execution.execute(request, body);
|
||||
})
|
||||
.build();
|
||||
return execution.execute(request, body);
|
||||
})
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,5 @@ package com.baeldung.apiservice.adapters.http;
|
|||
|
||||
import java.time.Instant;
|
||||
|
||||
public record TaskResponse(String id,
|
||||
String title,
|
||||
Instant created,
|
||||
UserResponse createdBy,
|
||||
UserResponse assignedTo,
|
||||
String status) {
|
||||
public record TaskResponse(String id, String title, Instant created, UserResponse createdBy, UserResponse assignedTo, String status) {
|
||||
}
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
package com.baeldung.apiservice.adapters.http;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.apiservice.adapters.tasks.Task;
|
||||
import com.baeldung.apiservice.adapters.tasks.TaskRepository;
|
||||
import com.baeldung.apiservice.adapters.users.UserRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RequestMapping("/")
|
||||
@RestController
|
||||
|
@ -27,15 +33,10 @@ public class TasksController {
|
|||
}
|
||||
|
||||
private TaskResponse buildResponse(Task task) {
|
||||
return new TaskResponse(task.id(),
|
||||
task.title(),
|
||||
task.created(),
|
||||
getUser(task.createdBy()),
|
||||
getUser(task.assignedTo()),
|
||||
task.status());
|
||||
return new TaskResponse(task.id(), task.title(), task.created(), getUser(task.createdBy()), getUser(task.assignedTo()), task.status());
|
||||
}
|
||||
|
||||
private UserResponse getUser(String userId) {
|
||||
private UserResponse getUser(String userId) {
|
||||
if (userId == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -47,6 +48,7 @@ public class TasksController {
|
|||
|
||||
return new UserResponse(user.id(), user.name());
|
||||
}
|
||||
|
||||
@ExceptionHandler(UnknownTaskException.class)
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
public void handleUnknownTask() {
|
||||
|
|
|
@ -2,10 +2,5 @@ package com.baeldung.apiservice.adapters.tasks;
|
|||
|
||||
import java.time.Instant;
|
||||
|
||||
public record Task(String id,
|
||||
String title,
|
||||
Instant created,
|
||||
String createdBy,
|
||||
String assignedTo,
|
||||
String status) {
|
||||
public record Task(String id, String title, Instant created, String createdBy, String assignedTo, String status) {
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@ public class TaskRepository {
|
|||
|
||||
public Task getTaskById(String id) {
|
||||
var uri = UriComponentsBuilder.fromUriString(tasksService)
|
||||
.path(id)
|
||||
.build()
|
||||
.toUri();
|
||||
.path(id)
|
||||
.build()
|
||||
.toUri();
|
||||
|
||||
try {
|
||||
return restTemplate.getForObject(uri, Task.class);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.baeldung.apiservice.adapters.users;
|
||||
|
||||
import com.baeldung.apiservice.adapters.users.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
@ -18,9 +17,9 @@ public class UserRepository {
|
|||
|
||||
public User getUserById(String id) {
|
||||
var uri = UriComponentsBuilder.fromUriString(usersService)
|
||||
.path(id)
|
||||
.build()
|
||||
.toUri();
|
||||
.path(id)
|
||||
.build()
|
||||
.toUri();
|
||||
|
||||
try {
|
||||
return restTemplate.getForObject(uri, User.class);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baelduung</groupId>
|
||||
<artifactId>lightrun-demo</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>lightrun</name>
|
||||
<description>Services for LightRun Article</description>
|
||||
<name>lightrun</name>
|
||||
<description>Services for LightRun Article</description>
|
||||
|
||||
<modules>
|
||||
<module>tasks-service</module>
|
||||
|
|
|
@ -1,67 +1,67 @@
|
|||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.6.7</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>tasks-service</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>tasks-service</name>
|
||||
<description>Tasks Service for LightRun Article</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-artemis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.6.7</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>tasks-service</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>tasks-service</name>
|
||||
<description>Tasks Service for LightRun Article</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-artemis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>artemis-jms-server</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -6,8 +6,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||
@SpringBootApplication
|
||||
public class TasksServiceApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(TasksServiceApplication.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(TasksServiceApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,10 +13,5 @@ package com.baeldung.tasksservice.adapters.http;
|
|||
|
||||
import java.time.Instant;
|
||||
|
||||
public record TaskResponse(String id,
|
||||
String title,
|
||||
Instant created,
|
||||
String createdBy,
|
||||
String assignedTo,
|
||||
String status) {
|
||||
public record TaskResponse(String id, String title, Instant created, String createdBy, String assignedTo, String status) {
|
||||
}
|
||||
|
|
|
@ -15,9 +15,6 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.baeldung.tasksservice.adapters.repository.TaskRecord;
|
||||
import com.baeldung.tasksservice.service.TasksService;
|
||||
import com.baeldung.tasksservice.service.UnknownTaskException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
|
@ -32,6 +29,10 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.tasksservice.adapters.repository.TaskRecord;
|
||||
import com.baeldung.tasksservice.service.TasksService;
|
||||
import com.baeldung.tasksservice.service.UnknownTaskException;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/")
|
||||
class TasksController {
|
||||
|
@ -46,13 +47,12 @@ class TasksController {
|
|||
}
|
||||
|
||||
@GetMapping
|
||||
public List<TaskResponse> searchTasks(@RequestParam("status") Optional<String> status,
|
||||
@RequestParam("createdBy") Optional<String> createdBy) {
|
||||
public List<TaskResponse> searchTasks(@RequestParam("status") Optional<String> status, @RequestParam("createdBy") Optional<String> createdBy) {
|
||||
var tasks = tasksService.search(status, createdBy);
|
||||
|
||||
return tasks.stream()
|
||||
.map(this::buildResponse)
|
||||
.collect(Collectors.toList());
|
||||
.map(this::buildResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
|
@ -67,16 +67,14 @@ class TasksController {
|
|||
}
|
||||
|
||||
@PatchMapping("/{id}")
|
||||
public TaskResponse patchTask(@PathVariable("id") String id,
|
||||
@RequestBody PatchTaskRequest body) {
|
||||
public TaskResponse patchTask(@PathVariable("id") String id, @RequestBody PatchTaskRequest body) {
|
||||
var task = tasksService.updateTask(id, body.status(), body.assignedTo());
|
||||
|
||||
return buildResponse(task);
|
||||
}
|
||||
|
||||
private TaskResponse buildResponse(final TaskRecord task) {
|
||||
return new TaskResponse(task.getId(), task.getTitle(), task.getCreated(), task.getCreatedBy(),
|
||||
task.getAssignedTo(), task.getStatus());
|
||||
return new TaskResponse(task.getId(), task.getTitle(), task.getCreated(), task.getCreatedBy(), task.getAssignedTo(), task.getStatus());
|
||||
}
|
||||
|
||||
@ExceptionHandler(UnknownTaskException.class)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package com.baeldung.tasksservice.adapters.jms;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baeldung.tasksservice.service.DeletedUserService;
|
||||
|
||||
|
|
|
@ -11,11 +11,12 @@
|
|||
|
||||
package com.baeldung.tasksservice.adapters.repository;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
@Table(name = "tasks")
|
||||
|
@ -32,8 +33,7 @@ public class TaskRecord {
|
|||
private String assignedTo;
|
||||
private String status;
|
||||
|
||||
public TaskRecord(final String id, final String title, final Instant created, final String createdBy,
|
||||
final String assignedTo, final String status) {
|
||||
public TaskRecord(final String id, final String title, final Instant created, final String createdBy, final String assignedTo, final String status) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.created = created;
|
||||
|
|
|
@ -2,26 +2,26 @@ package com.baeldung.tasksservice.service;
|
|||
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import com.baeldung.tasksservice.adapters.repository.TaskRecord;
|
||||
import com.baeldung.tasksservice.adapters.repository.TasksRepository;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baeldung.tasksservice.adapters.repository.TaskRecord;
|
||||
import com.baeldung.tasksservice.adapters.repository.TasksRepository;
|
||||
|
||||
@Service
|
||||
public class DeletedUserService {
|
||||
@Autowired
|
||||
private TasksRepository tasksRepository;
|
||||
@Autowired
|
||||
private TasksRepository tasksRepository;
|
||||
|
||||
@Transactional
|
||||
public void handleDeletedUser(String user) {
|
||||
var ownedByUser = tasksRepository.findByCreatedBy(user);
|
||||
tasksRepository.deleteAll(ownedByUser);
|
||||
@Transactional
|
||||
public void handleDeletedUser(String user) {
|
||||
var ownedByUser = tasksRepository.findByCreatedBy(user);
|
||||
tasksRepository.deleteAll(ownedByUser);
|
||||
|
||||
var assignedToUser = tasksRepository.findByAssignedTo(user);
|
||||
for (TaskRecord record : assignedToUser) {
|
||||
record.setAssignedTo(null);
|
||||
record.setStatus("PENDING");
|
||||
var assignedToUser = tasksRepository.findByAssignedTo(user);
|
||||
for (TaskRecord record : assignedToUser) {
|
||||
record.setAssignedTo(null);
|
||||
record.setStatus("PENDING");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,29 +11,33 @@
|
|||
|
||||
package com.baeldung.tasksservice.service;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.baeldung.tasksservice.adapters.repository.TaskRecord;
|
||||
import com.baeldung.tasksservice.adapters.repository.TasksRepository;
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baeldung.tasksservice.adapters.repository.TaskRecord;
|
||||
import com.baeldung.tasksservice.adapters.repository.TasksRepository;
|
||||
|
||||
@Service
|
||||
public class TasksService {
|
||||
@Autowired
|
||||
private TasksRepository tasksRepository;
|
||||
|
||||
public TaskRecord getTaskById(String id) {
|
||||
return tasksRepository.findById(id).orElseThrow(() -> new UnknownTaskException(id));
|
||||
return tasksRepository.findById(id)
|
||||
.orElseThrow(() -> new UnknownTaskException(id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteTaskById(String id) {
|
||||
var task = tasksRepository.findById(id).orElseThrow(() -> new UnknownTaskException(id));
|
||||
var task = tasksRepository.findById(id)
|
||||
.orElseThrow(() -> new UnknownTaskException(id));
|
||||
tasksRepository.delete(task);
|
||||
}
|
||||
|
||||
|
@ -51,7 +55,8 @@ public class TasksService {
|
|||
|
||||
@Transactional
|
||||
public TaskRecord updateTask(String id, Optional<String> newStatus, Optional<String> newAssignedTo) {
|
||||
var task = tasksRepository.findById(id).orElseThrow(() -> new UnknownTaskException(id));
|
||||
var task = tasksRepository.findById(id)
|
||||
.orElseThrow(() -> new UnknownTaskException(id));
|
||||
|
||||
newStatus.ifPresent(task::setStatus);
|
||||
newAssignedTo.ifPresent(task::setAssignedTo);
|
||||
|
@ -60,12 +65,8 @@ public class TasksService {
|
|||
}
|
||||
|
||||
public TaskRecord createTask(String title, String createdBy) {
|
||||
var task = new TaskRecord(UUID.randomUUID().toString(),
|
||||
title,
|
||||
Instant.now(),
|
||||
createdBy,
|
||||
null,
|
||||
"PENDING");
|
||||
var task = new TaskRecord(UUID.randomUUID()
|
||||
.toString(), title, Instant.now(), createdBy, null, "PENDING");
|
||||
tasksRepository.save(task);
|
||||
return task;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
server.port=8082
|
||||
|
||||
spring.artemis.mode=EMBEDDED
|
||||
spring.artemis.host=localhost
|
||||
spring.artemis.port=61616
|
||||
|
||||
spring.artemis.embedded.enabled=true
|
||||
|
||||
spring.jms.template.default-destination=my-queue-1
|
||||
|
||||
logging.level.org.apache.activemq.audit.base=WARN
|
||||
logging.level.org.apache.activemq.audit.message=WARN
|
||||
|
||||
|
|
|
@ -3,16 +3,21 @@
|
|||
This application exists as an example for the Lightrun series of articles.
|
||||
|
||||
## Building
|
||||
|
||||
This application requires [Apache Maven](https://maven.apache.org/) and [Java 17+](https://www.oracle.com/java/technologies/downloads/). It does use the Maven Wrapper, so it can be built with only Java available on the path.
|
||||
|
||||
As such, building the code is done by executing:
|
||||
|
||||
```
|
||||
$ ./mvnw install
|
||||
```
|
||||
|
||||
from the top level.
|
||||
|
||||
## Running
|
||||
|
||||
The application consists of three services:
|
||||
|
||||
* Tasks
|
||||
* Users
|
||||
* API
|
||||
|
@ -23,7 +28,9 @@ The Tasks and Users services exist as microservices for managing one facet of da
|
|||
|
||||
This does mean that the startup order is important. The JMS queue exists within the Tasks service and is connected to from the Users service. As such, the Tasks service must be started before the others.
|
||||
|
||||
Each service can be started either by executing `mvn spring-boot:run` from within the appropriate directory. Alternatively, as Spring Boot applications, the build will produce an executable JAR file within the `target` directory that can be executed as, for example:
|
||||
Each service can be started either by executing `mvn spring-boot:run` from within the appropriate directory. Alternatively, as Spring Boot applications, the build will produce an executable JAR file within the `target` directory that can be executed as, for
|
||||
example:
|
||||
|
||||
```
|
||||
$ java -jar ./target/tasks-service-0.0.1-SNAPSHOT.jar
|
||||
```
|
||||
|
|
|
@ -1,63 +1,63 @@
|
|||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.6.7</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>users-service</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>users-service</name>
|
||||
<description>Users Service for LightRun Article</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-artemis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.6.7</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>users-service</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>users-service</name>
|
||||
<description>Users Service for LightRun Article</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-artemis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -6,8 +6,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||
@SpringBootApplication
|
||||
public class UsersServiceApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(UsersServiceApplication.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(UsersServiceApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,5 @@
|
|||
|
||||
package com.baeldung.usersservice.adapters.http;
|
||||
|
||||
public record UserResponse(String id,
|
||||
String name) {
|
||||
public record UserResponse(String id, String name) {
|
||||
}
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
|
||||
package com.baeldung.usersservice.adapters.http;
|
||||
|
||||
import com.baeldung.usersservice.adapters.repository.UserRecord;
|
||||
import com.baeldung.usersservice.service.UsersService;
|
||||
import com.baeldung.usersservice.service.UnknownUserException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
|
@ -27,6 +24,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.usersservice.adapters.repository.UserRecord;
|
||||
import com.baeldung.usersservice.service.UnknownUserException;
|
||||
import com.baeldung.usersservice.service.UsersService;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/")
|
||||
class UsersController {
|
||||
|
@ -50,14 +51,14 @@ class UsersController {
|
|||
var user = usersService.createUser(body.name());
|
||||
return buildResponse(user);
|
||||
}
|
||||
|
||||
|
||||
@PatchMapping("/{id}")
|
||||
public UserResponse patchUser(@PathVariable("id") String id,
|
||||
@RequestBody PatchUserRequest body) {
|
||||
public UserResponse patchUser(@PathVariable("id") String id, @RequestBody PatchUserRequest body) {
|
||||
var user = usersService.updateUser(id, body.name());
|
||||
|
||||
return buildResponse(user);
|
||||
}
|
||||
|
||||
private UserResponse buildResponse(final UserRecord user) {
|
||||
return new UserResponse(user.getId(), user.getName());
|
||||
}
|
||||
|
|
|
@ -11,18 +11,17 @@
|
|||
|
||||
package com.baeldung.usersservice.service;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baeldung.usersservice.adapters.jms.JmsSender;
|
||||
import com.baeldung.usersservice.adapters.repository.UserRecord;
|
||||
import com.baeldung.usersservice.adapters.repository.UsersRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class UsersService {
|
||||
|
@ -33,12 +32,14 @@ public class UsersService {
|
|||
private JmsSender jmsSender;
|
||||
|
||||
public UserRecord getUserById(String id) {
|
||||
return usersRepository.findById(id).orElseThrow(() -> new UnknownUserException(id));
|
||||
return usersRepository.findById(id)
|
||||
.orElseThrow(() -> new UnknownUserException(id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteUserById(String id) {
|
||||
var user = usersRepository.findById(id).orElseThrow(() -> new UnknownUserException(id));
|
||||
var user = usersRepository.findById(id)
|
||||
.orElseThrow(() -> new UnknownUserException(id));
|
||||
usersRepository.delete(user);
|
||||
|
||||
jmsSender.sendDeleteUserMessage(id);
|
||||
|
@ -46,7 +47,8 @@ public class UsersService {
|
|||
|
||||
@Transactional
|
||||
public UserRecord updateUser(String id, Optional<String> newName) {
|
||||
var user = usersRepository.findById(id).orElseThrow(() -> new UnknownUserException(id));
|
||||
var user = usersRepository.findById(id)
|
||||
.orElseThrow(() -> new UnknownUserException(id));
|
||||
|
||||
newName.ifPresent(user::setName);
|
||||
|
||||
|
@ -54,7 +56,8 @@ public class UsersService {
|
|||
}
|
||||
|
||||
public UserRecord createUser(String name) {
|
||||
var user = new UserRecord(UUID.randomUUID().toString(), name);
|
||||
var user = new UserRecord(UUID.randomUUID()
|
||||
.toString(), name);
|
||||
usersRepository.save(user);
|
||||
return user;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
server.port=8081
|
||||
|
||||
spring.artemis.host=localhost
|
||||
spring.artemis.port=61616
|
||||
|
||||
spring.jms.template.default-destination=my-queue-1
|
||||
|
||||
logging.level.org.apache.activemq.audit.base=WARN
|
||||
logging.level.org.apache.activemq.audit.message=WARN
|
||||
|
||||
|
|
Loading…
Reference in New Issue