perform sequential transaction using ejb2 stateless session bean - java

I want to perform client request in order they called session bean. But sometimes second request executed successfully before first one.
Is sequential client request execution is possible using ejb2 stateless session Bean ?
public generate(){
.................
update()
.............
}
private update(){
debugLog(" update query for "+id);
//code for update query
debugLog(" execute update query for "+id);
}
When I send two request simultaneously i got log like ..
update query for 16
update query for 16
execute update query for 17
execute update query for 16
But i want to execute it serially like
update query for 16
update query for 16
execute update query for 16
execute update query for 17

EJB-3.x Specific :
You need singleton bean - #Singleton, here you are using stateless bean which might execute parallely & independently for requests in random order.
Now sequencing the events in order, you have to use locking mechanism at class/method level based on your requirements.
By default, beans annoted with #Singleton are container managed & uses locking mode LockType.WRITE, explicitly can apply #ConcurrencyManagement(CONTAINER). If any of the method is being called by a client, all the other requests will have to wait for the previous call to return.
You can also annotate at method level with #Lock(LockType.WRITE). Therefore, the sequence of the call will pertain the order in which they are called by clients.
EJB-2.x Specific :
You have to create singleton on your own as annotation aren't available.
Not sure about container managed concurrency in EJB-2.x, but synchronizing the entry method would definitely help, as it is calling other methods internally.
Edit : Delegate the requests from the beans to a singleton utility class & synchronize method appropriately. Therefore it will resolve both, the pooling & sychronizing issue with stateless beans.

Related

Difference between "Propagation.REQUIRED" e "Propagation.REQUIRES_NEW"?

I have a service class (named A) which has a method with #Async annotation. This method async from class A, calls another service class (named B) which has the annotation #Transactional(propagation = Propagation.REQUIRED). This class B, calls another service (named C) which also has the very same annotation from class B. And, the class C, calls a method from a repository class.
These sequence is all triggered by a post endpoint with a request body.
Being said, I'm facing an intermittent issue that, sometimes I get the result as expected and sometimes I do not have any result (using exaclty the same request body).
Looking into application's logs, I could see that, when I get no result, the endpoint do not reach the repository class and apparently the thread "dies" in the class A (when the async method is called).
So, my main question is: if I change the type of Propagation from REQUIRED to REQUIRES_NEW in the classe C, it would solve my async problem?
REQUIRED means a transaction will be created before the method is invoked, other nested services with REQUIRED will join this transaction.
REQUIRES_NEW in a nested service will create another transaction which will be independent from the first transaction it (with req_new) could be committed even if the first transaction (req) will be rolled back.
I doubt that the transaction propagation is responsible for the described behaviour ( thread "dies"). I would check the thread pools used for async also that there all invocations run through a proxy.

spring async method call with JPA transactions

I am implementing a backend service with Spring Boot. This service receives a REST request and executes some database operations and finally updates the status of the record.
After that, I would like to start a new async process and execute another data manipulation on the same record this way:
#Service
public class ClassA {
#Autowired
private ClassB classB;
#Autowired
private MyEntityRepository repo;
#Transactional
public void doSomething(Long id) {
// executing the business logic
if (isOk()) {
repo.updateStatus(id, Status.VERIFIED)
}
// I need to commit this DB transaction and return.
// But after this transaction is committed, I need
// to start an async process that must work on the
// same record that was updated before.
classB.complete(id);
}
}
And this is my async method:
#Service
public class ClassB {
#Autowired
private MyEntityRepository repo;
#Async
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void complete(Long id) {
Optional<MyEntity> myEntity = repo.findById(id);
if (myEntity.isPresent() && myEntity.get().getStatus == Status.VERIFIED) {
// execute 'business logic B'
}
}
}
The classA.doSomething() is called multiply times with the same id but business logic B must be executed only when the record status in the DB is VERIFIED.
The above solution works fine.
But my concern is the following: My test database is small and the classA.doSomething() method always finishes and closes its transaction BEFORE the classB.complete() starts to check the status of the same record in the DB. I see in the log that the SQLs are executed in the proper order:
* UPDATE STATUS FROM TABLE ... WHERE ID = 1 // doSomething()
* COMMIT
* SELECT * FROM TABLE WHERE ID = 1 // complete()
But is that 100% guaranteed that the 1st, classA.doSomething() method will always finish and commit the transaction before the 2nd classB.complete() async call check the status of the same record?
If the async method classB.complete() will be executed before classA.doSomething() finishes and execute its DB commit then I will break the business logic and the business logic B will be skipped (the new DB transaction will not see the updated status yet) and that will cause a big issue. Maybe this can happen if the database is huge and the commit takes longer than it takes in my small test DB.
Maybe I can operate with the DB transaction isolation levels described here but changing this can cause another issue in another part of the app.
What is the best way to implement this logic properly which guarantees the proper execution order with the async method?
It is NOT GUARANTEED that "the 1st, classA.doSomething() method will always finish and commit the transaction before the 2nd classB.complete() async call check the status of the same record".
Transactions are implemented as some kind of interceptors appropriate for the framework (this is true for CDI too). The method marked #Transactional is intercepted by the framework, so the transaction will not end before the closing } of the method. As a matter of fact, if the transaction was started by another method higher in the stack, it will end even later.
So, ClassB has plenty of time to run and see inconsistent state.
I would place the 1st part of doSomething in a separate REQUIRES_NEW transaction method (you may need to place it in a different class, depending on how you configured transaction interceptors; if you are using AOP, Spring may be able to intercept calls to methods of the same object, otherwise it relies on the injected proxy object to do the interception and calling a method through this will not activate the interceptor; again this is true for other frameworks as well, like CDI and EJB). The method doSomething calls the 1st part method, which finishes in a new transaction, then ClassB can continue asynchronously.
Now, in that case (as correctly pointed out in the comment), there is a chance that the 1st transaction succeeds and the 2nd fails. If this is the case, you will have to put logic in the system about how to compensate for this inconsistent state. Frameworks cannot deal with it because there is not one recipe, it is a per case "treatment". Some thoughts, in case they help: make sure that the state of the system after the 1st transaction clearly says that the second transaction should complete "shortly after". E.g. keep a "1st tx committed at" field; a scheduled task can check this timestamp and take action if it is too far in the past. JMS gives you all this - you get retries and a dead letter queue for the failed cases.

Spring + Hibernate+ HikariCP: how to handle DB connection while doing long running REST call?

I have a project running on Spring Boot 1.3.8, Hikari CP 2.6.1 and Hibernate (Spring ORM 4.2.8). The code on service layer looks like this:
public void doStuff() {
A a = dao.findByWhatever();
if (a.hasProperty()) {
B b = restService.doRemoteRequestWithRetries(); // May take long time
}
a.setProp(b.getSomethig());
dao.save(b);
}
Hikari configuration has this: spring.datasource.leakDetectionThreshold=2000.
The problem is that external REST service is quite slow and often takes 2+ seconds to respond, as a result we see a lot of java.lang.Exception: Apparent connection leak detected which are nothing else but false negatives, though the problem can be clearly seen: we hold DB connection for the time we executing rest request.
The question would be: how to properly decouple DB and REST stuff? Or how to tell hibernate to release connection in between? So that we return DB connection to pool while waiting for REST response.
I have tried setting hibernate.connection.release_mode=AFTER_TRANSACTION and it kind of helps, at least we do not have connection leak exceptions. The only problem is that our tests started showing this:
2018-04-17 15:48:03.438 WARN 94029 --- [ main] o.s.orm.jpa.vendor.HibernateJpaDialect : JDBC Connection to reset not identical to originally prepared Connection - please make sure to use connection release mode ON_CLOSE (the default) and to run against Hibernate 4.2+ (or switch HibernateJpaDialect's prepareConnection flag to false`
The tests are using injected DAO to insert records in DB and later check them via application API. They are not annotated with #Transactional and the list of listeners looks like this:
#TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class,
TransactionDbUnitTestExecutionListener.class
})
Any ideas what could be the problem with tests?
In the code
public void doStuff() {
A a = dao.findByWhatever();
if (a.hasProperty()) {
B b = restService.doRemoteRequestWithRetries(); // May take long time
}
a.setProp(b.getSomethig());
dao.save(b);
}
I see three tasks here - fetching entity A, connecting to remote service and updating entity A. And all these are in same transaction, so the underlying connection will be held till the method is complete.
So the idea is to split the tasks one and three into separate transactions, there by allowing the connection to be releases before making the call to remote service.
Basically, with spring boot you need to add spring.jpa.open-in-view=false. This will not register OpenEntityManagerInViewInterceptor and thus entityManager (in-turn connection) is not bound to the current thread/request.
Subsequently, split the three tasks into separate methods with #Transactional. This helps us bind the entityManager to the transaction scope and releasing connection at end of transaction method.
NOTE: And do ensure that there isn't any transaction started/in progress before (i.e., caller - like Controller etc) calling these methods. Else the purpose is defeated and these new #Transactional methods will run in the same transaction as before.
So the high-level approach could look like below:
In spring boot application.properties add property spring.jpa.open-in-view=false.
Next you need to split doStuff method into three methods in new service class. Intent is to ensure they use different transactions.
First method with #Transactionalwill call A a = dao.findByWhatever();`.
Second method makes remote call.
Third method with #Transactionalwill call rest of the code with JPA merge or hibernate saveOrUpdate on objecta`.
Now Autowired this new service in your current code and call the 3 methods.

hibernate interceptor for auditing log design issue due to time difference in calling of onSave and afterTransactionComplete

What i do
I have a async system which react whenever a new entity is created in main system and this async system query the database for the newly created entities.
How i do it
For creating the msgs for async system i use hibernate interceptor.
So whenever a new entity is created the onSave method of the interceptor is called and i
save the entity id in a list, and now when afterTransactionComplete(Transaction tx) is
called , i flush all the entity id in the list to async system using a messaging system(ActiveMq).
What is the problem
Now the problem arises when there are more then one transaction are in process.. and both
transactions creates entities.
Let me take a example:
Tx_A create entity EA1, EA2.
Tx_B creates entity EB1, EB2.
Now let say execution flow happens this way:
[1] onSave for EA1, i add EA1 id to flushList
[2] onSave for EB1, i add EB1 id to flushList
[3] afterTransactionComplete(tx) for Tx_A
Now at this point i will flush EA1 and EB1 id to async system which when query database
for EB1 found null as transaction Tx_B is still not completed.
Now this issue can be solve if in onsave call i can get the transaction id and then in afterTransactionCompletion i can flush only entity related to that transaction
[1] Now Is there a way to get this transaction id ?
[2] Is there some other solution for the above problem ?
i am using hibernate 4.2.2
the problem will arise only if we are using global scope interceptor.
If we use session scope interceptor then there is no problem as for each new transaction there is a new interceptor.

org.hibernate.lazyinitialization exception

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: pojo.Person.address, no session or session was closed.
I am getting this exception and I'm using Spring 3.0 and Hibernate 3.6.
It looks like you have an Entity called Person which has a lazily loaded mapped collection of Addresses? You have loaded the Person and the session it was loaded in has now been closed.
After the session was closed you then attempted to access that collection of address and Hibernate attempted to load them. However, that is not possible if the original session is no longer available.
In order to access the address property you have a few options:
Use the OpenSessionInView pattern to ensure that the Hibernate session is held open for the duration of the request/response cycle (Since you've tagged Spring MVC I'll assume this is a web based operation). This essentially scopes your Hibernate session to the HTTP request.
Ensure that all required properties are loaded before the session is closed (transaction committed). You can do this using
Hibernate.initialize(person.address)
or by writing HQL that uses a left join fetch. This could be something like:
createQuery("from Person as person left join fetch person.address")
This will override any lazy loading configuration for this query only and ensure that any collections are initialized.
Most probably, you don't have transaction management set up. That is, Spring uses default transaction scope, which is transaction per HibernateTemplate call, and closes session right after return from HibernateTemplate.
You can do one of three things:
set up transactions,
switch to explicit session handling,
use Criteria API or fetch join in order to prefetch the details you need.
I was seeing this issue because I had failed to annotate a method in a service with #Transactional. It seems that Hibernate closes the session when a call to another method is made (even within the same class) unless the caller is annotated appropriately.

Categories