2013-10-17 27 views
12

Tôi đã bắt đầu phát triển một ứng dụng Spring 3.2.4 mới và đang cố gắng sử dụng cấu hình dựa trên Java thay vì các tệp XML như tôi đã sử dụng trong quá khứ. Tuy nhiên, tôi gặp sự cố khi thực hiện chuyển đổi.Cách lấy JNDI bằng cách sử dụng Spring @Configuration thay vì cấu hình XML

Sử dụng XML, tôi sẽ mã nó như sau:

<!-- application datasource --> 
<bean id="dataSource.jndi" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton" lazy-init="true"> 
    <property name="jndiName" value="java:comp/env/jdbc/liment" /> 
</bean> 

<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
</bean> 

<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/> 
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"> 
    <property name="persistenceUnitName" value="persistenceUnit"/> 
    <property name="dataSource" ref="dataSource.jndi"/> 
</bean> 

Tuy nhiên, tôi đang rất nhiều khó khăn cố gắng tìm ra cách để làm điều này trong Java. Tôi đang cố gắng để tái tạo các cấu hình, nhưng chạy vào rắc rối:

@Configuration 
@EnableTransactionManagement 
@EnableJpaRepositories(basePackages={"com.ia"}) 
public class AppConfigJPA { 
    @Bean 
    public DataSource dataSource() { 
     // configure and return the necessary JDBC DataSource 
     JndiObjectFactoryBean dataSource = new JndiObjectFactoryBean(); 
     dataSource.setJndiName("java:comp/env/jdbc/liment"); 
     try { 
      dataSource.afterPropertiesSet(); 
     } catch (IllegalArgumentException | NamingException e) { 
      // rethrow 
      throw new RuntimeException(e); 
     } 
     return (DataSource)dataSource.getObject(); 
    } 

    @Bean 
    public EntityManagerFactory entityManagerFactory(){ 
     LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); 
     emf.setPersistenceUnitName("persistenceUnit"); 
     emf.setDataSource(dataSource()); 
      emf.afterPropertiesSet 
     return emf.getObject(); 
    } 

    @Bean 
    public PlatformTransactionManager transactionManager() { 
     return new JpaTransactionManager(entityManagerFactory()); 
    } 

} 

Tuy nhiên, tôi nhận được thông báo lỗi sau:

Caused by: java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation. 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:142) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.setBeanFactory(PersistenceExceptionTranslationInterceptor.java:117) 
    at org.springframework.data.repository.core.support.PersistenceExceptionTranslationRepositoryProxyPostProcessor.<init>(PersistenceExceptionTranslationRepositoryProxyPostProcessor.java:44) 
    at org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport.setBeanFactory(TransactionalRepositoryFactoryBeanSupport.java:85) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1502) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1470) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521) 
    ... 33 more 

tôi thiếu gì hoặc làm sai?

EDIT

Sau @SotiriosDelimanolis phản ứng, tôi đã sửa đổi mã của tôi để đọc phần sau đây:

@Autowired DataSource dataSource; 
@Autowired EntityManagerFactory entityManagerFactory; 


@Bean 
public JndiObjectFactoryBean dataSource() { 
    // configure and return the necessary JDBC DataSource 
    JndiObjectFactoryBean dataSource = new JndiObjectFactoryBean(); 
    dataSource.setJndiName("java:comp/env/jdbc/josak"); 
    return dataSource; 
} 

@Bean 
public LocalContainerEntityManagerFactoryBean entityManagerFactory(){ 
    LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); 
    emf.setPersistenceUnitName("persistenceUnit"); 
    emf.setDataSource(dataSource); 
    return emf; 
} 

@Bean 
public PlatformTransactionManager transactionManager() { 
    return new JpaTransactionManager(entityManagerFactory); 
} 

Nhưng đang nhận được ngoại lệ Autowired thay vì bây giờ:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: javax.sql.DataSource com.ia.system.configuration.AppConfigJPA.dataSource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:514) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285) 
    ... 31 more 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:988) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:858) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486) 
    ... 33 more 
+0

Bạn có thể xác minh rằng các tài liệu tham khảo trở bởi 'dataSource.getObject();' là 'null'? Điều đó sẽ không xảy ra nếu bạn gọi là 'afterPropertiesSet() '.Và vui lòng đăng theo dõi ngăn xếp lâu hơn. –

+0

@SotiriosDelimanolis Trên thực tế, tôi vừa gặp lỗi trong mã trước khi tôi thấy nhận xét của bạn. Tôi đã quên một cuộc gọi "afterPropertiesSet()" trong thực thểManagerFactory(). Nhưng bây giờ, tôi nhận được một Ngoại lệ khác liên quan đến một dịch giả ngoại lệ kiên trì. –

Trả lời

1

Đây là một thiết kế kỳ lạ (cho PersistenceExceptionTranslator) mà tôi không im trung gian hiểu, nhưng đây là giải pháp.

LocalContainerEntityManagerFactoryBean của bạn là FactoryBean nhưng cũng là PersistenceExceptionTranslator (thực hiện cả hai). Nhưng bạn không đặt LocalContainerEntityManagerFactoryBean vào ngữ cảnh của mình, bạn chỉ nhận được đối tượng được tạo của nó.

Thay vì

@Bean 
public EntityManagerFactory entityManagerFactory(){ 
    LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); 
    emf.setPersistenceUnitName("persistenceUnit"); 
    emf.setDataSource(dataSource()); 
     emf.afterPropertiesSet 
    return emf.getObject(); 
} 

làm

@Bean 
public LocalContainerEntityManagerFactoryBean entityManagerFactory(){ 
    LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); 
    emf.setPersistenceUnitName("persistenceUnit"); 
    emf.setDataSource(dataSource()); 
    return emf; 
} 

@Autowired 
private EntityManagerFactory entityManagerFactory; 

@Bean 
public PlatformTransactionManager transactionManager() { 
    return new JpaTransactionManager(entityManagerFactory); 
} 

mùa xuân sẽ chăm sóc gọi afterPropertiesSet()getObject() để đặt một đậu EntityManagerFactory vào ngữ cảnh.

Về cơ bản, bạn kết thúc với hai hạt, EntityManagerFactoryLocalContainerEntityManagerFactoryBean. Cấu hình JPA của bạn yêu cầu một bean PersistenceExceptionTranslator trong ngữ cảnh. Điều đó sẽ được thỏa mãn bởi LocalContainerEntityManagerFactoryBean.


FYI, bạn có thể làm điều tương tự cho JndiObjectFactoryBean hoặc FactoryBean bất kỳ khác.

+0

JpaTransactionManager đang mong đợi một EntityManagerFactory làm kiểu hàm khởi tạo của nó. Nếu entityManagerFactory() trả về một LocalContainerEntityManagerFactoryBean, làm thế nào để khởi tạo transactionManager()? Tương tự, nếu tôi trả về một JndiObjectFactoryBean từ dataSource(), làm thế nào để thiết lập emf.setDataSource() bằng teh JndiFactoryBean? –

+0

@EricB. Mùa xuân là phép thuật theo cách đó. Nó gọi phương thức '@ Bean' và trả về bean' FactoryBean' được tạo ra thay vì bản thân 'FactoryBean'. –

+0

Tôi không hiểu. Trả lại bean nhà máy làm cho trình biên dịch phàn nàn về 'return new JpaTransactionManager (entityManagerFactory())': 'Hàm tạo JpaTransactionManager (LocalContainerEntityManagerFactoryBean) là undefined' –

20

vui lòng tham khảo bên dưới liên kết -

http://forum.spring.io/forum/spring-projects/container/724356-how-to-use-javaconfig-to-declare-a-jndi-datasource

nguồn dữ liệu cần phải được tạo ra như thế này -

@Bean 
    public DataSource dataSource() { 
     final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup(); 
     dsLookup.setResourceRef(true); 
     DataSource dataSource = dsLookup.getDataSource("jdbc/yourJdbcGoesHere"); 
     return dataSource; 
    } 
+1

'setResourceRef' không cần thiết trong ngữ cảnh này vì JndiDataSourceLookup đặt nó thành true. Mã này chỉ đơn giản là 'new JndiDataSourceLookup(). GetDataSource ("jdbc/yourJdbcGoesHere") ' – Brice

Các vấn đề liên quan