|
#1
|
|||
|
|||
|
I'm trying to use Spring 2.0m1's @Configurable annotation to dependency inject a domain object loaded from Hibernate. Unfortunately, Hibernate is creating a new instance of my entity as part of the creation of the session factory bean. Tracing through the Hibernate code, I found that Hibernate is trying to determine the unsaved value for my entity and since one isn't specified directly, it instantiates a temporary instance and reads the ID property.
And here's where the problem lies. When the temporary instance is created, the AnnotationBeanConfigurer is called but it doesn't have a reference to the BeanFactory yet. Any ideas? Note that if I remove the entity from the annotated classes list and configure an xml mapping for it that defines a unsaved value for the ID property, everything works (since Hibernate doesn't need to instantiate the object). Last edited by mpilquist; Jan 5th, 2006 at 04:28 PM. |
|
#2
|
|||
|
|||
|
Try making your LocalSessionFactoryBean bean definition depend on the AnnotationBeanConfigurer instance with the "depends-on" attribute. This way the aspect will be available before Hibernate gets to do anything at all.
__________________
Rod Johnson - GM, SpringSource Division, VMware http://www.springsource.com Spring From the Source |
|
#3
|
|||
|
|||
|
That worked but now I have another (more complicated) issue. I'm injecting a service into the entity. The service is injected with a DAO and the DAO is injected with the sessionFactory. The problem now is that there is a circular reference. Trying to initialize the sessionFactory causes my service to be injected which eventually causes the same sessionFactory to be injected into my DAO and I get the following exception:
org.springframework.beans.factory.FactoryBeanNotIn itializedException: Error creating bean with name 'sessionFactory': FactoryBean returned null object: probably not fully initialized (maybe due to circular bean reference) |
|
#4
|
|||
|
|||
|
Ouch: this is nastier. Will investigate possible resolutions.
__________________
Rod Johnson - GM, SpringSource Division, VMware http://www.springsource.com Spring From the Source |
|
#5
|
|||
|
|||
|
Have same exact problem is there any possible solution to this problem?
Regards dickelberry |
|
#6
|
|||
|
|||
|
For the time being, I've written hibernate mapping files for the classes that I am injecting. In the mapping file, I specify an unsaved-value on the id. This prevents Hibernate from instantiating my domain object. Not a long term solution of course.
|
|
#7
|
|||
|
|||
|
I've found a solution to the problem. I don't know if it's the most elegant solution, the Spring gurus might know of a better way to solve it.
The solution involves using method injection on the service that's injected into the entity object. In this example I have an entity class Category, which is managed by Hibernate. The Category uses @Configurable to define that it needs an instance of MyService injected into it. MyService depends on a CategoryDao implementation, which depends on a Hibernate SessionFactory. This is a the same circular referece problem that you're experiencing, in the case where Hibernate during SessionFactory creation needs create a test instance of our Entity. I've tried to write down a full sample to make the solution clearer. The SessionFactory is configured using a depends-on to the object created by the <aop:spring-configured/> element, so the annotation aspect is available when the session factory starts initializing: Code:
<aop:spring-configured/> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"> <property name="dataSource"><ref local="dataSource"/></property> <property name="configLocation" value="hibernate.cfg.xml"></property> </bean> Code:
@Entity
...
@Configurable("category")
public class Category implements Serializable {
....
// --- Business logic dependencies
private transient MyService myService;
public void setMyService(MyService myService) {
this.myService = myService;
}
}
Code:
<bean id="category" class="com.test.Category" lazy-init="true"> <property name="myService" ref="myService"/> </bean> Code:
public class CategoryDaoImpl implements CategoryDao {
public CategoryDaoImpl(SessionFactory sessionFactory) {
setSessionFactory(sessionFactory);
}
...
}
Code:
<bean id="categoryDao" class="com.test.CategoryDaoImpl"> <constructor-arg><ref local="sessionFactory"/></constructor-arg> </bean> Code:
public class MyServiceImpl implements MyService {
private CategoryDao categoryDao;
...
public void getCategoryDao() {
return null;
}
...
}
Code:
<bean id="myService" class="com.test.MyServiceImpl"> <lookup-method name="getCategoryDao" bean="categoryDao"/> </bean>
__________________
/Jeppe Last edited by SKI_BUM; Jan 20th, 2006 at 05:17 AM. |
|
#8
|
|||
|
|||
|
Ok, I'm trying to do something similar but I'm not getting the set method called on my domain object - any ideas why this would be the case?
Here's the relevant portions of my application context: Code:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:spring-configured/>
<bean id="license" class="com.company.License" lazy-init="true">
<property name="cryptoService"><ref local="cryptoService"/></property>
</bean>
<bean id="cryptoService" class="com.company.CryptoService" lazy-init="false"/>
Code:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"> Code:
@Entity
@Configurable("license")
public class License extends DAFEntity
{
private transient CryptoService cryptoService = null;
public void setCryptoService(CryptoService cryptoService)
{
this.cryptoService = cryptoService;
}
}
|
|
#9
|
|||
|
|||
|
Did you weave the Spring AspectJ aspect into your entity? Either via compilation with ajc and an aspectlib or with load-time weaving?
I have been using load-time weaving with success. See http://www.eclipse.org/aspectj/doc/n...guide/ltw.html for details. |
|
#10
|
|||
|
|||
|
Good deal - I installed AJDT for Eclipse 3.1 (although I don't think this was required) and added
Code:
-javaagent:WEB-INF/lib/aspectjweaver.jar Is there some way to tell Eclipse to use that VM option for all Run/Debug commands, or do I need to put that into each one that I want to have AspectJ weaving enabled? Thanks a lot for your help! |
![]() |
| Thread Tools | |
| Display Modes | |
|
|