How synchronization works? - java

For example I have #Stateless java bean:
#Stateless(mappedName = "test")
public class Test implements ITest
{
#Override
public void updateActivity
(SomeObj activity)
throws Exception
{
em.persist(activity);
}
}
Because it's a container-managed bean, then tell me, when does the container decide to synchronize the context with a DB? In this case I immediately see the results in the DB, but sometimes they do not seem to immediately appear there, right?
Please explain me How the synchronization works with the context and the DB at Container-Managed mode? When does the container decide to synchronize the context with a DB?

This will be driven by the transaction propagation configuration as your EJB bean might be one of many managed beans participating in a single transaction. This gets more complex if there are multiple transaction sources in flight e.g. XA 2PC. Generally, the changes will be flushed into the database on transaction commit however this further depends on the transaction isolation level or the presence of savepoints when nested transactions are used.
Check the #TransactionAttribute annotation docs or look for a tutorial that explains transaction propagation.

Related

Transaction management in EJB 3.0 and hibernate

I am trying to understand the transactions management and try to use its power in my already existing application developed in Struts 2, EJB 3 and hibernate 5.2.
Now I have ejb in my business layer like below
#Stateless
#TransactionManagement(TransactionManagementType.CONTAINER)
public class MyEJb implements ejbxyz {
#Override
public void method(){
Dao dao=new Dao() //Dao class is simple java class
dao.fooMethod(); //this method updates some record
dao.barMethod(); // this method updates some other record
}
}
public class Dao{
fooMethid(){
Session session=sessFactory.openSession();
session.beginTransaction();
session.update(x);
}
barMethod(){
try{
Session session=sessFactory.getCurrentSession();
session.getNamedQuery("xyz").executeUpdate();
}catch(HibernateException ex){
session.getTransaction.rollback();
}
}
}
I understand that Transaction management should be done at service layer(at ejb in my case). But how can I achieve this over there. ?
Now the dependency is if barMethod() fails to update the record then I need to rollback the changes made in fooMethod. So basically I need both the methods to be done in one transaction.
When I execute the application it throws the below exception
Exception while barMethod getNamedQuery is not valid without active transaction
Its because I am not beginning any transaction in barMethod. But then I really dont want to start a new transaction and want to continue with the older transaction started in fooMethod.
Container managed transactions are indeed suported out of the box for EJB beans. However, your Dao class is not a managed bean - it is a regular pojo that you instantiate manualy - therefore it does not participate in any transaction started by your other ejb.
So move your Dao to separate file, annotate it with #Stateless and then inject it into your service using #EJB private Dao dao;
There is more to transactions in Ejb container though. You can control the transaction support on method level via #TransactionAttribute annotation, that specifies how should the container invoke your method with regard to transaction. That way you can control, whether your method requires its own transaction, or if it shall participate in a transaction initiated by the caller(e.g. when invoked from ejb bean). For more info have a look at official Java EE tutorial

declarative transaction vs programmatic transaction

If we go with programmatic transaction, we write
Session session=sessiongFactory.openSession();
Transaction tx=session.buildTransaction();
And for a session we can build as many transaction we want.
So, We have first session object than we get Transaction Object.
While in Declarative Transaction,If we declarative #Transaction annotation at service level.
"When this Service Method will be called,Transaction will be Open" so here there is not any inforamtion about Session.
Then in Dao we write
Session session=sessiongFactory.getCurrentSession();
Here we have first Transation then Session,
Can any one please help me in understanding ,How spring manages this Declarative Transaction.
According to documentation method sessiongFactory.getCurrentSession() obtains the current session, and"current session" means controlled by the CurrentSessionContext impl configured for use.
Documentation also provides this explanation for backwards compatibility: if a CurrentSessionContext is not configured but a JTA TransactionManagerLookup is configured, this will default to the JTASessionContext impl.
JTASessionContext implementation will generate Sessions as needed provided a JTA transaction is in effect. If a session is not already associated with the current JTA transaction at the time currentSession() is called, a new session will be opened and it will be associated with that JTA transaction.
With Spring declarative transaction management you can apply #Transactional at both method & class level.
It is enabled via AOP proxies. The combination of AOP with transactional metadata yields an AOP proxy that uses a TransactionInterceptor in conjunction with an appropriate PlatformTransactionManager implementation to drive transactions around method invocations.
Conceptually, calling a method on a transactional proxy looks like this…
When using proxies, you should apply the #Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the #Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings.
All transactions are associated with the session. Transactions are initiated on the service layer but they have to be associated with a session to be committed. First transaction completes then session is closed. A session can also span several transactions. If you are using hibernate, spring uses hibernate managed transaction manager which is responsible for associating transactions with hibernate session.
Spring transaction management abstract the transaction handling and decouples the transaction demarcation logic (e.g. #Transactional) from the actual transaction manager (e.g. RESOURCE_LOCAL, JTA).
The problem with programmatic transaction is that you tie your application code to the transaction management logic. On the other hand, Spring allows you to switch from JpaTransactionManager to JtaTransactionManager with just some configuration (no need to change the application code).
Spring only creates a transaction context that's used by the inner TransactionInterceptor to execute the actual transaction management hooks.
For RESOURCE_LOCAL, transactions are handled through the JDBC Connection commit() and rollback() methods.
For JTA, transactions are handled through the JTA UserTransaction commit() and rollback() methods.
Everything is explained in the docs. You may also want to take a look at Spring integration with ORM.
Basically, Spring creates a proxy which intercepts the transactional methods invocation and starts the transaction before delegating the call to the target method, and ends the transaction when the target method returns.

How does Spring Data Neo4j begin transaction work?

I have a comprehension question. I cannot understand how the database actions from the Neo4jTemplate like "getOrCreateNode()" belong to the surrounding transction. How is it implemented? The Neo4jTemplate would be shared in a multi-threaded environment? I cannot see a distinct membership of the transaction. I would understand if the actions are directly in the transaction object (e.g. tx.getOrCreateNode()).
#Service
public class TestService {
#Autowired
private Neo4jTemplate template;
public void save(IndexedTriple triple) {
GraphDatabase gdb = template.getGraphDatabase();
Transaction tx = gdb.beginTx();
Node subject = gdb.getOrCreateNode()
...
tx.success();
tx.finish();
}
}
Thanks in advance.
The below extract from the reference documentation pretty much sums it up. Use the spring transaction manager instead of using the Neo4j transactions and let spring take care of demarcation. Also, the transaction management is completely thread-safe. For you, I suggest using #Transactional annotation. If there is an existing transaction already, then spring joins that existing transaction as well.
Transactions
The Neo4jTemplate provides implicit transactions for some of its
methods. For instance save uses them. For other modifying operations
please provide Spring Transaction management using #Transactional or
the TransactionTemplate.

Why do we have to manually flush() the EntityManager in a extended PersistenceContext?

In our J2EE application, we use a EJB-3 stateful bean to allow the front code to create, modify and save persistent entities (managed through JPA-2).
It looks something like this:
#LocalBean
#Stateful
#TransactionAttribute(TransactionAttributeType.NEVER)
public class MyEntityController implements Serializable
{
#PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager em;
private MyEntity current;
public void create()
{
this.current = new MyEntity();
em.persist(this.current);
}
public void load(Long id)
{
this.current = em.find(MyEntity.class, id);
}
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void save()
{
em.flush();
}
}
Very important, to avoid too early commits, only the save() method is within a transaction, so if we call create(), we insert nothing in the database.
Curiously, in the save() method, we have to call em.flush() in order to really hit the database. In fact, I tried and found that we can also call em.isOpen() or em.getFlushMode(), well anything that is "em-related".
I don't understand this point. As save() is in a transaction, I thought that at the end of the method, the transaction will be committed, and so the persistent entity manager automatically flushed. Why do I have to manually flush it?
Thanks,
Xavier
To be direct and to the metal, there will be no javax.transaction.Synchronization objects registered for the EntityManager in question until you actually use it in a transaction.
We in app-server-land will create one of these objects to do the flush() and register it with the javax.transaction.TransactionSynchronizationRegistry or javax.transaction.Transaction. This can't be done unless there is an active transaction.
That's the long and short of it.
Yes, an app server could very well keep a list of resources it gave the stateful bean and auto-enroll them in every transaction that stateful bean might start or participate in. The downside of that is you completely lose the ability to decide which things go in which transactions. Maybe you have a 2 or 3 different transactions to run on different persistence units and are aggregating the work up in your Extended persistence context for a very specific transaction. It's really a design issue and the app server should leave such decisions to the app itself.
You use it in a transaction and we'll enroll it in the transaction. That's the basic contract.
Side note, depending on how the underlying EntityManager is handled, any persistent call to the EntityManager may be enough to cause a complete flush at the end of the transaction. Certainly, flush() is the most direct and clear but a persist() or even a find() might do it.
If you use extended persistence context all operations on managed entities done inside non-transactional methods are queued to be written to the database. Once you call flush() on entity manager within a transaction context all queued changes are written to the database. So in other words, the fact that you have a transactional method doesn't commit the changes itself when method exits (as in CMT), but flushing entity manager actually does. You can find full explanation of this process here
Because there is no way to know "when" the client is done with the session (extended scope).

Seeking a Spring (3.0.5) Solution for: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

I have a Transaction problem on Spring 3.0.5. In my case I get the so-called exception "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here"... I have tried everything so far. I can see in my log that the transactional services are detected and registered as Spring beans and I can also see in the logs that they are proxied and associated with underlying Spring transaction interceptors. (Advise) When I run my Spring MVC app my controller will call the service...... :-( but the transaction interceptors are not triggered. (??) I expect my Spring service proxy to open a session and start a transaction before calling my target service method. Since this does not happen, I get the above exception. I have been almost two days on this problem. Tried everything which I found on the internet...but in vain.
I have layered architecture: presentation (springmvc), service (transaction annotated), dataacess (Spring/Hibernate classic sessionfactory). My model objects are annotated with jpa (javax.persistence.*). My spring context config files are separated in appContext.xml, appContext-service.xml and appContext-dao.xml. I have defined my Spring LocalSessionFactoryBean, Datasource and TransactionManager (HibernateTransactionManager) in appContext-dao.xml. I have put in appContext-service.xml where my service implementations resides. In all of my config files I have included and to detect my beans through Controller, Service and Repository annotations.
I appreciate any kind of help.
It sounds like you are doing everything correctly and you know what you are doing. There's not much we can do here unless you show some configuration.
What I'd suggest is some debugging.
First: do you have Unit tests in the service layer that test the queries you are using? Perhaps you can find the error in the service layer.
Then: debug the MVC app, check the types of the injected services. Verify that they are proxies, not the original types.
If they are the original types, you
have an error in your transaction
configuration .
If they are proxies, step through the
query methods and verify that the
transaction logic is applied.
This sounds like accessing a lazily-loaded list or set of you dao after the closing of the transaction. This typically happens if you access that list in the view in stead of the controller, as your controller probably calls methods in transaction scope, and then leaves the transaction and forwards the loaded bean to the view.
Simple solutions:
Configure your data bean to eagerly load
Force loading of the dependencies in the controller (just loop through them)
have a look at this article ans possibly also quite a few right here on SO on lazy loading / lazy fetching of one-to-many associations and the like
Imagine:
// your dao
public class Foo {
// lots of other properties
List<Something> stuff;
// getters and setter for stuff
}
// repository
#Transactional
public class FooRepo {
public Foo loadFoo(int id) {
...
}
}
// Controller
public class Controller {
public void Control() {
sessionContext.set("foo", repo.loadFoo(1)); // transaction managed by spring
}
public void setFooRepo(FooRepo repo) {this.repo = repo};
}
// View
for (Something something : foo.getStuff()) {
// Ooops transaction is closed! stuff is lazily loaded so NOT AVAILABLE
// practical solutions:
// - do not load lazily (Foo.hbm.xml)
// - or force loading by getting all Somethings in the controller
}

Categories