#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 в уровень конструктора, это сработало.