3

I am running an email service on background (in command prompt) and it's meant to keep running and picking up records in the queue table to process.

This my Email.java:

public class Email {


    MySqlConnect con=new MySqlConnect();
    public PreparedStatement preparedStatement = null;

    public Connection con1 = con.connect();

    public Email() throws Exception {


    }

    //pick up queue and send email
    public void email() throws Exception {


        try{

            while(true) {
                String sql = "SELECT id,subject,recipient,content FROM emailqueue WHERE status='Pending' ";
                PreparedStatement statement = con1.prepareStatement(sql);
                ResultSet rs = statement.executeQuery();

                while (rs.next()) {

                    String subject = rs.getString("subject");

                    String recipient = rs.getString("recipient");

                    String content = rs.getString("content");

                    String id = rs.getString("id");

                    sendEmail(recipient, subject, content, id);


                }

            }


        }catch(Exception e){

            e.printStackTrace();

        }
        con1.close();
        Thread.sleep(2000);

    }


//Schedule a service for picking email
    public void schedule(){

        Thread service;
        service = new Thread(new Runnable() {

            public void run() {
                try {

                    System.out.println("Email service is ready");
                    email();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        service.start();


    }



    public void sendEmail(String recipient, String subject, String content,String id) {
        try {

            //final String fromEmail = "lordjesus0371@gmail.com"; //requires valid gmail id
            // final String password = "htasia123"; // correct password for gmail id
          //  InitialContext ctx = new InitialContext();


            String host = get_attributevalue("MAIL_SERVER");
            String port = get_attributevalue("MAIL_PORT");
            final String senderaddress = get_attributevalue("SENDER_ADDRESS");
            final String password = get_attributevalue("MAIL_PASSWORD");



            System.out.println("Please Wait, sending email...");




            /*Setup mail server */

            Properties props = new Properties();

            props.put("mail.smtp.host", host); //SMTP Host
            props.put("mail.smtp.port", port); //TLS Port
            props.put("mail.smtp.auth", "true"); //enable authentication
            props.put("mail.smtp.starttls.enable", "true"); //enable STARTTLS





            //create Authenticator object to pass in Session.getInstance argument
            Authenticator auth = new Authenticator() {
                //override the getPasswordAuthentication method
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(senderaddress, password);
                }
            };
            Session session = Session.getInstance(props, auth);


            session.setDebug(true);


            // Define message
            MimeMessage message = new MimeMessage(session);
            // Set From: header field of the header.
            message.setFrom(new InternetAddress(senderaddress));
            message.addRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient));
            // Set Subject: header field
            message.setSubject(subject);

            // Now set the actual message
            message.setText(content);


            Transport.send(message);

            delivered(id);
            System.out.print("Email sent");



        } catch (Exception e) {
            System.out.println(e.getMessage());
            try{
                error(id);
            } catch (SQLException e1) {
                e1.printStackTrace();
            }

        }


    }

And in my Main method:

public static void main(String[] args) throws Exception {



        Email runEmailService=new Email();

        runEmailService.schedule();



    }

It is able to pick up the records and process the email fine but after sometime it throws:

Exception in thread "Thread-1" java.lang.OutOfMemoryError: Java heap space

Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "Thread-1"

and the program stops running.

Is there a way to prevent this from happening so my program keeps running?

user207421
  • 305,947
  • 44
  • 307
  • 483
Daredevil
  • 1,672
  • 3
  • 18
  • 47

1 Answers1

2

Statements and resultsets resources probably haven't been released , and kept into memory since you didn't close them .

Consider closing them after the while(rs.next()) loop :

rs.close(); 
statement.close();

Note that you could use "try with reousrces" to let things get closed by themself instead :

try (PreparedStatement statement = con1.prepareStatement(sql); ResultSet rs = statement.executeQuery())

cf. Java 7 Automatic Resource Management JDBC (try-with-resources statement)

public void email() throws Exception {

    String sql = "SELECT id,subject,recipient,content FROM emailqueue WHERE status='Pending' ";

    while (true) {

        try (PreparedStatement statement = con1.prepareStatement(sql); ResultSet rs = statement.executeQuery()) {

            while (rs.next()) {

                String subject = rs.getString("subject");

                String recipient = rs.getString("recipient");

                String content = rs.getString("content");

                String id = rs.getString("id");

                sendEmail(recipient, subject, content, id);

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

    con1.close();
    Thread.sleep(2000);

}
Arnaud
  • 17,229
  • 3
  • 31
  • 44
  • See the above piece of code, here they are not inside the block `{}` , they are "parameters" `()` of the `try` block . You will have to declare your `sql` string before the `try` for this to work, though. – Arnaud Apr 18 '19 at 07:03
  • I get what you mean but why it is neccesary to put them in a try again if it can be handled by the outer try block? – Daredevil Apr 18 '19 at 07:15
  • Because this way they get closed automatically, you don't even have to call `close()` on them . As the position of the block wasn't clear, I just updated the anwer with the whole method. – Arnaud Apr 18 '19 at 07:24
  • I see. But is the send email method handled by try as well right? – Daredevil Apr 18 '19 at 07:29
  • Yes, if the email sending crashes, you will get into the `catch` block, and the resources will still be closed .Note that the resources closing part is totally independent from the `catch`, if no error is raised in the `try` block, they still will be closed automatically. – Arnaud Apr 18 '19 at 07:31
  • In your try block, why is not in `{}` braces but in bracket? Will my current way of try catch works fine? – Daredevil Apr 18 '19 at 08:05