Merge pull request #12225 from sazzer/lightrun
Source code for Lightrun articles
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# Lightrun Example Application - Tasks Management
|
||||
|
||||
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
|
||||
|
||||
These are all Spring Boot applications.
|
||||
|
||||
The Tasks and Users services exist as microservices for managing one facet of data. Each uses a database, and utilise a JMS queue between them as well. For convenience this infrastructure is all embedded in the applications.
|
||||
|
||||
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:
|
||||
```
|
||||
$ java -jar ./target/tasks-service-0.0.1-SNAPSHOT.jar
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
@@ -0,0 +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>
|
||||
|
||||
<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>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.apiservice;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class ApiServiceApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ApiServiceApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
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 javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
public class RequestIdGenerator implements HandlerInterceptor {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
String requestId = UUID.randomUUID().toString();
|
||||
|
||||
MDC.put(RequestIdGenerator.class.getCanonicalName(), requestId);
|
||||
response.addHeader("X-Request-Id", requestId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||
MDC.remove(RequestIdGenerator.class.getCanonicalName());
|
||||
}
|
||||
|
||||
public static String getRequestId() {
|
||||
return MDC.get(RequestIdGenerator.class.getCanonicalName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.apiservice;
|
||||
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
@Bean
|
||||
public RestTemplate restTemplate(RestTemplateBuilder builder) {
|
||||
return builder
|
||||
.additionalInterceptors((request, body, execution) -> {
|
||||
request.getHeaders().add("X-Request-Id", RequestIdGenerator.getRequestId());
|
||||
|
||||
return execution.execute(request, body);
|
||||
})
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.apiservice;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
@Autowired
|
||||
private RequestIdGenerator requestIdGenerator;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(requestIdGenerator);
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
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) {
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.baeldung.apiservice.adapters.http;
|
||||
|
||||
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
|
||||
public class TasksController {
|
||||
@Autowired
|
||||
private TaskRepository taskRepository;
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public TaskResponse getTaskById(@PathVariable("id") String id) {
|
||||
Task task = taskRepository.getTaskById(id);
|
||||
|
||||
if (task == null) {
|
||||
throw new UnknownTaskException();
|
||||
}
|
||||
|
||||
return buildResponse(task);
|
||||
}
|
||||
|
||||
private TaskResponse buildResponse(Task task) {
|
||||
return new TaskResponse(task.id(),
|
||||
task.title(),
|
||||
task.created(),
|
||||
getUser(task.createdBy()),
|
||||
getUser(task.assignedTo()),
|
||||
task.status());
|
||||
}
|
||||
|
||||
private UserResponse getUser(String userId) {
|
||||
if (userId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var user = userRepository.getUserById(userId);
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new UserResponse(user.id(), user.name());
|
||||
}
|
||||
@ExceptionHandler(UnknownTaskException.class)
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
public void handleUnknownTask() {
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package com.baeldung.apiservice.adapters.http;
|
||||
|
||||
public class UnknownTaskException extends RuntimeException {
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package com.baeldung.apiservice.adapters.http;
|
||||
|
||||
public record UserResponse(String id, String name) {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
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) {
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.baeldung.apiservice.adapters.tasks;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
@Repository
|
||||
public class TaskRepository {
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Value("${tasks-service.url}")
|
||||
private String tasksService;
|
||||
|
||||
public Task getTaskById(String id) {
|
||||
var uri = UriComponentsBuilder.fromUriString(tasksService)
|
||||
.path(id)
|
||||
.build()
|
||||
.toUri();
|
||||
|
||||
try {
|
||||
return restTemplate.getForObject(uri, Task.class);
|
||||
} catch (HttpClientErrorException.NotFound e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.baeldung.apiservice.adapters.users;
|
||||
|
||||
public record User(String id, String name) {
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
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;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
@Repository
|
||||
public class UserRepository {
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Value("${users-service.url}")
|
||||
private String usersService;
|
||||
|
||||
public User getUserById(String id) {
|
||||
var uri = UriComponentsBuilder.fromUriString(usersService)
|
||||
.path(id)
|
||||
.build()
|
||||
.toUri();
|
||||
|
||||
try {
|
||||
return restTemplate.getForObject(uri, User.class);
|
||||
} catch (HttpClientErrorException.NotFound e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
users-service.url=http://localhost:8081
|
||||
tasks-service.url=http://localhost:8082
|
||||
@@ -0,0 +1,17 @@
|
||||
<?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>
|
||||
<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>
|
||||
|
||||
<modules>
|
||||
<module>tasks-service</module>
|
||||
<module>users-service</module>
|
||||
<module>api-service</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -0,0 +1,33 @@
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
@@ -0,0 +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>
|
||||
|
||||
<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>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.tasksservice;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.jms.artemis.ArtemisConfigurationCustomizer;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class ArtemisConfig implements ArtemisConfigurationCustomizer {
|
||||
@Value("${spring.artemis.host}")
|
||||
private String hostname;
|
||||
|
||||
@Value("${spring.artemis.port}")
|
||||
private int port;
|
||||
|
||||
@Override
|
||||
public void customize(org.apache.activemq.artemis.core.config.Configuration configuration) {
|
||||
try {
|
||||
configuration.addAcceptorConfiguration("remote", "tcp://" + hostname + ":" + port);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to configure Artemis listener", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.tasksservice;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class TasksServiceApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(TasksServiceApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/****************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022 OCLC, Inc. All Rights Reserved.
|
||||
*
|
||||
* OCLC proprietary information: the enclosed materials contain
|
||||
* proprietary information of OCLC, Inc. and shall not be disclosed in whole or in
|
||||
* any part to any third party or used by any person for any purpose, without written
|
||||
* consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice.
|
||||
*
|
||||
******************************************************************************************************************/
|
||||
|
||||
package com.baeldung.tasksservice.adapters.http;
|
||||
|
||||
public record CreateTaskRequest(String title, String createdBy) {
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/****************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022 OCLC, Inc. All Rights Reserved.
|
||||
*
|
||||
* OCLC proprietary information: the enclosed materials contain
|
||||
* proprietary information of OCLC, Inc. and shall not be disclosed in whole or in
|
||||
* any part to any third party or used by any person for any purpose, without written
|
||||
* consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice.
|
||||
*
|
||||
******************************************************************************************************************/
|
||||
|
||||
package com.baeldung.tasksservice.adapters.http;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public record PatchTaskRequest(Optional<String> status, Optional<String> assignedTo) {
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/****************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022 OCLC, Inc. All Rights Reserved.
|
||||
*
|
||||
* OCLC proprietary information: the enclosed materials contain
|
||||
* proprietary information of OCLC, Inc. and shall not be disclosed in whole or in
|
||||
* any part to any third party or used by any person for any purpose, without written
|
||||
* consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice.
|
||||
*
|
||||
******************************************************************************************************************/
|
||||
|
||||
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) {
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/****************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022 OCLC, Inc. All Rights Reserved.
|
||||
*
|
||||
* OCLC proprietary information: the enclosed materials contain
|
||||
* proprietary information of OCLC, Inc. and shall not be disclosed in whole or in
|
||||
* any part to any third party or used by any person for any purpose, without written
|
||||
* consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice.
|
||||
*
|
||||
******************************************************************************************************************/
|
||||
|
||||
package com.baeldung.tasksservice.adapters.http;
|
||||
|
||||
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;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PatchMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/")
|
||||
class TasksController {
|
||||
@Autowired
|
||||
private TasksService tasksService;
|
||||
|
||||
@PostMapping
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public TaskResponse createTask(@RequestBody CreateTaskRequest body) {
|
||||
var task = tasksService.createTask(body.title(), body.createdBy());
|
||||
return buildResponse(task);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
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());
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public TaskResponse getTask(@PathVariable("id") String id) {
|
||||
var task = tasksService.getTaskById(id);
|
||||
return buildResponse(task);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public void deleteTask(@PathVariable("id") String id) {
|
||||
tasksService.deleteTaskById(id);
|
||||
}
|
||||
|
||||
@PatchMapping("/{id}")
|
||||
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());
|
||||
}
|
||||
|
||||
@ExceptionHandler(UnknownTaskException.class)
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
public void handleUnknownTask() {
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"local-tasks": {
|
||||
"host": "localhost:8082"
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
GET http://{{host}}/createdemoapplication1 HTTP/1.1
|
||||
|
||||
###
|
||||
GET http://{{host}}/unknown HTTP/1.1
|
||||
|
||||
###
|
||||
GET http://{{host}}?status=PENDING
|
||||
|
||||
###
|
||||
GET http://{{host}}?createdBy=baeldung
|
||||
|
||||
###
|
||||
GET http://{{host}}?createdBy=baeldung&status=COMPLETE
|
||||
|
||||
###
|
||||
DELETE http://{{host}}/createdemoapplication1 HTTP/1.1
|
||||
|
||||
###
|
||||
DELETE http://{{host}}/unknown HTTP/1.1
|
||||
|
||||
###
|
||||
POST http://{{host}} HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"title": "My Task",
|
||||
"createdBy": "graham"
|
||||
}
|
||||
###
|
||||
PATCH http://{{host}}/createdemoapplication1 HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"status": "COMPLETE"
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
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 com.baeldung.tasksservice.service.DeletedUserService;
|
||||
|
||||
@Service
|
||||
public class JmsConsumer {
|
||||
@Autowired
|
||||
private DeletedUserService deletedUserService;
|
||||
|
||||
@JmsListener(destination = "deleted_user")
|
||||
public void receive(String user) {
|
||||
deletedUserService.handleDeletedUser(user);
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/****************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022 OCLC, Inc. All Rights Reserved.
|
||||
*
|
||||
* OCLC proprietary information: the enclosed materials contain
|
||||
* proprietary information of OCLC, Inc. and shall not be disclosed in whole or in
|
||||
* any part to any third party or used by any person for any purpose, without written
|
||||
* consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice.
|
||||
*
|
||||
******************************************************************************************************************/
|
||||
|
||||
package com.baeldung.tasksservice.adapters.repository;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
@Table(name = "tasks")
|
||||
public class TaskRecord {
|
||||
@Id
|
||||
@Column(name = "task_id")
|
||||
private String id;
|
||||
private String title;
|
||||
@Column(name = "created_at")
|
||||
private Instant created;
|
||||
@Column(name = "created_by")
|
||||
private String createdBy;
|
||||
@Column(name = "assigned_to")
|
||||
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) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.created = created;
|
||||
this.createdBy = createdBy;
|
||||
this.assignedTo = assignedTo;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
private TaskRecord() {
|
||||
// Needed for JPA
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public Instant getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public String getAssignedTo() {
|
||||
return assignedTo;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setAssignedTo(final String assignedTo) {
|
||||
this.assignedTo = assignedTo;
|
||||
}
|
||||
|
||||
public void setStatus(final String status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/****************************************************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022 OCLC, Inc. All Rights Reserved.
|
||||
*
|
||||
* OCLC proprietary information: the enclosed materials contain
|
||||
* proprietary information of OCLC, Inc. and shall not be disclosed in whole or in
|
||||
* any part to any third party or used by any person for any purpose, without written
|
||||
* consent of OCLC, Inc. Duplication of any portion of these materials shall include this notice.
|
||||
*
|
||||
******************************************************************************************************************/
|
||||
|
||||
package com.baeldung.tasksservice.adapters.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface TasksRepository extends JpaRepository<TaskRecord, String> {
|
||||
List<TaskRecord> findByStatus(String status);
|
||||
|
||||
List<TaskRecord> findByCreatedBy(String createdBy);
|
||||
|
||||
List<TaskRecord> findByStatusAndCreatedBy(String status, String createdBy);
|
||||
|
||||
List<TaskRecord> findByAssignedTo(String assignedTo);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user