Reputation: 51
I spend hours of research my problem, but i find a solution.
I fire a thread with the @Asynchronous annotation and give a Future object back, so far so good. BUT, if I trie to cancel the future, it seems that the command doesn't cancel anything.
JSF file
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<h:commandButton actionListener="#{threadHandler.start()}" value="start"/>
<h:commandButton actionListener="#{threadHandler.stop()}" value="stop"/>
</h:form>
</h:body>
</html>
Java handler
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jsf.example;
import java.util.concurrent.Future;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.inject.Named;
@Named("threadHandler")
@Stateless
public class Handler {
Future future;
@Inject
MethodPool pool;
public void start(){
System.out.println("start thread");
future = pool.run();
System.out.println("finish thread start");
}
public void stop(){
System.out.println("future.cancel " + future.cancel(true));
}
}
Java thread
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jsf.example;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;
@Stateless
public class MethodPool {
@Asynchronous
public Future run(){
System.out.println("start run");
Integer runCondition = 1;
while(runCondition > 0){
try {
// simulate heavy stuff
Thread.sleep(1000);
System.out.println(". ");
} catch (InterruptedException ex) {
Logger.getLogger(MethodPool.class.getName()).log(Level.SEVERE, null, ex);
}
}
return new AsyncResult("finish run");
}
}
*EDIT: THX @bkail *
I will post the working code example for the next one who is desperate;)
@Resource
private SessionContext sessionContext;
@Asynchronous
public Future run(){
System.out.println("start run");
while(sessionContext.wasCancelCalled() == false){
try {
// simulate heavy stuff
Thread.sleep(1000);
System.out.println(". ");
} catch (InterruptedException ex) {
Logger.getLogger(MethodPool.class.getName()).log(Level.SEVERE, null, ex);
}
}
return new AsyncResult("finish run");
}
Upvotes: 2
Views: 1491
Reputation: 33936
EJB uses cooperative cancelling, so passing cancel(interrupt=true) does not actually interrupt. Instead, it sets a flag on the method invocation. In your EJB, use @Resource SessionContext context;
, and then check context.wasCancelCalled()
to check if cancel(interrupt=true) was called.
Upvotes: 4