- Let's first create a User POJO:
public class User {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User(Long id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "User{" + "id=" + id + ",
name=" + name + '}';
}
}
- And here is a slow bean that will return User:
@Stateless
public class UserBean {
public User getUser(){
try {
TimeUnit.SECONDS.sleep(5);
long id = new Date().getTime();
return new User(id, "User " + id);
} catch (InterruptedException ex) {
System.err.println(ex.getMessage());
long id = new Date().getTime();
return new User(id, "Error " + id);
}
}
}
- Now we create a task to be executed that will return User using some transaction stuff:
public class AsyncTask implements Callable<User> {
private UserTransaction userTransaction;
private UserBean userBean;
@Override
public User call() throws Exception {
performLookups();
try {
userTransaction.begin();
User user = userBean.getUser();
userTransaction.commit();
return user;
} catch (IllegalStateException | SecurityException |
HeuristicMixedException | HeuristicRollbackException |
NotSupportedException | RollbackException |
SystemException e) {
userTransaction.rollback();
return null;
}
}
private void performLookups() throws NamingException{
userBean = CDI.current().select(UserBean.class).get();
userTransaction = CDI.current()
.select(UserTransaction.class).get();
}
}
- And finally, here is the service endpoint that will use the task to write the result to a response:
@Path("asyncService")
@RequestScoped
public class AsyncService {
private AsyncTask asyncTask;
@Resource(name = "LocalManagedExecutorService")
private ManagedExecutorService executor;
@PostConstruct
public void init(){
asyncTask = new AsyncTask();
}
@GET
public void asyncService(@Suspended AsyncResponse response){
Future<User> result = executor.submit(asyncTask);
while(!result.isDone()){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) {
System.err.println(ex.getMessage());
}
}
try {
response.resume(Response.ok(result.get()).build());
} catch (InterruptedException | ExecutionException ex) {
System.err.println(ex.getMessage());
response.resume(Response.status(Response
.Status.INTERNAL_SERVER_ERROR)
.entity(ex.getMessage()).build());
}
}
}
To try this code, just deploy it to GlassFish 5 and open this URL:
http://localhost:8080/ch09-async-transaction/asyncService