Warning: include_once(/home/ryamar39/gearandtechblog.com/wp-content/plugins/google-sitemap-pro/google-sitemap-pro.php): failed to open stream: Permission denied in /home/ryamar39/gearandtechblog.com/wp-settings.php on line 305

Warning: include_once(): Failed opening '/home/ryamar39/gearandtechblog.com/wp-content/plugins/google-sitemap-pro/google-sitemap-pro.php' for inclusion (include_path='.:/usr/local/lib/php:/usr/local/php5/lib/pear') in /home/ryamar39/gearandtechblog.com/wp-settings.php on line 305

Warning: Cannot modify header information - headers already sent by (output started at /home/ryamar39/gearandtechblog.com/wp-settings.php:305) in /home/ryamar39/gearandtechblog.com/wp-content/plugins/wp-super-cache/wp-cache-phase2.php on line 60
Sending programmatic HTML Email with Spring + Thymeleaf + MyBatis + Database Templates

Sending programmatic HTML Email with Spring + Thymeleaf + MyBatis + Database Templates

This bit of code came out of a project I worked on for an application team that doesn’t have a Java developer, the goal was to create an email system that can be triggered based on database rows inserted by Mainframe COBOL code. The application reads a table and looks for a record telling it which email template to use, the database row also tells it some details about what information to include. That portion of the process is beyond the scope of this post, really this was the easy part of this process.

Because the app team that will own this application does not have a dedicated developer I wanted to create something that would be fairly easy for them to maintain without making Java code changes. I wanted them to be able to update the email templates without rebuilding the WAR file and going through the deployment process. I chose to store the email templates in the DB2 database, for the templates I used a VARCHAR field with a 32KB length. 32KB may not seem like much but the thymeleaf templates are amazingly compact. The most complex email report I have written weighs in at about 7200 bytes. Please note that in this case these are internal application status type emails so they don’t need to be flashy, they have the bare minimum of CSS and formatting. You may choose to have more complex templates.

The application I wrote also has a series of screens to allow the app team to edit the HTML templates, preview the templates, and control the process that sends the emails. I wont include any details on these parts as they should be very straight forward for you. I will speak to the guts of this process which includes sending email from Spring, using Thymeleaf HTML templates and creating a custom thymeleaf view resolver to access the templates stored in the database. I also use annotated MyBatis interfaces to simplify database access.

Dependencies

This pom.xml should be good enough for a working version.

 

Spring namespace configuration

applicationContext

In this context we will define the following,

  • Component scan path
  • SMTP connection using Springs JavaMailSenderImpl
  • Custom thymeleaf view resolver for access views stored on the database. We define this here so classes not annotated as @Controller can access them.
  • MyBatis configuration

servletContext

Here we will define the following,

  • Annotation driven MVC
  • Component scan for @Controller only this prevents objects from being picked up twice, I think I had to do this because proxies where being registered twice and it was affecting my EHCACHE implementation. You may not need this filtering.
  • Custom database template resolver, this allows us to preview the templates in the browser
  • Standard template resolver for pages

Database Table

Your table can be as simple as 3 columns

  1. email_type – ID column PK
  2. email_subject – Subject line for the email
  3. email_text – large text field for the html content

Custom Template Resolver and Resource Resolver

Here we will extend the Template Resolver and implement the IResourceResolver

  • Define a prefix so that we can call this resolver specifically, in my case I used the db2: prefix
  • Override the getResourceAsStream method
    • Use DAO to get template from the database as a String object
    • Turn the String object into a ByteArrayInputStream object and return it to the caller

EmailText bean

Straight forward bean

MyBatis DAO Interface

Simple interface to query the database for the template and return an EmailText object.

Email Service

This service accept the following arguments on the sendEmail method

  • viewName, this is the EMAIL_TYPE column on the database
  • recipientEmail, String Array containing the email addresses the mail will go to
  • data, object of any type. Type doesn’t matter because thymeleaf will use reflection to get the data. This is exactly the same as the object you would load into the model when serving a template in an spring mvc environment. I choose to always load it into the context under the name emailDataObject. Field names must comply with the java bean standards.

In this class we will do the following,

  • Create a thymeleaf Context and load the embeded .jpg logo (if needed) and the emailDataObject
  • Retrieve the html template from the database through a MyBatis DAO interface
  • Build mime message using the Spring JavaMailSender bean
  • Render the HTML content using Thymeleaf Template Engine
  • Get the logo.jpg from the class path and add it as an inline image. In my webapp I kept the .jsp in /src/main/resources

You can think of this class the same way as you would think of a @Controller and its supporting @Services. Here you will gather all of the data needed to render the HTML but instead of sending the HTML to the client (as in Spring MVC) you are putting it into an email. Replace the ModelMap object of a spring controller with the org.thymeleaf.context.Context object.

EmailData bean

Simple bean for this example. Make it as complex as you need. I am assuming you know how to work with Thymeleaf already.

Template

This is a super simple template with one field. Notice how the logo is referenced.

Reference

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/

http://www.thymeleaf.org/

http://mybatis.github.io/mybatis-3/

Leave a Reply

best blogs
best blogs