ZTemplates email service

June 25th, 2010

Has been a while since I last blogged, but I have been rather busy lately. Today I have done what I wanted to be doing a long time ago. I wrote a ztemplates service for sending out emails, using the powers of the rendering engine to create HTML emails. So I came up with the following service (note that I wrote this for version 0.9.9.6):

public class ZEmailService implements ZIEmailService {
 
	@Override
	public void render(Object obj, final String from, final String[] recipients, final String subject) throws Exception {
		render(obj, from, recipients, subject, "text/html");
	}
 
	@Override
	public void render(Object obj, final String from, final String[] recipients, final String subject, String mimeType) throws Exception {
 
		if(obj.getClass().isAnnotationPresent(ZEmail.class) == false) {
			throw new Exception("@ZEmail annotation not present on " + obj.getClass().getCanonicalName());
		}
 
		final ZIRenderService renderService = ZTemplates.getRenderService();
		final ZEmail emailAnnotation = obj.getClass().getAnnotation(ZEmail.class);
		final Properties properties = new Properties();
		final String body = renderService.render(obj);
 
		properties.put("mail.smtp.host", emailAnnotation.host());
 
		if(emailAnnotation.username() != null) {
			properties.put("mail.user", emailAnnotation.username());
		}
		if(emailAnnotation.username() != null) {
			properties.put("mail.password", emailAnnotation.password());
		}
		sendMail(properties, from, recipients, subject, mimeType, body);
	}
 
	private static void sendMail(final Properties properties, final String from, final String[] recipients, final String subject, final String mimeType, final String body) throws MessagingException {
		final Session session = Session.getDefaultInstance(properties, null);
		final Message message = new MimeMessage(session);
		final InternetAddress addressFrom = new InternetAddress(from);
		final InternetAddress[] addressTo = new InternetAddress[recipients.length];
 
		for (int i = 0; i < recipients.length; i++) {
			addressTo[i] = new InternetAddress(recipients[i]);
		}
 
		message.setFrom(addressFrom);
		message.setRecipients(Message.RecipientType.TO, addressTo);
		message.setSubject(subject);
		message.setContent(body, mimeType);
 
		Transport.send(message);
	}
}

Here is the interface:

public interface ZIEmailService extends ZIService {
 
	  public void render(Object obj, final String from, final String[] recipients, final String subject) throws Exception;
	  public void render(Object obj, final String from, final String[] recipients, final String subject, String mimeType) throws Exception;
}

And the code for the @ZEmail annotation:

@Retention(RetentionPolicy.RUNTIME)
public @interface ZEmail {
	String host() default "localhost";
	String username();
	String password();
}

Let’s say we have a view like:

@ZRenderer(value = ZJspRenderer.class)
@ZEmail(password = "secret", host = "somehost", username = "admin")
public class SomeView {
 
    @ZExpose
    public String someValue() {
    }
}

As you can see the @ZEmail annotation makes it possible to set mail server settings. To actually send the mail using that view we only have to do the following:

new ZEmailService().render(new SomeView(), "from@example.org", new String[] { "to@example.org" }, "subject");

As you can see I’m not using the ServiceRepository in this example, I added the service to ztemplates myself, so I’m running a custom version. Just instantiating the service works as well.

There are of course a lot of improvements possible, but this version matches my needs. I hope someone will have some use of it.

Note: Will probably also work using other renderers, didn’t test it ;-)

Required external libraries:

  • mail.jar
  • activation.jar

Hope to be blogging some more soon.

ZTemplates 0.9.9.6 and custom content types

September 30th, 2009

Quite recently I have been in a situation where I wanted to expose some XML using ZTemplates. So I used the servlet serivce to get the HttpServletResponse instance:

final HttpServletResponse response = ZTemplates.getServletService().getResponse();
response.setCharacterEncoding("utf-8");
response.setContentType("application/xml");

Followed by rendering a view:

ZTemplates.getServletService().render(view);

When I inspected the HTTP traffic using wireshark I noticed that I saw:

Content-Type: text/html;charset=utf-8

Rather than the expected application/xml. So I started looking into the code of the ZServletService that is responsible for rendering:

public void render(Object obj) throws Exception {
    render(obj, "text/html");
}
 
public void render(Object obj, String mimeType) throws Exception {
    String html = renderService.render(obj);
    // response.setCharacterEncoding(UTF8);
    response.setContentType(mimeType);
    response.getWriter().print(html);
}

That explained a lot, so now you could go ahead and do:

ZTemplates.getServletService().render(view, "application/xml");

However that does not give you control on the encoding, so I decided to create a custom rendering method instead:

public static void render(Object view, String encoding, String contentType ) throws Exception {
    final HttpServletResponse response = ZTemplates.getServletService().getResponse();
    final String renderResponse = ZTemplates.getRenderService().render(view);
    response.setCharacterEncoding(encoding);
    response.setContentType(contentType);
    response.getWriter().print(renderResponse);
}

So to fix my problem I only have to do the following now:

ZRenderUtils.render(view, "utf-8", "application/xml");

p.s. If you are wondering in this example, view, is just a String containing XML.

[quicky] Asterisk and incoming cli manipulation

January 15th, 2009

It is very common in professional VoIP that service providers put through CLIs transparently. If you are just a traffic routing party you usually don’t care about it, but for premium services however it can cause major issues. For example you have an application that matches the calling party’s CLI to an entry in a database. If you have built that application yourself it’s very easy to do some internal mangling, however some people buy products which are not suited to do the job properly.

So this article is about manipulating the calling party’s CLI, rather than the called number. Let’s take a look at the following call example. Person A (00123456789) calls service B(1223235325). Service B has a number in E.164 format, however person A does not. In this example person A is the calling party. However the service requires the calling number to be in E.164 format.

So what would we do in asterisk to fix that? Well, let’s say for example also the B-number has to zeros at the beginning of the number:

001223235325

In the asterisk configuration we could have the following example dial plan to strip the two zeros:

[example]
; match incoming 00xxxxxxx numbers and reformat
exten => 00X.,1,Goto(${EXTEN:2}, 1)
 
; normal dialplan
exten => _X.,1,Answer()
[...]

By using the ‘:2′ on the ‘EXTEN’ variable we get rid of the first ‘2′ digits, this is a substring operation.

So that was easy! However, when doing it for the incoming CLI it’s a totally different story. The incoming CLI is exposed by the CALLERID function. There is some regular expression support in Asterisk, so we can get going. Unfortunately it only supports matching. So no support for getting matched groups, which would be a lot easier. However after some twiddling I came up with the following:

[example]
; print cli as it came in
exten => _X.,1,Verbose(${CALLERID(num)})
 
; test if it matches 00XXX
exten => _X.,n,Set(STRIPCLI=${REGEX("^[0]\{2\}[1-9][0-9]+$" ${CALLERID(num)})})
 
; Depending if it is set to 0 or 1 goto continue or continue and format the cli
exten => _X.,n,GotoIf($["${STRIPCLI}" = "0"]?continue)
exten => _X.,n,Verbose(Formatting outbound CLI)
 
; format the CLI
exten => _X.,n,Set(CALLERID(num)=${CALLERID(num):2)})
 
; continue normal operation
exten => _X.,n(continue),Verbose(${CALLERID(num)})
exten => _X.,n,Dial(SIP/SOMESERVER/${EXTEN})
[..]

Let’s go back to our example now and how the dial plan handles it:

Verbose(00123456789)
Match on regular expression and put it a variable
if(STRIPCLI == false)
  continue normal dialplan
else
  format cli
 
normal dialplan:
 
Verbose(123456789)
Forward call to some service

As you can see the ‘00′ has been stripped of and the A number is now in E.164 format. I hope this will become useful for someone else as well :-)

[Quicky] Refactoring C++ in Microsoft Visual Studio

January 10th, 2009

Yesterday I started a simple C++ project in Visual Studio and I got some class property which I wanted to rename. I’m used to Eclipse and Netbeans IDE which have in-built refactoring utilities. So I decided to select that property and right click on it to see if I would get some refactoring options. I was surprised I didn’t, so I looked up the menu and couldn’t find anything there as well. For my small rename operation I then went to the class view and renamed the property there. However, I will probably need some basic refactoring tools in the coming future, so I started investigating.

A quick search on the internet lead me to a question on stackoverflow. Apperently it’s too difficult for Microsoft to implement refactoring for C++. Which on itself is sad, because Visual Studio is an expensive product to buy and I’d at least expect some refactoring support.

One of the replies to the question on stackoverflow mentions Refactor! for C++. Although the free version only provides some basic functionality, it does meet the expectations I have. In other words, it offers enough for me to do the job.

[Quicky] Shorewall and opening port ranges

December 6th, 2008

Imagine you want to open up a port range to your host ($FW) in your shorewall’s ‘rules’ file. So let’s say we run an Asterisk machine and we want to open RTP ports 10000 to 20000 to your machine, you would have to do something like:

ACCEPT  net  $FW  udp  10000:20000

For more reference on Asterisk’s firewall rules, click here.

[Quicky] JSTL and comparing strings

November 29th, 2008

This is the first article in a series of really short articles with problems I come across in my day to day development life. You can recognize these articles by the ‘[Quicky]‘ reference in the title and of course a ‘quicky’ tag is supplied. These ‘quickies’ don’t supply much explanation on why the problem exists, but more how to solve it.

Today I had to compare a variable with a string value using JSTL. Something like:

<c:choose>
  <c:when test="${variable eq "expected value"}">
    something
  </c:when>
</c:choose>

will obviously not work, because the XML becomes invalid. The way to do it however is:

<c:choose>
  <c:when test="${variable eq 'expected value'}">
    something
  </c:when>
</c:choose>

Replacing the double quotes surrounding the string value by single quotes does the trick.

[osdev] Invalidating a single page in the TLB

November 16th, 2008

After a long time of no development on my kernel I decided to do some work on my paging unit. In the past I always had problems with invalidating a single page in the Translation Lookaside Buffer. I knew there was a way to do it with invlpg but I never really got to the correct inline assembly statement for a GCC compiler. It didn’t always work and had random crashes. Untill recently I was left a bit clueless since I didn’t had time to do some research on it (disassembling and looking into the opcodes.) Today I figured it out:

 
__asm__ __volatile__("invlpg (%%eax)" : : "a" (address) );

I hope this becomes useful for somebody.

[ztemplates] Form validation with regular expressions

November 16th, 2008

Today I tried form validation with ZTemplates. For validating something I had to use a regular expression. In my view I created a pattern matching property like this:

private final ZStringProperty name = new ZStringProperty() {
@Override
  public ZError validate() {
 
  try {
 
    ZError error = super.validate();
 
    if (error != null) {				
      return error;
    }
 
    final Matcher matcher = Pattern.compile("[A-Z]+").matcher(getValue());
 
    if (matcher.matches() == false) {
      return new ZError("You didn't supply a valid identifier");
    }
 
    return null;
 
    }
    catch (Exception e) {
      return new ZError(e.getMessage());
    }
  }
};

I then had to do 10 more, which annoyed me a bit. I decided to look at the in-built ZIntProperty type and then I built my own ‘ZPatternProperty’:

ZPatternProperty.java:

package org.ztemplates.property;
 
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
 
import org.ztemplates.property.ZProperty;
import org.ztemplates.web.ZTemplates;
 
public class ZPatternProperty extends ZProperty<String> {
 
  String pattern;
 
  public ZPatternProperty(String pattern, ZProperty<?>... dependsOn) {
 
    super(dependsOn);
    this.pattern = pattern;
  }
 
  public ZPatternProperty(String value, String pattern, ZProperty<?>... dependsOn) {
 
    super(dependsOn);
    this.pattern = pattern;
    setValue(value);
  }
 
  @Override
  public String parse(String formattedValue) throws Exception {
 
    if(formattedValue == null) {
      return null;
    }
 
    Pattern propertyPattern;
 
    try {
      propertyPattern = Pattern.compile(pattern);
    }
    catch(PatternSyntaxException e) {
 
    throw new Exception(ZTemplates.getMessageService().getMessage(ZPatternProperty.class.getName(), "PatternSyntaxException"));
    }
 
    // check if the value matches the pattern
    if(propertyPattern.matcher(formattedValue).matches() == false) {
      throw new Exception(ZTemplates.getMessageService().getMessage(ZPatternProperty.class.getName(), "NoMatchException"));
    }
 
    return formattedValue;
  }
 
  @Override
  public String format(String obj) {
    return obj;
  }
}

My first code example now becomes:

 
  private final ZPatternProperty name = new ZPatternProperty("[A-Z]+");

Isn’t that much more robust?!

I also had to supply a ZPatternProperties.properties file for getting the exception message:

ZPatternProperty.properties:

PatternSyntaxException=Invalid pattern
NoMatchException=Value does not match the pattern

It needs some better exception messages in the future, but for me it’s fine.

I’ve also sent an email to the creator of the ztemplates framework including the code. I hope that in a new version of ztemplates there will be support for pattern validation.

[ztemplates] ZJspRenderer and exposed fields - with JSTL

November 15th, 2008

My previous article about ztemplates was about exposed values inside JSP code blocks. There is a also another possible approach and that is to use the JavaServer Pages Standard Tag Library. So let’s rewrite my last code example in the previous article.

Previous example:

<%
if(condition == true) {
 
  // notice the cast to the correct class type
  String message = (String)request.getAttribute("message");
 
  // When debugging it would be nice to check if the object is valid.
  if(message == null) {
 
    throw new Exception("DEBUG: message not exposed by render POJO.");
  }
 
  out.println(message);
}
%>

New example to see if the exposed ‘message’ field was set (with complete XHTML this time) :

<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
 
<!-- NOTICE: load the tag library -->
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Example</title>
  </head>
  <body>
    <c:choose>
      <c:when test="${message is null}">
        <p>You didn't provide a message!</p>
      </c:when>
      <c:otherwise>
        <p>Here is your message: ${message}</p>
      </c:otherwise>
    </c:choose>
  </body>
</html>

As you can see this is a much more robust way of doing things. Also take a look at this page for a more thorough introduction to JSTL.

Back to basics

November 13th, 2008

I’m always surprised by people saying that they don’t “understand” a problem. I always ask them ‘what don’t you understand?’ Most of the times the answer is, ‘the complete picture.’ It left me wondering a bit on the reasons and possible solutions.

The first action I take when I get such a response, is to ask what part of the problem they don’t understand. Most of the times I then get an answer like, ‘I can’t see how I would be able to solve the entire problem.’ Which still is not an answer to my question.

It looks like we are stuck. However, we are not. Those people just don’t like “the” high level problem description. So that implicitly means that they have some trouble with the basics of the problem. Basics are mandatory requirements for finishing a high level assignment.

How do we find out the missing basics? Well, in my experience these can be found out, just by asking questions. There are several possible ways to come up with these questions. An approach could be to do a top-down search for questions and answers. Basically this means you divide the high-level problem into subsets and possibly subsets of those subsets and make up questions for those subsets. However this scatters the problem into small problems, which will become unclear to the person having difficulties. Possibly you are missing things which are mandatory in the process of understanding the problem. Always wise to keep pen and papers near you.

What I prefer instead, is to use a bottom-top approach. You’ll need to find the core elements of the problem, which doesn’t seem easy. However most problems have some predecessors. Understand those predecessors and you most probably know the basics of the current problem. Once you have found those basics, you are able to get a level higher, until finally you have made your way to the top, the high level problem, which hopefully you understand now.

Basics are very important to understand before undertaking a new endeavor to find a solution for your problem. Understanding them makes the process to solve the issue more easy. If a problem looks to big to be solved, divide it into basics.

I have no intention to say that this is the best way to solve problems. My thoughts are based on my personal best practices. I could probably go a lot more in-depth by providing examples, however this article is meant to be a reminder to me and anyone else interested. Sometimes we just forget how we solved problems in the past. This way of doing things helped me fixing problems in the past and present, so can it do the same thing for you?!