Skip to content

Commit

Permalink
feat: add loan service with post mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
thisdudkin committed Sep 12, 2024
1 parent c910878 commit f48b4f8
Show file tree
Hide file tree
Showing 25 changed files with 676 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public ResponseEntity<BookRecordDto> getBookRecord(@PathVariable Integer bookId)
}

@Override
@PatchMapping("/{bookId}")
@PutMapping("/{bookId}")
public ResponseEntity<BookRecordDto> updateBookRecord(@PathVariable Integer bookId,
@RequestBody BookRecordDto dto) {
return new ResponseEntity<>(libraryService.updateBookRecord(bookId, dto), HttpStatus.OK);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ public BookRecordDto addBookRecord(BookRecordDto dto) {
}

@Override
public BookRecordDto getBookRecord(Integer id) {
BookRecord bookRecord = bookRecordRepository.findById(id)
.orElseThrow(() -> new BookRecordNotFoundException("Book not found with ID: " + id));
public BookRecordDto getBookRecord(Integer bookId) {
BookRecord bookRecord = bookRecordRepository.findByBookId(bookId)
.orElseThrow(() -> new BookRecordNotFoundException("Book not found with ID: " + bookId));
return bookRecordMapper.toDto(bookRecord);
}

Expand Down
133 changes: 133 additions & 0 deletions library-api-loan-service/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?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>library-api-loan-service</artifactId>
<packaging>jar</packaging>
<description>Library API Loan Service</description>

<parent>
<groupId>dev.earlspilner</groupId>
<artifactId>library-api</artifactId>
<version>1.1.0</version>
</parent>

<dependencies>
<!-- Spring Boot -->
<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-security</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-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

<!-- Spring Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<!-- Database -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>test</scope>
</dependency>

<!-- MapStruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>

<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>

<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${jjwt.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package dev.earlspilner.loans;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
* @author Alexander Dudkin
*/
@EnableFeignClients
@SpringBootApplication
public class LoanServiceApplication {

public static void main(String[] args) {
SpringApplication.run(LoanServiceApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dev.earlspilner.loans.config;

import feign.RequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @author Alexander Dudkin
*/
@Configuration
public class FeignConfig {

// maybe a bad practice
@Bean
public RequestInterceptor requestInterceptor() {
return requestTemplate -> {
requestTemplate.header("User-Agent", "Feign");
};
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package dev.earlspilner.loans.config;

import dev.earlspilner.loans.dto.BookRecordDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

/**
* @author Alexander Dudkin
*/
@FeignClient(
name = "library-service",
url = "http://localhost:9094/api/library",
configuration = FeignConfig.class
)
public interface LibraryClient {

@GetMapping("/{bookId}")
BookRecordDto getBookRecord(@PathVariable Integer bookId);

@PutMapping("/{bookId}")
void setBookOnLoan(@PathVariable Integer bookId, @RequestBody BookRecordDto bookRecordDto);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dev.earlspilner.loans.config;

import dev.earlspilner.loans.dto.UserDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
* @author Alexander Dudkin
*/
@FeignClient(
value = "users-service",
url = "http://localhost:9091/api/users/",
configuration = FeignConfig.class
)
public interface UserClient {

@RequestMapping(method = RequestMethod.GET, value = "/{username}")
UserDto getUser(@PathVariable String username);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package dev.earlspilner.loans.dto;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
import static com.fasterxml.jackson.annotation.JsonProperty.Access.READ_ONLY;

/**
* @author Alexander Dudkin
*/
@JsonInclude(NON_NULL)
public record BookRecordDto(
@JsonProperty(access = READ_ONLY) Integer bookId,
BookStatus status
) { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package dev.earlspilner.loans.dto;

/**
* @author Alexander Dudkin
*/
public enum BookStatus {
ON_LOAN, IN_LIBRARY;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.earlspilner.loans.dto;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
import static com.fasterxml.jackson.annotation.JsonProperty.Access.READ_ONLY;

/**
* @author Alexander Dudkin
*/
@JsonInclude(NON_NULL)
public record LoanDto(
@JsonProperty(access = READ_ONLY) Integer id,
@JsonProperty(access = READ_ONLY) Integer userId,
Integer bookId,
@JsonProperty(access = READ_ONLY) String issuedAt,
@JsonProperty(access = READ_ONLY) String dueTo,
@JsonProperty(access = READ_ONLY) String returnedAt
) { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dev.earlspilner.loans.dto;

import com.fasterxml.jackson.annotation.JsonInclude;
import dev.earlspilner.loans.security.UserRole;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;

import java.util.List;

import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;

/**
* @author Alexander Dudkin
*/
@JsonInclude(NON_NULL)
public record UserDto(
Integer id,
@NotNull String name,
@NotNull String username,
@Email @NotNull String email,
@NotNull String password,
String createdUtc,
String updatedUtc,
List<UserRole> roles
) { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package dev.earlspilner.loans.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang.builder.ToStringBuilder;

import java.time.Instant;
import java.time.temporal.ChronoUnit;

/**
* @author Alexander Dudkin
*/
@Entity @Getter
@Table(name = "loans")
public class Loan {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@Setter
@Column(name = "userId", nullable = false, updatable = false)
private Integer userId;

@Setter
@Column(name = "bookId", nullable = false, updatable = false)
private Integer bookId;

@Setter
@Column(name = "issuedAt", nullable = false)
private Instant issuedAt;

@Setter
@Column(name = "dueTo", nullable = false)
private Instant dueTo;

@Setter
@Column(name = "returnedAt")
private Instant returnedAt;

@PrePersist
protected void onCreate() {
this.issuedAt = Instant.now();
this.dueTo = Instant.now().plus(30, ChronoUnit.DAYS);
}

public Loan() {
}

public Loan(Integer userId, Integer bookId) {
this.userId = userId;
this.bookId = bookId;
}

public Loan(Integer id, Integer userId, Integer bookId, Instant issuedAt, Instant dueTo, Instant returnedAt) {
this.id = id;
this.userId = userId;
this.bookId = bookId;
this.issuedAt = issuedAt;
this.dueTo = dueTo;
this.returnedAt = returnedAt;
}

@Override
public String toString() {
return new ToStringBuilder(this)
.append("id", id)
.append("userId", userId)
.append("bookId", bookId)
.append("issuedAt", issuedAt)
.append("dueTo", dueTo)
.append("returnedAt", returnedAt)
.toString();
}

}
Loading

0 comments on commit f48b4f8

Please sign in to comment.