Community   SpringSource   Projects    Downloads    Documentation    Forums    Training   Exchange   Blogs

Go Back   Spring Community Forums > Core Spring Projects > AOP (Aspect Oriented Programming)

Reply
 
Thread Tools Display Modes
  #1  
Old Jan 5th, 2006, 01:05 PM
mpilquist mpilquist is offline
Junior Member
 
Join Date: Jan 2006
Posts: 7
Default Trouble with @Configurable and Hibernate 3 Annotations

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.
Reply With Quote
  #2  
Old Jan 6th, 2006, 03:54 AM
Rod Johnson Rod Johnson is offline
Senior Member
Spring Team
 
Join Date: Aug 2004
Location: San Mateo, CA
Posts: 1,264
Default

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
Reply With Quote
  #3  
Old Jan 6th, 2006, 08:05 AM
mpilquist mpilquist is offline
Junior Member
 
Join Date: Jan 2006
Posts: 7
Default

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)
Reply With Quote
  #4  
Old Jan 6th, 2006, 10:21 AM
Rod Johnson Rod Johnson is offline
Senior Member
Spring Team
 
Join Date: Aug 2004
Location: San Mateo, CA
Posts: 1,264
Default

Ouch: this is nastier. Will investigate possible resolutions.
__________________
Rod Johnson - GM, SpringSource Division, VMware
http://www.springsource.com
Spring From the Source
Reply With Quote
  #5  
Old Jan 18th, 2006, 09:18 AM
dickelberry dickelberry is offline
Junior Member
 
Join Date: Oct 2005
Location: Copenhagen, Denmark
Posts: 7
Question Have same exact problem

Have same exact problem is there any possible solution to this problem?

Regards

dickelberry
Reply With Quote
  #6  
Old Jan 18th, 2006, 10:54 AM
mpilquist mpilquist is offline
Junior Member
 
Join Date: Jan 2006
Posts: 7
Default

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.
Reply With Quote
  #7  
Old Jan 19th, 2006, 05:18 AM
SKI_BUM SKI_BUM is offline
Junior Member
 
Join Date: Sep 2004
Location: Århus, Denmark
Posts: 10
Thumbs up Found a solution

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>
Here's the Category class:
Code:
@Entity
...
@Configurable("category")
public class Category implements Serializable {
        .... 
	// --- Business logic dependencies
	private transient MyService myService;

	public void setMyService(MyService myService) {
		this.myService = myService;
	}
}
The Spring Bean configuration for category looks like the following:
Code:
<bean id="category" class="com.test.Category" lazy-init="true">
	<property name="myService" ref="myService"/>
</bean>
The CategoryDaoImpl looks like the following:
Code:
public class CategoryDaoImpl implements CategoryDao {
    public CategoryDaoImpl(SessionFactory sessionFactory) {
	setSessionFactory(sessionFactory);
    }
    ...
}
The Dao's bean configuration looks like the following:
Code:
<bean id="categoryDao" class="com.test.CategoryDaoImpl">
	<constructor-arg><ref local="sessionFactory"/></constructor-arg>
</bean>
Since I'm using Method injection in MyServiceImpl the dependency to CategoryDao is expressed using an empty implementation of the dependency method getCategoryDao():
Code:
public class MyServiceImpl implements MyService {
    private CategoryDao categoryDao;
    ...

    public void getCategoryDao() {
       return null;
    }
     ...
}
The configuration of the MyServiceImpl looks like the following:
Code:
<bean id="myService" class="com.test.MyServiceImpl">
	<lookup-method name="getCategoryDao" bean="categoryDao"/> 
</bean>
I hope this helps. If there is a better way to do it, please post the solution
__________________
/Jeppe

Last edited by SKI_BUM; Jan 20th, 2006 at 05:17 AM.
Reply With Quote
  #8  
Old Feb 2nd, 2006, 11:03 PM
DFielder DFielder is offline
Member
 
Join Date: Jan 2006
Posts: 43
Question Dependency injection on a Hibernate-loaded entity

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"/>
Here's the beginning of my session factory configuration:

Code:
<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
		depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect">
Here's the Hibernate loaded domain object I'm trying to inject into:

Code:
@Entity
@Configurable("license")
public class License extends DAFEntity
{
    private transient CryptoService cryptoService = null;

    public void setCryptoService(CryptoService cryptoService)
    {
        this.cryptoService = cryptoService;
    }
}
Reply With Quote
  #9  
Old Feb 3rd, 2006, 12:01 AM
mpilquist mpilquist is offline
Junior Member
 
Join Date: Jan 2006
Posts: 7
Default

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.
Reply With Quote
  #10  
Old Feb 3rd, 2006, 12:19 AM
DFielder DFielder is offline
Member
 
Join Date: Jan 2006
Posts: 43
Default

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
to the VM options under the Run and Debug commands in Eclipse after putting the aspectjweaver.jar file in the lib directory.

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!
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -5. The time now is 10:54 PM.


Contegix provides first-class managed hosting and partial sponsorship of these forums.

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.