Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ТЗ 16. Добавить докер и многомодульность #5

Merged
merged 2 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
version: '3.8'
services:
gateway:
build: gateway
image: gateway-image
container_name: gateway-container
ports:
- "8080:8080"
depends_on:
- server
environment:
- SHAREIT_SERVER_URL=http://server:9090

server:
build: server
image: server-image
container_name: server-container
ports:
- "9090:9090"
depends_on:
- db
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/shareIt
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=root
- SPRING_DRIVER_CLASS_NAME=org.postgresql.Driver

db:
image: postgres:14-alpine
container_name: db-container
ports:
- "6541:5432"
environment:
- POSTGRES_PASSWORD=root
- POSTGRES_USER=root
- POSTGRES_DB=shareIt
38 changes: 38 additions & 0 deletions gateway/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr

### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/

### Mac OS ###
.DS_Store
3 changes: 3 additions & 0 deletions gateway/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM amazoncorretto:11-alpine-jdk
COPY target/*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
65 changes: 65 additions & 0 deletions gateway/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?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>ru.practicum</groupId>
<artifactId>shareit</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>

<artifactId>shareit-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>

<name>ShareIt Gateway</name>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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-actuator</artifactId>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
12 changes: 12 additions & 0 deletions gateway/src/main/java/ru/practicum/shareit/ShareItGateway.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ru.practicum.shareit;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package ru.practicum.shareit.booking;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.util.DefaultUriBuilderFactory;
import ru.practicum.shareit.booking.dto.BookItemRequestDto;
import ru.practicum.shareit.booking.dto.BookingState;
import ru.practicum.shareit.client.BaseClient;

import java.util.Map;

@Service
public class BookingClient extends BaseClient {
private static final String API_PREFIX = "/bookings";

@Autowired
public BookingClient(@Value("${shareit-server.url}") String serverUrl, RestTemplateBuilder builder) {
super(
builder
.uriTemplateHandler(new DefaultUriBuilderFactory(serverUrl + API_PREFIX))
.requestFactory(HttpComponentsClientHttpRequestFactory::new)
.build()
);
}

public ResponseEntity<Object> getBookings(long userId, BookingState state, Integer from, Integer size) {
Map<String, Object> parameters = Map.of(
"state", state.name(),
"from", from,
"size", size
);
return get("?state={state}&from={from}&size={size}", userId, parameters);
}


public ResponseEntity<Object> bookItem(long userId, BookItemRequestDto requestDto) {
return post("", userId, requestDto);
}

public ResponseEntity<Object> getBooking(long userId, Long bookingId) {
return get("/" + bookingId, userId);
}

public ResponseEntity<Object> updateBooking(long userId, Long bookingId, Boolean approved) {
return patch("/" + bookingId + "?approved=" + approved, userId);
}

public ResponseEntity<Object> getOwnerBookings(long userId, BookingState state, Integer from, Integer size) {
Map<String, Object> parameters = Map.of(
"state", state.name(),
"from", from,
"size", size
);
return get("/owner?state={state}&from={from}&size={size}", userId, parameters);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package ru.practicum.shareit.booking;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import ru.practicum.shareit.booking.dto.BookItemRequestDto;
import ru.practicum.shareit.booking.dto.BookingState;

import javax.validation.Valid;
import javax.validation.constraints.Positive;
import javax.validation.constraints.PositiveOrZero;

import static ru.practicum.shareit.Constant.USER_HEADER;

@Controller
@RequestMapping(path = "/bookings")
@RequiredArgsConstructor
@Slf4j
@Validated
public class BookingController {
private final BookingClient bookingClient;

@GetMapping
public ResponseEntity<Object> getBookings(@RequestHeader(USER_HEADER) long userId,
Copy link

@PolnySkvorets PolnySkvorets Apr 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь лучше у userId установить тип Long, так , чтобы можно было валидировать этот параметр нормально, а не падать с исключением, если передан пустой параметр, аналогично ниже в других методах

@RequestParam(name = "state", defaultValue = "all") String stateParam,
@PositiveOrZero @RequestParam (name = "from", defaultValue = "0") Integer from,
@Positive @RequestParam (name = "size", defaultValue = "10") Integer size) {
BookingState state = BookingState.from(stateParam)
.orElseThrow(() -> new IllegalArgumentException("Unknown state: " + stateParam));
log.info("BOOKING_GATEWAY: Get booking with state {}, userId={}, from={}, size={}", stateParam, userId, from, size);
return bookingClient.getBookings(userId, state, from, size);
}

@PostMapping
public ResponseEntity<Object> bookItem(@RequestHeader(USER_HEADER) long userId,
@RequestBody @Valid BookItemRequestDto requestDto) {
log.info("BOOKING_GATEWAY: Creating booking {}, userId={}", requestDto, userId);
return bookingClient.bookItem(userId, requestDto);
}

@GetMapping("/{bookingId}")
public ResponseEntity<Object> getBooking(@RequestHeader(USER_HEADER) long userId,
@PathVariable Long bookingId) {
log.info("BOOKING_GATEWAY: Get booking {}, userId={}", bookingId, userId);
return bookingClient.getBooking(userId, bookingId);
}

@PatchMapping("/{bookingId}")
public ResponseEntity<Object> updateBooking(@RequestHeader(USER_HEADER) @Positive long userId,
@PathVariable @Positive Long bookingId,
@RequestParam Boolean approved) {
log.info("BOOKING_GATEWAY: Update booking {}, userId={}", bookingId, userId);
return bookingClient.updateBooking(userId, bookingId, approved);
}

@GetMapping("/owner")
public ResponseEntity<Object> getOwnerBookings(@RequestHeader(USER_HEADER) long userId,
@RequestParam(name = "state", defaultValue = "all") String stateParam,
@PositiveOrZero @RequestParam(name = "from", defaultValue = "0") Integer from,
@Positive @RequestParam(name = "size", defaultValue = "10") Integer size) {
log.info("BOOKING_GATEWAY: Get booking with state {}, ownerId={}, from={}, size={}", stateParam, userId, from, size);
BookingState state = BookingState.from(stateParam)
.orElseThrow(() -> new IllegalArgumentException("Unknown state: " + stateParam));
return bookingClient.getOwnerBookings(userId, state, from, size);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package ru.practicum.shareit.booking.dto;

import java.time.LocalDateTime;

import javax.validation.constraints.Future;
import javax.validation.constraints.FutureOrPresent;
import javax.validation.constraints.NotNull;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class BookItemRequestDto {
private long itemId;
@NotNull(message = "Дата начала брони не может быть null")
@FutureOrPresent(message = "Дата начала брони не может быть в прошлом")
private LocalDateTime start;
@NotNull(message = "Дата завершения брони не может быть null")
@Future(message = "Дата завершения брони должна быть в будущем")
private LocalDateTime end;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ru.practicum.shareit.booking.dto;

import java.util.Optional;

public enum BookingState {
// Все
ALL,
// Текущие
CURRENT,
// Будущие
FUTURE,
// Завершенные
PAST,
// Отклоненные
REJECTED,
// Ожидающие подтверждения
WAITING;

public static Optional<BookingState> from(String stringState) {
for (BookingState state : values()) {
if (state.name().equalsIgnoreCase(stringState)) {
return Optional.of(state);
}
}
return Optional.empty();
}
}
Loading
Loading