Skip to content
Open
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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
An example implementation of Spring Boot R2DBC REST API with PostgreSQL database.

## Technology stack
* Java 17
* Java 21
* Maven
* PostgreSQL 16.1
* PostgreSQL 17
* Docker

## Java Dependencies
* Spring Boot 3.2.1
* Spring Boot 3.4.1
* Spring Data R2DBC
* R2DBC PostgreSQL Driver
* JUnit 5
Expand All @@ -30,7 +30,7 @@ An example implementation of Spring Boot R2DBC REST API with PostgreSQL database

2. Run generated docker image

`docker run -it -p8080:8080 --network="host" reactive-postgres:0.0.2-SNAPSHOT`
`docker run -it -p8080:8080 --network="host" reactive-postgres:0.0.3-SNAPSHOT`



Expand Down
3 changes: 1 addition & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
version: '3.8'
services:
postgresql:
container_name: db-postgres
image: postgres:16.1
image: postgres:17
ports:
- "5432:5432"
environment:
Expand Down
Empty file modified mvnw
100644 → 100755
Empty file.
40 changes: 10 additions & 30 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.1</version>
<version>3.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>dev.kamalhm</groupId>
<artifactId>reactive-postgres</artifactId>
<version>0.0.2-SNAPSHOT</version>
<version>0.0.3-SNAPSHOT</version>
<name>reactive-postgres</name>
<description>Demo project for Spring Boot</description>
<description>Example Spring Boot with R2DBC project</description>

<properties>
<java.version>17</java.version>
<java.version>21</java.version>
</properties>

<dependencies>
Expand All @@ -45,21 +45,15 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<groupId>org.postgresql</groupId>
<artifactId>r2dbc-postgresql</artifactId>
<version>0.8.6.RELEASE</version>
<scope>runtime</scope>
<version>1.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</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>
Expand All @@ -80,24 +74,10 @@
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>


</project>
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@
@EnableR2dbcAuditing
public class ReactivePostgresApplication {

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

@Bean
ConnectionFactoryInitializer initializer(@Qualifier("connectionFactory") ConnectionFactory connectionFactory) {
ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
initializer.setConnectionFactory(connectionFactory);
ResourceDatabasePopulator resource =
new ResourceDatabasePopulator(new ClassPathResource("schema.sql"));
initializer.setDatabasePopulator(resource);
return initializer;
}
@Bean
ConnectionFactoryInitializer initializer(@Qualifier("connectionFactory") ConnectionFactory connectionFactory) {
ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
initializer.setConnectionFactory(connectionFactory);
ResourceDatabasePopulator resource =
new ResourceDatabasePopulator(new ClassPathResource("schema.sql"));
initializer.setDatabasePopulator(resource);
return initializer;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
@Configuration
public class PostgresAuditorAwareConfiguration {

@Bean
ReactiveAuditorAware<String> auditorAware() {
return () -> Mono.just("AUDITOR");
}
@Bean
ReactiveAuditorAware<String> auditorAware() {
return () -> Mono.just("AUDITOR");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import dev.kamalhm.reactivepostgres.dto.CreateBalanceWebRequest;
import dev.kamalhm.reactivepostgres.entity.Balance;
import dev.kamalhm.reactivepostgres.repository.BalanceRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
Expand All @@ -13,19 +11,18 @@

@RestController
@RequestMapping(value = "/api/balance")
@RequiredArgsConstructor
@Slf4j
public class BalanceController {

private final BalanceRepository balanceRepository;
private final BalanceRepository balanceRepository;

@PostMapping
public Mono<Balance> createBalance(@RequestBody CreateBalanceWebRequest request) {
final Balance balance = Balance.builder()
.balance(request.getBalance())
.memberId(request.getMemberId())
.build();
return balanceRepository.save(balance);
}
public BalanceController(BalanceRepository balanceRepository) {
this.balanceRepository = balanceRepository;
}

@PostMapping
public Mono<Balance> createBalance(@RequestBody CreateBalanceWebRequest request) {
final Balance balance = new Balance(request.memberId(), request.balance());
return balanceRepository.save(balance);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import dev.kamalhm.reactivepostgres.entity.Member;
import dev.kamalhm.reactivepostgres.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -19,48 +17,50 @@

@RestController
@RequestMapping(value = "/api/member")
@RequiredArgsConstructor
@Slf4j
public class MemberController {

private final MemberRepository memberRepository;
private final MemberRepository memberRepository;

@GetMapping
public Flux<Member> getAll() {
return memberRepository.findAll();
}
public MemberController(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}

@GetMapping(value = "/{name}")
public Mono<Member> getOne(@PathVariable String name) {
return memberRepository.findByName(name);
}
@GetMapping
public Flux<Member> getAll() {
return memberRepository.findAll();
}

@PostMapping
public Mono<Member> createMember(@RequestBody Member member) {
return memberRepository.save(member);
}
@GetMapping(value = "/{name}")
public Mono<Member> getOne(@PathVariable String name) {
return memberRepository.findByName(name);
}

@PostMapping(value = "/{number}")
public Flux<Member> createMembers(@PathVariable int number) {
return generateRandomMember(number).subscribeOn(Schedulers.boundedElastic());
}
@PostMapping
public Mono<Member> createMember(@RequestBody Member member) {
return memberRepository.save(member);
}

private Flux<Member> generateRandomMember(int number) {
return Mono.fromSupplier(
() -> Member.builder().name(RandomStringUtils.randomAlphabetic(5)).build())
.flatMap(memberRepository::save)
.repeat(number);
}
@PostMapping(value = "/{number}")
public Flux<Member> createMembers(@PathVariable int number) {
return generateRandomMember(number).subscribeOn(Schedulers.boundedElastic());
}

@PutMapping
public Mono<Member> updateMember(@RequestBody Member member) {
return memberRepository
.findByName(member.getName())
.flatMap(memberResult -> memberRepository.save(member));
}
private Flux<Member> generateRandomMember(int number) {
return Mono.fromSupplier(
() -> new Member(RandomStringUtils.randomAlphabetic(5)))
.flatMap(memberRepository::save)
.repeat(number);
}

@DeleteMapping
public Mono<Void> deleteMember(@RequestBody Member member) {
return memberRepository.deleteById(member.getId());
}
@PutMapping
public Mono<Member> updateMember(@RequestBody Member member) {
return memberRepository
.findByName(member.name())
.flatMap(memberResult -> memberRepository.save(member));
}

@DeleteMapping
public Mono<Void> deleteMember(@RequestBody Member member) {
return memberRepository.deleteById(member.id());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import dev.kamalhm.reactivepostgres.dto.CreateTransactionWebRequest;
import dev.kamalhm.reactivepostgres.entity.Balance;
import dev.kamalhm.reactivepostgres.service.TransactionalService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -14,15 +12,17 @@

@RestController
@RequestMapping("/api/transaction")
@RequiredArgsConstructor
@Slf4j
public class TransactionController {

private final TransactionalService transactionalService;
private final TransactionalService transactionalService;

@PostMapping
@Transactional
public Mono<Balance> createTransaction(@RequestBody CreateTransactionWebRequest request) {
return transactionalService.doTransaction(request);
}
public TransactionController(TransactionalService transactionalService) {
this.transactionalService = transactionalService;
}

@PostMapping
@Transactional
public Mono<Balance> createTransaction(@RequestBody CreateTransactionWebRequest request) {
return transactionalService.doTransaction(request);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package dev.kamalhm.reactivepostgres.dto;

import lombok.Data;

@Data
public class CreateBalanceWebRequest {

private String memberId;
private Long balance;
public record CreateBalanceWebRequest(Long memberId, Long balance) {
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
package dev.kamalhm.reactivepostgres.dto;

import lombok.Data;

@Data
public class CreateTransactionWebRequest {

private String from;
private String to;
private Long amount;
public record CreateTransactionWebRequest(Long from, Long to, Long amount) {
}
37 changes: 13 additions & 24 deletions src/main/java/dev/kamalhm/reactivepostgres/entity/Balance.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,23 @@
package dev.kamalhm.reactivepostgres.entity;

import java.util.UUID;
import lombok.Builder;
import lombok.Data;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.relational.core.mapping.Column;

@Builder
@Data
public class Balance {

@Id
private UUID id;
@Column("member_id")
private String memberId;
private Long balance;
@CreatedBy
@Column("created_by")
private String createdBy;
@CreatedDate
@Column("created_date")
private Long createdDate;
@LastModifiedBy
@Column("last_modified_by")
private String lastModifiedBy;
@LastModifiedDate
@Column("last_modified_date")
private Long lastModifiedDate;
public record Balance(
@Id Long id,
@Column("member_id") Long memberId,
Long balance,
@CreatedBy @Column("created_by") String createdBy,
@CreatedDate @Column("created_date") Long createdDate,
@LastModifiedBy @Column("last_modified_by") String lastModifiedBy,
@LastModifiedDate @Column("last_modified_date") Long lastModifiedDate
) {
public Balance(Long memberId, Long balance) {
this(null, memberId, balance, null, null, null, null);
}
}

Loading