Lombok Maven settings

dependency

<dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <version>1.16.16</version>
 <optional>true</optional>
</dependency>

plugin

<plugin>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok-maven-plugin</artifactId>
 <version>1.16.18.0</version>
 <executions>
  <execution>
   <phase>generate-sources</phase>
   <goals>
    <goal>delombok</goal>
   </goals>
   <configuration>
    <outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
   </configuration>
  </execution>
 </executions>
</plugin>

Then, all domain classes goes to src/main/lombok(manually add source folder)
(optional)Eclipse build path ignore pattern for src/main/lombok: **/*.java
If you don’t want to ignore java files in the above folder, Eclipse will complain something like type already exists. It’s ok, because maven won’t pick up the lombok folder unless it’s explicitly set to be included.

This blog may not be up to date. Please see the original post from Blogger http://ift.tt/2tUTzp6
via IFTTT.

Develop AspectJ Library

AspectJ is an aspect-oriented programming (AOP) extension created at PARC for the Java programming language. – Wikipedia

In fact, things like Servlet Filters, EJB interceptors, or even database triggers are all sharing the concept of AOP. This article will focus on AspectJ in particular. Personally, I feel AspectJ gives a every different view on how software can be written. A weird thing that I found was most AspectJ related documentations were quite old. But, since it’s popular in many mordern frameworks such as Spring, I guess it’s worth to learn.

How is an AspectJ project used by other projects as a library?

To develop an AspectJ project and make other projects to use it, you have to know how the aspects are applied to the targeted components. AspectJ uses bytecode manipulation mechanism to intervene certain life cycle events of java classes at compile time. Because of that, it wouldn’t work if an AspectJ project is just being imported normally. Instead, it must be picked up at compile time to manipulate the bytecode when the targeted classes are generated. In fact, AspectJ has its own compiler, which could either be used standalone or work together with your chosen javac for jdk version control purposes.
To prepare for the practice in the rest sections, you need to have AspectJ Development Tools (AJDT) installed on your Eclipse. Although, I’ll introduce based on Eclipse, you can also develop AspectJ project with Intellij and NetBeans.

Eclipse plugin

AJDT is an eclipse plugin. You can find multiple versions of it. The latest one is 4.6 (copy the url as an Eclipse repository to install).

Intellij setup

You can find an introduction of how to set up your Intellij to work with AspectJ.

NetBeans plugin

There is a third party plugin called AspectJ-for-NetBeans developed quite a while ago (I heard it was developed by one person, which is very impresive).

Build an AspectJ project

There are various ways to create an AspectJ project: you can simply create an AspectJ project from scratch; you can have an existing Java project to convert to an AspectJ project. The way I’m going to do it is to create a Maven AspectJ project. By doing so, I would be able to just install my project to a local or remote repository. When it turns to that other project needs to import this AspectJ project, it can be done by just configuring the Maven configurations.

Create a Maven AspectJ project

A Maven AspectJ project is a maven project with a few AspectJ related configurations to assist while going through compile phase. Therefore, a simple Maven project is good to go for this practice.
Here is the initial pom.xml file I have (really nothing more than a simple initial pom file):
<project xmlns="http://ift.tt/IH78KX"
    xmlns:xsi="http://ift.tt/ra1lAU"
    xsi:schemaLocation="http://ift.tt/IH78KX http://ift.tt/VE5zRx">
    <modelVersion>4.0.0</modelVersion>
    <groupId>ca.ljz</groupId>
    <artifactId>special-logger</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</project>
By default, this project would not compile with AspectJ. To do that, we need to add:
  1. aspectj-maven-plugin
  2. aspectjrt (AspectJ run time dependency)
Optional: properties are optional. I added the above plugins and dependencies in <pluginManagement> and <dependencyManagement> first, which can be added to <plugins> and <dependencies> directly.
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.source-target.version>1.8</java.source-target.version>
    <aspectj.version>1.8.7</aspectj.version>
</properties>
<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>${java.source-target.version}</source>
                    <target>${java.source-target.version}</target>
                    <!-- IMPORTANT -->
                    <useIncrementalCompilation>false</useIncrementalCompilation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.7</version>
                <configuration>
                    <!-- OPTIONAL
                    <showWeaveInfo>true</showWeaveInfo>
                    -->
                    <source>${java.source-target.version}</source>
                    <target>${java.source-target.version}</target>
                    <Xlint>ignore</Xlint>
                    <complianceLevel>${java.source-target.version}</complianceLevel>
                    <encoding>${project.build.sourceEncoding}</encoding>
                    <!-- OPTIONAL
                    <verbose>true</verbose>
                    -->
                    <!-- OPTIONAL
                    <warn>
                        constructorName,
                        packageDefaultMethod,
                        deprecation,
                        maskedCatchBlocks,
                        unusedLocals,
                        unusedArguments,
                        unusedImport
                    </warn>
                    -->
                </configuration>
                <executions>
                    <execution>
                        <!-- IMPORTANT -->
                        <phase>process-sources</phase>
                        <goals>
                            <goal>compile</goal>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </pluginManagement>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
        </plugin>
        <!-- OPTIONAL
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
        </plugin>
        -->
    </plugins>
</build>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
    </dependency>
</dependencies>
The Maven AspectJ project now is created. As we mentioned above, the project needs to be compiled with either ajc (AspectJ compiler) or both ajc and javac. Please refer to the comments in the above pom settings to figure out how to do it in either way.

Create an annotation (optional)

Creating an annotation is not a must. But since it’s a common practice, I just want to show how to work with annotations in AspectJ. So, create an annotation first. It can be something like this:

package ca.ljz.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(java.lang.annotation.ElementType.METHOD)
public @interface Log{
    String prefix() default "";
}

The purpose of this annotation is to let user place it on a specific method to log. It doesn’t sound like how most loggers work, but it’s good for this example.
Other than using an annotation, AspectJ can also catch a predefined signature pattern, e.g. a method signature pattern such as set* or get* etc. But, when programming a library, it’s very unlikely to use pattern matches in most case. The exceptions are setters and getters, etc.

Create an aspect

In AspectJ, an aspect is a special entity contains the descriptions of when and how to deal with life cycle events of targeted java classes. The following code stub describes a log aspect for what we are doing:

package ca.ljz.aspects;

import ca.ljz.annotations.Log;
import org.aspectj.lang.reflect.MethodSignature;

public aspect LogAspect {

    pointcut log() : execution(* *(..)) && @annotation(Log);

    before() : log() {
        System.out.println("enter "
            + ((MethodSignature) thisJoinPoint.getSignature()).
                getMethod().getAnnotation(Log.class).prefix()
            + thisJoinPoint.getSignature());
    }

    after() : log() {
        System.out.println("exit "
            + ((MethodSignature) thisJoinPoint.getSignature()).
                getMethod().getAnnotation(Log.class).prefix()
            + thisJoinPoint.getSignature());
    }
}
Here is a list of the meanings of each part of the pointcut declaration.

  • log(): the identifier of this pointcut, which can be referred in advices
  • execution: the action of the target to be intercepted
  • 1st *: this star indicate that the return type can be anything
  • 2nd *: this is the name pattern of methods, which in this case, means any name
  • (..): this refers to the parameter pattern, which in this case, means any parameter(s)
  • &&: this is an logic operator, which indicates both sides condition must satisfied
  • @annotation(Log): this means that there must be a Log annotation

before() and after() are the time points to indicate when the advice should be executed.
To know more about AspectJ syntax, here are some useful links:

Install the library

There are several types of places you can install your library. Just to keep things as simple as possible, I’m just going to run a built-in maven phase: install. You can easily find it by right click on the project, and it’s in Run As sub menu.

Import an AspectJ project

Like building an AspectJ project, to import an AspectJ project also requires to add/change to the AspectJ compiler. Depending on how you build your project, there are different ways to accomplish this.

Non-maven project

For a non-maven project, you need to:

  1. Convert the Java project to AspectJ project (right click project -> configure);
  2. Add the library into Project Build
  3. Add the library into AspectJ Build Inpath (project properties -> AspectJ Build);

Maven project

For a maven project, you need to:

  1. Configure the project into a Maven AspectJ project (see Create a Maven AspectJ project section);
  2. Add the library as a dependency;
  3. Add the library as an <aspectLibrary> into <configuration> in aspectj-maven-plugin
To add the library into aspectj-maven-plugin <configuration>, it needs to include <groupId> and <artifactId>. The aspect library is something like this:

<aspectLibraries>
    <aspectLibrary>
        <groupId>ca.ljz</groupId>
        <artifactId>special-logger</artifactId>
    </aspectLibrary>
</aspectLibraries>

In particular, to use this library, you just need to add @Log on any method. The project to import AspectJ library project can be either a jar or a war project.

This blog may not be up to date. Please see the original post from Blogger http://ift.tt/2i8nNMm
via IFTTT.

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");
        }
    }
}