Hibernate - Centralized entity instantiation - java

I have some old code that basically uses singleton services inside entities to perform some tasks, and to start cleaning up thinks, I want to inject those services on entities, so at least I can break that hard dependencies for now.
I'm trying to find some place in Hibernate where I can control entities instantiation, by now I've found some possible hooks, like:
- org.hibernate.tuple.Instantiator
- org.hibernate.Interceptor
I need to control that instantiation when an object is first loaded from database, as well as when it's loaded from cache... Also, maybe a global PreLoadEvent may help, I just need to make sure that when an object is returned from Hibernate, it has all it's (service) dependencies injected (spring is already here).
Can someone please point me to where to continue the search?

You could use #Configurable annotation,
see this blog post for more info.

Well, after some testing, an instance of org.hibernate.event.PreLoadEventListener does the trick.
It gets called always, no matter where the instance came from. This way I'm not controlling instantiation, but at least I have a place to inject dependencies befor the instance is returned to client code.
Thanks all for your time!

Related

Spring: Scoped fields

I wrote this idea on the Spring JIRA and even though I know this is not a key feature and has minor priority, I'd still expect some answer by now. I publicize the idea, because I want to know what you guys think about it, if it's cool and I should implement it myself, or is the need for this is a sign of bad architecture.
So the idea itself is - as the title suggests - is a field in a Spring Bean, which has a different scope then the bean itself. We already have something like this, in the shape of scoped proxies, however it works only for bean dependencies. I might want to store a list of Strings of session scope in a bean of singleton scope. I, then have to create a new bean, with scope of session for one field and some functions to use that field. It seems a waste of code and I'd find it bad, because I wouldn't be able to use that bean anywhere else, because it'd already have that data the first class put into it.
I could rephrase the mess above and say that I want to have named beans with arbitrary type (so not necessarily spring beans) and on top of the scope we configure it to have, that field would also be different for every instance of the parent class.
This could make a field instance broader than a prototype scoped bean, but also less broad then the actual scope we'd like to use it in. Kind of a middle ground.
Here is the JIRA issue I wrote: https://jira.spring.io/browse/SPR-16971
In my understanding, Scopes only work with Dependency Injection as it's the DI Container that decides if it should return a new instance or an already existing one. So everything that is #Autowired can be scoped.
I can't imagine how scoping a normal field would work. If I change it, should it change in all other objects that "use" it? I would have to be some kind of proxy object then and neve a primivive value. If on the other hand you have a proxy object, why not use the currently available autowire mechanism.

Weld: Inject dependency inside Thread J2EE

I'm currently going into a huge problem and any help would be highly appreciated.
First of all, the following is occuring in a J2EE environment and I know I shouldn't be managing a Thread myself, but unfortunately I can't change that nor use EJB. The environment is based on the Tomcat Web Container and Weld CDI manager.
My structure contains lots of RESTful services, Service layer and DAO layer implementations, and all of them are getting one another injected by using
#Inject and it works fine. The issue comes when I need to get my Service layer injected into my Run method and I get
WELD-001303 No active contexts for scope type javax.enterprise.context.RequestScoped.
I already have a method to return the desired bean with its contextual, as the following code describes:
BeanManager manager = (BeanManager) jndiContext.lookup("java:/comp/BeanManager");
Bean<T> bean = (Bean<T>) manager.getBeans(beanClass).iterator().next();
CreationalContext<?> ctx = manager.createCreationalContext(bean);
return (T) manager.getReference(bean, beanClass, ctx);
But even I use this method I get the error. So, is there any way in which I could inject my beans inside a Thread created and managed by me?
Thank you.
Sorry, but nope - this just won't work.
CDI, as it is, does not support context propagation across threads. It is bound to one thread only. Having it otherwise would present a severe overhead due to synchronization.
As a proof of my thread-bound claim above, look at Weld source code, where there is ThreadLocal<BeanStore> used as a storage for beans in given context. The class I refer to in the link is a predecessor to context implementing classes. Also note that this is not Weld-only "problem", any CDI impl out there work on the same basis.
You could activate given Context/Scope in a different thread but that means everything will be created anew and any state you had saved in your (for instance) #ApplicationScoped bean, will not propagate. Also, with some definitely not nice hacking, you might be able to access the bean store and make a copy to the other thread. That would give you a read-only access but I am not sure how to do that and if that's even worth the efforts.
Last but not least, CDI allows you to implements you own context or even supplement your version of built-in contexts. That way you would be able to provide a full-blown version of context working across threads, but there are so many challenged to it, that I am not sure it's doable/reasonable.

Strange Spring Transaction Behavior

I'm having a difficult time understanding Spring Transactions. First off, I am trying to use as little of Spring as possible. Basically, I want to use #Transactional and some of its injection capabilities with JPA/Hibernate. My transactional usage is in my service layer. I try to keep them out of test cases. I use CTW and am spring-configured. I have component scan on the root of my packages right now. I also am using Java configuration for my datasource, JpaTransactionManager, and EntityManagerFactory. My configuration for the JpaTransactionFactory uses:
AnnotationTransactionAspect.aspectOf().setTransactionManager( txnMgr );
I do not use #EnableTransactionManagement.
Unfortunately, I'm having a hard time understanding the rules for #Transactional and can't find an easy page that describes them simply. Especially with regards to Session usage. For example, what if I want to use #Transactional on a class that does not have a default no-arg constructor?
The weirdest problem I'm having is that in some of the POJO service classes Transacitonal works great while in others I can see the transactions being created but operations ultimately fall saying that there is "no session or the session has been closed". I apologize for not having code to reproduce this, I can't get it down to a small set. This is why I am looking for the best resources so I can figure it out myself.
For example, I can have a method that gets a lazily fetched collection of children, iterates through it and puts it into a Set and returns that set. In one class it will work fine while in another class also marked with #Transactional it will fail while trying to iterate through the PersistentSet saying that there is no session (even though there IS a transaction).
Maybe this is because I create both of these service objects in a test case and the first one is somehow hijacking the session?
By the way, I have read through the spring source transaction documents. I'm looking for a clear set of rules and tips for debugging issues like this. Thanks.
Are you sure you loaded your parent entity in the scope of the very transaction where you try to load the lazy children? If it was passed in as parameter for example (that is, loaded from outside your #Transactional method) then it might not be bound to a persistence context anymore...
Note that when no #Transactional context is given, any database-related action may have a short tx to be created, then immediately closed - disabling subsequent lazy-loading calls. It depends on your persistence context and auto-commit configurations.
To put it simply, the behaviour with no transactional context being sometimes unexpected, the ground rule is to always have one. If you access your database, then you give yourself a well-defined tx - period. With spring-tx, it means all your #Repository's and #Services are #Transactional. This way you should avoid most of tx-related issues.

how does spring allow for lazy-loading?

If you have a call in a Dao method like (pseudo code):
return ..getHibernateTemplate( get by id );
Now say that entity has a lazy-loaded collection. Once you return from your Dao using the hibernateTemplate helper method, how come the session stays in scope and allows you to lazy-load a collection?
Is the session initialized and committed at a global level on a per request basis?
Update
Please explain where exactly the call to 'getcurrentsession' is made, and when is it actually closed/committed?
From what I understand, the spring framework has to handle the session lifecycle, where does it do this? at what point the in the requests lifecycle?
It is handling the Unit of work also, where/how?
Once you return from your Dao using the hibernateTemplate helper method, how come the session stays in scope and allows you to lazy-load a collection?
Because the Session hasn't been closed yet and your entity is thus still Persistent (as opposed to the Detached object state). As long as your entity has not been detached, you can lazy load collections and proxies. See chapter 10.1. Hibernate object states for more details on these states (it's very important to understand them and the terminology used).
Is the session initialized and committed at a global level on a per request basis?
With web applications, it's typically per request. As mentioned in the javadoc of HibernateTemplate:
Lazy loading will also just work with an open Hibernate Session, either within a transaction or within OpenSessionInViewFilter/Interceptor.
And if you look at the javadoc of OpenSessionInViewFilter or OpenSessionInViewInterceptor, you'll read that they are slightly different but both binds a Hibernate Session to the thread for the entire processing of the request and provide an implementation of the "Open Session in View" pattern.
Please explain where exactly the call to 'getcurrentsession' is made, and when is it actually closed/committed?
You could look at the sources and use a debugger for this you know :) Look at HibernateTemplate, more precisely the doExecute() method, this is where the session is obtained. For the close/commit, look at the previously mentioned OpenSessionInViewFilter/Interceptor, both have methods for this purpose.
From what I understand, the spring framework has to handle the session lifecycle, where does it do this? at what point the in the requests lifecycle?
I think I covered that part: the session is created at the start of a request and closed at the end.
It is handling the Unit of work also, where/how?
I'm not sure to get this one. To me, Hibernate's Session is an implementation of the unit of work pattern. So this question is actually the same as the previous one.
PS: I provided some links that show that everything is actually clearly documented. Spring and Hibernate have extremely nice documentation and javadoc. Take advantage of that, look at them by yourself, look at the code by yourself, use your debugger, you'll learn a lot more.
Hibernate returns a custom implementation of the collection which does the loading only whenever any of the collection methods is been invoked. This collection has been constructed with the session as argument.
Do a sysout of getSomeCollection().getClass() to see which Hibernate custom class it is and check the appropriate javadocs/sourcecode to see how exactly they did it.
If you ever questioned the sense/use/value of interfaces and declaring against interfaces, now, this is a good example. You didn't see anything from it, did you? ;)
Is the session initialized and committed at a global level on a per request basis?
It's typically initialized on a per-request basis using ... (wait for it)
Please explain where exactly the call to 'getcurrentsession' is made, and when is it actually closed/committed?
It: org.springframework.orm.hibernate3.HibernateTemplate
... is the heart of Spring's integration with Hibernate. HibernateTemplate will initialize the session as necessary (or pull an already existing one from a ThreadLocal store) and provide it to any callbacks you give to the HibernateTemplate#execute* methods.
From what I understand, the spring framework has to handle the session lifecycle, where does it do this? at what point the in the requests lifecycle?
Also done by HibernateTemplate, and ...
It is handling the Unit of work also, where/how?
Done by HibernateTransactionManager, if you have one configured in your applicationContext.
If this was a web application I would use the OpenSessionInViewFilter

How to know what made a hibernate persisted object dirty?

An object I mapped with hibernate has strange behavior. In order to know why the object behaves strangely, I need to know what makes that object dirty. Can somebody help and give me a hint?
The object is a Java class in a Java/Spring context. So I would prefer an answer targetting the Java platform.
Edit: I would like to gain access to the Hibernate dirty state and how it changes on an object attached to a session. I don't know how a piece of code would help.
As for the actual problem: inside a transaction managed by a Spring TransactionManager I do some (read) queries on Objects and without doing an explicit save on these Objects they are saved by the TransactionManager because Hibernate thinks that some of these (and not all) are dirty. Now I need to know why Hibernate thinks those Objects are dirty.
I would use an interceptor. The onFlushDirty method gets the current and previous state so you can compare them. Implement the Interceptor interface and extend EmptyInterceptor, overriding onFlushDirty. Then add an instance of that class using configuration.setInterceptor (Spring may require you to do this differently). You can also add an interceptor to the session rather than at startup.
Here is the documentation on interceptors.
create a Test Case or similar, so you can reproduce the problem with a single click.
enable logging for org.hibernate check the logging for the string "dirty" (actually you don't need all of org.hibernate, but I don't know the exact logger.
Find to spots in the program, one where the entity is not dirty, one where it is dirty. Find the middle of the code between the two points, and put a logging statement there, for logging the isdirty Value. Continue with the strategy until you have reduced the code to a single line.
Check out the hibernate code. Find the code that does the dirty checking. Use a debugger to step through it.
Assuming that the state of the object cannot be accessed directly (e.g. no public or package protected fields) and is not fiddled with by reflection, you can put a breakpoint at the start of all of the object's methods and run through the scenario that makes the object dirty in the debugger.

Categories