Spring 3.1 configuration: environment not injected

2020-04-02 08:54发布

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.

6条回答
闹够了就滚
2楼-- · 2020-04-02 08:55

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.

查看更多
够拽才男人
3楼-- · 2020-04-02 08:56

Not sure why, but using the @Resource annotation worked for me. @Autowired always returned null.

查看更多
对你真心纯属浪费
4楼-- · 2020-04-02 09:04

I also had the similar issue with spring-social-sample app.

After I converted field level @Inject to constructor level inject it worked.

查看更多
乱世女痞
5楼-- · 2020-04-02 09:08

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.

查看更多
可以哭但决不认输i
6楼-- · 2020-04-02 09:10

@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!

查看更多
做自己的国王
7楼-- · 2020-04-02 09:12

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.

@Configuration
//@ComponentScan(basePackages = "de.webapp.daocustomer", excludeFilters = {@ComponentScan.Filter(Configuration.class), @ComponentScan.Filter(Controller.class)})
@ImportResource({"classpath*:componentScan.xml","classpath*:properties-config.xml","classpath*:security-context.xml"})
public class AppConfig
{
...
@Bean
public SessionFactory sessionFactory() throws Exception
{
    AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean();
    bean.setDataSource(dataSource());
    bean.setPackagesToScan(new String[] {"de.webapp"});
    bean.setHibernateProperties(hibernateProps());
    bean.afterPropertiesSet();
    return bean.getObject();
}

Also interesting fact: if @ComponentScan is included, a breakpoint set in method sessionFactory() was never reached !

查看更多
登录 后发表回答