views:

2840

answers:

4

We have a Hibernate/Spring application that have the following Spring beans:

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" />

When wiring the application together we get the following error when using private constructors in our hibernate entities:

Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: No visible constructors in class 'ourclass'

The entities are typical domain objects such as an Employee or the like.

When changing the constructor's visibility modifier to package (or public) the application runs fine and the entities gets stored/loaded in the database. How do we/can we use private constructors/static factory methods with Spring/Hibernate transaction management?

We use Hibernate annotations to map the entities/relationships. No bean definitions are declared in the applicationContext.xml for the domain class that is related to the problem. It is a pojo that should have a static factory method and a private constructor.

How can we make Hibernate (org.springframework.spring-orm.hibernate3 classes i guess) make use of the static factory method instead of the constructor? Or possibly make it call a private constructor if necessary?

Using the spring factory-method configuration would make sense but the entities are not mapped as beans in our applicationContext.xml. They are only annotated with the @Entity annotation for Hibernate persistence.

Hope this edit clearifies (rather than mystifies) the question. :)

+1  A: 

Do you know about the property "factory-method" ? You can make spring call that method instead of the constructor to instantiate a bean.

BraveSirFoobar
Could you elaborate a bit on how to do this so that the Hibernate transaction manager uses the factory method? It is the transaction manager that throws the exception. And we use Hibernate annotations to map the entities/relationships.
Mattias Holmqvist
Can you post your configuration file, along with the relevant parts of classes ?
BraveSirFoobar
the factory-method is used when instantiating Spring beans. In this case, it seems that the problem is the instantiation of Hibernate beans.
Guillaume
A: 

I don't think you can make Hibernate (or any external framework) call a private constructor on your objects, unless it's through some javassist or cglib runtime created subclass.

If you want to let Hibernate call your constructor, why don't you just make it public, or package? Hibernate instantiates your objects by calling the default no-argument constructor. The documentation states your classes must have the default no-arg constructor with package or public visibility. Your classes must not be final because Hibernate creates proxies for them when using associations.

Chochos
Well, I don't want public or package (package is actually ok but not nice) constructors since it makes the API less clean. I want a static factory method (or factory) to be used when instantiating the class from other classes. It would be ideal if hibernate could use a static factory method as well.
Mattias Holmqvist
A: 

Section 3.2.3.2 of the Spring Reference discusses the few different ways of instantiating beans in Spring.

You're either interested in the static factory or instance factory methods. All sub sections are pretty short. Take a look and see if you have any further questions.

Spencer K
Thanks for the down-vote without the comment as to why. The original question was the usage of static factory calls, which I was referencing.
Spencer K
+3  A: 

While I haven't used Spring, I have used Hibernate in a project which has classes which must either be instantiated by factory methods or through multiple argument constructors.

You can do this through an Interceptor, which is a class which listens in to several key hibernate events, such as when an object needs to be instantiated or when an object is loaded.

To make Hibernate use your own means of instantiating the object, do something like this:

public class MyInterceptor extends EmptyInterceptor {

    public Object instantiate(String entityName, EntityMode entityMode, Serializable id) {
        if(entityName.equals(Foo.class.getName())
             return Foo.create();
        return null;
    }
}

I'm a little suprised that you are having issues with Hibernate not instantiating objects with a non visible constructor, considering that it can be worked around with reflection and I haven't had that issue in my project (non of the classes actually have visible constructors). It may be something with Spring. Check which version of hibernate you are using as well.

deterb
Since it is the Hibernate classes withing org.springframework.spring-orm.hibernate that are causing problems i'm pretty convinced it's related to Spring. The AnnotationSessionFactoryBean is a suspect...
Mattias Holmqvist