• ava EE 7



    或者直接把

    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.

  • 相关阅读:
    HDU 3068 Manacher
    HDU 6188最小费用流
    Codeforces Round #442 (Div. 2) Danil and a Part-time Job
    并查集
    HDU 5988最小网络流(浮点数)
    HOJ
    HOJ
    POJ
    POJ
    关于async
  • 原文地址:https://www.cnblogs.com/bigben0123/p/7009119.html
Copyright © 2020-2023  润新知