Home > Enterprise >  Spring Boot create @Bean based on @Values
Spring Boot create @Bean based on @Values

Time:10-14

I want to get values from my application.properties from spring.datasource.* fields but those fields are null.

Here is what I'm doing:

@Configuration
@ComponentScan
public class DatabaseConfig {

@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;

@Bean(name = "database_url")
public String getDatabaseUrl() {
    return url "?user=" username "&password=" password;
}
}

application.properties

spring.datasource.url=jdbc:postgresql://db:5432/endlessblow_db
spring.datasource.username=kuba
spring.datasource.password=pass
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.platform=postgres
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect

this db in url is my docker postgre container host and it works fine.

EDIT DatabaseConnection.java

public class DatabaseConnection {

    private String databaseUrl;

    @Autowired
    void setDatabaseUrl(@Qualifier("database_url") String databaseUrl) {
        this.databaseUrl = databaseUrl;
    }

    private static DatabaseConnection instance;
    private Connection connection;

    private DatabaseConnection() {
        try {
            Class.forName("org.postgresql.Driver");
            this.connection = DriverManager.getConnection(databaseUrl);
        } catch (Exception ex) {
            System.out.println("Database Connection Creation Failed : "   ex.getMessage());
        }
    }


    public Connection getConnection() {
        return connection;
    }

    public static DatabaseConnection getInstance() throws SQLException, URISyntaxException, IOException {
        if (instance == null) {
            instance = new DatabaseConnection();
        } else if (instance.getConnection().isClosed()) {
            instance = new DatabaseConnection();
        }
        return instance;
    }
}

What's wrong with this code? Thank you!

CodePudding user response:

For some reasons @Value annotated fields are not initialized I guess. try sending values as @Bean method params.

@Configuration
@ComponentScan
public class DatabaseConfig {

 @Bean(name = "database_url")
 public String getDatabaseUrl(@Value("${spring.datasource.url}") String url,
  @Value("${spring.datasource.username}")String username,
  @Value("${spring.datasource.password}") String password
  ) {
    return url "?user=" username "&password=" password;
 }
}

CodePudding user response:

String is immutable class, meaning each time a new String is created normally a new String might be created in the string pool and a new reference might be returned.

For this reason you can't have String object as a bean in your application context.

@Bean(name = "database_url")
public String getDatabaseUrl() {  <----------------The return type of String is wrong
    return url "?user=" username "&password=" password;
}

So just create a custom object in this @Bean method which could be transferred and used in the application context

Why not return a DatabaseConnection from that @Bean method this would seem the optimal solution in your problem.

CodePudding user response:

You have to create a new file where you 2st read data from property file

@Configuration
@Getter
@Setter
@ConfigurationProperties(prefix = "spring.datasource")
public class DatabaseLoginProperties{
    private String url;
    private String username;
    private String password;
}

----Now above value you can uses in your java file -------------------

@Configuration
public class DatabaseConfig {
    @Autowired
    private DatabaseLoginProperties databaseLoginProperties;
    @Bean
    public String getDatabaseUrl() {
        return databaseLoginProperties.getUrl() "?user=" databaseLoginProperties.getUsername() "&password=" databaseLoginProperties.getPassword();
    }
}
  • Related