Friday, December 9, 2011

WebSphere 6.1 and NatJet

In this post, I will show how to deploy a simple NatJet Web application on WebSphere 6.1.

WebSphere is the IBM web app server. Version 6.1 is the first version to rely on Java 5 which is a minimum for NatJet. WebSphere uses its own Java runtime : IBM Java runtime. It is installed when installing WebSphere.

The IBM documentation says that WebSphere 6.1 supports Servlet 2.4. The default Servlet of a NatJet 4.0 project is 2.5. I have noticed that for some projects I got an error with the default NatJet project. I’ve needed to change the web.xml to have a 2.4 declaration and then it  has worked.

When writing this post, I was not anymore on the default Websphere 6.1 : I had added two feature packs : EJB 3.0 and WebService supports (it was a 6.1.0.13). I didn’t found anything on the documentation, but it seems that the feature packs add the support of Servlet 2.5, because I haven’t had any problem when writing this tutorial with a Servlet 2.5 declaration in the web.xml. This sound quite possible because one difference between 2.4 and 2.5 is the support of annotations and this is needed for EJB and WebServices.

NatJet 4.0 supports servlet specification 2.4 and plus. The 2.4 minimal request is due to Spring listener RequestContextListener, we rely on.

Complete JEE application servers like WebLogic and JBoss or WebSphere come with some additional libraries. By default, these jar libraries supersedes the ones delivered with your web app. I won’t go deeper on this point as it was not a problem with NatJet.

For this kind of server, security is a must and you must follow production standard : this means mainly in our case, two things :

  • deploying with a EAR
  • a database connections pool handled by the server.

NatJet with WebSphere

Deploying a NatJet application on a WebSphere server implies 2 additional tasks compare to deploying on Tomcat. These tasks are common tasks for deploying on WebSphere :

  • building an EAR file instead of a simple WAR
  • configuring the database pool

As we seen before some versions 6.1 of WebSphere supported only servlet 2.4. In this case we need adapting the web.xml to WebSphere with moving it back to 2.4.

I want this post to be a good starting point to somebody not really aware of WebSphere administration. As guiding someone through WebSphere administration is quite a long process, I will split the problem in two posts :

  • this post will describe
    • the basic NatJet project and its ant task
    • and deploying onto WebSphere 6.1
  • A second post that will describe the configuration of the database pool.

To allow you to follow me easily, I will create a very simple NatJet project : in this post, it will not use any database connection.

At the end of this post, I show you how to handle some problem you may encounter as changing the servlet specification of you web.xml.

Part I : Simple NatJet Web App

In this post, I will work with a very simple NatJet Web App without database connection. This part is mainly on NatJet .

Creating a simple NatJet Web App

I will go quickly to the essential, as I suppose you may already be familiar with some basics of NatJet.

In the NatJet Perspective, select in the File menu New –> NatJet Project Wizard.

  • The name of the new project will be NatJetWebSphere.
  • I let the target runtime as : Apache runtime
  • I change the Dynamic web version to 2.5. When doing so, the Configuration move to Custom instead of NatJet
  • I put back in Configuration, “NatJet v4.0 Project”

Press 3 times the button Next to get the “Configure NatJet Project” screen.

Select Custom Package root and enter the following indication :

  • Package root : fr.natsystem.demo.was
  • Main Module Name : NatJetWebSphere
  • Package name for the main Module : fr.natsystem.demo.was.ui

And then press the Finish button.

The project is created.

Creating Ant configuration

At this point, we want to deploy on WebSphere and we need to build a EAR file. We will do this using an ant task.

I already went through a quite complete post on using ant with NatJet : http://insidenatjet.blogspot.com/2010/11/using-ant-with-natjet.html. I will go quickly on this point.

We will work with a buildConfDir folder that will handle configuration files that may be specific to an environment.

We will store the application.xml file needed for a EAR in this folder.

We will then create the build.xml ant file and the build.properties. Inthis file we will add the ant task that generate the EAR file at the end.

Creating buildConfDir and application.xml

First we will create the new folder as root of our project.

Right click on the project node in the project explorer, and select New –> Other…. In the dialog box that popup, select the folder “General” and the node “Folder” and then press Next.

Enter “buildConfDir” as folder name and press Finish. The folder is created.

Then we will create the PRODapplication.xml file that will be used by the ant task.

Right click on the new “buildConfDir” node in the project explorer, and select New –> Other…. In the dialog box that popup, select the folder “XML” and the node “XML” and then press Next.

Enter “PRODapplication.xml” as file name and press Finish. The file is created and opened. As it has been opened with the wrong editor, close it and open it with the XML Editor.

Complete the file with the following code :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN" "http://java.sun.com/dtd/application_1_3.dtd">

   <application id="Application_ID">
      <display-name>NatJetWebSphere</display-name>
      <module id="WebModule_1">
         <web>
            <web-uri>NatJetWebSphere.war</web-uri>
            <context-root>/NatJetWebSphere</context-root>
         </web>
      </module>
   </application>

I put in bold, the part of the file that may need to be adapted to your configuration/project.

Creating build.properties

This file is created at the root level of the project

Right click on the project node in the project explorer, and select New –> Other…. In the dialog box that popup, select the folder “General” and the node “File” and then press Next.

Enter “build.properties” as file name and press Finish. The file is created and opened for editing. I click on the tab build.properties on the bottom of the editor to use the text editor

Complete the file with the following code :

project-name = NatJetWebSphere
tomcat-home = C:/NatJet4.0.0/thirdparty/apache-tomcat-6.0.29
builder=Nat System
#Specific environnement propeties
dtdLocation="../webapps/myProject/hibernate-configuration-3.0.dtd"

contextFile=contextProd.xml
#Contient les fichiers de configuration
buildConf-directory=buildConfDir

For explanation on this file refer to my post on ant with NatJet : http://insidenatjet.blogspot.com/2010/11/using-ant-with-natjet.html.

You may need to adapt the tomcat-home repository to the one available on you PC.

Creating build.xml ant file

This file is also created at the root level of the project

Right click on the project node in the project explorer, and select New –> Other…. In the dialog box that popup, select the folder “XML” and the node “XML” and then press Next.

Enter “build.xml” as file name and press Finish. The file is created and opened. As it has been opened with the wrong editor, close it and open it with the XML Editor.

Complete the file with the following code :

I put in bold the part that may be specific to the project or the standard configuration. These parts are :

  • the project name
  • the junit.package that will be excluded from compilation
  • the compile task were we force Java 1.5 as JDK to be compliant with WebSphere 6.1
  • the ant task at the end : this is the task that use the PRODapplication.xml file created before

<?xml version="1.0" encoding="UTF-8"?>
<project name="NatJetWebSphere" basedir="." default="war">

    <property file="build.properties" />

    <!-- Define Web Project Environnement -->
    <property name="source-directory"  value="src" />
    <property name="classes-directory"  value="build/classes" />
    <property name="web-directory"  value="WebContent" />
    <property name="war-file-name" value="${project-name}.war" />
    <property name="web-xml-file" value="${web-directory}/WEB-INF/web.xml" />
  
    <!-- Allow to exclude jUnit testcase—>
<property name="junit.package" value="fr/natsystem/demo/test/**" />

  
    <fail message="You need to specify contextFile property" unless="contextFile"/>
  
    <tstamp prefix="build-info">
        <format property="current-date" pattern="d-MMMM-yyyy" locale="fr" />
        <format property="current-time" pattern="hh:mm:ss a z" locale="fr" />
        <format property="year-month-day" pattern="yyyy-MM-dd" locale="fr" />
    </tstamp>
    <property name="build-directory" value="build" />

    <path id="project-classpath">
        <fileset dir="${web-directory}/WEB-INF/lib" includes="*.jar" />
        <fileset dir="${tomcat-home}/bin" includes="*.jar" />
        <fileset dir="${tomcat-home}/lib" includes="*.jar" />
    </path>

    <target name="clean">
        <delete dir="${classes-directory}" />
        <mkdir dir="${classes-directory}" />
    </target>

<target name="clean-context" description="Prepare files that needs to be modified depending on environment">
    <delete file="${source-directory}/hibernate.cfg.xml"/>
    <copy file="${source-directory}/hibernateAntMaster.cfg.xml" tofile="${source-directory}/hibernate.cfg.xml"/>      
</target>

<target name="copy-context-delivery" depends="clean-context" description="Task that updates files for the target environment">
    <replace file="${source-directory}/hibernate.cfg.xml" token="@@DTD-Declaration@@" value="${dtdLocation}"/>
    <delete file="${web-directory}/META-INF/context.xml"/>
    <copy file="${web-directory}/META-INF/${contextFile}" tofile="${web-directory}/META-INF/context.xml"/>
</target>
  
    <target name="copy-context-dev" depends="clean-context" description="Task to set the development environment, should be used to update modification of master files">
    <replace file="${source-directory}/hibernate.cfg.xml" token="@@DTD-Declaration@@" value="http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"/>
    <delete file="${web-directory}/META-INF/context.xml"/>
    <copy file="${web-directory}/META-INF/contextDev.xml" tofile="${web-directory}/META-INF/context.xml"/>

    </target>
  
    <target name="copy-non-java-files">
        <copy todir="${classes-directory}" includeemptydirs="false">
            <fileset dir="${source-directory}" excludes="**/*.java" />
        </copy>
    </target>

   <!-- Pour WAS java 1.5 -->
    <target name="compile" depends="clean,copy-non-java-files">
        <echo>jUnit Package ${junit.package}</echo>
        <javac srcdir="${source-directory}" destdir="${classes-directory}"
        classpathref="project-classpath"
               compiler="javac1.5"
            source="1.5"
            target="1.5"
        excludes="${junit.package}"/>
    </target>

    <target name="war" depends="compile">
        <mkdir dir="${build-directory}/bin" />
        <delete file="${build-directory}/bin/${war-file-name}" />
        <war warfile="${build-directory}/bin/${war-file-name}" webxml="${web-xml-file}">
            <classes dir="${classes-directory}" />
          
            <fileset dir="${web-directory}">
                <!-- Need to exclude it since webxml is an attribute of the war tag above -->
                <exclude name="WEB-INF/web.xml" />
                <!-- Exclude NatJet xml files for the description of panels -->
                <exclude name="resources/**" />
                <excludesfile/>
            </fileset>
            <manifest>
                <attribute name="Built-By" value="${builder}" />
                <attribute name="Built-On" value="${build-info.current-date}" />
                <attribute name="Built-At" value="${build-info.current-time}" />
            </manifest>
        </war>
    </target>
   
    <!-- CREATION DU binaire EAR de PROD -->
    <target name="ear-PROD" depends="war"
        description="création du fichier EAR de Production de l'application">
        <ear destfile="${build-directory}/bin/${project-name}.ear" appxml="${basedir}/${buildConf-directory}/PRODapplication.xml">
            <fileset dir="${build-directory}/bin" includes="${war-file-name}"/>
            <manifest>
                <attribute name="Environment" value="PROD" />
                <attribute name="Built-By" value="${builder}" />
                <attribute name="Built-On" value="${build-info.current-date}" />
                <attribute name="Built-At" value="${build-info.current-time}" />
            </manifest>
        </ear>
    </target>
   

</project>

For explanation on this file refer to my post on ant with NatJet : http://insidenatjet.blogspot.com/2010/11/using-ant-with-natjet.html.

In this version, we rely on a buildConfDir where we store the configuration file : in my previous post we store the file directly in the project. The approach in this post is better as we do not deliver configuration file from other environments.

All the files used by this ant file are not available at this point of the project.

Fixing Java files

If we try to build the project with ant, we may have the following error fro 6 java files :

src\fr\natsystem\demo\was\NatJetWebSphere.java:6: package fr.natsystem.resource.localization.NatJetWebSphere does not exist
[javac] import fr.natsystem.resource.localization.NatJetWebSphere.*;

We are going to fix these errors.

Before starting, we need to rebuild with Eclipse our project : the ant task has deleted all class files. Thus a lot of your Java class may shows up in error (already or at the first save you will do).

  1. To fix this point, go to menu “Project” and select menu item “Clean…”
  2. Select your project : and press OK. This will rebuild the project.

If you do not do this after an incorrect ant build, you will have plenty of errors in your project as the class files have been deleted.

Then for each of the files with the error, you edit the file and do an “Organize imports” (Crt Shift O) and save it. This will delete from the Java class the import to an empty package.

Then you can rebuild using ant. This time, you should get the following output

Buildfile: C:\Users\jltho.NATSYSTEM\Documents\wksp400\NatJetWebSphere\build.xml
clean:
   [delete] Deleting directory C:\Users\jltho.NATSYSTEM\Documents\wksp400\NatJetWebSphere\build\classes
    [mkdir] Created dir: C:\Users\jltho.NATSYSTEM\Documents\wksp400\NatJetWebSphere\build\classes
copy-non-java-files:
     [copy] Copying 12 files to C:\Users\jltho.NATSYSTEM\Documents\wksp400\NatJetWebSphere\build\classes
compile:
     [echo] jUnit Package fr/natsystem/demo/test/**
    [javac] Compiling 12 source files to C:\Users\jltho.NATSYSTEM\Documents\wksp400\NatJetWebSphere\build\classes
    [javac] Note: Some input files use or override a deprecated API.
    [javac] Note: Recompile with -Xlint:deprecation for details.
war:
    [mkdir] Created dir: C:\Users\jltho.NATSYSTEM\Documents\wksp400\NatJetWebSphere\build\bin
      [war] Building war: C:\Users\jltho.NATSYSTEM\Documents\wksp400\NatJetWebSphere\build\bin\NatJetWebSphere.war
ear-PROD:
      [ear] Building ear: C:\Users\jltho.NATSYSTEM\Documents\wksp400\NatJetWebSphere\build\bin\NatJetWebSphere.ear
BUILD SUCCESSFUL
Total time: 10 seconds

If you do a refresh of the project (F5) you should now see in build/bin the file NatJetWebSphere.ear.

 

Part II : Deploying on WebSphere 6.1

Your server should be started.

To know if it is started you can try to connect to the administrative console : https://localhost:9043/ibm/console/logon.jsp

If you got the login form, the server is started.

If this is not the case go to your Windows menu : “Tous les programmes” –> “IBM Websphere” –> “Application Server V6.1” –> Profils –> AppSrv01 –> “Démarrer le serveur”.

Connect to the administrative console : https://localhost:9043/ibm/console/logon.jsp

You will need a login account. Then select in “Applications” the link : “Installation d’une nouvelle application” (sorry but my web console is in French).

NJWAS01installed

In the next page, using the Browse button to select your EAR.

NJWAS02installedSelectEAR

And then press Next/Suivant button. You should got after a few seconds, the following page :

NJWAS03installedOption

Just press Next/Suivant on this first step.

After a while you should get the mapping page (step 2) :

NJWAS04installedMapping

Just press Next/Suivant, you should get the page (step 3) :

NJWAS05installedStep3

Just press Next/Suivant, to get the summary page

NJWAS06installedStep4SUmmary

Then press Terminate/Terminer. You have to wait several long seconds before to get the result.

Then press Save and go to start the application.

You should get on the top of the application page after a while :

NJWAS07Started

Testing

At this point you should be able to display your web app in the browser at the following URL : http://localhost:9080/NatJetWebSphere

It should display the standard page of a new NatJet project.

 

Problems you may encounter

Servlet 2.5 does not work

If your WebSphere 6.1 is really the basic version, it may not support servlet 2.5. In this case, you need to change your web.xml file.

If you don’t you wil get an error message when deploying or starting the web  app.

To fix your problem, you need to edit the WebContent/WEB-INF/web.xml file, and change the web-app declaration tag of your XML file.

You should have now the following code :

<?xml version="1.0" encoding="UTF-8"?>

<web-app id="WebApp_ID" version="2.4"
    xmlns="
http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>NatJetWebSphere</display-name>
    <servlet>
        <servlet-name>WebContainerSpringServletNS</servlet-name>
        <servlet-class>
            fr.natsystem.natjet.echo2.webcontainer.WebContainerSpringServletNS</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>WebContainerSpringServletNS</servlet-name>
        <url-pattern>/app</url-pattern>
    </servlet-mapping>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
    <session-config>
        <session-timeout>5</session-timeout>
    </session-config>
</web-app>

This point should fix your problem. This is the way to move back a NatJet web app to a servlet 2.4 container.

 

Deploying EAR on WebSphere doesn’t finish

Sometimes deploying on WebSpshere 6.1, I get stuck on the following items (action SEJ0400I) :

ADMA5005I: L'application NatJetWebSphere est configuré dans le référentiel WebSphere Application Server.

SECJ0400I: La mise à jour de l'application NatJetWebSphere avec les informations appContextIDForSecurity information a abouti.

 

 
When I get this, I first wait one or two minutes as this task can be long, and the if nothing change I click on the link “application entreprise” on the left panel. The new page have a warning message on the top :
 
NJWAS08Blocked
 
Click on the link “Save/Sauvegarder”.
Then I can start your web app.
 
This work around help me a lot when working on WebSphere 6.1. I’m not a WebSphere admin and I didn’t have time to understand what was going on, but the trick does the job.
 

Conclusion

We’ve seen how to deploy a simple NatJet applications on WebSphere 6.1 and how to handle some little problems.

In this post you have a complete build.xml sample that will help you build a EAR with ant from a NatJet project.

Deploying a NatJet web app that used a database connection (if you are using the server database connection pool) may be a bit more complicated (due to WebSphere). I will try to write soon a post on this subject.

Wednesday, September 7, 2011

How to send email from a NatJet WebApp

Having to send an email, it is a quite common task for a Web App : it may be a receipt, a confirmation message… This kind of email are automatically sent by the web application : there is no need for a human interaction.

This post is a tutorial on how to send an email from a NatJet application.

Architecture

The solution will rely on :

  • NatJet 4.0
  • Spring
  • JavaMail.

Testing will be achieved using jUnit 4.0.

Introducing JavaMail

The main Java library to send email is JavaMail : This is the Oracle’s (former Sun) standard to send email. JavaMail allows a Java application to behave as a client mail : you still need a mail server as Microsoft Exchange, SendMail or any email services like GMail or Yahoo Mail.

JavaMail behaves as an abstraction layer on top of different mail protocols as IMAP or SMTP that allows communication between a client mail and its server.

NatJet 4.0 Architecture with Spring

NatJet 4.0 includes Spring 3.0. Spring includes some services to configure and use easily JavaMail.

As always with Spring, this solution is a nice and easy way to separate the configuration of the communication between the client and the server from you application code.

The Bean org.springframework.mail.javamail.JavaMailSenderImpl from Spring will allows the configuration of the service. It’s part of NatJet 4.0.

Remember that the NatJet application and NatJet application context are two NatJet beans created by Spring : so it will be quite easy to inject the Spring mail service inside a NatJet application.

Spring Beans

The solution relies on 3 beans

  • mailSender : this is the Spring Bean that handles the JavaMail configuration. The implementation is org.springframework.mail.javamail.JavaMailSenderImpl as seen before.
  • sendMailManager : this is a bean that we will develop to render the service of sending an email. This bean relies on the previous bean. This is where we will code using the JavaMail API
  • NatJet Application bean (called applicationInstance) : This bean can be simply retrieved from NatJet with the getApp() method. That’s why we will simply inject the bean sendMailManager there allowing an easy access to it.

 

Configuration of the Project

The first step is to create a NatJet project for the demo. Then we will add the necessary JavaMail jars. And we will configure Spring to create and inject the correct beans.

Creating a new NatJet Project

In the NatJet Perspective, select in the File menu New –> NatJet Project Wizard. The name of the new project will be NatJetMail. Press 3 times the button Next to get the “Configure NatJet Project” screen.

Select Custom Package root and enter the following indication :

  • Package root : fr.natsystem.demo.email
  • Main Module Name : NatJetMail
  • Package name for the main Module : fr.natsystem.demo.email.ui

TE02Creationprojet

And then press the Finish button.

The project is created.

Add JavaMail Jar

For the demo, we need to download JavaMail.jar and the Activation.jar if you use Java 5.0 as I do.

Go to the Oracle website : www.oracle.com/technetwork/java/javamail. Select on the right part the Download link.

I’ve used the JavaMail 1.4.4 version. Press the Download button. Read and accept the Licence Agreement to get access to the link : javamail1_4_4.zip. Download and save the file.

TE07ConfigureDownload

Extract the file, we will use only the jar file mail.jar in javamail1_4_4.

If you are using Java 5.0 we need as specified on Oracle website to download the JavaBean Activation Framework. The best, is starting from www.oracle.com/technetwork/java/javamail, click on link “Javabeans Activation Framework (JAF)”.

Then on the new page, select JAF_1.1.1 link. On the next page, select Download button. On the new page, Accept License Agreement et click on link jaf-1_1_1.zip.

Download and save on your disk, then extract files. We will use only the jar file activation.jar in jaf-1_1_1.

To add the two jars to your NatJet project, in Eclipse open the node WebContent/WEB-INF/lib. Select the jar mail.jar in javamail1_4_4 in the Windows Explorer and drag and drop it on the lib node. Do the same with the file activation.jar in jaf-1_1_1.

TE08ConfigureAjoutMail.jar

You’ve just added two new jars in your NatJet project :

  • activation.jar
  • mail.jar

 

Defining beans in natjetInstanceContext.xml

In WebContent/WEB-INF you can find several configuration xml file for Spring. We will modified natjetInstanceContext.xml to add there the declaration of the two new beans : mailSender et sendMailManager.

This is also where you can find the declaration of the NatJet Application bean applicationInstance that we need to modify : we need to inject the new sendMailManager bean.

In NatJetMail project select natjetInstanceContext.xml node in WebContent/WEB-INF, click right and select Open with… –> XML editor.

The XML file is opened. Modify the file as following (new or modified sections are in bold).

Order of beans are important, so we need to add the two new beans declaration before the import declaration.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <!-- <bean/> definitions here –>

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com"/>
<property name="username" value="myemail@mycompany.fr"/>
<property name="password" value="mypassword"/>
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<!-- used by gmail smtp server -->
<prop key="mail.smtp.starttls.enable">true</prop>
</props>
</property>
</bean>

<bean id="sendMailManager" class="fr.natsystem.demo.email.servicemail.SendMailManager">
<property name="mailSender" ref="mailSender"/>
</bean>


<import resource="ContextBean/emptyContextBean.xml" />


<bean id="applicationInstance" class="fr.natsystem.demo.email.NatJetMail"
        scope="prototype"> 
   <property name="context"> 
        <ref bean="natjetSessionContext" /> 
   </property> 
   <property name="sendMailManager" ref="sendMailManager"/>         
</bean>

<bean id="mainLayout" class="fr.natsystem.demo.email.ui.Layout3Panels"
        scope="prototype"> 
</bean>
</beans>

Be careful ! You need to adapt at least the username and password fields, but you may need to change more parameters depending of your email server.

For GMail or Google Apps Gmail, username is your email : myaccouunt@gmail.com for a  personnal gmail account or myemail@mycompany.fr if you are using Google Apps. The password is the one of your email account.

Save and close the file.

Modifying Application Class : NatJetMail.java

In the src node of your project, you can find the Application class NatJetMail in fr.natsystem.demo.email.

We need to add a new property and setter to store and retrieve the sendMailManager bean. Be careful to be consistent with the declaration we’ve made in the previous chapter : the name of the property in the java class should match the name of the property in the bean.

Edit the class and add the sendMailManager property and its getter and setter as follow.

public class NatJetMail extends AbstractNatJetMail {
    private static final long serialVersionUID = -4417253215596027617L;
    //Spring Bean : Email service
    private SendMailManager sendMailManager;
   
  public NatJetMail () {
    super();
  }
 
  public fr.natsystem.natjet.window.NsMainLayout initApp() {
    NsLogger.debug(this, " init application ");
    fr.natsystem.natjet.window.NsMainLayout natJetMainWindow = (fr.natsystem.natjet.window.NsMainLayout) NsConfig.getSpringBean("mainLayout");
    setMainWindow(natJetMainWindow);
    return natJetMainWindow;
  }

public SendMailManager getSendMailManager() {
    return sendMailManager;
}

public void setSendMailManager(SendMailManager sendMailManager) {
    this.sendMailManager = sendMailManager;
}
 
 
}

The class is in error as the SendMailManager as not yet been defined. Save and close.

Creating SendMailManager class

This is the main part of the coding. This is where we send email using JavaMail API.

We will do 2 samples :

  • a simple email message
  • a mail with an attachment as a JPEG file or a PDF file

Create the class SendMailManager

Select in the File menu, the New –> Class item.

Enter as follow :

  • Package : fr.natsystem.demo.email.servicemail
  • Name : SendMailManager

This has to map the Spring declaration of the bean sendMailManager.

TE05ClassMailManager

Press Finish button. The class is created, we need now to complete it.

We need, first to add the property we specified in the bean declaration : mailSender and it setter.

At this point, the class should look like this :

package fr.natsystem.demo.email.servicemail;

import org.springframework.mail.javamail.JavaMailSender;

public class SendMailManager {
    private JavaMailSender mailSender;

    public void setMailSender(JavaMailSender mailSender) {
        this.mailSender = mailSender;
    }
   
}

 

Update NatJetMail

Before continuing, edit the class NatJetMail.java and do an Organize Import (ctrl Shift O). Save. This will add the correct import for SendMailManager. You shouldn’t have any error left.

Method to send a simple mail

The first sample we are going to do is sending a simple email in which we will specify :

  • Recipient
  • Subject
  • Body

For this we will create the method sendSimpleMail:

public void sendSimpleMail(final String pEmail, final String pSubject,  final String pEmailText) {
    
     MimeMessagePreparator preparator = new MimeMessagePreparator() {
   
        public void prepare(MimeMessage mimeMessage) throws Exception {
   
            mimeMessage.setRecipient(Message.RecipientType.TO,
                    new InternetAddress(pEmail));
            mimeMessage.setText(pEmailText);
            mimeMessage.setSubject(pSubject);
        }
    };
    try {
        this.mailSender.send(preparator);
    }
    catch (MailException ex) {
        // simply log it and go on...
        System.err.println(ex.getMessage());           
    }
}

We need to add the following import declaration :

import javax.mail.Message;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessagePreparator;

Save the java class.

Using the service form NatJet

To use the service we will modify the MainPanel panel.

MainPanel.xml

In WebContent/resources/NatJetMail select the MainPanel.xml and double click on it to open it with NatJet editor.

We will add :

  • 2 labels : “Email recipient” and “Text email”
  • 1 Textfield emailTF for the email address with the Regex Type email.
  • 1 Textarea textTA for the text
  • 1 PushButton sendSimpleMailPB to send the email

It could look to the following panel :

TE03Ecran

Save the panel.

Calling the mail service from NatJet

Select the pushbutton Send, and in the Properties view select Executed event and press the arrow. The java code for MainPanel.java is displayed.

To complete the action, we need to retrieve the service bean to send email : this is quite simple as there is a method getApp() to retrieve the NatJet application instance. Then as we add a getter to the bean in this class, we have the bean and we just need to trigger the method handling the correct parameters :

  • emailTF.getText() to retrieve the email input by the user
  • For the subject we will use a static value : “Simple mail”
  • textTA.getText() to retrieve the text.

The java code of the method is as follow :

@Override
public void sendSimpleMailPB_ExecutedEvent(NsExecutedEvent arg0){
    getApp().getSendMailManager().sendSimpleMail(emailTF.getText(), "Simple mail", textTA.getText());
}

Save the java class.

Testing

Testing from NatJet Web App

First we will test from the NatJet Web App

At this point it is easy to test your NatJet Web App as usual : just select your NatJetMail node and select Run As >  Run on server. Select you server and run.

You should get an opened browser with your NatJet page.

Enter an email and a text message and press Send button. A quick “Please wait…” message may appear and then you should receive an email with subject “Simple mail”.

Testing from JUnit

As we build a service class, it can be efficient to test the service from JUnit.

The first step is to add the JUnit library to the project. Then we will build a JUnit test class and the test configuration file.

Adding JUnit 4 to a NatJet project

In the Package Explorer view, select the node of NatJetMail project and click right. Select “Build path” menu and “Add library…” menu item. The dialog “Add Library” is opened.

Select JUnit and press “Next>” button. On next screen, select JUnit 4 as JUnit library version, and then press Finish.

TE34junitAddJarJunit

A JUnit 4 node will appear in Package Explorer view under your project node NatJetMail.

Adding a JUnit test class

In the File menu, select New –> Other… The dialog New is opened.

Select JUnit Test Case in the folder JUnit and press Newt> button.

On the New JUnit Test Case dialog :

  • Select radio button “New JUnit 4 test”
  • Package : fr.natsystem.test.demo.email.servicemail : this naming convention allows to exclude easily all test package when packaging the final production delivery.
  • Name: TestSendMailManager

You can select class SendMailManager for class under test, but this will only create an empty test method for SendSimpleMail.

The class is created, then we will add some Spring plumbing :

  • First we will add the RunWith and ContextConfiguration annotations to tell JUnit that we will used Spring to run the test and use a Spring Configuration file
  • Then, we will add a Autowired property to store and retrieve the bean sendMailManager that we want to test.

To finish, we need to call the service. In our case, this is quite easy we just need to call the method with some parameters.

The final java code for the class is :

package fr.natsystem.test.demo.email.servicemail;

import static org.junit.Assert.fail;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import fr.natsystem.demo.email.servicemail.SendMailManager;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"EmailTestConfig.xml"})
public class TestSendMailManager {
   
    @Autowired
    private SendMailManager sendMailManager;

    /**
     * Test method for {@link fr.natsystem.demo.email.servicemail.SendMailManager#sendSimpleMail(java.lang.String, java.lang.String, java.lang.String)}.
     */
    @Test
    public final void testSendSimpleMail() {
        sendMailManager.sendSimpleMail("testaccount@mycompany.fr", "Suject : testSendSimpleMail",
"This is a simple JUnit test");
    }

}

Save the java class.

Creating JUnit Spring Configuration file

In the ContextConfiguration annotation we specified a file name : this is the configuration file Spring will use. This file need at least to specify the sendMailManager to allow the Autowired annotation to work.

Select the package fr.natsystem.test.demo.email.servicemail, then right click and select New –> Other… The dialog New is opened.

Select XML in the folder XML and press Newt> button.

Enter EmailTestConfig.xml in the file name and press Finish.

The file is created, closed the tab and reopen it with a right click and “open wit XML editor”.

Enter the following code:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
   
    xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <!-- <bean/> definitions here
        <property name="loggerFormat" value="[%id:%ip] %M : ATtention %M est très couteux" />
    -->
    <bean id="nslogger" class="fr.natsystem.nslogger.NsLogger">
        <property name="loggerFormat" value="***[%id:%ip]" />
        <property name="storeRequest" value="true" />
        <property name="dumpRequest" value="false" />
        <property name="logElapsedTime" value="false" />
    </bean>
   
    <!-- Pour JUnit -->
    <bean id="nsconfig" class="fr.natsystem.nsconfig.NsConfig">
    </bean>

    <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
          <property name="host" value="smtp.gmail.com"/>
          <property name="username" value="testaccount@mycompany.fr"/>
          <property name="password" value="mypassword"/>
        <property name="javaMailProperties">
        <props>
            <prop key="mail.smtp.auth">true</prop>
            <!-- used by gmail smtp server -->
            <prop key="mail.smtp.starttls.enable">true</prop>
        </props>
        </property>
    </bean>


    <bean id="sendMailManager" class="fr.natsystem.demo.email.servicemail.SendMailManager">
          <property name="mailSender" ref="mailSender"/>
    </bean>
</beans>

Save the file.

Be careful to change at least the username and password properties of the mailSender bean.

Run JUnit test

This is as for all JUnit test, right click on the TestSendMailManager java class, select the menu Run As -> JUnit Test.

The test is launch and you should receive quickly a new email on your test account.

This test does not allow checking the result : thus you may have noticed that we didn’t use the assertEqual method. The only errors you can get is an exception or not receiving an email.

Sending an attached File

To finish, this tutorial we will add the case of sending an email with an attached file.

For this, we will create a new method in SendMailManager.java class and a new test method in TestSendMailManager java.

Sending email with attachment in JavaMail

Open SendMailManager.java and add the following method

public void sendMailWithAttachment( String pEmail,  String pSubject, String pEmailText,  String pFileName) throws IOException {

    // Retrieve the mimeMessage from Spring
    MimeMessage mimeMessage = mailSender.createMimeMessage();

    try {
        mimeMessage.setRecipient(Message.RecipientType.TO,
                new InternetAddress(pEmail));
        // In MultiPart email : setText in the MimeMessage is useless
        // It has to be done on one of the part (usually the first)
         mimeMessage.setSubject(pSubject);

         // --------------------------------Message Part
        MimeBodyPart mbp1 = new MimeBodyPart();
        mbp1.setText(pEmailText);
        // --------------------------------Attachment
        MimeBodyPart mbp2 = new MimeBodyPart();
        mbp2.attachFile(pFileName);

        // --------------------------------Merging message + Attachment
        Multipart mp = new MimeMultipart();

        mp.addBodyPart(mbp1);
        mp.addBodyPart(mbp2);

        mimeMessage.setContent(mp);
        // --------------------------------------------------------//
       
        // Sending the email
        this.mailSender.send(mimeMessage);


    }
    catch (MessagingException e) {
        NsLogger.error(this, "sendMailWithAttachment MessagingException:"+e.getMessage());
        NsLogger.printStack(e);
    }
}

Notice the instruction to retrieve a JavaMail MimeMessage : generally it is created by coding. Working with Spring we retrieve it from the mailSender bean with the correct initialization.

It is then possible to use all standard JavaMail API.

MimeMessage mimeMessage = mailSender.createMimeMessage();

The method can throw an IOException when the filename is incorrect.

Save the java class.

JUnit test.

We add to the JUnit test class 2 new methods :

  • one to test a correct use of the method
  • one to test the reaction with an invalid email address

 

@Test
public final void testSendAttachment() {
    try {
        sendMailManager.sendMailWithAttachment("testaccount@mycompany.fr", "Suject : testSendAttachment", "This is a  JUnit test with a file attached","C:/yourJpeg.jpg" );
    } catch (IOException e) {
        NsLogger.printStack(e);
        fail("incorrect file IOException"+e.getMessage());
    }
}

@Test
public final void testSendAttachmentInvalidEmail() {
    try {
    sendMailManager.sendMailWithAttachment("invalidemail", "Suject : testSendAttachmentInvalidEmail", "This is a  JUnit test with a file attached","C:/yourJpeg.jpg" );
} catch (IOException e) {
    NsLogger.printStack(e);
    fail("incorrect file IOException"+e.getMessage());
} catch (MailException e) {
    assertEquals("Check error message when invalid adress :"  ,"Failed messages: javax.mail.SendFailedException: Invalid Addresses;",e.getMessage().substring(0, 67));
    assertNull("testSendAttachmentInvalidEmail MailException getRootCause:",e.getCause());
}
}

The file C:/yourJpeg.jpg has to exist to work, thus you need to adapt your test with the correct email address (for the first one) and a valid filename for both.

Notice that in the second test we analyze the exception to confirm that it’s an invalid email address.

Conclusion

You have through a complete project using JavaMail, Spring and NatJet. The coding of JavaMail is standard programming minus the configuration part that can be handled transparently by Spring.