Zaw Than oo
Zaw Than oo

Reputation: 9935

parallel method process

How can I do the asynchronous process in java?

In my program, there are two process.

  1. Send the notification message to customer by mail.
  2. Add the order information to database.

I would like to do parallel process for sendMessage() and addNewOrder(). Actually, I have no experience in Multi-Threading.

OrderService.java

public void addNewOrder(Order order) {
    mailer.sendMessage(order.getCustomer());
    orderDAO.insert(order);
}

SMTPMailer.java

public void sendMessage(Customer customer) {
    // send notification message
}

OrderDAO.java

public void insert(Order order) {
    // insert order to database
}

I want, insert() method need to run even sendMessage() process is failed.

BTW, Should I use JMS because my development environment is

  1. JBoss 7.1
  2. Spring 3.0.
  3. JSF 2.0 with Primefaces 3.5
  4. JPA 2.0
  5. JBoss Seam 2.3

Upvotes: 1

Views: 194

Answers (3)

jpmc26
jpmc26

Reputation: 29856

This is a bad idea. In fact, the current order of operations needs to be changed. You need to save to the DB first, then notify the customer:

public void addNewOrder(Order order) {
    orderDAO.insert(order);
    mailer.sendMessage(order.getCustomer());
}

Why?

If saving the order fails, you do not want to send the customer a confirmation notice! This would be misleading the customer. They would think their order has been placed when in fact the order was completely lost.

In fact, you need some error handling in the event the order fails to save. Upon error, the customer should be given some kind of error notification in the response page. The error handling probably shouldn't be in this method, but put it somewhere.

That said...

You could have the e-mail be sent by another thread if you're concerned about the request blocking too long while the e-mail is being sent. This does introduce some risk that the notification e-mail may be lost if it fails to send. If you're willing to take that risk, you should only even try to send the e-mail if saving the order succeeds. If you do that, then this might be a highly simplified version of the code you could use for that:

public void addNewOrder(Order order) {
    orderDAO.insert(order);
    Runnable mailRunnable = new Runnable() {
        public void run() {
            mailer.sendMessage(order.getCustomer())
        }
    }
    new Thread(mailRunnable).start();
}

Thread class documentation is here, and Runnable is here.

I'm not sure the closure aspect (capturing mailer and order) works here. If not, implement Runnable separately and make them arguments to the constructor. The Runnable needs error handling, too. (It should probably just log any errors somewhere.)

Upvotes: 2

planben
planben

Reputation: 700

you can use the ExecutorService for more elegant solution :

// prepare the callables 
    class MailerCallable implements Callable<Void>{

        Customer customer;
        public MailerCallable(Customer customer){
            this.customer = customer;
        }
        @Override
        public Void call() throws Exception {
            mailer.sendMessage(customer);
            return null;
        }
    }

    class OrderCallable implements Callable<Void>{

        Order order;

        public OrderCallable(Order order){
            this.order = order;
        }
        @Override
        public Void call() throws Exception {
            orderDAO.insert(order);
            return null;
        }
    }

    // prepare the executor service
    ExecutorService service = Executors.newFixedThreadPool(2);
    List<Callable<Void>> callables = new ArrayList<Callable<Void>>();
    callables.add(new MailerCallable(order.getCustomer()));
    callables.add(new OrderCallable(order));

    // execute all and wait for the results
    try{
        service.invokeAll(callables);
    }
    catch (InterruptedException e){
        e.printStackTrace();
    }

Upvotes: 0

morgano
morgano

Reputation: 17422

An idea of how to do it:

public void addNewOrder(Order order) {

    Thread sendMessageThread = new Thread(new Runnable() {

        public void run() {
            mailer.sendMessage(order.getCustomer());
        }

    });

    Thread insertOrderThread = new Thread(new Runnable() {

        public void run() {
            orderDAO.insert(order);
        }

    });

    // Start both threads;
    sendMessageThread.start();
    insertOrderThread.start();

    // wait for them to finish
    sendMessageThread.join();
    insertOrderThread.join();
}

Upvotes: 0

Related Questions