或者直接把

MyTask类内嵌如MyBean中,这样可以在myBean中inject 数据库连接,在内嵌类内访问。

java ee 引入了并发执行。因为是在服务器执行并发,所以要用java ee包里面的并发类:javax.enterprise.concurrent.ManagedScheduledExecutorService。并发是异步执行,需要实现run/call函数。由于是异步执行,我们实现类的创建不能用@Inject,因为这样会导致只能创建一个实例。我们也不能用new 创建实例,会导致无法访问容器中的datasource等容器提供的实例。

这种情况下,只能用Instance创建实例。

@Stateless
public class MyBean {
@Resource
ManagedExecutorService managedExecutorService;
@PersistenceContext
EntityManager entityManager;
@Inject
Instance<MyTask> myTaskInstance; public void executeAsync() throws ExecutionException, InterruptedException {
for(int i=0; i<10; i++) {
MyTask myTask = myTaskInstance.get();
this.managedExecutorService.submit(myTask);
}
}

https://martinsdeveloperworld.wordpress.com/2014/02/25/using-java-ees-managedexecutorservice-to-asynchronously-execute-transactions/

https://stackoverflow.com/questions/21078616/java-ee-7-injection-into-runnable-callable-object

Using Java EE’s ManagedExecutorService to asynchronously execute transactions

One year has passed by since the Java EE 7 specification has been published. Now that Wildfly 8 Final has been released, it is time to take a closer look at the new features.

One thing which was missing since the beginning of the Java EE days is the ability to work with fully-fledged Java EE threads. Java EE 6 has already brought us the @Asynchronous annotation with which we could execute single methods in the background, but a real thread pool was still out of reach. But all this is now history since Java EE 7 introduced the ManagedExecutorService:

1
2
@Resource
ManagedExecutorService managedExecutorService;

Like the well-known ExecutorService from the Standard Edition, the ManagedExecutorService can be used to submit tasks that are executed within a thread pool. One can choose if the tasks submitted should implement the Runnable or Callable interface.

In contrast to a normal SE ExecutorService instance, the ManagedExecutorService provides threads that can access for example UserTransactions from JNDI in order to execute JPA transactions during their execution. This feature is a huge difference to threads started like in a SE environment.

It is important to know, that the transactions started within the ManagedExecutorService’s thread pool run outside of the scope of the transaction of the thread which submits the tasks. This makes it possible to implement scenarios in which the submitting thread inserts some information about the started tasks into the database while the long-running tasks execute their work within an independent transaction.

Now, after we have learned something about the theory, let’s put our hands on some code. First we write a @Stateless EJB that gets the ManagedExecutorService injected:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Stateless
public class MyBean {
    @Resource
    ManagedExecutorService managedExecutorService;
    @PersistenceContext
    EntityManager entityManager;
    @Inject
    Instance<MyTask> myTaskInstance;
 
    public void executeAsync() throws ExecutionException, InterruptedException {
        for(int i=0; i<10; i++) {
            MyTask myTask = myTaskInstance.get();
            this.managedExecutorService.submit(myTask);
        }
    }
 
    public List<MyEntity> list() {
        return entityManager.createQuery("select m from MyEntity m", MyEntity.class).getResultList();
    }
}

The tasks that we will submit to the ManagedExecutorService are retrieved from CDI’s Instance mechanism. This lets us use the power of CDI within our MyTask class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class MyTask implements Runnable {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyTask.class);
    @PersistenceContext
    EntityManager entityManager;
 
    @Override
    public void run() {
        UserTransaction userTransaction = null;
        try {
            userTransaction = lookup();
            userTransaction.begin();
            MyEntity myEntity = new MyEntity();
            myEntity.setName("name");
            entityManager.persist(myEntity);
            userTransaction.commit();
        } catch (Exception e) {
            try {
                if(userTransaction != null) {
                    userTransaction.rollback();
                }
            } catch (SystemException e1) {
                LOGGER.error("Failed to rollback transaction: "+e1.getMessage());
            }
        }
    }
 
    private UserTransaction lookup() throws NamingException {
        InitialContext ic = new InitialContext();
        return (UserTransaction)ic.lookup("java:comp/UserTransaction");
    }
}

Here we can inject the EntityManager to persist some entities into our database. The UserTransaction that we need for the commit has to be retrieved from the JNDI. An injection using the @Resource annotation is not possible within a normal managed bean.

To circumvent the UserTransaction we could of course call the method of another EJB and use the other EJB’s transaction to commit the changes to the database. The following code shows an alternative implementation using the injected EJB to persist the entity:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyTask implements Runnable {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyTask.class);
    @PersistenceContext
    EntityManager entityManager;
    @Inject
    MyBean myBean;
 
    @Override
    public void run() {
        MyEntity myEntity = new MyEntity();
        myBean.persit(myEntity);
    }
}

Now we only need to utilize JAX-RS to call the functionality over a REST interface:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Path("/myResource")
public class MyResource {
    @Inject
    private MyBean myBean;
 
    @Path("list")
    @GET
    @Produces("text/json")
    public List<MyEntity> list() {
        return myBean.list();
    }
 
    @Path("persist")
    @GET
    @Produces("text/html")
    public String persist() throws ExecutionException, InterruptedException {
        myBean.executeAsync();
        return "<html><h1>Successful!</h1></html>";
    }
}

That’s it. With these few lines of code we have implemented a fully working Java EE application whose functionality can be called over a REST interface and that executes its core functionality asynchronously within worker threads with their own transactions.

Conclusion: The ManagedExecutorService is a great feature to integrate asynchronous functionality using all the standard Java EE features like JPA and transactions into enterprise applications. I would say the waiting was worthwhile.

Example source code can be found on github.

ava EE 7 - Injection into Runnable/Callable object ejb entityManager Concurrency ManagedExecutorService 异步调用如何获取context的更多相关文章

  1. java 多线程实现四种方式解析Thread,Runnable,Callable,ServiceExcutor,Synchronized ,ReentrantLock

    1.Thread实现: import java.util.Date; import java.text.SimpleDateFormat; public class MyThread extends ...

  2. callable object与新增的function相关 C++11中万能的可调用类型声明std::function<...>

    在c++11中,一个callable object(可调用对象)可以是函数指针.lambda表达式.重载()的某类对象.bind包裹的某对象等等,有时需要统一管理一些这几类对象,新增的function ...

  3. callable(object)

    callable(object) 中文说明:检查对象object是否可调用.如果返回True,object仍然可能调用失败:但如果返回False,调用对象ojbect绝对不会成功. 注意:类是可调用的 ...

  4. SpringMVC异步调用,Callable和DeferredResult的使用

    Callable和DeferredResult都是springMVC里面的异步调用,Callable主要用来处理一些简单的逻辑,DeferredResult主要用于处理一些复杂逻辑 1.Callabl ...

  5. object C—类中函数的调用

    Object C-类中函数的调用 创建,三个类.然后,在代码中调用相同名字的函数.观察他们的调用次序. @interface test : NSObject - (void)print; @end @ ...

  6. 使用Callable或DeferredResult实现springmvc的异步请求

    使用Callable实现springmvc的异步请求 如果一个请求中的某些操作耗时很长,会一直占用线程.这样的请求多了,可能造成线程池被占满,新请求无法执行的情况.这时,可以考虑使用异步请求,即主线程 ...

  7. 内置函数callable(object)

    如果对象object参数是可以调用的对象,就返回True:否则返回False.不过要注意的是,当一个对象是可以调用的,并不表示调用该对象时执行一定成功,但不可调用的对象去调用时一定不会成功.如果类对象 ...

  8. java并发编程--Runnable Callable及Future

    1.Runnable Runnable是个接口,使用很简单: 1. 实现该接口并重写run方法 2. 利用该类的对象创建线程 3. 线程启动时就会自动调用该对象的run方法 通常在开发中结合Execu ...

  9. Java 多线程 socket 取款例子 runnable callable

    socket部分参考 http://blog.csdn.net/kongxx/article/details/7259465 取款部分参考 http://blog.csdn.net/dayday198 ...

随机推荐

  1. Highgo 瀚高数据库的简单搭建以及处理参数等.

    1. 获取一个瀚高数据库的安装文件 我这边只获取了 瀚高的 2.0.4 的windows x64 版本的. 来源: 同事从供应商那里获取的. 2. windows上面简单安装 很简单 exe 一路ne ...

  2. Java 线程的生命周期

    当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,在线程的生命周期中,它要经过新建(New).就绪(Runnable).运行(Running).阻塞(Blocked)和死 ...

  3. Vue 获得所选中目标的状态(checked)以及对应目标的数据,并进行相应的操作

    一.我们现在要拿取购物车中选中商品的状态和该商品的所有数据或者id <ul v-if="shopList.list.length>0"> <li class ...

  4. InputFormat的数据划分、Split调度、数据读取

    在执行一个Job的时候,Hadoop会将输入数据划分成N个Split,然后启动相应的N个Map程序来分别处理它们.数据如何划分?Split如何调度(如何决定处理Split的Map程序应该运行在哪台Ta ...

  5. python爬虫之pandas

    一.简介: Python Data Analysis Library 或 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的.Pandas 纳入了大量库和一些标准的数据模 ...

  6. Ubuntu16.04 启动纯文本界面方法

    问题: Ubuntu16.04 如何启动纯文本界面. 解决方法: 1.系统启动后,在登陆界面点击Ctrl+Shift+F1切换到文本登陆界面: 2.修改为默认从文本界面登陆: sudo vi /etc ...

  7. linux下ssh无法连接的原因

    在虚拟机上安装了ubuntu16.04 server,用本机 ssh 连接的时候 无法连接上: 忽然想起在安装的时候有个openssh好像没有勾选,所以在虚拟机上 apt install openss ...

  8. July 算法习题 - 字符串4(全排列和全组合)

    https://segmentfault.com/a/1190000002710424 思想:当前层各节点首元素不同,则各节点的剩余元素也不同:下一层节点交换范围为首元素以外的元素 全排列算法: vo ...

  9. hibernate主配置文件中指定session与当前线程绑定

    配置一条属性 <property name="hibernate.current_session_context_class">thread</property& ...

  10. codeforces569B

    Inventory CodeForces - 569B Companies always have a lot of equipment, furniture and other things. Al ...