Sunday, January 14, 2007

Secure SMTP with Spring JavaMailSender

Like many cost-effective individuals out there I migrated most of my email service which I was paying approximately $50/year for to use Google Apps For Your Domain. This is a free service that in fact I am very satisfied with. But using the smtp service with the Spring JavaMailSender on my old email account was straight forward. The problem I now have is that Google Apps For Your Domain uses the smtps protocol to send emails and because I was using an older version of Java Mail (1.3) I could not programmatically send emails using the secure smtp protocol. In addition to that, the default implemation of JavaMailSender (JavaMailSenderImpl.java) in Spring Framework currently does not have the ability to smoothly handle sending messages using the secure smtp (smtps) protocol.

I stumbled into this when developing a web application that requires an SMTP account to send test emails and other email notifications to the users of this application. Not having the luxury to run my own SMTP server I decided that I would just temporarily use a Gmail (TM) account for sending the messages during development. It just so happens that Gmail uses Secure SMTP to send email messages and on top of that it requires the user to authenticate.

Java Libraries You Will Need

In further investigating this issue it turns out that pre Java Mail 1.4, there is no support for SMTPS Protocol. So we need to download the latest version at Java Mail.

  • Option #1:

    Download the latest Java Mail API jars.
    When using this route be warned that on the final click to download the java mail product you will be re-routed to install the Sun(TM) Download Manager. I am just really puzzled why Sun(TM) has the need to create their own download managers.

  • Option #2:

    Download the latest Java Platform Enterprise Edition and use the mail.jar that came with that product.

The particular class file that you want to check for in these jars are: com.sun.mail.smtp.SMTPSSLTransport.
Please note that for either options you will still need the Java Activation Framework (activation.jar).

JavaMailSenderImpl with Secure SMTP/SMTPS Support

In my own extension of the the JavaMailSenderImpl.java (see Source Code), it will automatically set the protocol to smtps and add Java Mail smtps properties if the property smtp.isSecure is set to true. Basically, the properties smtp host, username, password, and port will be required.  Also note the property smtp.isSecure is not a Java Mail property. It is just the property name that I came up with so that the code can toggle between normal smtp and smtps protocol.

I also created an override for the super.doSend(..) method so that after calling the Transport.connect(..) method, it will test for connection via the Transport.isConnected() method. This is just an extra step to make sure that we are connected to the SMTPS server and may not be needed in some cases.

Futhermore, If you have a CRUD for the server configuration,  the mail.properties value may be replaced with an implementation that retrieves its values from the database as well.

Friday, January 12, 2007

Spring Acegi: Force Re-Authenticating Other Users When Roles Change

Here's the Scenario that I have an issue with:

A System Administrator edits a user role and the user whose role is currently logged in could possibly already be logged in.

When System Administrators log into a website and edit a user role, the default implementation of Spring Acegi does not re-authenticate the user if the user is currently logged in to the system. In short, if the user in question is an administrator and you remove the admin role from the user the changes doesn't take effect until the next time this user re-authenticates--i.e. log-out then log back in.

The Solution:

The ideal solution would be for the system without turning on the alwaysReauthenticate to detect that the user information has changed and will automatically re-authenticate user in question is already logged in to the system.

How do I get acegi to re-authenticate the user who is currently logged in whenever this person's user roles are edited? I don't want to turn on alwaysReauthenticate property on the FilterSecurityInterceptor. The solution I came up with is whenever the EditUserFormController executes (only executed by admins) to save the user information (including but not limited to user roles), I clear the userCache entry for that user and added a filter that will check whether the user exists in the userCache. If it doesn't it will set the Authentication.authenticated property to false, hence to be forced to re-authenticate in FilterSecurityInterceptor. This filter executes before the FilterSecurityInterceptor in the filter chain.

This seems to work fine but without turning on the alwaysReauthenticate property this is the most perfomance-saavy solution until a functionality like this (if it makes sense to implement) is implemented in Spring Acegi.

Here's the code snippet from the filter I created:
protected void reAuthenticateAsNeeded() {
    Authentication authentication = SecurityContextHolder.getContext()
            .getAuthentication();
    if (!("anonymous".equalsIgnoreCase(authentication.getName()))
            && authentication.isAuthenticated()
            && m_userCache.getUserFromCache(authentication.getName()) == null) {
        authentication.setAuthenticated(false);
    }
}

Please note that the following FilterSecurityInterceptor is then executed and will re-authenticate the user.
(see also AbstractSecurityInterceptor#beforeInvocation())

Wednesday, December 20, 2006

Got MyEclipseIDE?

I've been a Java/J2EE Consultant for over 8 years now and I've been a MyEclipse subscriber since approximately 1993. I am always impressed in how fast MyEclipse kept up with the version of Eclipse and Eclipse plugins being released. New technologies emerge all the time and before you could think about it, the tools you love to use is already integrated on their next beta and eventually GA release.

When pair-programming with other developers I noticed that they are always in awe when they observe how I can modify my code on-the-spot without re-starting the web or application server. Of course the hot-code replace feature was never a surprise to me because I've been a MyEclipse user for quite a while now and previously a WebSphere/Rational Application Developer (WSAD) user as well which had similar set of tools for development (only WSAD is more expensive).

WebSphere/Rational Application Developer is a very similar IDE that comes with it's own suite of tools that will aid developers in whatever aspect of programming they are tasked to do. The big difference is that MyEclipseIDE uses mostly open source plugins and IBM develop its own. I think this price difference is worth noting. I have had the priviledge to read a couple of email responses to MyEclipseIDE lately and these emails were shaming MyEclipseIDE for "stealing" opensource tools. The responses really surprised me since on the other side IBM Develops it's own suite of tools and a single license cost $2220 while MyEclipseIDE uses opensource tools and their lowest subscription cost $31.75. Why are these people slamming MyEclipseIDE for delivering quality low-cost development tools?

I have also been in several projects where WebSphere was used and compared to MyEclipseIDE, WSAD was so bloated that normal day-to-day tasks would take longer than expected. Not to mention that it takes literally a day or two to install WSAD. I honestly am not sh*tting you. I hated installing WSAD. Take a look at the pricing for IBM Rational Application Developer (formerly known as WebSphere Application Developer) and try not to freak out. WSAD is a very nice tool but the price-to-performance ratio for WSAD just doesn't compare to MyEclipseIDE.

Cost Justification
For every consulting company that I have been in I have always used MyEclipse. Most of a consultants effort on the first week is getting setup with the company's development environment and most will have a base eclipse and numerous plug-ins to install. At an average, it will take at least 2 to 4 to set someone up on a new machine.
  • Install plug-ins
    (Struts, Spring Framework, Subversion, a plug-in to run an application server)
  • Install Database tools

So to do a calculation for 2 people at an average cost of $40/hr.

2 people x $40 x 4 hours = $320.

This applies for all new employees or consultant that needs to be setup. I want to note that as of now, here are the different types of MyEclipse subscriptions:

  • Standard Edition (SE) $31.75
  • Professional Edition $52.95

I have also witnessed a setup time of one hour but then later on the users of these inferior plugins continue to have day-to-day issues and it does get costly when your IDE is crashing all the time and in addition you experience code synchronization issues between the source in your IDE and the application server (just to note some examples).

So I hope that this is a no-brainer for all managers out there. Got MyEclipseIDE?

MyEclipseIDE Features That Stand Out

Web Deployment Tools

This feature has been around since day one and it's got to be one of my favorite. This particular feature handles how a web project deploys it's sources and reference libraries. If your web application refers to dependent projects, they can either be placed in the specified web classes output directory or be deployed as a [project].jar files. What typically happens in a non-MyEclipseIDE environment is that if you have a situation where a project refers to another project. When the child project changes, a ant build task is manually launched and jar the dependent project and gets placed in the WEB-INF/lib web project directory. Now, try and imagine if you are working on the child project. You would have to do this every time you make a code change and then restart your application server. How annoying is that? MyEclipseIDE updates the code every time you save so even when running Tomcat the hot-code-replace is awesome. Which developer do you think will be more productive?

Asynchronous JavaScript (AJAX) Tools

If you've already jumped in the AJAX bandwagon you might be dreading it right now because it's hard to debug javascript code. But thank goodness that MyEclipseIDE comes with it's own suite of AJAX tools and the most useful tool to me is the AJAX debugger.

The debugger is so neat you can debug any live web address and then put a bookmark on any of its javascript code (this is possible since javascript is a public html resource). I urge you to watch this MyEclipseIDE Features Overview (also mentioned above).

Database Tools

I love this feature and is compatible with any JDBC-compliant database servers. What I find handy for this is the generation of the database entity relationship diagram (or ERD). I may have a task to implement a feature and as a consultant I am what you call a "business-rule" blind and I need to see the big picture. This allows you to generate the entire ERD or selectively. It prints out really nice as well. This is a cool feature to show to other non-MyEclipseIDE users because it is a developer productivity aid. I wanted to also note that it supports typical JDBC queries, table creates, etc..

Other Features Worth Noting

There are several others worth noting like the hot-code-replace for launching application servers; Framework integration plug-ins for Spring, Hibernate, Java Server Faces, Struts, JSTL, Tapestry, etc...

Upgrading

When new features come up, the freebie developer (a developer using Eclipse with manually installed plug-ins), will get the word somehow that a new upgrade for a particular plug-in has been released. That developer then downloads and installs the plug-in to find out later one that the plug-in is not compatible with the current version of Eclipse they are using. What I usually see happen is that other developers download and install the plug-ins as well, so now you have N developers that are *screwed* because no one has tested this plug-in. And if someone has tested them it's only for a particular version of Eclipse and not everyone is running the same version of it. So what ends up happening is that developers refrain from downloading a plug-in until someone else can guarantee that this will not break their current install. This could end up costing the company some amount of money as well for the time spent trying to resolve this issue, not to mention it will hinder developer productivity and lowers the developer tool confidence level as well.

So here I am at my workstation LMAO because I never have those issues being a MyEclipseIDE user. When I upgrade to the newest GA version the plug-ins in MyEclipseIDE are guaranteed to work. I never have to question whether this will break my development environment. It is always guaranteed that the integrated plug-ins are tested. And if a bug arises there's a place that I can go to for support and this rarely happens for me. For as long as I can remember I have never rolled back a GA version of MyEclipseIDE.

The MyEclipseIDE Influence
I don't usually convince or sell MyEclipseIDE to people and I think most of them will find that there a lot of benefits using this tool and I myself demonstrating developer productivity first hand is enough for companies to start buying several subscriptions themselves.
MyEclipseIDE: A Killer App?
I don't believe MyEclipseIDE is a killer app but I believe it's overall the best Java Development IDE out there that focuses on (1) low cost, (2) minimal bugs and (3) fast support turn-around at a very low price per seat. Every now and then when new features come out some of them may be quirky (like the Hibernate support tools) but they usually get better on future versions.
Reference:

Friday, December 08, 2006

Dealing with Html Buttons

I've gone through several deviations and techniques of handling HTML buttons in an action handler code and so far this is the best and proven code that I have came up with.

The class is called HtmlButtons and it is designed to handle buttons and image buttons in your HTML/JSP page.

Suppose we have the follwing HTML form:

<form action="/createNewUser.do">
<input type="text" name="username"/>
<input type="password" name="password"/>
<input type="submit" name="createButton" value="createButton"/>
<input type="image" name="deleteButton" value="deleteButton"/>
</form>

With HtmlButtons, the way to handle this in your action handler class would be very simple. The following is an example of a Struts Action handler:

public ActionForward execute(ActionMapping mapping, ActionForm form, 
        HttpServletRequest request, HttpServletResponse response) 
            throws Exception {
            
    ActionForward forward = mapping.getInputForward();
    HtmlButtons buttons = new HtmlButtons(request);
    if (buttons.pressed("createButton")) {
        // Create User
    } else if (buttons.pressed("deleteButton")) {
        // Delete User
    }
    return forward;
}

On top of that, if you create an abstract base action class, you could actually make the HtmlButtons class be a part of your method arguments:

// ActionBase#executeAction (abstract)
public ActionForward execute(ActionMapping mapping, ActionForm form, 
    HttpServletRequest request, HttpServletResponse response) 
        throws Exception {
        
    return executeAction(mapping, form, request, response, new HtmlButtons(request));
}

// Action Class Implementation
public ActionForm executeActionActionMapping mapping, ActionForm form, 
    HttpServletRequest request, HttpServletResponse response, 
    HtmlButtons buttons) throws Exception {
    
    if (buttons.pressed("createButton")) {
        // Create User
    } else if (buttons.pressed("deleteButton")) {
        // Delete User
    }    
}

View HtmlButtons.java

I Hate Casting!

I don't mean to sound like Grumpy Smurf but did I tell you I hate casting? Thanks to the new JDK 1.5 templating I can finally eliminate them!

  Eliminate Them! (A quote from Star Trek Insurrection)

An Enterprise Java Bean Example
// Old
private UserSessionHome getUserSessionHome() throws Exception {
    return (UserSessionHome) initialContext.lookup("ejb/UserSession");
}

private AccountHome getAccountHome() throws Exception {
    return (AccountHome) initialContext.lookup("ejb/Account");
}


// New
private UserSessionHome getUserSessionHome() throws Exception {
    return getHome("ejb/UserSession");
}

private AccountHome getAccountHome() throws Exception {
    return getHome("ejb/Account");
}

private <T> T getHome(String jndiName) throws Exception {
    return (T) initialContext.lookup(jndiName);
}

Usage Example:

UserSession userSession = getUserSessionHome().create();
userSession.createUser(userInfo);

A Spring DAO example
@SuppressWarnings("unchecked")
public <T> T get(Class entityClass, Serializable id) {
    return (T) super.getHibernateTemplate().get(entityClass, id);
}

In your DAO Implementation Class:

// OLD (with Casting)
public User getUser(String username) {
    return (User) super.getHibernateTemplate().get(User.class, username);
}

// New
public User getUser(String username) {
    return get(User.class, username);
}

Hey, wouldn't it be nice if the Spring developers provide an IBatis SqlMapTemplate and HibernateTemplate specifically for JDK5 to eliminate casting.

My 2 cents...

Sunday, September 10, 2006

Binding Tabular Data with SpringFormControllers

This blog discusses the nature of dynamic tabular data in web applications and how this is handled in Spring Framework. The main point here is that the tabular data cannot be modified in any way or else an IndexOutOfBoundsException will occur.

Assume for a moment that we have tabular data we want to edit the quantity on our cart items. The tabular field is indexed using open and closing square brackets [].

<c:forEach var="item" items="${shoppingCartForm.items}" varStatus="s">
    <spring:bind path="shoppingCart.items[${s.count-1}].quantity">
    <input type="text" name="${status.expression}" value="${status.value}"
        style="width: 100%;"/>
    </spring:bind>
</c:forEach>

Override SimpleFormController's formBackingObject method in your form controller class:

protected Object formBackingObject(HttpServletRequest request) 
        throws Exception {
    Long cartId = RequestUtils.getRequiredLongParameter(request, "cartId");
    ShoppingCart cart = shoppingCartManager.findShoppingCart(cartId);
    return new ShoppingCartCommand(cart);
}
The Detailed Explanation

When spring binds the array it expects items to have contents. Therefore, we need to override the SimpleFormController.formBackingObject to always retrieve the current data.

During the form rendering (showForm()) our page is rendered and the moment the Controller processes the request after the form is submitted, the controller will retrieve the most current data via the SimpleFormController.formBackingObject().

If for some reason the shopping cart items increased (via some method in the JSP) the binding will throw an IndexOutOfBoundsException because the items currently in our database will be less than what we are trying to bind.

If we have this situation we need to explicitly correlate the number of items to be persisted with the ShoppingCartCommand.items to avoid the exception.

Number of items from the database: 3
The user added another item which totals to 4
In the SimpleFormController.formBackingObject() method we need to figure out how many new items were added and increase the list size so the binding can occur. In our case we need to increase the list size by 1.

Internet Explorer Submit Button Bug

I've know about this problem for almost 3 years now. I guess It's time to put the blog out.

Affeted IE Version: 5 and 6
Opera: ???
Firefox, Bon Echo: Not affected

The Bug

If we have a form where only one text field exists:

<form>
    First Name: <input type="text" name="firstName"/><br/>
    Roles:  
    admin: <input type="radio" name="role" value="admin" />
    user: <input type="radio" name="role" value="user"checked="checked"/><br/><br/>
    <input type="submit" name="submitButton" value="submit"/>
</form>

When the user enters a first name and hits the enter button, here's the query string and by George the submitButton is missing!

ie_submit_button_form.htm?firstName=John&role=user   

I know what you're thinking: IE sucks! Microsoft is Evil! Son-of-a-$*#@@#&!
I know. I know. But nobody writes perfect code so I'll show you how to fix this problem.

What's suppose to happen by default is that the first declared submit button should be set. In our case it's the submitButton. In IE, this doesn't happen.

The Workaround

So the way to fix this bug is add another text field.
In most cases where you don't have a choice and there's only 1 text field in the form, you can add an invisible text field (a hack):

<input type="text" style="display:none;"/>

Now let's try this again, given the following code:

<form>
    First Name: <input type="text" name="firstName"/><br/>
    Roles:  
    admin: <input type="radio" name="role" value="admin" />
    user: <input type="radio" name="role" value="user" checked="checked"/><br/><br/>
    <input type="submit" name="submitButton" value="submit"/>
</form>

Focus on the first name field and type a name, then press Enter key.

Here is the query string and the submitButton is set:

ie_submit_button_form.htm?firstName=George&role=user&submitButton=submit

Putting an invisible text field is not a bad hack and does not require code change when new versions of IE come out. It's also not going to affect the other browsers that are functioning properly...nevertheless, it's a hack!