How to use Bean Configuration in Spring Boot with an Example

In this article, let us look at what is spring boot configuration bean and how to use bean in configuration spring boot with an example

Introduction

In our previous articles, we have seen in detail about Dependency Injection in Spring Boot and how we register a class for dependency injection in a Spring Boot application.

We have seen that to register a Class into Spring Dependency Injection, we need to first mark the class as Component or any derivatives of the Component annotation.

But sometimes we may wish to register the objects of any 3rd party Libraries which are not local to our application. Examples such as Database Connections, Rest Clients, Kafka Connections, AWS Cloud Clients etc.

These are libraries which are outside of our application and may not have been marked Components or anything related to spring. We don’t even be able to modify their source code because these are external libraries included into the application via Jar files.

So how do we make Spring Container take care of the object management for such libraries which are outside to our application but are used in our code. In such cases we use Configuration Beans.

In this article, let us look at the approach of Configuration Beans in Spring and how do we do it with some illustrating examples.

What are Spring Configuration Beans

A Configuration Bean is a method that returns an Object of such external libraries which are not part of the Spring application, but will be managed by the Spring Container.

Although we are not tagging the library classes as components inside our application, we tag a method that returns the object of such libraries as a Component and hence will qualify for dependency injection everywhere in our application.

We do this in 3 simple steps –

  1. Create a class and mark it with @Configuration annotation
  2. Create a method that returns the object of the library we want to be object managed and mark it with @Bean annotation
  3. Wherever we want the object of the library to be injected, we use the method name as the bean identifier

Spring Configuration Bean with an Example

To illustrate this, let us assume we have included a new functionality in our Heroes API – one Repository that pulls data from a Mysql database using JDBC Queries.

Now since JDBC library is external to the Spring Boot application and is included as an external JAR file, we never know whether the required classes are already tagged for use in Spring Boot.

Instead we use Spring Configuration Beans to register objects of the library. To connect to the database, we use the JdbcTemplate library of the Spring framework.

Let’s do it following the steps mentioned above –

Creating a @Configuration Class

First we create a class that will contain a method to have these library instance created and returned. This class is marked as Configuration. In our case, the external libraries to connect to is a JdbcTemplate.

Our configuration class looks like below

package com.myjpa.helloapp.config;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
import com.mysql.cj.jdbc.MysqlDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

@Configuration
public class MyExtDbJdbcTemplateConfig {
    public MyExtDbJdbcTemplateConfig() {
        System.out.println("MyExtDbJdbcTemplateConfig object creating");
    }
}

Creating a @Bean method

Second, the method we create will have the library class objects created and returned. This method has the return type of the Type being returned and is marked with a Bean annotation. This means that the method is treated as a Bean and will be marked for Injection.

We will add a new method inside our MyExtDbJdbcTemplateConfig class that returns an object of JdbcTemplate, which will be annotated using the @Bean annotation. The class looks like below –

package com.myjpa.helloapp.config;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
import com.mysql.cj.jdbc.MysqlDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

@Configuration
public class MyExtDbJdbcTemplateConfig {
    public MyExtDbJdbcTemplateConfig() {
        System.out.println("MyExtDbJdbcTemplateConfig object creating");
    }

    @Autowired
    @Qualifier("myExtDbProperties")
    MyExtDbProperties dbProperties;

    @Bean("myExtDbJdbcTemplate")
    public JdbcTemplate myExtDbJdbcTemplate() {
        MysqlDataSource datasource = new MysqlDataSource();
        datasource.setPassword(dbProperties.getPassw());
        datasource.setUser(dbProperties.getUser());
        datasource.setServerName(dbProperties.getServer());
        datasource.setDatabaseName(dbProperties.getDatabase());
        JdbcTemplate jdbcTemplate = new JdbcTemplate(datasource);
        return jdbcTemplate;
    }
}
Configure Application Properties in Spring Boot

For the JdbcTemplate to be created, we need to provide the database details like the Server, Database and the User credentials.

I have created a Class that binds on these configuration values from application.properties file to make things simple. This is done as below –

package com.myjpa.helloapp.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties("mysql.db")
public class MyExtDbProperties {
    private String server;
    private String user;
    private String passw;
    private String database;

    public String getServer() {
        return server;
    }

    public void setServer(String server) {
        this.server = server;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassw() {
        return passw;
    }

    public void setPassw(String passw) {
        this.passw = passw;
    }

    public String getDatabase() {
        return database;
    }

    public void setDatabase(String database) {
        this.database = database;
    }
}
# application.properties file

mysql.db.server=localhost
mysql.db.user=root
mysql.db.passw=abc@123
mysql.db.database=mydb

Injecting the @Bean into other Spring Beans

Third, wherever we want the Object of the Library to be available, we inject the object with a variable. The identifier should match the method name that is marked as Bean and that returns the Object of that Type.

I have created another implementation of the IHeroRepository named JdbcHeroRepository which uses JdbcTemplate and pulls data from the database using SQL queries. The implementation is as below –

package com.myjpa.helloapp.repositories;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public class JdbcHeroRepository implements IHeroRepository {

    private final JdbcTemplate jdbcTemplate;

    public JdbcHeroRepository(@Qualifier("myExtDbJdbcTemplate") JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
        System.out.println("JdbcHeroRepository object creating");
    }

    @Override
    public List<String> getHeroes() {
        return jdbcTemplate.queryForList("select name from heroes", String.class);
    }
}

Now observe that we have declared a class variable jdbcTemplate that is of type JdbcTemplate. Now we assign an injected value of type JdbcTemplate within the constructor using Constructor Injection.

What’s interesting is that we have used a Qualifier to exactly point to what Bean needs to be injected here and the bean id is same as that of the method name we have defined in the Configuration class.

Running the Application

Now when I run this application, I can see the beans created and injected –

Configuration Bean created and Injected into JdbcHeroRepository

When I run this application and hit the getHeroes endpoint – I get data returned from the Mysql database queried via the JdbcTemplate.

package com.myjpa.helloapp.services;

import com.myjpa.helloapp.repositories.IHeroRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

@Service
public class HeroService {
    public HeroService() {
        System.out.println("HeroService object creating");
    }

    @Autowired
    @Qualifier("jdbcHeroRepository")
    private IHeroRepository repository;

    public List<String> getHeroes() {
        return repository.getHeroes();
    }
}

One change I made is that I now made the HeroService require an instance of JdbcHeroRepository by using a Qualifier of the same.

Data is pulled from the Database and returned by the API

Conclusion

In this article, we have looked into the what-if scenario of injecting class objects of libraries which are not a part of Spring application. This is a common and frequently occurring scenario because not every business logic we work on will be internal to our application.

To do this we make use of Configuration Beans, which are methods that return an object of the respective library class.

We have looked into an illustrating example, that demonstrates the use of JdbcTemplate in our Spring application by creating a Configuration Bean and injecting the same.

By using this approach, we let Spring take care of the object management of that class, although it is not a part of the Spring Boot code we are working on. The advantage here is that it simplifies the process of creating and injecting such objects into our code, while still following the concept of Inversion of Control.

Ram
Ram

I'm a full-stack developer and a software enthusiast who likes to play around with cloud and tech stack out of curiosity. You can connect with me on Medium, Twitter or LinkedIn.

Leave a Reply

Your email address will not be published. Required fields are marked *