2011-11-09 16 views
9

Używam następujących do wiosny 3.1 konfiguracji:Wiosna: środowisko niewtryskiwaną

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

problem jest, że zmienna env nie jest wstrzykiwany i zawsze ma wartość null.

Nie zrobiłem nic o konfiguracji środowiska, ponieważ nie wiem, czy jest to potrzebne i jak to zrobić. Spojrzałem na przykład w szklarni i nie znalazłem nic specjalnie dla środowiska. Co należy zrobić, aby wstrzyknąć env?

odpowiednie pliki:

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

} 

w applicationContext.xml, to tylko dwie importowane plików XML do pamięci podręcznej config i Cassandry, więc to nie może być ważne.

+0

Czy używasz serwera zgodnego z Java EE? – maks

Odpowiedz

1

Jeśli nie używasz pełnego kompatybilnego serwera Java EE, musisz dodać javax.inject.jar do ścieżki klasy projektu, aby dodać obsługę @Inject. Możesz także spróbować użyć natywnej adnotacji sprężynowej @Autowired.

+0

Dzięki, Maks, inject.jar tam jest. Ten projekt korzystał z konfiguracji xml, a obsługa adnotacji działała dobrze. Próbuję zobaczyć, jak to jest z 3.1 i nie może przejść tej przeszkody. To musi być coś, czego nie mogę wymyślić. – jfd

+0

Hmm, próbowałem użyć @inject ze środowiskiem na wiosnę 3.1 i działa dobrze. Proszę, pokaż swoją konfigurację xml, jeśli to możliwe. – maks

+0

Witaj, Maks. Aktualizuję oryginał z większą liczbą plików. nie wiem jak tu coś dodać. dzięki – jfd

1

@jfd,

ja nie od razu widzę nic złego w konfiguracji, co mogłoby spowodować awarię wstrzyknąć środowiska.

Jeśli zaczynasz od zera pustą klasą @Configuration, a następnie @Inject the Environment, czy to działa?

Jeśli tak, to w którym momencie zaczyna się to nie udać?

Czy byłbyś skłonny ograniczyć przykład do najmniejszej możliwej konfiguracji i przesłać go jako projekt reprodukcyjny? Poniższe instrukcje ułatwiają to: https://github.com/SpringSource/spring-framework-issues#readme

Dzięki!

+0

dzięki Chris. kiedy usuwam wszystko i stopniowo dodam je z powrotem. Zauważyłem, że przyczyną problemu jest secrityConfig.java. Nadal próbuj zrozumieć, dlaczego. ale potem utknąłem na innym problemie, że hibernacja narzeka "Nie znaleziono klasy dialektu: MYSQL", która nie była problemem w xml. więc myślę, że część emf/transakcja nadal nie jest poprawna – jfd

+0

To jest zbyt subtelne. Odkryłem, że muszę wywołać wszystkie właściwości dodatkowe, jeśli istnieje, lub cały postConstruct. czy to prawda? Inną rzeczą, którą dostałem, jest załadowanie niektórych plików konfiguracyjnych, a niektóre z nich nigdy nie skanują pakietu, więc nie działa autowire, ponieważ niektóre pliki konfiguracyjne nigdy nie zostały wywołane. – jfd

+0

Cześć Chris, myślę, że problem może dotyczyć bezpieczeństwa wiosennego, jak się dowiedziałem. – jfd

2

Problem polega na bezpieczeństwie sprężystym dla funkcji zapamiętaj mnie. jeśli wezmę tę linię <code> <remember-me data-source-ref="dataSource" /> </code> na zewnątrz. wszystko dziala. jeśli ta linia przedstawia, spróbuje wczytać bazę danych zanim cokolwiek innego i env nigdy nie zostanie wstrzyknięte.

1

Wykryłem podobny błąd dla mojego projektu, jak wspomniano here. Odkryłem również, że wywołanie właściwości dodatkowych jest niezbędne do uzyskania właściwości sessionFactory. ... i tak, używam także Spring Security (co może być źródłem problemu).

Moja przypisana klasa @Configuration używa @ComponentScan dla pakietów zawierających DAO oparte na Hibernacji i metodę adnotacji @Bean do tworzenia właściwości SessionFactory używanej przez DAO. W czasie wykonywania zgłaszany jest wyjątek, o którym nie wspomniano, że "sessionFactory" lub "hibernateTemplate". Wygląda na to, że DAO są konstruowane przed utworzeniem SessionFactory. Jednym ze sposobów obejścia tego problemu było ponowne umieszczenie dyrektywy skanowania komponentu w pliku XML() i zastąpienie @ComponentScan @importResource tego pliku.

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

także interesujący fakt: jeśli @ComponentScan wliczono ustawić punkt przerwania w metodzie SessionFactory() nigdy nie został osiągnięty!

+0

Poddałem ten problem, umieszczając plik konfiguracyjny tylko do skanowania i wczytałem go jako ostatni (używając @Import (xxx.class)). podczas przechodzenia do konfiguracji Java należy zwrócić szczególną uwagę na: 1) zaległości lub po wywołaniu wywołań funkcji; 2) enum i źródło ścieżek klas innych niż łańcuchy; 3) środowisko naturalne inne niż stary sposób własności itp. Niektóre z nich powinny być traktowane w maszynie wiosennej, jak rzeczy pospolitej. – jfd

1

Miałem również podobny problem z aplikacją wiosenno-społecznościową.

Po przekonwertowaniu poziomu pola @Inject na wstrzyknięcie poziomu konstruktora zadziałało.

5

Nie wiem dlaczego, ale przy użyciu adnotacji @Resource zadziałał dla mnie. @Autowired zawsze zwracał wartość null.