JBOSS EAP 6 blocked to call ejb method after asynchronous method - java

I have a stateless bean that insert some data using asynchronous method of other bean ( local injection). This data insertion takes a time , so I do not wait to finish for this operation. After this data insertion, I am calling another method of same bean. When I put a debug point to method, server waits for approximately 90 seconds to reach this point. May be Jboss waits for transaction to complete for asynchronous method. I do not know what is going on. .
#Stateless
public class SimulationNodePersistenceBean implements SimulationNodePersistenceRemote, SimulationNodePersistenceLocal {
#Resource
SessionContext context;
#EJB
private SimulationResultGraphPersitenceBean graphPersistenceBean;
#Asynchronous
#TransactionAttribute(TransactionAttributeType.REQUIRED)
private void addResultGraphsToDatabase(long id, Graph[] graphList) {
ResultGraph paramGraph;
ResultGraphPoint dataPoint;
Graph graph;
for (int i = 0; i < graphList.length; i++) {
graph = graphList[i];
paramGraph = new ResultGraph();
try {
graphPersistenceBean.persistGraph(paramGraph);
} catch (Exception databaseException) {
// TODO add error message to the contingency simulation messages
// list
logger.error("Error saving ResultGraph:" + paramGraph);
}
}
long duration = System.nanoTime() - startTime;
logger.debug("Graphs inserted to DB in (sec) :" + (duration / NANO_SECOND_CONVERSION_FACTOR));
}
// #Asynchronous
public void persistSimulationResults(long contingencySimulationId, Graph[] graphList,
List<AB> reiList) {
if (graphList != null) {
addResultGraphsToDatabase(contingencySimulationId, graphList);
}
if (reiList != null) {
//another method
}
calculateContSimStability(contingencySimulationId);
}
#Override
public void calculateSimIndex(long id) {
}
This is other bean called from main bean
#Stateless
public class SimulationResultGraphPersitenceBean {
#PersistenceContext(unitName = "DBService")
private EntityManager em;
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
#Asynchronous
public void persistGraph(ResultGraph graph) throws SiGuardPersistenceException {
try {
ResultGraphService service = new ResultGraphService(em);
service.create(graph);
em.flush();
} catch (Exception ex) {
throw new PersistenceException("Error persisting graph", ex);
}
}
This is client calls main bean.This works asynchronously.
getSimulationEJB().persistSimulationResults(id, tsaParser.getLstFile().getGraphArray());
After calling this method, I call another method of SimulationNodePersistenceBean.This method waits for some minutes.
getSimulationEJB().calculateSimIndex(contSimId);
I have created a thread dump using jstack. Actually I do not have this problem in Jboss As 6. I migrated my application to Jboss EAP 6. 4. May be I need to make some configuration changes in configuration. But I do not know what should I do.
I checked thread dump. I did not find any thread in BLOCKING state. Should I look for other keywords?

As I already pointed out in the comments, you are mixing the calling of Asynchronous and Synchronous methods. In your example, you are calling the addResultGraphsToDatabase method (Which is a Asynch method) from persistSimulationResults method (which is a synch method - since you have commented out the asynchronous annotation on top of it). Therefore, right now the addResultGraphsToDatabase method is behaving like a Synchronous method despite the Asynchronous annotation.
I am not sure if you took a look at the link that I posted in the comments but you need to call the Asynch method using the SessionContext. Something like this:
At the class level:
#Inject
SessionContext ctx;
The, within the persistSimulationResults method:
ctx.addResultGraphsToDatabase
For a more detailed example, please take a look at the link I have posted in the comments.

Related

Java Spring issue with java.lang.IllegalThreadStateException

I have an app in Java which is giving me this error (java.lang.IllegalThreadStateException) when I call two different times the same method while the first one is still running....
For the solution I read, I should create a new instance of the Thread, but I think that it is not an option for me as I'm Autowiring all the classes... So if I forced to create a new instance, the other services (which are inside the thread) won't be instanciated.
So, let go to the code...
In my spring-config.xml I added the following bean so I can access to EmailThread (Which is the thread I want to create to send emails) without stopping the app (as the emails takes several seconds to be sent)
<bean id="emailThread" class="com.cobranzasmoviles.services.EmailThread"></bean>
This is my EmailThread
#Component
public class EmailThread extends Thread {
Client client;
CollectionBO collection;
boolean confirmation;
#Autowired
private EmailService emailService;
public void update(Client client, CollectionBO collection, boolean confirmation){
this.client = client;
this.collection = collection;
this.confirmation = confirmation;
}
#Override
public void run() {
try {
if(this.client != null && this.collection != null)
emailService.send(this.client, this.collection, this.confirmation);
} catch (Exception e) {
e.printStackTrace();
}
}
}
And here is how I call it (if I remove the while and the timeout, I get the error I meantioned)
#Autowired
EmailThread emailThread;
private void sendEmail(Client client, CollectionBO collection, boolean confirmation){
try {
this.emailThread.update(client, collection, false);
State state = this.emailThread.getState();
while(!state.name().equalsIgnoreCase("NEW") && !state.name().equalsIgnoreCase("TERMINATED"))
Timeout.seconds(1000);
this.emailThread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
The issue with this solution is that I'm stopping the app execution waiting for the state to change finalized.
So as you can see, I cannot simple do new EmailThread()... Is there any solution? I'm using the wrong strategy to send emails?
UPD
I changed my method to
#Async
private void sendEmailService(Client client, CollectionBO collection, boolean confirmation){
try {
// this.emailThread.update(client, collection, false);
// State state = this.emailThread.getState();
// while(!state.name().equalsIgnoreCase("NEW") && !state.name().equalsIgnoreCase("TERMINATED"))
// Timeout.seconds(1000);
// this.emailThread.start();
this.emailService.send(client, collection, confirmation);
} catch (Exception e) {
e.printStackTrace();
}
}
But the app is still waiting for the email to be sent to continue with the execution... Am I missing something?
I'm calling the method with:
this.sendEmailService(client, colResponse, false);
Is the #Async enough or should I add anything else?
UDT2:
I added #EnableAsync on my WebConfig.java
#Configuration
#EnableWebMvc
#EnableAsync
#EnableAspectJAutoProxy(proxyTargetClass=true)
public class WebConfig extends WebMvcConfigurerAdapter {
In one class I'm calling the #Async method in this way
this.emailService.send(client, colResponse, true);
In the interface I added teh #Async as well (not sure if required)
#Async
public void send(Client client, CollectionBO collection, boolean confirmation) throws Exception;
And in the method implementation also added the #Async
#Async
public void send(Client client, CollectionBO collection, boolean confirmation) {
But it is not working.. I mean, the app still wait for the email to be sent to complete the flow. The email is the last step in the flow, so I'm trying to send the response to the frontend, without waiting for the email.
But I don;t get any response until the email is sent.
If you don't want to wait for the emailService to perform the send operation, you could annotate it with #Async. As the method is void, you don't need to handle the Future provided by the proxy, so the change has minimum impact.
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/annotation/Async.html

Automatic retry of transactions/requests in Dropwizard/JPA/Hibernate

I am currently implementing a REST API web service using the Dropwizard framework together with dropwizard-hibernate respectively JPA/Hibernate (using a PostgreSQL database).
I have a method inside a resource which I annotated with #UnitOfWork to get one transaction for the whole request.
The resource method calls a method of one of my DAOs which extends AbstractDAO<MyEntity> and is used to communicate retrieval or modification of my entities (of type MyEntity) with the database.
This DAO method does the following: First it selects an entity instance and therefore a row from the database. Afterwards, the entity instance is inspected and based on its properties, some of its properties can be altered. In this case, the row in the database should be updated.
I didn't specify anything else regarding caching, locking or transactions anywhere, so I assume the default is some kind of optimistic locking mechanism enforced by Hibernate.
Therefore (I think), when deleting the entity instance in another thread after selecting it from the database in the current one, a StaleStateException is thrown when trying to commit the transaction because the entity instance which should be updated has been deleted before by the other thread.
When using the #UnitOfWork annotation, my understanding is that I'm not able to catch this exception, neither in the DAO method nor in the resource method.
I could now implement an ExceptionMapper<StaleStateException> for Jersey to deliver a HTTP 503 response with a Retry-After header or something like that to the client to tell it to retry its request.
But I'd rather first like to retry to request/transaction (which is basically the same here because of the #UnitOfWork annotation) while still on the server.
Is there any example implementation for a server-sided transaction retry mechanism when using Dropwizard? Like retrying a configurable amount of times (e.g. 3) and then failing with an exception/HTTP 503 response.
How would you implement this? First thing that came to my mind is another annotation like #Retry(exception = StaleStateException.class, count = 3) which I could add to my resource.
Any suggestions on this?
Or is there an alternative solution to my problem considering different locking/transaction-related things?
Alternative approach to this is to use an injection framework - in my case guice - and use method interceptors for this. This is a more generic solution.
DW integreates with guice very smoothly through https://github.com/xvik/dropwizard-guicey
I have a generic implementation that can retry any exception. It works, as yours, on an annotation, as follows:
#Target({ElementType.TYPE, ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface Retry {
}
The interceptor then does (with docs):
/**
* Abstract interceptor to catch exceptions and retry the method automatically.
* Things to note:
*
* 1. Method must be idempotent (you can invoke it x times without alterint the result)
* 2. Method MUST re-open a connection to the DB if that is what is retried. Connections are in an undefined state after a rollback/deadlock.
* You can try and reuse them, however the result will likely not be what you expected
* 3. Implement the retry logic inteligently. You may need to unpack the exception to get to the original.
*
* #author artur
*
*/
public abstract class RetryInterceptor implements MethodInterceptor {
private static final Logger log = Logger.getLogger(RetryInterceptor.class);
#Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if(invocation.getMethod().isAnnotationPresent(Retry.class)) {
int retryCount = 0;
boolean retry = true;
while(retry && retryCount < maxRetries()) {
try {
return invocation.proceed();
} catch(Exception e) {
log.warn("Exception occured while trying to executed method", e);
if(!retry(e)) {
retry = false;
} {
retryCount++;
}
}
}
}
throw new IllegalStateException("All retries if invocation failed");
}
protected boolean retry(Exception e) {
return false;
}
protected int maxRetries() {
return 0;
}
}
A few things to note about this approach.
The retried method must be designed to be invoked multiple times without any result altering (e.g. if the method stores temporary results in forms of increments, then executing twice might increment twice)
Database exceptions are generally not save for retry. They must open a new connection (in particular when retrying deadlocks which is my case)
Other than that this base implementation simply catches anything and then delegates the retry count and detection to the implementing class. For example, my specific deadlock retry interceptor:
public class DeadlockRetryInterceptor extends RetryInterceptor {
private static final Logger log = Logger.getLogger(MsRetryInterceptor.class);
#Override
protected int maxRetries() {
return 6;
}
#Override
protected boolean retry(Exception e) {
SQLException ex = unpack(e);
if(ex == null) {
return false;
}
int errorCode = ex.getErrorCode();
log.info("Found exception: " + ex.getClass().getSimpleName() + " With error code: " + errorCode, ex);
return errorCode == 1205;
}
private SQLException unpack(final Throwable t) {
if(t == null) {
return null;
}
if(t instanceof SQLException) {
return (SQLException) t;
}
return unpack(t.getCause());
}
}
And finally, i can bind this to guice by doing:
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Retry.class), new MsRetryInterceptor());
Which checks any class, and any method annotated with retry.
An example method for retry would be:
#Override
#Retry
public List<MyObject> getSomething(int count, String property) {
try(Connection con = datasource.getConnection();
Context c = metrics.timer(TIMER_NAME).time())
{
// do some work
// return some stuff
} catch (SQLException e) {
// catches exception and throws it out
throw new RuntimeException("Some more specific thing",e);
}
}
The reason I need an unpack is that old legacy cases, like this DAO impl, already catch their own exceptions.
Note also how the method (a get) retrieves a new connection when invoked twice from my datasource pool, and how no modifications are done inside it (hence: safe to retry)
I hope that helps.
You can do similar things by implementing ApplicationListeners or RequestFilters or similar, however I think this is a more generic approach that could retry any kind of failure on any method that is guice bound.
Also note that guice can only intercept methods when it constructs the class (inject annotated constructor etc.)
Hope that helps,
Artur
I found a pull request in the Dropwizard repository that helped me. It basically enables the possibility of using the #UnitOfWork annotation on other than resource methods.
Using this, I was able to detach the session opening/closing and transaction creation/committing lifecycle from the resource method by moving the #UnitOfWork annotation from the resource method to the DAO method which is responsible for the data manipulation which causes the StaleStateException.
Then I was able to build a retry mechanism around this DAO method.
Examplary explanation:
// class MyEntityDAO extends AbstractDAO<MyEntity>
#UnitOfWork
void tryManipulateData() {
// Due to optimistic locking, this operations cause a StaleStateException when
// committed "by the #UnitOfWork annotation" after returning from this method.
}
// Retry mechanism, implemented wheresoever.
void manipulateData() {
while (true) {
try {
retryManipulateData();
} catch (StaleStateException e) {
continue; // Retry.
}
return;
}
}
// class MyEntityResource
#POST
// ...
// #UnitOfWork can also be used here if nested transactions are desired.
public Response someResourceMethod() {
// Call manipulateData() somehow.
}
Of course one could also attach the #UnitOfWork annotation rather on a method inside a service class which makes use of the DAOs instead of directly applying it to a DAO method. In whatever class the annotation is used, remember to create a proxy of the instances with the UnitOfWorkAwareProxyFactory as described in the pull request.

No EntityManager bound to this thread JPA

I have a POJO(Myclass in this example) which I persist/update/delete in my app.
I detect changes to that object using a listener class and then in listener class I save the changes to another table.
Here is my class (dummy example) :
EntityListeners({MyListener.class})
class MyClass {
String name;
String surname;
/*...getters...setter..etc */
public void save() {
JPA.em().persist(this);
return this;
}
public void update() {
JPA.em().merge(this);
}
}
class MyListener {
#preUpdate
public void preUpdate() {
/*...some logic to save the changes irrelevant*/
someAuditObj.createWithData(.......);
someAuditObj.save();
}
}
I'm building my web app using play framework v2.1.3, and all this was working great, I was really happy the way it works.
Today I updated play framework to a newer version v2.2.1.
And the for some reason when instance of MyClass changes and the listener picks up the change and it tries to save the changes the transaction fails and I find this in the log :
Caused by: java.lang.RuntimeException: No EntityManager bound to this thread
So it took me a while to figure out that for some reason transaction is not propagated to listener and then I tried something to fix it (Listener class):
#preUpdate
public void preUpdate() {
/*...some logic to save the changes irrelevant*/
JPA.withTransaction(new F.Callback0() {
#Override
public void invoke() throws Throwable {
someAuditObj.createWithData(.......);
someAuditObj.save();
});
}
So this fixes it, and it works like before without issues.
My question(s) is :
Why did it work before without meddling manually with transactions with earlier version of play framework
Is there a better way of achieving the same thing more elegantly (I'm not sure that is the right word for it)?
Update
This is my controller method :
#Transactional
public Result updateName(Long id, String name){
MyClass c = MyClass.findById(id);
c.setName(name);
c.update();
return ok();
}
So transaction should be propagated to all methods right? but why not to listener as well?
My estimate was this :
if a method has #Transactional annotation then all calls that happens inside should be in a transaction?
Seems that you got same problem as mine. Look at my issue: https://github.com/playframework/playframework/issues/2042
Same JPA code works with 2.1.0 but not working with 2.2.1
So i think it's a bug.
Why did it work before without meddling manually with transactions
with earlier version of play framework
Is there a better way of
achieving the same thing more elegantly (I'm not sure that is the
right word for it)?
We have just to wait till this issue will solved or wait some explanation about using threads with JPA transaction from play2 developers in this issue. At this moment issue is open.
In our view, the problem is that JPA.withTransaction() (and #Transactional uses this too) blocks cannot be nested since .withTransaction() unbinds the em unconditionally, and if its an inner .withTransaction(), the outer block will be left without a bound em.
So this test fails at c.save() (save persists the entity in our case)
#Test
public void nestedJPACalls() {
JPATestEntity a = new JPATestEntity();
JPATestEntity b = new JPATestEntity();
JPATestEntity c = new JPATestEntity();
JPA.withTransaction(() -> {
a.save();
JPA.withTransaction(() -> {
b.save();
});
c.save();
});
}
The .withTransaction() methods should check if the em is already bound, and if so, neither bind nor unbind it. I've added that to the discussion at https://github.com/playframework/playframework/issues/2042
We're working on a clean solution now. A temporary but ugly solution is to just try/catch and run your code inside JPA.withTransaction() only if you get the "No EntityManager bound to this thread" exception.
// Create receipt asynch
Akka.future(new Callable() {
public Object call() {
// Issue Receipt
JPA.withTransaction(new F.Callback0() {
#Override
public void invoke() throws Throwable {
// TODO Auto-generated method stub
issueReceipt(pgTxn); // test
}
});
return null;
}
});

java #Asynchronous Methods: not running async

I try to get an async process running.
Based on this example: http://tomee.apache.org/examples-trunk/async-methods/README.html
But the method addWorkflow(Workflow workflow) will only return when the code in run(Workflow workflow) is fully completed.
Then when it returns and result.get(); is called I'll get the exception:
Caused by: java.lang.IllegalStateException: Object does not represent an acutal Future
Any suggestion what I'm missing?
#Singleton
public class WorkflowProcessor {
#EJB
private WorkflowManager workflowManager;
private final static Logger log = Logger.getLogger(WorkflowProcessor.class.getName());
public void runWorkflows(Collection<Workflow> workflows) throws Exception{
final long start = System.nanoTime();
final long numberOfWorkflows = workflows.size();
Collection<Future<Workflow>> asyncWorkflows = new ArrayList<>();
for(Workflow workflow : workflows){
Future<Workflow> w = addWorkflow(workflow);
asyncWorkflows.add(w);
}
log.log(Level.INFO, "workflow jobs added {0}", new Object[]{numberOfWorkflows});
for(Future<Workflow> result : asyncWorkflows){
result.get();
}
final long total = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start);
log.log(Level.INFO, "WorkflowProcessor->runWorkflows {0} workflows completed in:{1}", new Object[]{numberOfWorkflows, total});
}
#Asynchronous
#Lock(LockType.READ)
#AccessTimeout(-1)
private Future<Workflow> addWorkflow(Workflow workflow){
run(workflow);
return new AsyncResult<Workflow>(workflow);
}
private void run(Workflow workflow){
this.workflowManager.runWorkflow(workflow);
}
So the normal way would be to have the #Asynchronous method in another bean from the caller method.
#Stateless
public class ComputationProcessor {
#Asynchronous
public Future<Data> performComputation {
return new AsyncResult<Data>(null);
}
}
#Stateless
public class ComputationService {
#Inject
private ComputationProcessor mProcessor;
public void ...() {
Future<Data> result = mProcessor.performComputation();
...
}
}
As you discovered, it won't work if the #Asynchronous method is in the same bean than the caller.
The issue is that Java can't decorate the implicit this pointer.
In other words, the #Asynchronous annotation won't be processed and you're doing an ordinary method call.
You can inject your so singleton with a reference to itself (call this e.g. "self"), then call self.addWorkflow.
You might also want to consider running your async code in a stateless bean. You are using a read lock for addWorkflow, but runWorkflow still has a write lock. I think you have a dead lock now: you're holding the lock until work is done, but no work can be done until the write lock is released.

Spring Tests : transaction not rolling back after test method executed

I'm trying to create integration tests for a legacy application deployed on Weblogic 8.1 using a subclass of AbstractTransactionalJUnit4SpringContextTests.
My test method has the following annotations :
#Test
#Rollback(true)
public void testDeployedEJBCall throws Exception {...}
My test class also references beans of type org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean, which proxy the EJBs deployed on my weblogic server.
When I call methods on this proxy bean in a sequencial manner in my test method, the transaction rolls back correctly at the end of the test.
e.g. :
#Test
#Rollback(true)
public void testDeployedEJBCall throws Exception {
Long result1 = myejb.method(100L);
Long result2 = myejb.method(200L);
...
}
However, I would like to make 2 parallel calls to the same EJB method. Therefore I've made an inner class that implements Callable, in order to call my methods in 2 different Threads and hope to run those in parallel.
However, doing this seems to make the ejb methods to be called outside my transaction, and nothing is rolled back.
Here is what the full test class would like when I run the method calls in parallel :
import org.springframework.test.annotation.*;
#RunWith(SpringJUnit4ClassRunner.class)
#Transactional
#ContextConfiguration(locations = {"classpath:path/to/tests-config.xml"})
#TransactionConfiguration(defaultRollback=true)
public final class IntegrationTests extends AbstractTransactionalJUnit4SpringContextTests {
#Autowired
protected JndiTemplate jndiTemplate;
#Resource
protected Proxy myEJB;
public IntegrationTests() {
super();
this.logger = Logger.getLogger(IntegrationTests.class);
}
#Test
#Rollback(true)
public void testDeployedEJBCall() throws Exception {
// Create a thread pool for parallel execution.
ExecutorService exec = Executors.newFixedThreadPool(2);
// Prepare the tasks for parallel execution
List<CallEJBTask> tasks = new ArrayList<CallEJBTask>();
tasks.add(new CallEJBTask(100L, this.myEJB));
tasks.add(new CallEJBTask(200L, this.myEJB));
// Execute all pending tasks in the exec Threadpool
List<Future<Long>> results = exec.invokeAll(tasks);
// Get the results of each task
Long result1 = results.get(0).get();
Long result2 = results.get(1).get();
...
}
}
private class CallEBJTask implements Callable<Long> {
private final Long valueToTest;
private final MyEJB myEJB;
public CallEJBTask(Long valueToTest, Proxy myEJBProxy)
this.valueToTest = valueToTest;
this.myEJB = (MyEJB)myEJBProxy;
}
public Long call() throws Exception {
return getResult();
}
public Long getResult() {
Long result = null;
try {
result = this.myEJB.method(this.patient);
} catch (Exception e) {
...
}
return result;
}
}
Is there a way to make this rollback ???
Thanks for your help.
Regards,
Philippe
Not automatically, no. The problem is that the two extra threads don't participate in the transaction, hence their actions don't rollback.
What is the purpose of the two parallel executions? You will unlikely be able to test for concurrency issues with this approach, if that is what you're aiming for.
Edit: The problem is that testing for concurrency issues is very hard, because your tests are, at best, probabilistic ­­­­– success or failure depend on subtle timing issues that may only surface on the billionth run. See this Serverside article for a good summary of the basics.
The rule of thumb should be to avoid hand-coding threading whenever possible, as it is hard to get right and difficult to test. If you can, avoid shared state between threads, and if there is no way around it, rely on the concurrent data structures and asynchronous executors from the java.util.concurrent package.

Categories