views:

352

answers:

5

Hi,

I am writing an application where user can add and remove other users as friends. My page has a list of diffrent users and each user is given with a button to add them in friend list. I am sending a AJAX request to Java servlet to add the selected user as a friend. I am showing alert message at UI to show the result of process.

My problem is i have to sent a mail when user is added as friend this code is written in the same method in the servlet.

Because of this piece of code my alert message comes very late.

I need to run a separate pthread to run this send mail function so that once user is added i will get the result and mail will be send in separate process.

My code in the Servlet is

private void sendMail(long inviteeID) {
    User inviteeUser = null;
    try {
        inviteeUser = userHandler.getUser(inviteeID);
    } catch (DataException e) {
        sLog.error("User does not exist.", e);
    } catch (UserNotFoundException e) {
        sLog.error("User does not exist.", e);
    }
    MailUtility.send(inviteeUser.getUserEmailAddress().trim(),
            "[email protected]", "add friend message", Utility
                    .getAddFriendMessageBody(LoginHelper
                            .getLoggedInUserEmail()), false);
}



private String inviteAsFriend(long inviteeID) {

    boolean result = false;

    if (LoginHelper.isUserLoggedIn()) {
        try {
            User user = userHandler.findUserByEmail(LoginHelper
                    .getLoggedInUserEmail());

            if (userHandler.isUserFriend(user.getUserId(), inviteeID)) {

                if (userHandler.addFriend(user, inviteeID)) {

                    result = true;
                    return "Member added successfully as your friend.";
                } else {

                    return "Member could not be added as your friend. Please try again later.";
                }

            } else {

                return "Member is already your friend.";
            }

        } catch (DataException e) {

            return "User does not exist.";
        } catch (UserNotFoundException e) {

            return "User does not exist.";
        } catch (Exception e) {

            return "Member could not be added as your friend. Please try again later.";
        } finally {
            if (result) {
                sendMail(inviteeID);
            }
        }
    } else {
        return "User not logged in.";
    }
}
A: 

Read the documentation at

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html

You should subclass java.lang.Thread implementing your run method. It will probably be like your current sendMail. Then you call the method start on the thread, and control returns immediately to the next line of code while the thread is executed in background.

silviot
A preferred way would be to define a class that implements Runnable and then construct a Thread passing in the Runnable instance. Sub-classing Thread is a form of implementation inheritence and is generally not recommended.
Adamski
+1  A: 

I'm not sure this is the problem. Sending an email is not quite that expensive operation - it just informs the SMTP server that the mail should be sent, and the SMTP server takes care from there on.

Still, you could try:

new Thread(new Runnable() {
    public void run() {
        MailUtility.send(inviteeUser.getUserEmailAddress().trim(),
            "[email protected]", "add friend message", Utility
                    .getAddFriendMessageBody(LoginHelper
                            .getLoggedInUserEmail()), false);
    }
}).start();
Bozho
+1  A: 

I'd suggest defining an ExecutorService within your servlet and then submit a Runnable or Callable to the service in order to perform the work of sending the email.

private ExecutorService execService = Executors.newFixedThreadPool(1);

...

execService.submit(new Runnable()) {
  public void run() {
    // Send email.
  }
};

Advantages of this approach include:

  • You do not perform the expensive operation of creating a new Thread each time.
  • You retain greater control over the total #threads running in your servlet (as email requests are simply queued up).
  • Error handling can be centralised, either by subclassing ThreadPoolExecutor and overriding afterExecute(Runnable, Throwable) or by defining a CompletionService to inspect the results of each completed Runnable.
  • Your calling thread is passed back a Future, which can potentially be used to marshall the results back or block until the asynchronous computation has completed.
Adamski
+1  A: 

fairly simple in java 5 or above:

private final ExecutorService executor = Executors.newFixedThreadPool(MAX_ALLOWED_THREADS);
private void sendMail(long inviteeID) {
    User inviteeUser = null;
    try {
        inviteeUser = userHandler.getUser(inviteeID);
    } catch (DataException e) {
        sLog.error("User does not exist.", e);
    } catch (UserNotFoundException e) {
        sLog.error("User does not exist.", e);
    }
    executor.submit(new Runnable() {
         public void run() {
            MailUtility.send(inviteeUser.getUserEmailAddress().trim(),
               "[email protected]", "add friend message", Utility
                    .getAddFriendMessageBody(LoginHelper
                            .getLoggedInUserEmail()), false);
         }
    });
}

ps. you may need to make some variables final in order for it to be usable inside the runnable, but i ll leave that as an exercise for the reader :)

Chii
+1  A: 

Hello,

Another option to do your task(to send email in background) is to have another small program(may be a daemon) which will periodically read the special Table in DB and send email. Program may be writen in any language and starting in OS background proccess.

Here is the advantages of doing that way:

  1. You may use hwatever you like to write such a daemon.
  2. You can control the behaivor of such daemon: to detect when two people trying to add each other to friends.
  3. Perfomance - sending emails may abuse server(especially network interface). Having such a daemon you can install it on defferent server with different network interface.
  4. ....
ponkin