I am using the following for the spring 3.1 configuration:
@Configuration
@EnableTransactionManagement
public class DataConfig {
@Inject
private Environment env;
@Inject
private DataSource dataSource;
// @Bean
public SpringLiquibase liquibase() {
SpringLiquibase b = new SpringLiquibase();
b.setDataSource(dataSource);
b.setChangeLog("classpath:META-INF/db-changelog-master.xml");
b.setContexts("test, production");
return b;
}
@Bean
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean b = new LocalContainerEntityManagerFactoryBean();
b.setDataSource(dataSource);
HibernateJpaVendorAdapter h = new HibernateJpaVendorAdapter();
h.setShowSql(env.getProperty("jpa.showSql", Boolean.class));
h.setDatabasePlatform(env.getProperty("jpa.database"));
b.setJpaVendorAdapter(h);
return (EntityManagerFactory) b;
}
@Bean
public PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
PersistenceExceptionTranslationPostProcessor b = new PersistenceExceptionTranslationPostProcessor();
// b.setRepositoryAnnotationType(Service.class);
// do this to make the persistence bean post processor pick up our @Service class. Normally
// it only picks up @Repository
return b;
}
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager b = new JpaTransactionManager();
b.setEntityManagerFactory(entityManagerFactory());
return b;
}
/**
* Allows repositories to access RDBMS data using the JDBC API.
*/
@Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource);
}
@Bean(destroyMethod = "close")
public DataSource dataSource() {
BasicDataSource db = new BasicDataSource();
if (env != null) {
db.setDriverClassName(env.getProperty("jdbc.driverClassName"));
db.setUsername(env.getProperty("jdbc.username"));
db.setPassword(env.getProperty("jdbc.password"));
} else {
throw new RuntimeException("environment not injected");
}
return db;
}
}
the issue is that the variable env
is not injected and is always null.
I have not done anything about the Environment setup since I do not know if it's needed or how to. I looked at the greenhouse example and i did not find anything specifically for Environment. What should I do to make sure the env
is injected?
The related files:
// CoreConfig.java
@Configuration
public class CoreConfig {
@Bean
LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
/**
* Properties to support the 'standard' mode of operation.
*/
@Configuration
@Profile("standard")
@PropertySource("classpath:META-INF/runtime.properties")
static class Standard {
}
}
// the Webconfig.java
@Configuration
@EnableWebMvc
@EnableAsync
// @EnableScheduling
@EnableLoadTimeWeaving
@ComponentScan(basePackages = "com.jfd", excludeFilters = { @Filter(Configuration.class) })
@Import({ CoreConfig.class, DataConfig.class, SecurityConfig.class })
@ImportResource({ "/WEB-INF/spring/applicationContext.xml" })
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**").addResourceLocations(
"/images/");
}
@Bean
public BeanNameViewResolver beanNameViewResolver() {
BeanNameViewResolver b = new BeanNameViewResolver();
b.setOrder(1);
return b;
}
@Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver b = new InternalResourceViewResolver();
b.setSuffix(".jsp");
b.setPrefix("/WEB-INF/jsp/");
b.setOrder(2);
return b;
}
@Bean
public CookieLocaleResolver localeResolver() {
CookieLocaleResolver b = new CookieLocaleResolver();
b.setCookieMaxAge(100000);
b.setCookieName("cl");
return b;
}
// for messages
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource b = new ResourceBundleMessageSource();
b.setBasenames(new String[] { "com/jfd/core/CoreMessageResources",
"com/jfd/common/CommonMessageResources",
"com/jfd/app/AppMessageResources",
"com/jfd/app/HelpMessageResources" });
b.setUseCodeAsDefaultMessage(false);
return b;
}
@Bean
public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
SimpleMappingExceptionResolver b = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
mappings.put("org.springframework.web.servlet.PageNotFound", "p404");
mappings.put("org.springframework.dao.DataAccessException",
"dataAccessFailure");
mappings.put("org.springframework.transaction.TransactionException",
"dataAccessFailure");
b.setExceptionMappings(mappings);
return b;
}
/**
* ViewResolver configuration required to work with Tiles2-based views.
*/
@Bean
public ViewResolver viewResolver() {
UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
viewResolver.setViewClass(TilesView.class);
return viewResolver;
}
/**
* Supports FileUploads.
*/
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(500000);
return multipartResolver;
}
// for configuration
@Bean
public CompositeConfigurationFactoryBean myconfigurations()
throws ConfigurationException {
CompositeConfigurationFactoryBean b = new CompositeConfigurationFactoryBean();
PropertiesConfiguration p = new PropertiesConfiguration(
"classpath:META-INF/app-config.properties");
p.setReloadingStrategy(new FileChangedReloadingStrategy());
b.setConfigurations(new org.apache.commons.configuration.Configuration[] { p });
b.setLocations(new ClassPathResource[] { new ClassPathResource(
"META-INF/default-config.properties") });
return b;
}
@Bean
org.apache.commons.configuration.Configuration configuration()
throws ConfigurationException {
return myconfigurations().getConfiguration();
}
// and the SecurityConfig.java
@Configuration
@ImportResource({ "/WEB-INF/spring/applicationContext-security.xml" })
public class SecurityConfig {
@Bean
public BouncyCastleProvider bcProvider() {
return new BouncyCastleProvider();
}
@Bean
public PasswordEncryptor jasyptPasswordEncryptor() {
ConfigurablePasswordEncryptor b = new ConfigurablePasswordEncryptor();
b.setAlgorithm("xxxxxx");
return b;
}
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder b = new org.jasypt.spring.security3.PasswordEncoder();
b.setPasswordEncryptor(jasyptPasswordEncryptor());
return b;
}
}
in the applicationcontext.xml, it only imported two xmls to config cache and cassandra, so it may not be important.
If you don't use full Java EE compatible server you have to include
javax.inject.jar
to your project classpath to add the support of@Inject
. You can also try to use spring's native@Autowired
annotation.Not sure why, but using the @Resource annotation worked for me. @Autowired always returned null.
I also had the similar issue with spring-social-sample app.
After I converted field level @Inject to constructor level inject it worked.
The problem is with the spring security for the remember me feature. if I take this line
<code> <remember-me data-source-ref="dataSource" /> </code>
out. everything works fine. if this line presents, it will try to load the db before anything else and env was never injected.@jfd,
I don't immediately see anything wrong with your configuration that would cause a failure to inject the Environment.
If you start from scratch with an empty @Configuration class, and then @Inject the Environment, does it work for you?
If yes, then at what point does it begin to fail?
Would you be willing to reduce the example down to the smallest possible configuration that fails and submit it as a reproduction project? The instructions here make this as simple as possible: https://github.com/SpringSource/spring-framework-issues#readme
Thanks!
I've detect a similar error for my project as mentioned here. I've also figure out, that a call of afterproperties is necessary to get the sessionFactory. ... and yes, I'm using Spring Security too (which may be the source of the problem).
My @Configuration annotated class uses @ComponentScan for packages containing Hibernate based DAOs and a @Bean annotated method for creating the SessionFactory used by the DAOs. At runtime, a exception is thrown, mentioned that 'sessionFactory' or 'hibernateTemplate' was not found. It seems that the DAOs are constructed before the SessionFactory was created. One workaround for me was to put the component scan directive back in a XML file () and replace @ComponentScan with @ImportResource of that file.
Also interesting fact: if @ComponentScan is included, a breakpoint set in method sessionFactory() was never reached !