Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions .nginx/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
COPY default.conf /etc/nginx/conf.d
12 changes: 12 additions & 0 deletions .nginx/default.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
server {
listen 80;
server_name nginx;

location /api/0.1 {
proxy_pass http://backend:5001;
}

location / {
proxy_pass http://frontend:5002;
}
}
18 changes: 17 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
language: java
jdk: openjdk8
install: true

cache:
directories:
- $HOME/.m2

script:
- cd spring-boot-postgres && mvn -B verify && cd ..
- cd backend && mvn -B verify && cd ..

after_success:
- bash <(curl -s https://codecov.io/bash)

notifications:
email:
recipients:
- egnaf@yahoo.com
on_success: never
on_failure: always
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
[![Build Status](https://travis-ci.org/egnaf/spring-boot-docker-samples.svg)](https://travis-ci.org/egnaf/spring-boot-postgres-docker)
[![Build Status](https://travis-ci.org/egnaf/spring-boot-docker-example.svg)](https://travis-ci.org/egnaf/spring-boot-docker-example)
[![codecov](https://codecov.io/gh/egnaf/spring-boot-docker-example/branch/dev/graph/badge.svg)](https://codecov.io/gh/egnaf/spring-boot-docker-example)
# spring-boot-docker-example

# spring-boot-docker-samples
## Stack
- Spring Boot 2.2.0
- Spring Data 2.2.0
- Postgres 9.4
- Docker 3
- Maven 4
- Tomcat 9

## Installation
Change directory path to project directory with `cd`, build services and run in containers with run the `start.sh`.
## Install
To build services and launch them in containers, you need to run `start.sh`.
```bash
$ cd project-name
$ ./start.sh
$ bash start.sh
```

## Contribute
For any problems, comments, or feedback please create an issue
[here](https://github.com/egnaf/design-patterns/issues).
[here](https://github.com/egnaf/spring-boot-docker-example/issues).
<br>

## License
Project is released under the [MIT](https://en.wikipedia.org/wiki/MIT_License).
Project is released under the [MIT](https://en.wikipedia.org/wiki/MIT_License).
4 changes: 4 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM openjdk:8-jre-alpine
WORKDIR /app/backend
COPY target/app.jar ./app.jar
CMD ["/usr/bin/java", "-jar", "app.jar"]
107 changes: 107 additions & 0 deletions backend/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>

<groupId>com.github.egnaf.spring-docker-example</groupId>
<artifactId>backend</artifactId>
<version>0.1</version>
<packaging>jar</packaging>

<name>Spring boot docker example</name>
<description>
An example of a simple Spring Boot application and other services running
with docker-compose file configuration
</description>

<developers>
<developer>
<id>1</id>
<name>Sherzod Mamadaliev</name>
<email>egnaf@yahoo.com</email>
</developer>
</developers>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
</parent>

<dependencies>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4.1210</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.195</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.5.1</version>
</dependency>
</dependencies>

<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeDevtools>false</excludeDevtools>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.4</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.github.egnaf.spring_docker_example;

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

@SpringBootApplication
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.github.egnaf.spring_docker_example.config;

import org.dozer.DozerBeanMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DozerConfig {

@Bean
public DozerBeanMapper dozer() {
return new DozerBeanMapper();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.github.egnaf.spring_docker_example.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

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

@Column(name = "nickname")
private String nickname;

@Column(name = "email")
private String email;

@Column(name = "password")
private String password;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.github.egnaf.spring_docker_example.exception;

public class UserExistsException extends RuntimeException {

public UserExistsException() {
super("User exists");
}

public UserExistsException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.github.egnaf.spring_docker_example.exception;

public class UserNotFoundException extends RuntimeException {

public UserNotFoundException() {
super("User not found");
}

public UserNotFoundException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.github.egnaf.spring_docker_example.repository;

import com.github.egnaf.spring_docker_example.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

boolean existsByEmail(String email);

boolean existsByNickname(String nickname);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.github.egnaf.spring_docker_example.rest;

import com.github.egnaf.spring_docker_example.domain.User;
import com.github.egnaf.spring_docker_example.service.UserService;
import com.github.egnaf.spring_docker_example.transfer.UserDto;
import lombok.extern.slf4j.Slf4j;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
public class UserController {

private final UserService userService;
private final Mapper mapper;

@Autowired
public UserController(UserService userService, Mapper mapper) {
this.userService = userService;
this.mapper = mapper;
}

@GetMapping("/users")
public List<UserDto> getUsers() {
List<UserDto> users = userService.getUsers().stream()
.map(user -> mapper.map(user, UserDto.class))
.collect(Collectors.toList());
log.debug(users.toString());
return users;
}

@GetMapping("/users/{id}")
public UserDto getUser(@PathVariable long id) {
UserDto user = mapper.map(userService.getUser(id), UserDto.class);
log.debug(user.toString());
return user;
}

@PostMapping("/users")
public UserDto addUser(@RequestBody User user) {
UserDto newUser = mapper.map(
userService.addUser(user.getNickname(), user.getEmail(), user.getPassword()), UserDto.class);
log.debug(newUser.toString());
return newUser;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.github.egnaf.spring_docker_example.rest.error;

import com.github.egnaf.spring_docker_example.exception.UserExistsException;
import com.github.egnaf.spring_docker_example.exception.UserNotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
public class ErrorHandlerController extends ResponseEntityExceptionHandler {

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleOtherException(Exception e) {
return new ResponseEntity<>(
new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()),
HttpStatus.INTERNAL_SERVER_ERROR);
}

@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFoundException(Exception e) {
return new ResponseEntity<>(
new ErrorResponse(HttpStatus.NOT_FOUND.value(), e.getMessage()),
HttpStatus.NOT_FOUND);
}

@ExceptionHandler(UserExistsException.class)
public ResponseEntity<ErrorResponse> handleExistsException(Exception e) {
return new ResponseEntity<>(
new ErrorResponse(HttpStatus.BAD_REQUEST.value(), e.getMessage()),
HttpStatus.BAD_REQUEST);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.github.egnaf.spring_docker_example.rest.error;

import lombok.Data;

@Data
class ErrorResponse {
private int status;
private String message;

ErrorResponse(int status, String message) {
this.status = status;
this.message = message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.github.egnaf.spring_docker_example.service;

import com.github.egnaf.spring_docker_example.domain.User;
import com.github.egnaf.spring_docker_example.exception.UserExistsException;
import com.github.egnaf.spring_docker_example.exception.UserNotFoundException;

import java.util.List;

public interface UserService {

List<User> getUsers();
User getUser(long id) throws UserNotFoundException;
User addUser(String nickname, String email, String password) throws UserExistsException;
}
Loading