Setup MySQL connection in WildFly and Eclipse

You need to Install JDBC Driver on your Application Server, and make sure your database is up and running properly before you start.

Configurations in WildFly

In web panel, go to Configuration -> Subsystems -> Datasources -> Non-XA, and click Add. Basically, Non-XA is generally for development environment or small systems, which does not control transaction across servers. Whereas, XA will take control of transactions across servers, which is more suitable for production environment. Once you select Non-XA and click Add button, it will prompt a list of datasource types. Here I use MySQL as an example, so choose MySQL Datasource and hit next. Then give a name and JNDI name. Click on next button and it turns to JDBC Driver. Because I’ve installed/deployed MySQL Driver, I go to Detected Driver tab, and select something like this: mysql-connector-java-5.1.39-bin.jar_com.mysql.jdbc.Driver_5_1 (don’t do the Fabric one). Next, specify the connection URL, which should include your database name. Also fill out the database username and password, and leave security domain blank. Then go next and test connection. If everything goes right, it should return success. Click finish to store this datasource.

Setup DB Development Connection in Eclipse

First, open Eclipse and switch to Database Development Perspective. In the Data Source Explorer panel, right click on Database Connection -> new. Choose MySQL and hit next. Click on New Driver Definition icon and select the corresponding version of your downloaded connector JAR file. Go to JAR List tab and Clear All the Driver files. Click Add JAR/Zip and select the JAR file you downloaded. Go to Properties and specify Connection URL, Database Name, Password and User ID. Leave Driver Class as it is. Click OK. You should now see everything setup in the previous window, and click on Test Connection. If something gets wrong, compare the to the example I have here.

Database: Your database name
URL: jdbc:mysql://localhost:3306 (by default)
Username: database username
Password: database password
Save password: checked

Click finish to store the configures. (You can hit next to review your settings, but there is nothing to change.) You will see your new database connection listed under Database Connections. Right click on it and connect to database. Database tables are listed under Connection Name/Database Name/Schemas/Database Name/Table. To run a SQL, right click on the connection name to open SQL scrapbook. In SQL Scrapbook, select connection name (database type will be auto selected once you select a name), and then select database. Then you can write and execute any SQL in this scrapbook by right click on any line of your SQL. You can execute all, or few selected lines.

* I find if you use oracle database, you can integrate Beaver DB which is in Eclipse Marketplace in order to create tables and constraints in GUI. In my personal experience, to build a new project, I usually start with creating tables in database, then generate Entity Beans in project in the first place. But if I’m going to switch database types afterward, I just use Entity Beans to generate tables in the new database, instead of writing SQL for all the different Databases.

 

Advertisements

Setup WildFly in Eclipse

First, you need an Eclipse IDE up and running.
Since WildFly needs JDK, you need to add JDK into your Eclipse environment. Do the following to add it:

  1. Make sure you have JDK installed/unzipped on your computer. I like to just unzip it, so that I can have multiple versions of JDKs. Check my another article on how to Unzip JDK from installation package.
  2. Go to Window -> Preferences -> Java -> Installed JREs
  3. Click Add, then select Standard VM, and hit next
  4. Give the directory of your JDK to JRE home. It’ll list all the libraries, and in the JRE name, you should see it start with jdk, not jre. Then, click Finish
  5. Check the jdk which you just added, and apply

Once you added JDK, under Java EE perspective, select Servers tag. Right click on the blank area, then New -> Server.
If you haven’t ever installed WildFly, you need to install WildFly tools First. Here, you go to JBoss by Red Hat folder, and select JBoss/WildFly tools. Hit next, it will start downloading and installation. While it’s installing the WildFly tools, you can download WildFly server if you haven’t had one. Here is the link for version 10.0.0.Final: WildFly.
After you successfully installed WildFly tools and restart your Eclipse, go back to this wizard. Then, you will find JBoss Community folder. Select the WildFly version of whichever you downloaded. Hit next. In this step, for a typical development, you want to select local and Filesystem and shell operations. Uncheck Server lifecycle is externally managed, and choose Create new runtime (if you just download WildFly, then this is the only option. Otherwise, you can select an exist one, which you can view the Runtime Details).
Next, name your server, and specify the WildFly Home Directory, which is the WildFly folder of wherever you unziped your server files, and it should contain the bin folder. Select Runtime JRE. By default, it will pick up the one your Eclipse is using. You can associate Java versions with JREs/JDKs by clicking on Environments. You can also add JREs/JDKs by clicking on Installed JREs. To select a Runtime JRE, you can ether select the java version which you’ve assoicated with a JRE/JDK as the Excution Environment, or directly select the actual JRE/JDK as the Alternate JRE. (If you are using lower version wildfly, you can select a higher version JDK. But no vice versa) The Server base directory is where you want to make a copy of the server, just like a domain in GlassFish. In base directory, the instance of your server specified files will be stored. The configuration file by default is standalone.xml, which stores the configurations of this server instance. Click on Next, and then Finish. Now, you have your WildFly server ready to run.

Bonus Component:

You’ll be probably asked to create user to login WildFly console at first time. Simply go to the bin folder and double click on add-user.bat. Then follow the propt to create a management user.
Note whenever it asks yes/no, type yes/no insteand of y/n. When it asks if you want to add the user to a group, just leave blank and hit Enter. When it asks if the user is going to be used for one AS process to connect to another AS process, you need to type no (unless you know what you are doing).

Once you add a management user, reenter localhost:9990 to login with the user.

Setup GlassFish in Eclipse

First, you need an Eclipse IDE up and running.
Since GlassFish needs JDK, you need to add JDK into your Eclipse environment. Do the following to add it:

  1. Make sure you have JDK installed/unzipped on your computer. I like to just unzip it, so that I can have multiple versions of JDKs. Check my another article on how to Unzip JDK from installation package.
  2. Go to Window -> Preferences -> Java -> Installed JREs
  3. Click Add, then select Standard VM, and hit next
  4. Give the directory of your JDK to JRE home. It’ll list all the libraries, and in the JRE name, you should see it start with jdk, not jre. Then, click Finish
  5. Check the jdk which you just added, and apply

Once you added JDK, still in Preferences window, go to Server -> Runtime Environment, and click Add to start a wizard to setup the server.
If you haven’t ever installed GlassFish, you need to install GlassFish tools First. Note that, you can also install it in Eclipse Marketplace. Here, you go to Oracle folder, and select GlassFish tools. Hit next, it will start downloading and installation. While it’s installing the GlassFish tools, you can download GlassFish server if you haven’t had one. Here are the links for different versions: GlassFish 3.1.2, GlassFish 4.1.1, or Payara.
After you successfully installed GlassFish tools and restart your Eclipse, go back to this wizard. Then, you will find GlassFish folder. Select a GlassFish version. Check Create a new local server. By creating a new local server (domain), you are prevented to mess arround with the original copy of your GlassFish server, so that you can always setup a new domain using this server. Hit next.
Name your server, and specify the GlassFish location, which is the glassfish folder of wherever you unziped your server files, e.g. glassfish4.1.1\glassfish. You may specify the Java location if you need one different to the default one (the one you set for Eclipse). Next.
Click on New Domain icon on the top right line, and set the Domain path to the one you just create. Configure the admin name and password (you can leave password blank, it’s just metter of production environment security). Debug port if for debuging the server (8009). Preserve sessions across redeployment will prevent losing sessions from redeployment (better to uncheck it). Use JAR to deploy is to use JAR instead of WAR, EAR etc (uncheck). Finish.

Finally, you want to create a server by using the Server runtime environment you just set. to do that, switch Eclipse prespective to Java EE and select Servers tag. Right click to New -> Server. Then you can create a server by using the runtime you’ve just created.

Send and read emails with JavaMail API

In this article, I’m going to talk about sending and receiving email with JavaMail API. There are two ways of doing it: manually or with application server such as glassfish.

Manually send email

I personally feel that JavaMail API is somewhat complicated, because there are many way to do the same thing and the components are overwriting each other. Plus, as you test the functions with mail services provided on internet, it’s sometimes hard to track what goes wrong. So, first I’m going to post a way that is tested to work well with my Gmail and Sina mail.

First, you need to import the library. If you’re using maven, then the dependencies would be like this:

 <build>
     <plugins>
         <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-compiler-plugin</artifactId>
             <version>3.5.1</version>
             <configuration>
                 <source>1.8</source>
                 <target>1.8</target>
             </configuration>
         </plugin>
     </plugins>
 </build>

 <dependencies>
     <dependency>
         <groupId>javax.mail</groupId>
         <artifactId>javax.mail-api</artifactId>
         <version>1.5.5</version>
     </dependency>
     <dependency>
         <groupId>com.sun.mail</groupId>
         <artifactId>javax.mail</artifactId>
         <version>1.5.5</version>
     </dependency>
 </dependencies>

There are 2 parts you need to modify for your pom.xml file. The build part is just for me to specify the jdk version, because I’m using some new features of jdk 1.8, and by diffault it’s jdk 1.5.

The javax.mail.javax.mail-api is interface and com.sum.mail.javax.mail is the implementation. I listed them because of their relationship. However, you don’t really need the first one since the interfaces are also included in com.sum.mail. Note there are other implementations you can find.

The java code is like this:

import java.io.File;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class TestSend {

    public static void main(String[] args) throws Exception {
        Properties props = new Properties();
        Session session = Session.getInstance(props);

/* The comment out part not working */
//      Session session = Session.getInstance(props, new Authenticator() {
//          @Override
//          protected PasswordAuthentication getPasswordAuthentication() {
//              return new PasswordAuthentication("username", "password");
//          }
//      });

        Message message = new MimeMessage(session);
        Address myAddress = new InternetAddress("from@sender.com", "sender");
        Address recipient = new InternetAddress("to@recipient.com");
        message.setFrom(myAddress);
        message.setRecipient(Message.RecipientType.TO, recipient);
        message.setSubject("Subject");
        message.setText("This will be overwrite by msgText");
		
        String msgText = "The text to send";

        MimeBodyPart messageBodyPart = new MimeBodyPart();
        messageBodyPart.setContent(msgText, "text/plain");

        MimeBodyPart fileBodyPart = new MimeBodyPart();
        fileBodyPart.attachFile(new File("filepath")); // This line shows how to attach a file
        Multipart multipart = new MimeMultipart();
        multipart.addBodyPart(messageBodyPart);
        multipart.addBodyPart(fileBodyPart);

        message.setContent(multipart);

        Transport t = session.getTransport("smtps"); // most email service providers don’t support smtp anymore. This is where the most tricks come from.
        t.connect("smtp.sender.com", "username", "password"); // in most case, the username is the first part (left part of @) of your primary email address, if you have more than one bound to your account.

        t.sendMessage(message, message.getAllRecipients()); // It looks for an array. So, you can do this way, or just put all addresses into an array, then pass in.

        t.close();
    }
}

I instantiated a Properties() instance, but had never set anything in it. If you would like to store the configurations with Properties(), please refer the property settings which will discuss in the following sections. You can also find all the property keywords in JavaMail API documentation. Furthermore, I want to mention that the Authenticator class is abstract, but there is no unimplemented method. The way they are doing this is to let you overwrite getPasswordAuthentication() method which is the only method not marked as final in this class. If you look into the source code, you will find the original one is returning null, which would be good for if the mail provider doesn’t ask for a password or any kind of authentication. But in most cases, a PasswordAuthentication class should be returned with your username and password.

Manually read email/check inbox

As you see, the connection setup is very similar between sending and receiving. You need to change protocol and configure the store. Then connect to the server and download emails from a particular folder. Note that, for pop3 protocol, the folder is not really something you need to choose, because the server will not be syncing the folders on your client/java program. On the other hand, imap will sync folders, so you want to take care of it.
In addition, Message class has several methods to specifically pick up the certain part of your email, e.g. header, body, etc. In my code list, you can see how it works.

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;

public class TestReceive {

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

        Properties props = new Properties();
        props.put("mail.pop3.host", "pop.domain.com");
        props.put("mail.store.protocol", "pop3");

        Session session = Session.getInstance(props, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("username", "password");
            }
        });

        Store store = session.getStore("pop3");

        store.connect();

        Folder inbox = store.getFolder("INBOX");

        inbox.open(Folder.READ_ONLY);

        Message[] messages = inbox.getMessages();

        for (Message message : messages) {
            System.out.println("Email subject: " + message.getSubject());

            switch (message.getContentType().split(";")[0]) {
            case "text/plain":
                System.out.println("Body: " + message.getContent());
                break;

            case "multipart/mixed":
                Multipart parts = (Multipart) message.getContent();

                for (int i = 0; i < parts.getCount(); i++) {
                    BodyPart part = parts.getBodyPart(i);

                    if (part.getDisposition() == null) {
                        System.out.println("Body: " + part.getContent());
                        continue;
                    }

                    switch (part.getDisposition()) {
                    case Part.INLINE: // a signal to tell Browser/MUA to display it if possible
                        saveFile("misc/display/" + part.getFileName(), part.getInputStream());
                        break;

                    case Part.ATTACHMENT: // a signal to let Browser/MUA to just download it
                        saveFile("misc/store/" + part.getFileName(), part.getInputStream());
                        break;

                    default:
                        System.out.println("unknown disposition");
                        break;
                    }
                }
            break;
            default:
                System.out.println("unknown type");
                break;
            }
        }
        inbox.close(false);
        store.close();
    }

    private static void saveFile(String path, InputStream inputStream) {
        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path));
                BufferedInputStream bis = new BufferedInputStream(inputStream)) {
            byte[] b = new byte[1024];
            while (-1 != bis.read(b))
                bos.write(b);
			
            bos.write(b); // write the the last part which contains less than 1024 bytes data.

            bos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Send Email with GlassFish

To send and receive emails with GlassFish, you need to configure JavaMail Sessions, as well as modify some java code. If you haven’t setup a GlassFish server, then you need to do it first. For setting up GlassFish Application Server, see here.

If you have followed along with this article, you should have a simple maven project. To use GlassFish, you need to turn your project into a deployable project, e.g. Dynamic Web Module. To do that, you should first convert your project to faceted form. Go to the project Properties -> Project Facets -> Convert to faceted form. Then select Dynamic Web Module (DWM), and hit Apply butto. Then you select GlassFish Web Extensions, and click Apply.
Optionally, you can specify the targeted runtime. Still in the project Property window, go to Targeted Runtimes, select a GlassFish server you want to deploy to, and apply. Then, go to Server, choose the server, and apply.

Configure GlassFish

Go to GlassFish web console (localhost:4848) -> Resources -> JavaMail Sessions. Create a new session, and configure it as follow (use gmail as an example):

JNDI Name: mail/gmail (name for JNDI lookup)
Mail Host: smtp.gmail.com
Default User: username
Default Sender Address: username@gmail.com (or other email address bound to your account)
Deployment Order: 100 (default: 100)
Description: You can leave it blank or put whatever
Status: check Enabled

Advanced (You can leave them as default, unless the protocols are different)
Store Protocol: imap
Store Protocol Class: com.sun.mail.imap.IMAPStore (You can use auto-complete function in Eclipse IDE to check com.sun.mail package to find more classes)
Transport Protocol: smtp
Transport Protocol Class: com.sun.mail.smtp.SMTPTransport
Debug: uncheck Enabled

Additional Properties
mail.smtp.password:password
mail.smtp.auth:true (indicates the mail server asks for authentication)
mail.smtp.port:587 (If you tried configuring your SMTP server on port 465 (with SSL/TLS) and port 587 (with STARTTLS), but are still having trouble sending mail, try configuring your SMTP to use port 25 (with SSL/TLS). )
mail.smtp.starttls.enable:true (corresponds with port 587. For example, if you use port 465, then you need to set mail.smtp.ssl.enable:true )

Note: The protocol portion in property name (e.g. mail.smtp.something) must be as exact the same as the corresponding protocol. Otherwise, they’ll not be picked up by the program.

Java Code

There is no big change in Java code. Instead of running everything within the main method, I put the code in a method called send, and set up a timer to call it. In addition, I use resource injection to use the configurations I just set in GlassFish.

import java.io.File;
import javax.annotation.Resource;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

@Singleton
public class TestSend {

    @Resource(lookup = "mail/gmail")
    private Session session;

    @Schedule(second = "0", minute = "*/2", hour = "*") // The simplest way to define a Schedule, you have to have at least second, minute and hour variables of Schedule annotation
    public void timer() {
        send();
    }

    public void send() {

        System.out.println("Sending Start");

        try { // if you just throw out the exceptions, you will not get a message since this method is called by a Schedule
            Message message = new MimeMessage(session);
            Address recipient = new InternetAddress("ljz0863@sina.com");
            message.setRecipient(Message.RecipientType.TO, recipient);
            message.setSubject("Subject");
            message.setText("This will be overwrite by msgText");

            String msgText = "The text to send";

            MimeBodyPart messageBodyPart = new MimeBodyPart();
            messageBodyPart.setContent(msgText, "text/plain");

            MimeBodyPart fileBodyPart = new MimeBodyPart();
            fileBodyPart.attachFile(new File(getClass().getClassLoader().getResource("logo.png").toURI())); // .getResource() method this actually look up all the files in the domain directory, and find whatever matches the given pattern
            // fileBodyPart.attachFile(new File(Thread.currentThread().getContextClassLoader().getResource("logo.png").toURI())); // Another way of targeting the resource
            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(messageBodyPart);
            multipart.addBodyPart(fileBodyPart);

            message.setContent(multipart);

            Transport.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("End Sending");
        }
    }
}

Read Email with GlassFish

Configure GlassFish

Go to GlassFish web console (localhost:4848) -> Resources -> JavaMail Sessions. Create a new session, and configure it as follow (use gmail as an example):

JNDI Name: mail/gmail
Mail Host: imap.gmail.com
Default User: username
Default Sender Address: username@gmail.com
Deployment Order: 100
Description: You can leave it blank or put whatever
Status: check Enabled

Advanced (You can leave them as default, unless the protocols are different)
Store Protocol: imap
Store Protocol Class: com.sun.mail.imap.IMAPStore
Transport Protocol: smtp
Transport Protocol Class: com.sun.mail.smtp.SMTPTransport
Debug: uncheck Enabled

Additional Properties
mail.imap.ssl.enable:true
mail.imap.password:password

Java Code

For the Java code, I set it to just display the subjects of my emails.

import javax.annotation.Resource;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Store;

@Singleton
public class TestReceive {

    @Resource(lookup = "mail/sina")
    private Session session;

    @Schedule(second = "*/30", minute = "*", hour = "*")
    public void receive() {

        System.out.println("Receiving Start");

        try {
            Store store = session.getStore();

            store.connect();

            Folder inbox = store.getFolder("INBOX");

            inbox.open(Folder.READ_ONLY);

            Message[] messages = inbox.getMessages();

            for (Message message : messages)
                System.out.println("Email subject: " + message.getSubject());

            inbox.close(false);
            store.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("End Receiving");
        }
    }
}

Install Mysql JDBC Driver on WildFly

First of, I found an article which explains how to install a jdbc driver on WildFly in a fancy way. However, I’m going to introduce an easy way to do it at the end. So let’s start with the one I found.

You may want to Initialize MySQL to begin with.

Configure JDBC Driver on WildFly 8

Used technologies in the tutorial:

  • Wild Fly 8.2.0.Final (Tested on WildFly 10 and it worked)
  • Mysql Connector 5.1.33 (Tested with MySQL Connector 5.1.39 and it worked)

1. Create the jboss module

Enter in the file path ${EAP_HOME}/modules/system/layers/base and create the directories com/mysql/driver/main.

Into the folder main copy the driver library jar, and create a file module.xml as showed in the sample below

<module xmlns="urn:jboss:module:1.3" name="com.mysql.driver">
    <resources>
        <resource-root path="mysql-connector-java-5.1.33.jar" />
    </resources>
    <dependencies>
        <module name="javax.api"/>
        <module name="javax.transaction.api"/>
    </dependencies>
</module>

For an explanation about the meaning of the fields take a look at Jboss Module Documentation.

2. Register the module as driver with CLI.
Start the server from the directory ${EAP_HOME}/bin and excute ./standalone.sh --server-config=${server-profile}
Start the management CLI by executing ./jboss-cli.sh (if you’re using windows, you should do it in cmd. Go to ${EAP_HOME}/bin, and execute jboss-cli)
Run the the command: /subsystem=datasources/jdbc-driver=mysql:add(driver-name=mysql,driver-module-name=com.mysql.driver,driver-class-name=com.mysql.jdbc.Driver)”
If the operation is successful then the message below will be shown
{"outcome" => "success"}
In addition, the code below should be added to standalone.xml

...
<driver name="mysql" module="com.mysql.driver">
    <driver-class>com.mysql.jdbc.Driver</driver-class>
</driver>
...

The easy way

Login to WildFly web console, go to Deployments -> add a managed deployment. Then you can choose any divers you would like to deploy.

How about GlassFish?

For glassfish, these is no need to “install” the driver. before starting the server up, place the driver in the directory of %{your domain folder}\lib\ext. Then you will be good to go. You can then add pool and datasource under Resources -> JDBC within web console (add pool first, then ds). There are bugs with this module in GlassFish4. You may want to do it in GlassFish3 or Payara.
P.S. It seems if you reopen IDE, and do a clean startup of the server, then it will be ok.