Spring:: If a fork a new thread will it be enforced in transaction by Spring - spring

We are using declarative spring transaction attribute for database integrity. Some of our code call webservice which do bunch of stuffs in sharepoint. The problem is when webservices take longer time users get deadlock from spring which is holding up backend.
If I make a new thread inside a function which has spring transaction declarative attribute will that be ignored from spring?
[Transaction(TransactionPropagation.Required, ReadOnly = false)]
public void UploadPDFManual(/*parameters*/)
{
//DO some data base related things
if (revisionPDFBytes != null)
{
//my sharepoint call which calls webservice
Task.Factory.StartNew(() => DocumentRepositoryUtil.CreateSharepointDocument(docInfo)); // I draw a new thread from ASPNET worker thread pool.
}
}
Anything other options I should go for?

You don't need doing it in a transaction. Transaction makes a database save an object properly. That's it. All other stuff must be done after the transaction commit. In Java, you can make it with Spring's transaction synchronization or JMS. Take a look at the accepted answer over here.
More useful info specific for .NET (see 17.8).

Related

JPA transactional proxy within a thread issue

In my Controller I have injected (#Autowired) this Service, which implements Runnable (I need multi-threading) and I call it like so:
Thread t = new Thread(service);
t.start();
t.join();
Then, in my Service's run() I call this Repository (simple JPARepository), which is injected in Service also with #Autowired:
repository.save(someEntity);
The problem is that it doesn't persist the entity with id=1. The transactional proxy (and Hibernate connection pool) is initialized after the unsuccessful saving of the first entity. After that, it works fine.
Can anyone point me to the right direction with my issue: how to force the Thread to initialize the Hibernate transactional proxy before persisting the first entity?
You should consider to start the thread after Spring context is refreshed. This is safer because all your beans may be in an inconsistent state.
#EventListener(ContextRefreshedEvent.class)
public void handleContextStart() {
// ...
}

Multitenancy support when using Apache Camel and Hibernate (in a Spring application)

I have a Spring application which uses the Hibernate schema strategy and a TenantContext class to store the tenant identifier (same design shown here: https://vladmihalcea.com/hibernate-database-schema-multitenancy/).
Everything works fine when dealing with synchronous HTTP requests handled by Spring.
Besides that, I have some Camel routes which are triggered by chron jobs. They use the JPA component to read from or write to a datasource. The Exchange object knows the tenant identifier. How to transfer that information to Hibernate?
I was thinking about using a listener or interceptor to get the tenant id from the Exchange and set the TenantContext object at every step in the route. The TenantContext will then be used by the Hibernate CurrentTenantIdentifierResolver class to resolve the tenant.
How should the TenantContext look like? Is it ThreadLocal a viable option? What about async threads?
In general, do you have any good solution to support Hibernate multitenancy when using Camel?
In general, it depends on your use case ;)
But we have done something similar, using a ThreadLocal in the CurrentTenantIdentifierResolver.
Then in the places where we need to set the tenant (e.g. at the start of the job being executed by the cronjob, in your case), we have an instance of tenantIdentifierResolver used like so:
tenantIdentifierResolver.withTenantId(tenant, () -> {
try {
doWhatever(param1, param2, etc);
} catch (WhateverException we) {
throw new MyBusinessException(we);
}
});

Where should i store thread dependent data within a receiving rabbitListener component in a multithreaded environment?

I'm using the annotation based approach of spring amqp in a multithreaded environment (i have multiple consumers => multiple rabbit listener containers).
#RabbitListener(queues = "tasks")
public void receiveMessage(#Payload Task task) {
// usage of httpClient here with its own httpContext (would be fine)
// this method gets called from different listenerContainers / threads
}
My component which contains the annotated receiveMessage() method needs to do some http calls with the apache http client. Since i'm working with multiple consumers at the same time, this method gets called from different threads and the apache http client documentation says that i should create a httpContext for each thread to be thread safe. Since all threads are calling the same component method i can't put the httpContext into the component.
Is there something like a listener container context for each listener container where i can put the httpClientContext? Or does somebody have an idea how to solve this easy? I thought about ThreadLocal or a central registry for httpContexts but it would be fine if this would be more easy.
There is nothing like that provided by the framework; the simplest solution is to store them in something like a LinkedBlockingQueue and check one out, use it, and put it back in the queue when you're done (creating one as necessary if the queue is empty).
ThreadLocal will work too, but I prefer to use a pool.

How to create an application to poll 10 JMX URI and store in DB in Spring

How to create an application to poll 50 JMX URI and store the mbeans in DB.
I have created a class which will connect to jmx server and fetch the mbeans value.
My question is how to trigger my created class and method to continues polling.
Moreover, I need two function to start and stop this polling anytime.
What can I use - Spring Scheduler, Spring Integration and how or should I create different class having thread and infinite loop.
Take a look at Spring Integration and its JMX Tree Polling Channel Adapter.
With Spring Scheduler (#Schedule annotation) it is easy to have a method that is invoked (for example) every minute. But it is not possible* to change (disable) that scheduling.
Anyway you could:
use the quarz-framework directly, then you could change the scheduling, or
do implement a dirty (but easy) hack:
Let the schueduler run, but disable the invocation of the real polling method:
private volantile boolean pollingEnabled;
#Schedule(fixedRate=1000)
public void pollTrigger() {
if (pollingEnabled) {
doPolling();
}
}
*more precise: to my knowlege there is no easy way

Pre-bound JDBC Connection found

We have an app that is using hibernate, spring, and DB2 in websphere 7. We have audit triggers and we need to set so the triggers can know the logged in user (we use generic logon to the database). We came up with a new scheme for setting this in a new app so that it can automatically join in new transactions. We overrode the transaction manager and did the work in the doBegin.
These scheme worked great in one app, and seemed to work great in a second app, but now, weeks later, and not consistently (behavior is intermittent and does not happen in local development), we are getting this Pre-bound JDBC Connection found error. Looking online most posts say this is when you use two transaction managers against one data source. That is now what we are doing.
I also read one post wondering if it was because he mixed annotation and AOP based transactions. This app does some of that. I don't really buy that theory, but thought I'd mention it.
Exception:
Caused by:
org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC Connection found! HibernateTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single HibernateTransactionManager for all transactions on a single DataSource, no matter whether Hibernate or JDBC access.
at java.lang.Throwable.<init>(Throwable.java:67)
at org.springframework.core.NestedRuntimeException.<init>(NestedRuntimeException.java:54)
at org.springframework.transaction.TransactionException.<init>(TransactionException.java:34)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:475)
at gov.usdoj.afms.umc.utils.hibernate.AfmsHibernateTransactionManager.doBegin(AfmsHibernateTransactionManager.java:28)
Code (note that the exception comes from the super.doBegin()):
protected void doBegin(Object arg0, TransactionDefinition arg1) {
super.doBegin(arg0, arg1);
if (!Db2ClientInfo.exists()) {
clearDBProperty();
} else {
setDBProperty(Db2ClientInfo.getClientUserId(), Db2ClientInfo.getClientApplicationId());
}
}
private void setDBProperty(String uId, String appName) {
Session session = getSessionFactory().getCurrentSession();
Properties props = new Properties();
props.setProperty(WSConnection.CLIENT_ID, uId);
props.setProperty(WSConnection.CLIENT_APPLICATION_NAME, appName);
try {
Connection nativeConn = new SimpleNativeJdbcExtractor().getNativeConnection(session.connection());
if (nativeConn instanceof WSConnection) {
WSConnection wconn = (WSConnection) nativeConn;
wconn.setClientInformation(props);
} else {
logger.error("Connection was NOT an instance of WSConnection so client ID and app could not be set");
}
} catch (Exception e) {
throw new RuntimeException("Cannot set DB parameters!", e);
}
}
I just realized I never answered this. It turns out that the exception had nothing whatever to do with our Tx manager. It was the fact that this particular EAR has two apps in it, each pointing to the same data source. Evidently this confuses hibernate. We've plans to separate the apps some day, but creating an identical (except in name) data source and pointing the apps at them separately fixes the issue for now.
Instead of modifying the transaction manager it might be easier (better?) to create a wrapper around your datasource (extending DelegatingDataSource from spring) and override the 2 getConnection methods. For the cleanup you could wrap the connection in a proxy and intercept the close method.
That should be a safer (and easier I guess) way then trying to fiddle with the transaction manager and it works for every technology (JDBC, Hibernate, JPA etc.) as long as you use the wrapped datasource. (The registration could be done with a BeanPostProcessor which detects DataSource instances and simply wraps them in the delegate).
If that is to radical (as it means changing your current applications instead of updating a library). It could be a configuration problem, make sure that you are only loading your configuration (and thus DataSource and TransactionManager) only once, duplicating bean instances might lead to a similair behavior.
For posterity, I just got this problem and the answers here weren't very helpful. We resolved the problem by removing a double import of a core XML file which had the AOP transaction manager definition in it:
<tx:annotation-driven transaction-manager="..."
proxy-target-class="true" />
I'm thinking that it causes there to be 2 transaction managers overlapping the same namespace. To fix it, we moved the imports around so they were being done once.
Hope this helps someone else.

Resources