views:

224

answers:

1

Hi,

I would like to implement something like a PDO pattern in conjunction with Spring. All domain objects are implemented according to their interface. Each domain object implementation also has an autowired DAO implementation to be able to directly persist the object. (e.g. foo.persist()). This works pretty well, Spring also inserts the proper DAO implementation.

To create those beans I implemented a BeanFactory which just creates the Beans with the aid of Spring. Nevertheless Spring creates Dynamic Proxies and that's where the problem begins. Once I have a many-to-one relationship and, I get two different Dynamic Proxy objects. When persisting, Hibernate tells me:

"could not get a field value by reflection getter".

The interface of the two objects is defined as follows:

public interface Client {
 public Long getId();
 public void setId(Long id);
}

The interface of the user is defined as follows:

public interface User {
 public Long getId();
 public Client getClient();
 public void setClient(Client client);
 public void setId(Long id);
}

The implementation of the User is made according to the JPA, I've used the tag targetEntity to link to the right Implementation of the Client object. Nevertheless persisting doesn't work when inserting a Client object which has been created through Spring. Hope one from your side can help regarding this issue.

Regards

Matthias

+1  A: 

You just don't put your domain objects in the spring context. This is an anti-pattern. There is no need for the domain objects to be managed by spring.

How do you create such an object? By calling context.getBean(), or by injecting them. The former case is ugly (and needs the domain objects to be of scope prototype, the latter just won't work, because the default scope of all beans is singleton - i.e. you will be given the same object every time. Otherwise you will need all your beans to be of scope prototype in order to have a new instance of the domain object.

Separate you DAO from your domain objects - this is a must. The domain objects should be nothing more than annotated POJOs - no interface needed (in the general case).

After telling you what's wrong with your code and how to fix it properly, I'll help you fixing it improperly. But do it only in case the deadline is tomorrow, or it is a huge legacy project are are not entitled to rearchitecture.

If you use (in your applicationContext.xml)

<aop:config proxy-target-class="true">
</aop:config>

Then your classes will be extended by CGLIB (instead of dynamic proxies), and their properties and methods is likely to be preserved. But have in mind this is just wrong.

Bozho
Hi thanks for this answer. How would you proceed if you would like to have the dao implementation inserted into the the domain object, so that you can directly call on the object client.persist() while the implementation will pass the own object to the dao implementation inserted by spring. If I directly create the domain object, the autowiring for the dao which I would like to have as a private property in the domain object will not work.
Matthias Kneissl
Autowire the DAO in the Service layer, not in the domain object.In other words - Autowire the DAO in the class where you call "client.persist()", and call dao.persist(client) instead.
Bozho
Well exactly that's one of the problems. I would like to have the service layer in the object itself, so that the object has a method persist. Something likeClient client = new Client();client.setName("Test");client.persist();is this a pattern which is not usual with Spring and can not be implemented?
Matthias Kneissl
it is a pattern that is wrong :). Plus that - yes, it is not usual with spring. If you really insist on doing it this way, retain your configuration and add the aop:config from my original answer. It should work.
Bozho
oh, and make all your beans in scope prototype.. well, I'd say it again - don't do it this way, it's wrong and will bring you a lot of headaches
Bozho