How to Deploy the Email Answering System

Note: This description is couched in terms of deploying to the J2EE reference implementation from Sun since that is easily available, and most people are familiar with it. Deployment to other J2EE containers should be similar, although actually doing it is still on the ToDo list.

Libraries

I added soft links to the following jar files in the $JAVA_HOME/jre/lib/ext directory:
  • classes11.zip - Oracle jdbc driver
  • mail.jar - javax.mail API
  • imap.jar - IMAP mail access
  • smtp.jar - SMTP mail access
  • activation.jar - mime type jar
  • but I'm only sure that the Oracle driver is necessary for pure J2EE deployment. The mail infrastructure should come within the j2ee.jar, but if you're using javax.mail outside of the container, you'll need these other jars. The Oracle jar comes with your Oracle installation, the mail jars are available here, and the activation framework is here.

    Permissions

    As it says within the deployment descriptor, the resource adapter must be granted thread manipulation rights to be able to poll a pop3 server in the background.

    This involves adding the following permission clauses to the j2ee/lib/security/server.policy file:

    grant codeBase "file:${com.sun.enterprise.home}/connector/adapters/email.rar" {
        permission java.lang.RuntimePermission "modifyThreadGroup";
        permission java.lang.RuntimePermission "modifyThread";
        permission java.lang.RuntimePermission "stopThread";
    };
    grant codeBase "file:${java.home}/lib/rt.jar" {
        permission java.lang.RuntimePermission "modifyThreadGroup";
        permission java.lang.RuntimePermission "modifyThread";
        permission java.lang.RuntimePermission "stopThread";
    };
    
    I suppose if you're not going enable background polling you don't need it, but that would preclude proper operation of the system, since it relies on the background thread to detect incoming email. You could still use the resource adapter directly to send and receive email without this in a synchronous fashion.

    Server Configuration

    Add the Oracle jdbc driver oracle.jdbc.driver.OracleDriver to the list of jdbc drivers.

    The Email Answering System needs two data sources (I suppose only one would do if both sources point to the same instance as they do here):

    JNDI Name Data Source
    jdbc/Phone jdbc:oracle:thin:@vortex:1521:vortex
    jdbc/Dictionary jdbc:oracle:thin:@vortex:1521:vortex

    It also needs two queue and five topic destinations as follows (more if you've added robots):

    JNDI Name Destination Type
    jms/Inbox Queue
    jms/Outbox Queue
    jms/phone Topic
    jms/stock Topic
    jms/weather Topic
    jms/word Topic
    jms/www Topic

    I used the existing JMS connection factories, but you may need to create these as well:

    JNDI Name Factory Type
    jms/QueueConnectionFactory Queue
    jms/TopicConnectionFactory Topic

    Deploy

    Open the email.rar from the lib directory. This contains the Email Resource Adapter, the J2EE connector for sending and receiving email. Open the email.ear from lib directory. You should see seven beans:

  • Dispatch - The EJB that listens to the Inbox and dispatches to robots.
  • Responder - The EJB that mails messages from Outbox.
  • Dictionary - The word lookup robot.
  • Phone - The phonebook lookup robot.
  • Stock - The stock quote robot.
  • Weather - The weather report robot.
  • Web - The web page robot.
  • Each of these has some configuration needs. Specific components are discussed below.

    Email Resource Adapter

    The resource adapter has the most configuration properties, but they can be classified into three groups:

  • javax.mail settings - configuration needed for the javax.mail infrastructure, settings you would need to run any javax.mail client
  • background thread settings - items to condition the background polling thread, mostly delay terms used for good citizen operation of the thread
  • queue settings - details about the queue used with background polling, specifies what to do with a message received in the background
  • If you are building or unit testing the email answering system, there is a configuration dialog to assist with the connector (resource adapter) configuration. This dialog will 'preconfigure' the items described below.

    javax.mail Configuration

    These configuration items fall into two groups except for one catch-all item. For each operation, send and receive, there are six parameters. They are used in the initialization call to the javax.mail subsystem:
            url = new URLName (
                TransportProtocol,
                TransportHost,
                TransportPort,
                TransportFile,
                TransportUserName,
                TransportPassword);
            session.getTransport (url);
    
    and
            url = new URLName (
                StoreProtocol,
                StoreHost,
                StorePort,
                StoreFile,
                StoreUserName,
                StorePassword);
            session.getStore (url);
    
    The session object is initialized with the contents of the MailProperties configuration item:
            session = Session.getInstance (MailProperties, authenticator);
    
    where the authenticator object is charged with the username and password for both transport and store.

    Name Description Type Value
    TransportUserName The login name to use when sending email. String user name
    TransportPassword The login password to use when sending email. String user password
    TransportProtocol The protocol for the email transport, i.e smtp or imap. String smtp
    TransportHost The host name of the email transport server, smtp or imap. You should be able to ping this. String host name
    TransportPort The port to use when connecting to the transport host. Use -1 for the default port. Integer -1
    TransportFile I don't know what this is, but the javax.mail spec has it. String  
    StoreUserName The login name to use when receiving email. String user name
    StorePassword The login password to use when receiving email. String user password
    StoreProtocol The protocol to use when accessing the email inbox, either pop3 or imap. String pop3
    StoreHost The host name of the email store server, pop3 or imap. You should be able to ping this. String host name
    StorePort The port to use when connecting to the store host. Use -1 for the default port. Integer -1
    StoreFile I don't know what this is, but the javax.mail spec has it. String  
    MailProperties The javax mail properties used to condition the session. This list is passed to the jaxax.mail.Session getInstance() method and would be used to set properties that are not included explicitly on the connector. A typical use would be to set mail.debug to true when first installing the connector to be able to view the progress of the underlying mail system. These settings are implementation specific, but here is the list of the properties honoured by the reference implementation. The format of this property is dWW=YYdXX=ZZd where d is a delimiter (usually a pipe | that is a vertical bar), WW and XX are keys such as mail.from and mail.debug and YY and ZZ are the values to assign to them respectively. The MailProperties are parsed from the supplied configuration string using the first character as a delimiter. By default the delimiter is a vertical bar or pipe (|) but it can be any character that is not used in the key names or values of the actual settings (i.e. a dot would not be a good choice because all of the keys contain dots e.g. "mail.debug").
    The default values are those I found I needed (or more than I needed I guess). The timeouts are needed to avoid the background thread from hanging in an infinite wait for the mail server to respond. Either the smtp or the pop3 only would be needed. The mail.smtp.auth is needed for my ISP since it uses authorization when getting and sending mail.
    String |mail.smtp.auth=true
    |mail.smtp.connectiontimeout=10000
    |mail.smtp.timeout=10000
    |mail.pop3.connectiontimeout=10000
    |mail.pop3.timeout=10000
    |mail.debug=false|

    Background Thread Configuration

    The background polling thread can be enabled or disabled. If it is enabled three configuration items dictate the startup wait interval, the between poll interval and the failure retry interval. All the items are in milliseconds.

    Name Description Type Value
    BackgroundThread Enables/disables the background thread. If true, the instantiation of a EmailManagedConnectionFactory will start a thread that polls the store for incoming messages. Boolean true
    BackgroundThreadInitialDelay If the background thread is enabled, this is the number of milliseconds to pause before commencing the background thread. This is useful if the j2ee container has not been completely initialized when the EmailManagedConnectionFactory starts the background thread, and can be used to wait for a quiescent state before connecting to the message store and requesting email messages. Integer 10000
    BackgroundThreadReconnectDelay If the background thread is enabled, this is the number of milliseconds to wait between reconnect attempts after three failed store requests. This is useful to avoid wear and tear on the server when the email store has gone walkies or the network has been disconnected. Integer 300000
    BackgroundThreadPollDelay If the background thread is enabled, this is the number of milliseconds between polls of the store. Processing time for the received emails is included in this time. This value is also the interval between inbox polls for the synchronous 'receive' interaction, that is, if no messages are available initially on a receive, this value specifies the number of milliseconds between in box polls until either something is received or the ExecutionTimeout is exceeded. Integer 30000

    Queue Configuration

    If the background thread is enabled, the mechanism to use to forward the email message as a JMS message is specified by two queue parameters.

    Name Description Type Value
    QueueConnectionFactory
    ResourceReference
    If the background thread is enabled, this is the connection factory to use when placing email messages in the Inbox. String jms/QueueConnectionFactory
    QueueConnectionReference If the background thread is enabled, this is the message queue to use as the Inbox, i.e. where to send incoming messages. String jms/Inbox

    When deployed, the connector must be used to create a new connection factory (of type javax.resource.cci.ConnectionFactory) which is expected to be named TheMailSession. This step is performed in the Server Configuration dialog on the Resource Adapters tab. The JNDI name must match the JNDI name used by the Responder bean. The Recovery Settings must be filled in (although they are not used to my knowledge, being involved with transaction rollback I think).

    Dispatch EJB

    This is the most complicated message bean, because it has to know about all the other beans. Basically, it reads messages from the Inbox and dispatches messages to one of five JMS topics. The topics are statically configured in the Subject Topic Map but each topic in the map must be a resource-env-ref on the bean. Sorry.

    Name Description Type Value
    jms/Inbox The queue to read from.   jms/Inbox
    Subject Topic Map The static mapping between email subjects and JMS topics. env-entry String |weather=jms/weather|
    www=jms/www|www+=jms/www|
    phone=jms/phone|
    word=jms/word|stock=jms/stock|
    jms/TopicConnectionFactory The connection factory to use when accessing the word, phone, weather and www topics. resource-ref javax.jms.TopicConnectionFactory jms/TopicConnectionFactory
    jms/QueueConnectionFactory The connection factory to use when accessing the Outbox queue. resource-ref javax.jms.QueueConnectionFactory jms/QueueConnectionFactory
    jms/Outbox The queue to send responses such as 'help' and bounces to. resource-env-ref javax.jms.Queue jms/Outbox
    jms/phone The topic to send 'phone' emails to. resource-env-ref javax.jms.Topic jms/phone
    jms/stock The topic to send 'stock' emails to. resource-env-ref javax.jms.Topic jms/stock
    jms/weather The topic to send 'weather' emails to. resource-env-ref javax.jms.Topic jms/weather
    jms/word The topic to send 'word' emails to. resource-env-ref javax.jms.Topic jms/word
    jms/www The topic to send 'www' and 'www+' emails to. resource-env-ref javax.jms.Topic jms/www

    Responder EJB

    The Responder EJB is a simple one-input, one-output message bean. The only complication is that the output is the email connector.

    Be careful here using the reference implementation, the TheMailSession resource-ref has a default username and password which must be set correctly and the application saved before deploying, because there is no way to override it at deploy time and they are used (passed to the resource adapter).

    The J2EE specification allows for resource adapters within the .ear file, but Iona's product (and probably others) considers this a corruption. This and other problems regarding simultaneous deployment requiring a restart of the container in the reference implementation has caused me to ship the resource adapter (.rar) separately from the enterprise application (.ear). The deployment is a five step process:

  • edit the username and password in two places on the resource adapter (Store and Transport) and save the .rar
  • deploy the adapter
  • perform the server configuration that deploys the resource adapter connection factory
  • edit the username and password on the Responder and save the .ear
  • perform the actual deployment that moves the EJB's to the container
  • Name Description Type Value
    jms/Outbox The queue to read from. JNDI Name jms/Outbox
    TheMailSession The connector to use when sending emails. resource-ref javax.resource.cci.ConnectionFactory TheMailSession

    Robot Beans

    Each of the robot beans reads from a topic and responds to the Outbox queue. The topic it reads from is specific to the bean, but the connection to the Outbox queue is the same for all (and the Dispatch bean too).

    Name Description Type Value
    jms/XXXX The topic to read from. JNDI Name jms/www or jms/weather or jms/word or jms/stock or jms/phone
    jms/QueueConnectionFactory The connection factory to use when accessing the Outbox queue. resource-ref javax.jms.QueueConnectionFactory jms/QueueConnectionFactory
    jms/Outbox The queue to send responses such as 'help' and bounces to. resource-env-ref javax.jms.Queue jms/Outbox

    Summary

    So the step by step sequence is:

  • set up the jdbc and mail jars needed in the java/lib directory
  • edit the server.properties file to provide threading permissions to the resource adapter
  • run the deploytool to add the Queues and Topics required
  • edit the username and password in the resource adapter and save it
  • deploy resource adapter
  • create the resource adapter connection factory
  • edit the username and password in two places within the .ear and save it
  • deploy the beans
  • send a test email