Skip to main content

Apache Geronimo JNDI naming and Java resource connection pools, Part 3: Mail sessions

Use Geronimo and JNDI to create, access, and verify receipt of e-mail

Dale de los Reyes (dreyes4@hotmail.com), Freelance Writer, Freelance
Dale de los Reyes graduated with a degree in computer science from California Polytechnic State University, San Luis Obispo in 1996. His experience includes application development in J2EE, C++ for Microsoft® Windows®, and COBOL for Mainframes. In his spare time he takes photographs, practices martial arts, and pursues independent projects.

Summary:  So far in this series you've built a data source connection and a Java Message Service (JMS) resource group and explored how each works with Apache Geronimo and the Java™ Naming and Directory Interface (JNDI). This article, the third in a four-part series, documents how Apache Geronimo, the JNDI, and mail sessions interrelate. You'll learn how to create a mail session and access it in a simple Geronimo application using JNDI.

View more content in this series

Date:  13 Feb 2007
Level:  Intermediate
Activity:  1476 views
Comments:  

Introduction

A mail session is a JavaMail resource. JavaMail is an API that models an e-mail system. Unlike the JMS API covered in Part 2 of this series, the messages processed by JavaMail are intended for human consumption. The JavaMail API is implemented by a third party, such as Sun. However, Geronimo has its own implementation as well, and it's mature enough to send out e-mail messages independently.

This article continues where Part 2 left off. You'll create a new JavaServer Pages (JSP) component that lets the user contact customers in a special interest group via e-mail. This e-mail will then be sent from the Geronimo application server to the Apache James Mail Server 2.2. Next, you'll create a console-based client to read any e-mail messages in James to verify the new functionality.

The Customer Service utility included in this series is a simple Web application that allows users to save basic customer information into a database. You'll build it using Ant 1.6.5 and Java 1.4.2_10 and deploy it on Geronimo 1.1 with Tomcat. You'll use both the Apache Derby database and the ActiveMQ JMS provider, which come bundled with Geronimo.


Set up James

The Apache James Mail Server is distributed with a default configuration that is sufficient for simple tests:

  1. Install the application by extracting it into an appropriate location, and then name it JAMES_HOME.
  2. Start James by running the script JAMES_HOME/bin/run.bat in a console. Figure 1 shows what the console looks like after James has started.
  3. Stop James by pressing Ctrl+C in the console.
  4. Change directories to JAMES_HOME/work/james-<system generated id>/SAR-INF/lib. This directory only gets created after James has first started. Copy the activation.jar and mail-1.3.1.jar files into JAMES_HOME/lib.
  5. Restart James and note the port numbers, especially for the Remote Manager Service.
  6. Assuming James is installed on the local machine, connect to the Remote Manager Service by typing telnet localhost 4555. Use the default login and password root and root.
  7. Create user accounts and passwords by typing adduser [user] [password]. For example, typing adduser smith smith, creates a user named smith with the password smith. Repeat this step as needed.
  8. Finally, modify the CustomerService/resource/build.properties file for Part 3 to reflect the appropriate locations of both Geronimo and James.

Figure 1. James started in Windows console
James started in Windows console

The James Mail Server is now ready to receive e-mail from Geronimo. The default configuration file is located in JAMES_HOME/apps/james/SAR-INF/config.xml. This file doesn't need to be modified for the purposes of this article; it's only mentioned in case you want to further explore the James settings.

Now you need to create or edit test customers in the Geronimo database. Access the Customer Service utility at http://localhost:8080/service, then go to the Customer Processing Page and create a customer with an e-mail address at localhost like the one displayed in Figure 2.


Figure 2. John Smith's updated e-mail address
John Smith's updated e-mail address

Here, a customer named John Smith has just had his e-mail address updated. Note that the domain name is localhost. This matches the default James configuration that expects this domain name when receiving incoming mail for this person. The next step is to declare a mail session in JNDI, which is detailed in the next section.


Create Geronimo deployment descriptors

Configuring the descriptor files is important because it's the mechanism that allows these components to be used in Geronimo. It's also how JNDI names get associated with a given Java object. Components deployed in Geronimo typically have two deployment files: the standard Java 2 Platform, Enterprise Edition (J2EE) or Java Platform, Enterprise Edition (Java EE) deployment descriptor and the Geronimo-specific deployment plan.

The new JSP interface allows a user to send e-mail to customers in a special interest group. This e-mail is sent from within the CustomerServiceJavaBean in the Web tier. Listing 1 contains the additional tag needed to specify the JavaMail resource in the standard web.xml J2EE/Java EE deployment descriptor.


Listing 1. Partial listing of web.xml

   <resource-ref>
      <res-ref-name>mail/CustomerServiceMailSession</res-ref-name>
      <res-type>javax.mail.Session</res-type>
      <res-auth>Container</res-auth>
      <res-sharing-scope>Shareable</res-sharing-scope>
   </resource-ref>

This <resource-ref> tag associates the JNDI name to the resource object's type, which in this case is javax.mail.Session. If it looks familiar, it's because it's the same tag used to declare the object types of other resources like data sources (for JDBC) or connection factories (for JMS). Both of these resource types have already been used elsewhere in the example application. Listing 2 contains the tag needed in the corresponding Geronimo-specific plan.


Listing 2. Partial listing of geronimo-web.xml

   <resource-ref>
      <ref-name>mail/CustomerServiceMailSession</ref-name>
      <resource-link>mail/CustomerServiceMailGBean</resource-link>
   </resource-ref>

The <ref-name> corresponds to the <res-ref-name> in web.xml, and it's also the JNDI name by which this mail session resource will be called. The <resource-link> specifies the name of the MailGBean, which is responsible for generating the JavaMail sessions. This name is declared at the application level and is contained in Listing 3.


Listing 3. Listing of geronimo-appliction.xml
<application 
xmlns="http://geronimo.apache.org/xml/ns/j2ee/application-1.1">
   <dep:environment 
xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.1">
      <dep:moduleId>
         <dep:groupId>default</dep:groupId>
         <dep:artifactId>CustomerService</dep:artifactId>
         <dep:version>1.0</dep:version>
         <dep:type>ear</dep:type>
      </dep:moduleId>

      <dep:dependencies>
         <dep:dependency>
            <dep:groupId>geronimo</dep:groupId>
            <dep:artifactId>geronimo-mail</dep:artifactId>
            <dep:version>1.1</dep:version>
            <dep:type>jar</dep:type>
         </dep:dependency>

         <dep:dependency>
            <dep:groupId>geronimo</dep:groupId>
            
<dep:artifactId>geronimo-javamail-transport</dep:artifactId>
            <dep:version>1.1</dep:version>
            <dep:type>jar</dep:type>
         </dep:dependency>
      </dep:dependencies>

      <dep:hidden-classes/>
      <dep:non-overridable-classes/>
   </dep:environment>

   <module>
      <connector>tranql-connector-1.2.rar</connector>
      <alt-dd>CustomerServicePool-alt.xml</alt-dd>
   </module>

   <gbean name="mail/CustomerServiceMailGBean" 
class="org.apache.geronimo.mail.MailGBean">
      <attribute name="transportProtocol">smtp</attribute>
      <attribute name="useDefault">false</attribute>
      <attribute name="host">localhost</attribute>
      <attribute name="properties">
         mail.debug=true
         mail.smtp.port=25
      </attribute>   
   </gbean>
</application>

The two <dependency> tags for geronimo-mail-1.1.jar and geronimo-javamail-transport-1.1.jar are required because they contain the implementations for the MailGBean and Transport, respectively. Both are needed to support the <gbean> declaration. The name of this <gbean> is the same name that is specified in the <resource-link> of geronimo-web.xml listed earlier.

The transportProtocol attribute specifies the protocol, smtp, which will send out the e-mail. The host attribute specifies the domain name or IP address where the mail server is located. For this article, James is installed on the same machine as Geronimo 1.1. Otherwise, any accessible mail server that's properly configured can be used, and real e-mail addresses can be used rather than localhost. The properties attribute allows any additional attributes to be set using name/value pairs. In this case, debug messages are displayed in the Geronimo output console. The smtp port matches the same port of the James Mail Server. Finally, the scope of this <gbean> is application level only, because it's specified in the application-level descriptors. Now that the relevant components have been configured, it's time to look up these objects in code using JNDI.


Customer Service utility and JavaMail

The enhanced Customer Service utility is almost ready. The next step is to call the mail session using JNDI to use JavaMail to send out messages. The complete JNDI strings are displayed in Listing 4.


Listing 4. Listing of JNDI names in customer.properties
# Specify JNDI names here
jndi.customer.ejb=java:/comp/env/ejb/CustomerEntityBean
jndi.process.ejb=java:/comp/env/ejb/ProcessCustomerSessionBean
jndi.group.ejb=java:/comp/env/ejb/InterestGroupEntityBean
jndi.jms.connector=java:comp/env/jms/CustomerServiceConnectionFactory
jndi.jms.topic=java:comp/env/jms/CustomerServiceTopic
jndi.mail.session=java:comp/env/mail/CustomerServiceMailSession

The name declared earlier in the <ref-name> tag of the Web archive descriptors is now listed in its full JNDI name context. All the names are prefaced according to the recommended J2EE naming convention. The code in Listing 5 shows how to perform a lookup of CustomerServiceMailSession using the full JNDI name context.


Listing 5. Partial listing of CustomerServiceJavaBean.java performing JNDI lookup
public CustomerServiceJavaBean()
   {
      InitialContext initial = null;
      Object objref = null;

      bundle = ResourceBundle.getBundle("customer", Locale.getDefault(), 
CustomerServiceJavaBean.class.getClassLoader());
      JNDI_PROCESS_EJB = bundle.getString("jndi.process.ejb");
      JNDI_MAIL_SESSION = bundle.getString("jndi.mail.session");

      try
      {
         initial = new InitialContext();
         objref = initial.lookup(JNDI_PROCESS_EJB);
         processHome = (ProcessCustomerHome)PortableRemoteObject.narrow(objref, 
ProcessCustomerHome.class);
         System.out.println("looking up: " + JNDI_PROCESS_EJB);

         objref = initial.lookup(JNDI_MAIL_SESSION);
         mailSession = (Session)PortableRemoteObject.narrow(objref, 
javax.mail.Session.class);
         System.out.println("looking up: " + JNDI_MAIL_SESSION);
      } // end try

      catch (Exception e)
      {
         e.printStackTrace();
      } // end catch
   } // end CustomerServiceJavaBean

It should be apparent that the code for looking up a mail session is similar to the code for looking up the ProcessCustomerSessionBean. The only parts that need to change are the references to the mail session. Listing 6 contains the code needed to send out an actual e-mail from Geronimo.


Listing 6. Partial listing of CustomerServiceJavaBean.java sending out e-mail
  
private boolean sendEmail(String toAddress, String fromAddress, String 
subject, String content)
   {
      boolean status = false;

      try
      {
         Date dateStamp = new Date();
         MimeMessage email = new MimeMessage(mailSession);

         email.setFrom(new InternetAddress(fromAddress));
         email.setRecipients(Message.RecipientType.TO,
                             InternetAddress.parse(toAddress, false));
         email.setSubject(subject);
         email.setText(content);
         email.setHeader("X-Mailer", "JavaMailer");
         email.setSentDate(dateStamp);

         Transport.send(email);
         status = true;
      } // end try

      catch (Exception e)
      {
         status = false;
         e.printStackTrace();
      } // end catch

      return status;
   } // end sendEmail

Again, the CustomerServiceJavaBean is part of the Web tier, and it's from this level that Geronimo sends out e-mails. The mailSession is obtained via a JNDI lookup displayed in the previous listing, and it's used to create a MimeMessage, which is the actual object representing an e-mail message. After the relevant attributes have been set, the message is sent to the mail server via the Transport object.

You'll want to verify that messages are successfully received by the mail server. To do this, you need a console-based client that can connect to the mail server, extract all messages pertaining to a given user, and simply output the contents of each message to the console. Listing 7 contains a partial listing of this client, called Reader, which generates mail sessions.


Listing 7. Reader.java method to generate JavaMail sessions
private Session generateSession(String host, String user, String password)
   {
      authentication = new PasswordAuthentication(user, password);

      Properties properties = new Properties();
      properties.put("mail.host", host);
      properties.put("mail.debug", "false");
      properties.put("mail.user", user);
      properties.put("mail.store.protocol", "pop3");

      Session session = Session.getInstance(properties, this);

      return session;
   } // end generateSession

The PasswordAuthentication verifies the given user name and password. Notice that this method doesn't make use of JNDI. Instead, it sets relevant properties that are then used to create the mail session. Listing 8 shows the actual code that extracts the e-mail messages.


Listing 8. Reader.java method to read all incoming e-mail for a given user
  
protected void readEmail(String host, String username, String password)
   {
      Store store = null;
      Folder inbox = null;

      try
      {
         Session mailSession = generateSession(host, username, password);

         store = mailSession.getStore();
         store.connect();
         Folder folder = store.getDefaultFolder();
         inbox = folder.getFolder("inbox");

         inbox.open(Folder.READ_ONLY);
         Message[] messages = inbox.getMessages();

         System.out.println("Inbox for userID: " + username);
         System.out.println("inbox size: " + messages.length);
         System.out.println("*****");

         for (int x = 0; x < messages.length; x++)
         {
            MimeMessage email = (MimeMessage)messages[x];

            System.out.println("FROM: " + email.getFrom()[0].toString());
            System.out.println("TO: " + 
email.getRecipients(Message.RecipientType.TO)[0].toString());
            System.out.println("DATE: " + email.getSentDate());
            System.out.println("SUBJECT: " + email.getSubject());
            System.out.println("CONTENT: " + email.getContent());
         } // end for

         System.out.println("*****");
      } // end try

      catch (Exception e)
      {
         e.printStackTrace();
      } // end catch

      finally
      {
         try
         {
            inbox.close(true);
            store.close();
         } // end try

         catch (Exception e)
         {
            e.printStackTrace();
         } // end catch
      } // end finally
   } // end readEmail

After a mail session has been created, it's used to obtain a message store that connects to the mail server. The inbox is a reserved folder name, and when a connection has been established, all the messages in this folder can be retrieved. After the messages have been retrieved, it's a simple matter of displaying their contents to the console.

The Customer Service utility is now ready to deploy on Geronimo:

  1. Modify the CustomerService/resources/build.properties file, and make sure the directory locations are properly defined.
  2. Open a console and change directories to the location of CustomerService/build.xml, and type ant. This builds and deploys the application that can be accessed at http://localhost:8080/service. It also packages the client Reader application. Figure 3 shows what the Groups Contact page looks like.

Figure 3. Send customer e-mail via Groups Contact page
Send customer e-mail via Groups Contact page

Here, the user has retrieved all customers in the Java special interest group. Now the user has decided to send one e-mail to the customer, John Smith. If necessary, the user can select all the customers displayed, and the same e-mail will go to each of them, provided the domain name (localhost) is valid and their user IDs have been created in the mail server. After the e-mail is sent, debug messages are displayed in the Geronimo output console, like those shown in Figure 4.


Figure 4. Geronimo console with JavaMail debug messages
Geronimo console with JavaMail debug messages

According to the output above, the message to John Smith was successfully sent to the James Mail Server. The next step is to examine the mail server to confirm the e-mail is residing in James. Run the Reader with the following: client localhost smith smith. This should produce output similar to that shown Figure 5.


Figure 5. Client output for e-mail received from James
Client output for e-mail received from James

All the messages sent to John Smith from the Group Contacts page should be displayed in the client's output. E-mail messages sent from Geronimo have been sent successfully to the James Mail Server. That's it for accessing JavaMail resources in JNDI!


Summary

In this article, you learned how to configure and call a JavaMail resource group. The Customer Service utility demonstrated how to access this resource from JNDI by sending an e-mail to customers from the Web interface to the Apache James Mail Server. Then you implemented a dedicated console application to verify that incoming e-mails were received. The next and final article in this series will discuss JNDI access to URL connections, which you'll use to complete the Customer Service utility.



Download

DescriptionNameSizeDownload method
Part 3 source codeCustomerService-part3.zip589KB HTTP

Information about download methods


Resources

Learn

Get products and technologies

Discuss

About the author

Dale de los Reyes graduated with a degree in computer science from California Polytechnic State University, San Luis Obispo in 1996. His experience includes application development in J2EE, C++ for Microsoft® Windows®, and COBOL for Mainframes. In his spare time he takes photographs, practices martial arts, and pursues independent projects.

Comments



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source, Java technology, WebSphere
ArticleID=195840
ArticleTitle=Apache Geronimo JNDI naming and Java resource connection pools, Part 3: Mail sessions
publish-date=02132007
author1-email=dreyes4@hotmail.com
author1-email-cc=ruterbo@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers