How to Use Event CDI on Java EE 8

Nowadays, the companies needs provide response faster and faster to the market, and its success depend of that. This necessity reflects directly on software, that need provide a faster response too. With this, software need be delivered faster and faster, need be scalable more and more and need decrease risks of impacts with updates. Thinking in that, the Java EE have been provided some tools that permit us use Reactive Programming and asynchronous processing, to permit us a faster response to end user and increase and scale the capacity of response to request.

In this post i will show how can we use Event CDI to process tasks using Reactive Programming. In our example i’ll demonstrate how to use Event CDI with synchronous and asynchronous way.

In our scenario, we’ll have a service that receive a request to send an e-mail, and then the service throw an event to an observer that will send an e-mail using JavaMail.

Tools used:

  • GlassFish 5.0
  • Java EE 8
  • IntelliJ IDEA 2017.3.4 (Ultimate Edition)
  • mailtrap.io (To use email test)
  • Postman (To test the service)

Creating the Qualifiers

First of all, we’ll create a qualifier to distinguish our events. To event of send an e-mail, i will create the qualifier called EmailSender. Below we have the qualifier.


@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.FIELD})
public @interface EmailSender {

}

Creating the Event

In this step we’ll create the event to send an e-mail. This event will have an attribute to email of destination and an attribute to message. Below we have the event example called EmailEvent.

public class EmailEvent {

    private String emailTo;

    private String message;

    public String getEmailTo() {
        return emailTo;
    }

    public void setEmailTo(String emailTo) {
        this.emailTo = emailTo;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public static EmailEvent build(String emailTo, String message ){

        EmailEvent emailEvent = new EmailEvent();
        emailEvent.setEmailTo(emailTo);
        emailEvent.setMessage(message);

        return emailEvent;

    }
}

Creating the Observer

In this step, we’ll create the observer, that will have two methods. One method to send e-mail with synchronous way and another method to send e-mail with asynchronous way. Below we have the observer example.

public class EmailSender {

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

    private Logger logger = LogManager.getLogger(this.getClass());

    //Method used to send email with synchronous way
    public void send(@Observes @net.rhuanrocha.eventcdiexample.qualifier.EmailSender EmailEvent emailEvent) throws NamingException {

        runSend(emailEvent);

        logger.info("Email sent!");
    }

    // Method used to send email with asynchronous way
    public void sendAsyn(@ObservesAsync @net.rhuanrocha.eventcdiexample.qualifier.EmailSender EmailEvent emailEvent) throws NamingException {

        runSend(emailEvent);
        logger.info("Email sent Async!");

    }

    private void runSend(EmailEvent emailEvent) throws NamingException {

        try {

            MimeMessage message = new MimeMessage(session);
            message.setFrom(session.getProperty("mail.address"));
            message.setRecipients(Message.RecipientType.TO, emailEvent.getEmailTo());
            message.setSubject("Sending email with JavaMail");

            message.setText(emailEvent.getMessage());
            /**Method to send the created message*/
            Transport.send(message,
                    session.getProperty("mail.smtp.user"),
                    session.getProperty("mail.smtp.pass"));

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
    }
}

Note that on runSend(EmailEvent emailEvent) method, we send an e-mail using the JavaMail spec, and the JavaMail Session is got from context using lookup. With this, you need make a configuration to JavaMail Session with the JNDI name “mail/MyMailSession” on the Server Application. Thus, to this example work well you need configure the following properties on the JavaMail Session:

  • mail.address = ${email_from}
  • mail.smtp.host=${smtp}
  • mail.smtp.port=${port}
  • mail.smtp.pass=${passowrd}
  • mail.smtp.user=${user}
  • mail.smtp.auth=${auth}

Writing the Resource

In this step we’ll create the JAX-RS resource, that will receive a request to send an e-mail and will throw the event to observer. This resource have two methods, one to send email with synchronous way and another to send email with asynchronous way. Below we have the resource called EmailResource.

@Path("email")
public class EmailResource {

    @Inject
    @EmailSender
    private Event emailEvent;

    private Logger logger = LogManager.getLogger(this.getClass());

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public Response sendEmail(@Email @NotBlank @FormParam("email") String email,
                              @NotBlank @FormParam("message") String message ){

        logger.info("email:"+email + " message:"+message);

        emailEvent.fire(EmailEvent.build(email,message));

        return Response.ok().build();

    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/async")
    public Response sendEmailAsync(@Email @NotBlank @FormParam("email") String email,
                              @NotBlank @FormParam("message") String message ){

        logger.info("email:"+email + " message:"+message);

        emailEvent.fireAsync(EmailEvent.build(email,message));

        return Response.ok().build();

    }
}

Outputs

To test these codes, i used the Postman and the following results was got.

With synchronous way:

Captura de tela de 2018-08-18 20-00-44

With asynchronous way:

Captura de tela de 2018-08-18 19-54-24

Note that using synchronous way we had a response with 2320 ms and using asynchronous way we had a response with 79 ms. With this, the asynchronous way replied very faster than synchronous way.

Conclusion

The use of Event in CDI permit us using the Reactive Programming in our application. With this, we can promote a decouple between logics and components turning the maintenance better. Furthermore, using Event in CDI we can promote a faster response to end user, because we can working with a non-blocking process.

If you want the completed codes of this example you can access the github and get the code.

https://github.com/rhuan080/jakartaee-event-cdi-example

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s