Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
2a0f96f
Add TestContainers sample for Doma Spring Boot (Fixes #290)
devin-ai-integration[bot] May 19, 2025
448f356
Revise TestContainers sample to use Spring Boot's native TestContaine…
devin-ai-integration[bot] May 19, 2025
5198bb1
Fix code formatting issues
devin-ai-integration[bot] May 19, 2025
1e42f72
Update TestContainers sample to use Spring Initializr generated approach
devin-ai-integration[bot] May 19, 2025
06610a1
Remove old TestContainersConfig.java file
devin-ai-integration[bot] May 19, 2025
45661c4
Update TestContainers sample based on feedback: use RestClient, remov…
devin-ai-integration[bot] May 19, 2025
87b5535
Update TestContainers sample based on feedback: remove explicit diale…
devin-ai-integration[bot] May 19, 2025
237ea2d
Change page and size parameters to integers in ApplicationTest
devin-ai-integration[bot] May 19, 2025
487094d
Update transaction manager logging to use JdbcTransactionManager
devin-ai-integration[bot] May 19, 2025
2a5fa14
Use diamond operator for ParameterizedTypeReference
devin-ai-integration[bot] May 19, 2025
ccf7bfc
Add Maven wrapper info to README and remove redundant application-tes…
devin-ai-integration[bot] May 19, 2025
ccbf51f
Add Maven wrapper files to TestContainers sample
devin-ai-integration[bot] May 19, 2025
cf62c8e
Address PR comments: add SQL logging, remove useless comment, remove …
devin-ai-integration[bot] May 19, 2025
5f6bdc4
Remove JUnit comment from pom.xml
devin-ai-integration[bot] May 19, 2025
5f5aa9a
Remove TestContainers comment from pom.xml
devin-ai-integration[bot] May 19, 2025
37dc226
Remove PostgreSQL Driver comment and fix README.md to remove H2 refer…
devin-ai-integration[bot] May 19, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Doma Spring Boot Sample with TestContainers

This sample demonstrates how to use [TestContainers](https://www.testcontainers.org/) with Doma and Spring Boot.

## Running the Sample

To run this sample, you need:
- Java 17 or later
- Maven
- Docker (for running TestContainers)

### Build and Run Tests

```bash
./mvnw clean test
Copy link
Member

Choose a reason for hiding this comment

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

Add maven wrapper

```

### Run with TestContainers

```bash
./mvnw spring-boot:test-run
```

This will start the application with a PostgreSQL container.

## Features Demonstrated

- Using TestContainers to start a PostgreSQL database for tests
- Spring Boot's native TestContainers integration with `@ServiceConnection`
- Using TestContainers at development time with `SpringApplication.from()`
- Running Doma queries against a real PostgreSQL database in tests
- Configuration for both development (H2) and test (PostgreSQL) environments
Copy link
Member

Choose a reason for hiding this comment

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

H2 is not used

Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?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>doma-spring-boot-sample-testcontainers</artifactId>
<packaging>jar</packaging>

<name>doma-spring-boot-sample-testcontainers</name>
<description>Demo project for Spring Boot with Doma and TestContainers</description>

<parent>
<groupId>org.seasar.doma.boot</groupId>
<artifactId>doma-spring-boot-samples</artifactId>
<version>2.5.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<dependencies>
<dependency>
<groupId>org.seasar.doma</groupId>
<artifactId>doma-core</artifactId>
<version>${doma.version}</version>
</dependency>
<dependency>
<groupId>org.seasar.doma</groupId>
<artifactId>doma-processor</artifactId>
<version>${doma.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.seasar.doma.boot</groupId>
<artifactId>doma-spring-boot-starter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- PostgreSQL Driver -->
Copy link
Member

Choose a reason for hiding this comment

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

Remove this comment

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
Copy link
Member

Choose a reason for hiding this comment

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

junit is managed by Spring Boot

<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Boot manages TestContainers dependencies -->
Copy link
Member

Choose a reason for hiding this comment

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

Remove this comment as well

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.seasar.doma.boot.sample;

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

@SpringBootApplication
public class Application {

@SuppressWarnings("resource")
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.seasar.doma.boot.sample;

import org.seasar.doma.*;

@Entity
@Table(name = "messages")
public class Message {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer id;

public String text;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.seasar.doma.boot.sample;

import java.util.List;

import org.seasar.doma.boot.Pageables;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/")
Copy link
Member

Choose a reason for hiding this comment

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

use path attriubte

public class MessageController {

private final MessageDao messageDao;

public MessageController(MessageDao messageDao) {
this.messageDao = messageDao;
}

@GetMapping
List<Message> list(@PageableDefault Pageable pageable) {
return messageDao.selectAll(Pageables.toSelectOptions(pageable));
}

@GetMapping(params = "text")
Message add(@RequestParam String text) {
Message message = new Message();
message.text = text;
messageDao.insert(message);
return message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.seasar.doma.boot.sample;

import java.util.List;

import org.seasar.doma.Dao;
import org.seasar.doma.Insert;
import org.seasar.doma.Select;
import org.seasar.doma.boot.ConfigAutowireable;
import org.seasar.doma.jdbc.SelectOptions;
import org.springframework.transaction.annotation.Transactional;

@Dao
@ConfigAutowireable
@Transactional
public interface MessageDao {
@Select
List<Message> selectAll(SelectOptions options);

@Insert
int insert(Message message);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT id, text FROM messages ORDER BY id;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Development configuration using TestContainers
Copy link
Member

Choose a reason for hiding this comment

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

This comment is useless

spring.sql.init.mode=always

# Doma configuration
doma.naming=SNAKE_LOWER_CASE
logging.level.org.springframework.jdbc.datasource.DataSourceTransactionManager=DEBUG
Copy link
Member

Choose a reason for hiding this comment

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

DataSourceTransactionManager is old. Use JdbcTransactionManager instead.

logging.level.org.springframework.jdbc.support.JdbcTransactionManager=DEBUG

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CREATE TABLE IF NOT EXISTS messages (
id SERIAL PRIMARY KEY,
text VARCHAR(255)
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.seasar.doma.boot.sample;

import static org.junit.jupiter.api.Assertions.*;

import java.util.List;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.context.annotation.Import;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.web.client.RestClient;
import org.springframework.web.util.UriComponentsBuilder;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@Import(TestcontainersConfiguration.class)
class ApplicationTest {
private RestClient restClient;
private final ParameterizedTypeReference<List<Message>> typedReference = new ParameterizedTypeReference<List<Message>>() {
Copy link
Member

Choose a reason for hiding this comment

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

Explicit type argument List<Message> can be replaced with <>

};
@LocalServerPort
private int port;

@BeforeEach
void setUp(@Autowired RestClient.Builder restClientBuilder) {
this.restClient = restClientBuilder
.baseUrl("http://localhost:" + port)
.defaultStatusHandler(__ -> true, (req, res) -> {
}).build();
}

@Test
void testWithTestContainers() {
Message message1 = restClient.get()
.uri("/?text={text}", "hello")
.retrieve()
.body(Message.class);
assertEquals(1, message1.id);
assertEquals("hello", message1.text);

Message message2 = restClient.get()
.uri("/?text={text}", "world")
.retrieve()
.body(Message.class);
assertEquals(2, message2.id);
assertEquals("world", message2.text);

{
List<Message> messages = restClient.get()
.uri("/")
.retrieve()
.body(typedReference);
assertEquals(2, messages.size());
assertEquals(message1.id, messages.get(0).id);
assertEquals(message1.text, messages.get(0).text);
assertEquals(message2.id, messages.get(1).id);
assertEquals(message2.text, messages.get(1).text);
}

{
List<Message> messages = restClient.get()
.uri("/?page={page}&size={size}", "1", "1")
Copy link
Member

Choose a reason for hiding this comment

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

page and size should be int

.retrieve()
.body(typedReference);
assertEquals(1, messages.size());
assertEquals(message2.id, messages.get(0).id);
assertEquals(message2.text, messages.get(0).text);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.seasar.doma.boot.sample;

import org.springframework.boot.SpringApplication;

public class TestApplication {

public static void main(String[] args) {
SpringApplication.from(Application::main).with(TestcontainersConfiguration.class).run(args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.seasar.doma.boot.sample;

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.DockerImageName;

@TestConfiguration(proxyBeanMethods = false)
class TestcontainersConfiguration {

@Bean
@ServiceConnection
PostgreSQLContainer<?> postgresContainer() {
return new PostgreSQLContainer<>(DockerImageName.parse("postgres:latest"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Test configuration for PostgreSQL
spring.sql.init.mode=always
Copy link
Member

Choose a reason for hiding this comment

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

redundant file

1 change: 1 addition & 0 deletions doma-spring-boot-samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<module>doma-spring-boot-sample-event-handler</module>
<module>doma-spring-boot-sample-two-datasource</module>
<module>doma-spring-boot-sample-unified-criteria</module>
<module>doma-spring-boot-sample-testcontainers</module>
</modules>

<properties>
Expand Down