When does the disposer execute? - java

I have a pojo producer which produces MyResourceManager.
#TraderResouceManager #RequestScoped public MyResourceManager(){ ... ... }
MyResourceManger is injected into SLSB
#inject #TraderDB private MyResourceManager rm;
The disposer is a follows
public void close(#Disposes #TraderResouceManager MyResourceManager rm) {
rm.close();
}
Question
When does the close() execute ?
Is it before closing transaction or after closing the transaction ?
EDIT : The question perhaps needs additional explanation. Lets take a database connection analogy.
I create a #producer with #RequestScoped, using a pojo which creates a new connection per request.
What I need is to dispose the connection at the end of request.
This connection is shared by other beans (for now SLSB). In a given request there may be many beans involved running inside a transaction.
Hence additionally I need to close the connection only after all the transactions are logically closed.
Question
Will I be able to achieve this behavior with above code when I use container managed transactions ?

Close() executes when the current request is terminated since your producer method is request-scoped. If you call your SLSB from a JSF request or a servlet, then the lifeclye of those requests determines when MyResourceManager will be disposed. If your SLSB is remote, it will be terminated as soon as the call returns.

Related

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.

Spring Boot propagate transaction (and db connection) to #Async method

we experience the following problem: We have got some service bean that does some handling and will iterate over a set and start an async thread for each entry, which will look like following:
#Service
public class ServiceBean {
#Autowired
private AsyncHandler asyncHandler;
public void doService(Set<?> theSet) {
for (Object obj : theSet) {
Future<?> future = asyncHandler.doHandle(obj);
// ...
}
// wait for all futures to complete
}
}
#Service
public class AsyncHandler {
#Async
public Future<?> doHandle(Object object) {
// dosth
return future;
}
}
Now we see that each thread will hold its own transaction and thereby database connection, which will cause the connection pool to run empty very fast.
What is the desired way to share the transaction accross all threads?
Thanks in advance!
What is the desired way to share the transaction accross all threads?
Don't do that. That makes it incredibly hard to understand what is going on. There's a reason why a transaction is attached to the thread that has created it. I guess your plan is to start all those asynchronous threads and then wait for them to complete to send the commit signal.
If you don't, who's going to complete the transaction? If a thread rollbacks the transaction, what happens in other threads that are still using it? You could pass the Connection around obviously but I'd expect things to be serialized anyway as most connection implementation are using synchronized in various places.

Java EE Request scope and Asynchronous

I am attempting to time an log performance using an interceptor.
#LogPerformance
#Interceptor
public class PerformanceInterceptor {
The times are stored in a request scoped bean. When the the request has finished the times are written to a log file.
When I changed several of the logged methods to be asynchronous, the logging for those operations stopped being output.
#Asynchronous
#LogPerformance
public Future<String> getString() {
I believe the new EJB thread is defining a new request scope. I can log output from the interceptor and see the request scoped object, but there are two different addresses attached to the objects. One address for the http thread and a different address for the EJB thread.
Is there a way to allow the interceptors from the async methods to write to the object in the http request scope? Is there another way to get the data back into the parent scope?
The container will propagate the javax.ejb.EJBContext to the thread that executes the asynchronous method.
You can inject this EJBContext into your interceptor and stash any state (such as your request scoped bean) that you want into it via javax.ejb.EJBContext.getContextData().

Spring transaction management

I am working on spring4 mvc to introduce in our new web application and currently we are using struts1.x and wanted to use new framework for support html5/ajax request as simple as possible and wanted to use the power of DI and spring webflow support.
Currently in our struts1.x application db transaction management is done at our custom GenericAction which is subclass of Action, In GenericAction we are getting the connection from data source and handover to the subclasses then any exception raised then caught and rollback, otherwise commit such that database atomicity (transaction management )is done at one place. All the module action classes should extends GenericAction such that database connection will be available and performs the module related stuff and after completing connection will be either rollback or commit in GenericAction as said above.
In spring, scope of the Transaction is started with #Transactional annotation and then ends with a method in Service Class since the service class marked as #Transactional. This is not feasible solution for me. I have read several documents related to the spring transaction before starting and below are my questions.
I am using HibernateTransactionManager as transaction manager
Transaction should start from interceptors in case web request or any class (in case of unit testing).
Transaction should ends with the after interceptor is executed in case of web request or any class in case of unit testing.
In case of any exception raised then our HandlerExceptionResolverImpl handler will execute then connection should be rollback.
Any workaround or best practices would be greatly appreciate.
Thanks
Dhorrairaajj
In my opinion, you can achieve this with minimal change on the current application by following what Spring does in its org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(Object, TransactionDefinition). In detail, I think something like following should work:
On the GenericAction, get connection from data source (as you've already done)
Bind the connection via its holder with the current data source:
TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
Eventually, commit the transaction as org.springframework.jdbc.datasource.DataSourceTransactionManager.doCommit(DefaultTransactionStatus).
In any case, Spring's http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/support/TransactionTemplate.html can help to achieve any programmatic transactional scenario that you want. Just need to ensure that the right transactional resource is bound to the opening transaction.
Hope this helps.
Thanks for you reply. Your post/suggestion drives to do the following
I written an interceptor called TxtManager and below are methods to perform the transaction management.
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception
{
Session session = sessionFactory.openSession();
SessionHolder hold = new SessionHolder(
session);
TransactionSynchronizationManager.bindResource(sessionFactory, hold);
// passing null would accept the default transaction definition.
status = transactionManager.getTransaction(null);
return true;
}
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception
{
Exception hanlderEx = (Exception) request
.getAttribute(HandlerExceptionResolverImpl.EXCEPTION_KEY);
if (hanlderEx != null)
{
transactionManager.rollback(status);
}
else
{
transactionManager.commit(status);
}
}
In HandlerExceptionResolverImpl class which responsible for handling things upon exception, put an exception object in request and read the same exception to rollback or commit in afterCompletion method of the interceptor.
In between(preHandler and afterCompletion) we will going to use the standard practices to perform the module related stuff including any other interceptos. Unit testing may not be supported, i will check other alternative for unit testing.
Finally we were able to simulate the existing frame work with your suggestion Thanks
Any suggestion to improves this would be much appreciate !!..
Thanks
Dhorrairaajj

Spring declarative transactions and manually scheduling threads

I'm having a strange issue.
In a class I have:
private final ScheduledExecutorService executor
= Executors.newSingleThreadScheduledExecutor();
public MyClass(final MyService service) {
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
service.foo();
}
}, 0, 30, TimeUnit.SECONDS);
}
MyService is a spring bean that has #Transactional on its foo method. MyClass is instantiated only once (effectively singleton in the application)
After the first invocation of service.foo() (which works fine), on subsequent requests to the application I am randomly getting:
java.lang.IllegalStateException: Already value [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[]])] for key [org.hibernate.impl.SessionFactoryImpl#2cd91000] bound to thread [http-bio-8080-exec-10]
A few observations:
when the exception is thrown, the session stored in the TransactionSynchronizationManager is closed
the transaction synchronization manager resource map for the manually scheduled thread is empty
the exception occurs in http-bio-8080-exec threads, but the manually scheduled one is a pool- thread - so there is no 'thread polution'
MyClass is instantiated on startup, in a thread named "Thread-5", i.e. it is not in any way related to the http-bio threads.
If I comment the invocation to service.foo(), or get rid of the #Transactioanl annotation, everything works (except, of course, that data is not inserted in the db)
Any clues what the issue might be?
(Note: I prefer not to use #Scheduled - I don't want MyClass to be a spring bean, and the runnable has to operate on some of its internal state before invoking the service)
Update: After a while I'm able to reproduce it even without the scheduling stuff. So probably a general spring problem with the latest snapshot I'm using.
I assume that exception comes from an invocation of the TransactionInterceptor or the like (some Spring infrastructure bean), or are you using the TransactionSynchronizationManager from your own code somewhere? It appears to me that something is binding sessions to a thread being managed by your container (is that Tomcat 7?) and failing to unbind them before they're returned to the container's thread pool. Thus when the same thread is used for another transactional request later, Spring can't bind the new Session to it because the old one wasn't cleaned up.
I don't actually see anything to make me think it's directly related to your custom scheduling with MyClass. Are you sure it's not just a coincidence that you didn't see the exception when you remove the service.foo() call?
If you could catch one of those threads in a debugger when it's being returned to the pool with a Session still bound to it, you might be able to backtrack to what it was used for. An omniscient debugger would theoretically be perfect for this, though I've never used one myself: ODB and TOD are the two I know of.
Edit: An easier way to find the offending threads: add a Filter (servlet filter, that is) to your app that runs "around" everything else. After chain.doFilter(), as the last act of handling a request before it leaves your application, check the value of TransactionSynchronizationManager.getResourceMap(). It should be an empty map when you're done handling a request. When you find one that isn't, that's where you need to backtrack from to see what happened.

Categories