App.java
/***************************************************************************
Copyright 2012 Emily Estes
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
***************************************************************************/
package net.metanotion.emailqueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.metanotion.sql.DbUtil;
import net.metanotion.sql.SchemaPoolSwitcher;
import net.metanotion.util.AppUtil;
import net.metanotion.util.JDBCConfig;
/** This is the main class for the background email queue service.
The command line parameters for this class are:
emailqueue configFile.ini [ log4jConfig.xml [ reloadTimeoutForLog4jConfig ] ]
On startup, this program connects to a PostgreSQL database and collects preexisting
messages and attempts to clear the queue based on the burst rate and intervals set
in the config file. After this, the queue process wakes up to check for more messages from
PostgreSQL in the mail queue table, and then starts processing the queue if any exists. */
public final class App {
private static final Logger logger = LoggerFactory.getLogger(App.class);
/** A class representing the configuration options for the email queue. */
public static final class Config {
/** The connection options for the database server. */
public JDBCConfig jdbc;
/** The postgresql schema for the mail table. */
public String schemaPath;
/** The address of the SMTP server to connect to. */
public String smtpServer;
/** The port of the SMTP server to connect to. */
public int smtpPort;
/** The username to use when connecting to the SMTP server. */
public String smtpUsername;
/** The password to use when connecting to the SMTP server. */
public String smtpPassword;
/** The host to use when connecting to the SMTP server. */
public String smtpHost;
/** The maximum number of emails to attempt to retrieve from the DBMS at once and to attempt to send. */
public int mailBurstRate;
/** How long to sleep in milliseconds before querying the PostgreSQL notification queue for new emails. */
public int mailSleepInMS;
/** The maximum number of attempts to try to send an email before giving up on it. */
public int mailMaxRetries;
}
/** The defaults for this server to use. */
public static final class Defaults {
/** The default name of the configuration file. */
public static final String SERVER_CONF = "mqd.conf";
/** The minimum number of threads to keep in the thread pool for the executor service. */
public static final int THREAD_POOL_MIN = 5;
/** The default schema for the mail table is to just use the default schema search path. */
public final String schemaPath = null;
/** The default SMTP port. */
public final int smtpPort = 587;
/** The default number of emails to pull in a single query. */
public final int mailBurstRate = 20;
/** The default amount of time to sleep (in milliseconds) between queue polls. */
public final int mailSleepInMS = 30000;
/** The maximum number of attempts to retry an email. */
public final int mailMaxRetries = 1;
}
/** Start up the email sending queue app server. This app server takes two command line
parameters. The first one is the filename of the configuration file for the app server.
If no file is specified it defaults to looking for "mqd.conf" in the working directory.
The second parameter (which can only be specified if you specify the configuration filename)
is the filename containing the logback configuration for the app server.
@param args The commandline arguments. Should be length 0, length 1 = specifying the
configuration file, length = 2 specifies the configuration file and the
logging configuration file.
*/
public static void main(final String[] args) {
try {
/* Parse the configuration options. */
final Config config = AppUtil.standardStart(args, Defaults.SERVER_CONF, Config.class, new Defaults());
/* Start Database Connection Pooling Driver */
final DataSource dataSource = DbUtil.startDBConnectionPool(config.jdbc);
final DataSource mailDataSource =
(config.schemaPath != null) ? new SchemaPoolSwitcher(dataSource, config.schemaPath) : dataSource;
/* Initialize Thread Pool */
final ScheduledExecutorService es = Executors.newScheduledThreadPool(Defaults.THREAD_POOL_MIN);
/* Initialize mail server. */
final SmtpSender mailSender =
new SmtpSender(config.smtpServer, config.smtpPort, config.smtpUsername, config.smtpPassword, config.smtpHost);
final MailQueue mq =
new MailQueue(mailDataSource,
es,
mailSender,
config.mailBurstRate,
config.mailMaxRetries,
config.mailSleepInMS);
mq.run();
} catch (final Exception e) {
logger.error("Critical error: {}", e);
}
}
}