Конфигурация Spring 3.1: среда не введена

#java #spring #configuration #environment

#java #spring #конфигурация #Окружающая среда

Вопрос:

Я использую следующее для конфигурации spring 3.1:

 @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;
    }
}
  

проблема в том, что переменная env не введена и всегда равна null.

Я ничего не делал с настройкой среды, поскольку не знаю, нужно ли это и как. Я просмотрел пример с теплицей и не нашел ничего специально для среды. Что я должен сделать, чтобы убедиться, что env введено?

Связанные файлы:

 // 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;
    }

}
  

в applicationcontext.xml в config cache и cassandra было импортировано только два XML-файла, поэтому это может быть не важно.

Комментарии:

1. Используете ли вы сервер, совместимый с Java EE?

Ответ №1:

Не уверен почему, но использование аннотации @Resource сработало для меня. @Autowired всегда возвращал значение null.

Ответ №2:

Проблема заключается в безопасности spring для функции «запомнить меня». если я уберу эту строку <code> <remember-me data-source-ref="dataSource" /> </code> . все работает нормально. если появится эта строка, она попытается загрузить базу данных перед чем-либо еще, и env никогда не вводился.

Ответ №3:

Если вы не используете сервер, полностью совместимый с Java EE, вам необходимо включить javax.inject.jar в свой проект classpath, чтобы добавить поддержку @Inject . Вы также можете попробовать использовать собственную @Autowired аннотацию spring.

Комментарии:

1. Спасибо, Макс, за inject.jar есть. В этом проекте использовалась конфигурация xml, и управление аннотациями работало нормально. я пытаюсь понять, как это работает с 3.1, и не могу преодолеть это препятствие. Должно быть, что-то упущено, что я не могу понять.

2. Хм, я пытался использовать @inject с Environment в spring 3.1, и это работает нормально. Пожалуйста, покажите вашу конфигурацию xml, если это возможно

3. Привет, Макс, я обновляю оригинал, добавляя в него больше файлов. я не знаю, как сюда что-то добавить. Спасибо

Ответ №4:

@jfd,

Я не вижу сразу ничего неправильного в вашей конфигурации, что могло бы привести к сбою при внедрении среды.

Если вы начинаете с нуля с пустого класса @Configuration, а затем @Inject the Environment, работает ли это для вас?

Если да, то в какой момент начинается сбой?

Не могли бы вы сократить пример до минимально возможной конфигурации, которая завершается сбоем, и представить его в качестве проекта воспроизведения? Приведенные здесь инструкции делают это как можно более простым: https://github.com/SpringSource/spring-framework-issues#readme

Спасибо!

Комментарии:

1. спасибо, Крис. когда я удаляю все и постепенно добавляю их обратно. Я обнаружил, что secrityConfig.java является причиной проблемы. Все еще пытаюсь выяснить, почему. но затем я застрял на другой проблеме, заключающейся в том, что hibernate жаловался на «Класс диалекта не найден: MYSQL», который не был проблемой в xml. итак, я предполагаю, что часть emf / transaction все еще неверна

2. Это слишком тонко. Я обнаружил, что мне нужно вызвать все afterproperties, если таковой имеется, или всю PostConstruct. это правда? еще одна вещь, с которой я столкнулся, — это то, что часть файла конфигурации загружена, а часть никогда, затем они сканируют пакет, поэтому не работает автозапуск, поскольку часть файла конфигурации никогда не вызывалась.

3. Привет, Крис, я думаю, что проблема может быть в spring security, как я выяснил.

Ответ №5:

Я обнаружил аналогичную ошибку для своего проекта, как упоминалось здесь. Я также выяснил, что для получения SessionFactory необходим вызов afterproperties. … и да, я тоже использую Spring Security (что может быть источником проблемы).

Мой аннотированный класс @Configuration использует @ComponentScan для пакетов, содержащих DAO на основе гибернации, и аннотированный метод @Bean для создания SessionFactory, используемого DAO. Во время выполнения генерируется исключение, в котором упоминается, что ‘SessionFactory’ или ‘HibernateTemplate’ не были найдены. Похоже, что DAO создаются до создания SessionFactory. Одним из обходных путей для меня было поместить директиву проверки компонентов обратно в XML-файл () и заменить @ComponentScan на @ImportResource этого файла.

 @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();
}
  

Также интересный факт: если включен @ComponentScan, точка останова, установленная в методе SessionFactory(), никогда не была достигнута !

Комментарии:

1. Я решил эту проблему, поместив файл конфигурации только для сканирования и загрузив его последним (используя @Import (xxx.class )). при переходе к конфигурации java следует обратить внимание на многое: 1) вызовы функций afterproperty или postconstruct; 2) ресурс перечисления и пути к классу, отличный от strings; 3) строка el среды, отличная от старого способа свойства и т.д. Некоторые из них должны обрабатываться в spring-механизме, например, afterproperty.

Ответ №6:

У меня также была аналогичная проблема с приложением spring-social-sample.

После того, как я преобразовал уровень поля @Inject в уровень конструктора, это сработало.