Introducing Dev Services for Spring Boot using Arconia

Enhance the Spring Boot developer experience with Arconia: zero-code and zero-config infrastructure provisioning. Add one dependency. That's it!

Silhouette Of Trees - Photo by James Wheeler

Have you ever felt the pain of setting up local infrastructure for a Spring Boot application? Perhaps you've struggled with configuring a PostgreSQL database, an OpenTelemetry collector, or even an AI inference service like Ollama. Whether you're using Docker Compose or Testcontainers for defining the external services your application depends on, the process can involve a lot of boilerplate code, manual configuration, and changes to your development workflow.

Before you can even start coding the business logic, you might find yourself spending time with preliminary tasks that detract from your productivity. If you bootstrap new applications often, you'll have to repeat these steps each time, risking being trapped in a cycle of copying and pasting boilerplate code from one project to another. And if you're just getting started with Spring Boot, all this setup can feel even more overwhelming.

Wouldn't it be great if you could just add a dependency to your application project and have everything work out of the box? That's exactly what Arconia Dev Services bring to the table.

In this article, I'll present the main features of Arconia Dev Services and how they can transform your local development experience. Then, I'll walk you through how to use Arconia Dev Services to provide a PostgreSQL database when running a Spring Boot application with Spring Data JDBC and Flyway. You'll see how easy it is to get started without any boilerplate code or extra configuration.

๐Ÿš€
Developer experience is one of my focus areas. I've been working on a new book about it together with my friend Mauricio Salatino, who I thank for the insightful conversations and feedback on the subject. You can already check out Developer Experience on Kubernetes in the early release version here.

What is Arconia?

Arconia is an open-source framework that acts as an add-on for Spring Boot. I created Arconia to enhance the development of modern enterprise applications with Java. You can add Arconia to an existing Spring Boot application to boost developer experience, reduce boilerplate, and seamlessly adopt cloud native patterns.

Some of the key features Arconia aims to provide include:

  • Developer Experience. Introducing first-class support for development and testing modes in Spring Boot applications for making local development and testing easier, more productive, and more fun. This includes features like Dev Services, a solution pioneered by Quarkus to handle the automatic provisioning of external services using containers.
  • Generative AI. Extending integration capabilities for Spring Boot applications to include AI observability and evaluation platforms, AI inference services, and AI document processors.
  • Kubernetes. Simplifying the configuration and deployment of Spring Boot applications to Kubernetes, including the build of multi-architecture container images, support for the Service Binding specification, and automatic generation of Kubernetes manifests.
  • Multitenancy. Offering built-in support for multitenant applications, including web, data, security, and configuration aspects.
  • Observability. Providing unified observability for Spring Boot applications, combining full support for OpenTelemetry API, SDK, and Instrumentation with full support for Micrometer API and Instrumentation. Currently, using OpenTelemetry in Spring Boot is not straightforward. The goal is to provide a single, unified observability solution for Spring Boot applications that can give you the best of both worlds: the standardization and ubiquity of OpenTelemetry combined with the robustness and stability of Micrometer.

The framework is currently in active development and working towards the first stable release planned for early 2026. Many of the core features are already available, including Arconia Dev Services.

Why Arconia Dev Services?

Let's face it: wiring up local infrastructure is tedious and time-consuming. You often have to write a lot of boilerplate code and configuration to get everything working. This can lead to frustration, especially when you're trying to focus on building features rather than setting up infrastructure.

Arconia Dev Services solve this by providing automatic, containerized services for development and testing. Here's the beauty of it: add a single dependency, and you get a fully managed instance of your desired service spun up for you: no configuration, no code changes, no headaches.

This behaviour should feel familiar since it's how Spring Boot auto-configuration works. You add a dependency, and Spring Boot configures everything for you. Arconia Dev Services extend this concept to external services, making it incredibly easy to get started.

๐Ÿ™
I would like to thank the Quarkus team for pioneering this concept with their Quarkus Dev Services, showing how great the Java developer experience could be.

Arconia Dev Services leverage Testcontainers under the hood, but with a twist. Instead of requiring you to write boilerplate code to define and manage containers, Arconia detects what services your application needs based on the dependencies you include. It then automatically starts and configures those services when you run your application or tests. That's made possible by building on top of Spring Boot's support for development-time services with Testcontainers, responsible for managing the lifecycle of containers as beans, and determining the connection details.

๐Ÿ™
Thanks to the Spring Team for introducing development-time services in Spring Boot 3.1. Without that feature, Arconia Dev Services wouldn't be possible!

Dev Services work seamlessly with your existing development workflow. There's no need to change how you run your applications or tests. Once you add the appropriate Arconia Dev Service dependency, you can focus on building features while Arconia handles the plumbing.

At this point, you might be wondering how Arconia Dev Services compare to Spring Boot's native Testcontainers support. I'll get to it in a moment, but first, let's have a look at a practical example.

Arconia Dev Services for PostgreSQL

Let's build a practical example to demonstrate how Arconia Dev Services can simplify your local development experience. We'll create a simple Spring Boot application that uses Spring Data JDBC to interact with a PostgreSQL database, with Flyway managing our database migrations.

The complete source code for this example is available on GitHub.

1. Project Setup

Start by creating a new Spring Boot project. You can use the Spring Initializr or set it up manually. From the Spring Initializr, choose the following options: Spring Web, Spring Data JDBC, PostgreSQL, and Flyway.

For this example, I'll use Gradle and Java 25. Here's how the dependencies section of your build.gradle file should look:

dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-web'
  implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
  implementation 'org.flywaydb:flyway-core'
  implementation 'org.flywaydb:flyway-database-postgresql'
  runtimeOnly 'org.postgresql:postgresql'
    
  testImplementation 'org.springframework.boot:spring-boot-starter-test'
  testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

That's a standard Spring Boot setup for an application of this type. Now, on top of that, we add the Arconia Dev Service for PostgreSQL. You could specify the version directly in the dependency declaration, but I recommend using a BOM to manage versions consistently across your project:

dependencies {
  testAndDevelopmentOnly 'io.arconia:arconia-dev-services-postgresql'
}

dependencyManagement {
  imports {
    mavenBom "io.arconia:arconia-bom:0.17.1"
  }
}
โš ๏ธ
Notice the testAndDevelopmentOnly scope for the Arconia Dev Service dependency. This ensures the service is only available during development and testing, and is completely excluded from production builds: exactly what you want for a development tool.

You can optionally add the Spring Boot DevTools dependency for live-restart support during development:

dependencies {
  developmentOnly 'org.springframework.boot:spring-boot-devtools'
}

Here's where it gets interesting: when DevTools is present, Arconia keeps the PostgreSQL container running between code changes so you don't have to wait for it to restart every time. This makes the development experience much smoother.

๐Ÿ’ก
If you're using Maven instead of Gradle, check out the Dev Services with Maven section in the Arconia Dev Services documentation for the equivalent configuration.

2. Define the Domain Model

Let's create a simple Book record that represents our core domain:

record Book(@Id Long id, String title) {}

Spring Data JDBC encourages the use of immutable data classes, and Java records are a perfect fit for that. The @Id annotation marks the primary key field.

3. Create the Repository

Spring Data offers a repository abstraction that makes data access straightforward. Here's how to define a repository for our Book entity:

interface BookRepository extends ListCrudRepository<Book, Long> {}

As you can see, there's no database-specific code here. Spring Data JDBC handles the SQL generation and mapping automatically, while Arconia ensures there's a database ready to connect to.

4. Implement the REST Controller

Now let's expose the book data through a simple HTTP API:

@RestController
@RequestMapping("/books")
class BookController {
  private final BookRepository bookRepository;

  BookController(BookRepository bookRepository) {
    this.bookRepository = bookRepository;
  }

  @GetMapping
  List<Book> getBooks() {
    return bookRepository.findAll();
  }

  @PostMapping
  Book createBook(@RequestBody Book book) {
    return bookRepository.save(book);
  }

  @GetMapping("/{id}")
  Optional<Book> getBookById(@PathVariable("id") Long id) {
    return bookRepository.findById(id);
  }
}

This controller provides endpoints to create and retrieve books. The data persistence is delegated to the BookRepository, which interacts with the PostgreSQL database.

5. Database Schema with Flyway

In a real application, you would typically use a tool like Flyway to manage your database schema.

Create a Flyway migration file (src/main/resources/db/migration/V1__Create_book_table.sql) to set up your database schema:

CREATE TABLE book (
  id BIGSERIAL PRIMARY KEY NOT NULL,
  title VARCHAR(255) NOT NULL
);

Each migration represents a discrete change to your database schema and is controlled through versioned SQL scripts. By default, the naming convention for Flyway migration files is V<version>__<description>.sql. Spring Boot auto-configures Flyway to run these migrations on application startup. If the migrations have already been applied, Flyway will skip them.

6. Run the Application

It's time to see everything in action. Fire up your app using the standard Spring Boot command for Gradle:

./gradlew bootRun

Or, if you prefer using the Arconia CLI:

arconia dev

When you run the application, you'll notice several things happening in the logs:

  1. Arconia detects the application is running in development mode and activates the dev profile.
  2. Arconia automatically starts a PostgreSQL container using Testcontainers that will keep running as long as your application is running. If you have Spring Boot DevTools enabled, the services will keep running even across code changes, so you don't have to wait for it to restart every time.
  3. Spring Boot detects the PostgreSQL container and configures a DataSource to connect to it automatically. That means you don't need to configure explicitly the spring.datasource.url, spring.datasource.username, and spring.datasource.password properties.
  4. Flyway runs the migration scripts to set up the database schema.
  5. Finally, your application starts up and is ready to handle requests.

By default, Arconia will provision a PostgreSQL container using the postgres image from Docker Hub with the default username, password, and database name all set to test. You can customize these settings through application properties if needed, but for most development scenarios, the defaults work perfectly.

Arconia also lets you define SQL scripts for Testcontainers to run when the database starts, which is useful for initialization tasks only needed during development or testing. You can find all the configuration options in the PostgreSQL Dev Service documentation.

7. Call the Application

Let's verify the application is working as expected. For this example, I'll use httpie, a command-line HTTP client that makes it easy to interact with HTTP APIs.

First, create a new book:

http :8080/books title="The Hitchhiker's Guide to the Galaxy"

Then, retrieve the list of books:

http :8080/books

Finally, get a specific book by its ID:

http GET :8080/books/1

You should see your data being persisted correctly in the PostgreSQL database and retrieved through the API.

๐Ÿ’ก
If you're running the application from IntelliJ IDEA, I recommend checking the Spring Debugger plugin. When you run the application in debug mode, it will automatically detect the PostgreSQL container and let you inspect its state directly from the IDE without any manual configuration.

8. Integration Testing

Let's not forget about testing. Integration tests are crucial for ensuring your application works correctly with the database. Arconia ensures that the Dev Services are available during tests as well, all without any extra configuration.

As an example, here's a simple integration test for our application:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class ApplicationTests {

	@Autowired
	private WebTestClient webTestClient;

	@Test
	void createBook() {
		webTestClient
			.post()
			.uri("/books")
			.bodyValue(new Book(null, "The Decameron"))
			.exchange()
			.expectStatus().isOk()
			.expectBody(Book.class)
			.value(book -> {
				assertThat(book.id()).isNotNull();
				assertThat(book.title()).isEqualTo("The Decameron");
			});
	}

}

Under the hood, Arconia will start a PostgreSQL container for the test context, and Spring Boot will configure the datasource to connect to it. Once the tests complete, the container will be automatically stopped and removed.

You can run the tests using Gradle:

./gradlew test

Or with the Arconia CLI:

arconia test
๐Ÿงช
If you'd like to learn more about the most effective ways of testing Spring Boot applications, I recommend you check out the Testing Spring Boot Applications Masterclass by Philip Riecks. And if you're struggling with slow tests, Philip has created an open-source tool to help you analyse and accelerate them: the Spring Test Profiler.

Arconia vs. Spring Boot Development-time Services

Spring Boot 3.1 introduced native support for Testcontainers, including the ability to automatically start containers for databases and other services during development and testing. You might be wondering how Arconia Dev Services compare to this built-in functionality.

Let's consider the example above with PostgreSQL and imagine we remove the Arconia Dev Service dependency and instead rely solely on Spring Boot's native support. First, you would need to add these dependencies to the project:

dependencies {
  testImplementation 'org.springframework.boot:spring-boot-testcontainers'
  testImplementation 'org.testcontainers:postgresql'
}

Notice how the dependencies are included to the testImplementation scope, meaning that the feature will only be available in test mode.

If using Spring Boot DevTools, you would need to change the scope of the dependency from developmentOnly to testAndDevelopmentOnly:

dependencies {
  testAndDevelopmentOnly 'org.springframework.boot:spring-boot-devtools'
}

Next, you would create a test application class in the test classpath (e.g., src/test/java/com/example/demo/TestApplication.java) with a main method that bootstraps the main application class (the one with the @SpringBootApplication annotation) and activates the TestcontainersConfiguration class:

public class TestApplication {

  public static void main(String[] args) {
    SpringApplication.from(Application::main)
      .with(TestcontainersConfiguration.class)
      .run(args);
  }

}

Then, you would need to create a configuration class (e.g., src/test/java/com/example/demo/TestcontainersConfiguration.java) that defines a bean for the PostgreSQL container and marks it with the @ServiceConnection annotation. Optionally, if you're using Spring Boot DevTools, you would also need to add the @RestartScope annotation to support live restart:

@TestConfiguration(proxyBeanMethods = false)
class TestcontainersConfiguration {

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

}

If you want the PostgreSQL container to be provisioned when running a certain integration test, you would need to annotate the test class with @Import to import the configuration class containing the container bean definition:

@SpringBootTest
@Import(TestcontainersConfiguration.class)
class DemoApplicationTests {
  ...
}

Finally, you would need to change your development workflow. Instead of running the application from the main class, you would need to run it from the test application class you created earlier. This is necessary to ensure that the TestcontainersConfiguration class is activated and the PostgreSQL container is started, since the Testcontainers support is only active in the test classpath.

So, instead of running the application with the standard command (./gradlew bootRun or ./mvnw spring-boot:run), you would need to run it using a special command that runs the Spring Boot application from the test classpath:

./gradlew bootTestRun

Or with Maven:

./mvnw spring-boot:test-run

If you're running the application from an IDE, you would need to create a separate run configuration that runs the TestApplication class instead of the main application class. IntelliJ IDEA and Visual Studio Code both detect the main method in the test classpath, but it's not the default run configuration. So you would need to select it explicitly when running the application.

You can think of Arconia Dev Services as a higher-level feature built on top of Spring Boot's Testcontainers support for development-time services. It abstracts away all the boilerplate code and configuration required to set up and manage containers, aiming at providing the most seamless developer experience possible when working with Spring Boot applications.

I hope the Spring Boot project will eventually offer a similar experience to Arconia Dev Services natively. Until then, Arconia Dev Services can fill that gap and provide a more streamlined experience for developers. I have suggested this feature to the Spring Boot team. If you're interested in seeing it implemented, please upvote the feature request on GitHub.

Conclusion

In this article, I introduced you to Arconia Dev Services and demonstrated how they can enhance the developer experience by automatically provisioning and managing local infrastructure for Spring Boot applications. The key takeaway is that you can now add a single dependency to your project and have everything work out of the box, without any boilerplate code or configuration. Furthermore, you don't need to change your development workflow or how you run your applications and tests.

If your projects are already using Spring Boot development-time services with Docker Compose or Testcontainers, you can adopt Arconia Dev Services incrementally as they can co-exist in the same application. You can start by adding the Arconia Dev Service dependencies for the services you want to manage automatically, while keeping your existing Docker Compose or Testcontainers setup for any other services or custom configurations. Over time, you can migrate more services to be managed by Arconia Dev Services as needed.

Currently, Arconia offers Dev Services for data stores (MariaDB, MongoDB, MongoDB Atlas, MySQL, Oracle, Oracle XE, PostgreSQL, Redis), event brokers (Artemis, Kafka, RabbitMQ), Docling, Grafana LGTM/OpenTelemetry, Ollama, Phoenix. More services are planned for the future. You can find the complete list of available services in the Arconia Dev Services documentation.

๐Ÿ™
Many thanks to K. Siva Prasad Reddy and Bs Mahi for not only contributing some of the Dev Services modules, but also for sharing feedback on the Arconia contribution process. I really appreciate them taking the time and being the first contributors to this open-source project!

Stay tuned for more articles about Arconia and its features. In the coming weeks, I'll publish more tutorials and deep dives into other aspects of the framework, such as the observability features with OpenTelemetry, multitenancy patterns, and AI document processing with Docling.

Are you using Arconia Dev Services? What's your current experience with setting up local infrastructure for Spring Boot applications? I'd love to hear from you! Share your experience on Bluesky or LinkedIn. And if you'd like to contribute to the Arconia framework, feel free to reach out on our Github project!

Cover picture from Pexels.