3

I wanted to make a DatabaseConfig class to setup my database related stuff (EntityManager, DataSource, TransactionManager) and to get the properties I use @Value("${property.name}") on String fields

like

@Configuration
public class DataBaseConfig {
    @Value("${hibernate.connection.username}")
    private String hibernateConnectionUsername;
    @Value("${hibernate.connection.password}")
    private String hibernateConnectionPassword;
    @Value("${hibernate.connection.driver_class}")
    private String hibernateConnectionDriverClass;
    @Value("${hibernate.connection.url}")
    private String hibernateConnectionUrl;
    @Value("${hibernate.dialect}")
    private String hibernateDialect;
    @Value("${hibernate.showSql}")
    private String hibernateShowSql;
    @Value("${hibernate.generateDdl}")
    private String hibernateGenerateDdl;

// All my @Beans
}

The Problem is, that all those Strings are NULL instead of the values of my properties file.

if I put the code into my Application class (the one that has the main and is referenced in SpringApplication.run(Application.class, args);) the value injection works

In short, @Value works in my Application class, but not in my custom @Configuration classes :(

What could be wrong? Or are more informations needed?

UPDATE: More code

Way 1, DB Config and @Value in my Application.java works with and without the PropertySourcesPlaceholderConfigurer

import java.beans.PropertyVetoException;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import com.mchange.v2.c3p0.ComboPooledDataSource;

@Configuration
@ComponentScan
@EnableJpaRepositories
@EnableAutoConfiguration(exclude = HibernateJpaAutoConfiguration.class)
public class Application {
    public static void main(String[] args) throws Throwable {
        SpringApplication.run(Application.class, args);
    }

    // @Bean
    // public static PropertySourcesPlaceholderConfigurer properties() {
    // PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
    // pspc.setLocations(new Resource[] { new ClassPathResource("application.properties") });
    // return pspc;
    // }

    /*****************************/
    @Value("${hibernate.connection.username}")
    private String hibernateConnectionUsername;

    @Value("${hibernate.connection.password}")
    private String hibernateConnectionPassword;

    @Value("${hibernate.connection.driver_class}")
    private String hibernateConnectionDriverClass;

    @Value("${hibernate.connection.url}")
    private String hibernateConnectionUrl;

    @Value("${hibernate.dialect}")
    private String hibernateDialect;
    @Value("${hibernate.showSql}")
    private String hibernateShowSql;
    @Value("${hibernate.generateDdl}")
    private String hibernateGenerateDdl;

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setDatabasePlatform(hibernateDialect);
        boolean generateDdl = Boolean.parseBoolean(hibernateGenerateDdl);
        boolean showSql = Boolean.parseBoolean(hibernateShowSql);
        vendorAdapter.setGenerateDdl(generateDdl);
        vendorAdapter.setShowSql(showSql);

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setDataSource(dataSource());
        factory.setPackagesToScan("xxx");

        return factory;
    }

    @Bean
    public DataSource dataSource() {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(hibernateConnectionUsername);
        dataSource.setPassword(hibernateConnectionPassword);
        try {
            dataSource.setDriverClass(hibernateConnectionDriverClass);
        } catch (PropertyVetoException e) {
            throw new IllegalArgumentException("Wrong driver class");
        }

        dataSource.setJdbcUrl(hibernateConnectionUrl);
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

Way 2 (what i want to have), DB Stuff in its own file (DatabaseConfing.java) does not work regardles of where i have the PropertySourcesPlaceholderConfigurer (Application or DatabaseConfig) as it is always called AFTER the @Beans inside the DatabaseConfig :(

import java.beans.PropertyVetoException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

import com.mchange.v2.c3p0.ComboPooledDataSource;


@Configuration
public class DatabaseConfig {
    @Value("${hibernate.connection.username}")
    private String hibernateConnectionUsername;
    @Value("${hibernate.connection.password}")
    private String hibernateConnectionPassword;
    @Value("${hibernate.connection.driver_class}")
    private String hibernateConnectionDriverClass;
    @Value("${hibernate.connection.url}")
    private String hibernateConnectionUrl;
    @Value("${hibernate.dialect")
    private String hibernateDialect;
    @Value("${hibernate.showSql}")
    private String hibernateShowSql;
    @Value("${hibernate.generateDdl}")
    private String hibernateGenerateDdl;

        // @Bean
        // public static PropertySourcesPlaceholderConfigurer properties() {
        // PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
        // pspc.setLocations(new Resource[] { new ClassPathResource("application.properties") });
        // return pspc;
        // }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setDatabasePlatform(hibernateDialect);
        boolean generateDdl = Boolean.parseBoolean(hibernateGenerateDdl);
        boolean showSql = Boolean.parseBoolean(hibernateShowSql);
        vendorAdapter.setGenerateDdl(generateDdl);
        vendorAdapter.setShowSql(showSql);

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setDataSource(dataSource());
        factory.setPackagesToScan("xxx");

        return factory;
    }

    @Bean
    public DataSource dataSource() {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(hibernateConnectionUsername);
        dataSource.setPassword(hibernateConnectionPassword);
        try {
            dataSource.setDriverClass(hibernateConnectionDriverClass);
        } catch (PropertyVetoException e) {
            throw new IllegalArgumentException("Wrong driver class");
        }
        System.err.println(hibernateConnectionUrl);
        dataSource.setJdbcUrl(hibernateConnectionUrl);
        return dataSource;
    }
}
6
  • Not exactly an duplicate, but I would expect that the accepted solution works for you: stackoverflow.com/questions/17097521/… Commented Nov 16, 2013 at 13:56
  • Look at your container files (context of your app), @Value is processed just to be some sort of container-scoped, you have to add <context:property-placeholder location="classpath:the-path-to-your-property-file" /> into your context file Commented Nov 16, 2013 at 14:07
  • I' already tried to use the PropertySourcesPlaceholderConfigurer, but the placeholder was executed after my beans for the database stuff, regardless. regardless of the location of the code (db or appliction class) Commented Nov 16, 2013 at 14:19
  • Please post the rest of your config including the PropertySourcesPlaceholderConfiguere. Commented Nov 16, 2013 at 21:33
  • i just added more code. Commented Nov 17, 2013 at 9:06

2 Answers 2

9

Instead of your DatabaseConfig add the following application.properties to src/main/resources (and thus remove your DatabaseConfig class)

#DataSource configuration
spring.datasource.driverClassName=<hibernateConnectionDriverClass>
spring.datasource.url=<hibernateConnectionUrl>
spring.datasource.username=<hibernateConnectionUsername>
spring.datasource.password=<hibernateConnectionPassword>

#JPA/HIbernate
spring.jpa.database-platform=<dialect-class>
spring.jpa.generate-ddl=<hibernateGenerateDdl>
spring.jpa.show-sql=<hibernateShowSql>

Replace the < placeholder > with the actual value and spring-boot will take care of this.

Tip remove the C3P0 dependency as Spring will provide you (default) with the tomcat connection pool (which is newer and more activly maintained and despite the name is perfectly usable without/outside Tomcat).

Sign up to request clarification or add additional context in comments.

7 Comments

Are this the properties for the hibernate jpa autoconfigurer?
The spring.jpa properties are, the others are the basic spring jdbc properties (those also work in a plain jdbc environment).
nice, it works, but it seems there is another naming strategy configured by spring. while my old tables where camelcased like my enities they are now lowercase and _ seperated "HelloWorldEntity" -> "hello_world_entity" bit i think i don't care that much, as the project is pretty new and i see no reason to force the other naming strategy
By default the ImprovedNamingStrategy is used but by adding a property spring.jpa.hibernate.naming-strategy o the application.properties that can be overriden.
Thank you very much, are those properties(and others that are used for spring-boot autoconfigure) somewhere documented?
|
1
@Import({ CacheConfig.class, DatabaseConfig.class })
@ComponentScan(excludeFilters = @Filter(Configuration.class))

did the trick.

3 Comments

Where did you add this code? I'm having the same issue with a CacheConfig file I created.
i added this on the Application class
I ran into the same issue, Excluding the Configuration from the ComponentScan seem to solve the non-injection of @value in some configuration file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.