Seam

/Tag: Seam

Environment specific mail auth and Seam’s MailSession

If you are using Seam’s MailSession to send out going e-mail from your Seam application you can run into trouble if you have a mail server in any environment (dev, test, stage, prod) that allows outgoing mail based on the client’s IP address and does not use username and password based authentication.

The standard configuration for the MailSession is in the components.xml file and looks like this (if you’ve used SeamGen to create your project):

[xml] [/xml]

Then each of your environments has a components-{env}.properties file, which is deployed out and used to populate the @[email protected] placeholders in the components.xml file. For instance your components.dev.properties file might look like this:

[plain] jndiPattern=YourApp/#{ejbName}/local
debug=true
mailhost=mail.mydomain.com
mailport=25
mailusername=mailus3r
mailpassword=mailp4ss[/plain]

Which works great. However, if for instance your production environment uses IP based mail authentication for outbound e-mail, you might try to set your components-prod.properties file to look like this:

[plain] jndiPattern=YourApp/#{ejbName}/local
debug=false
mailhost=prodmail.mydomain.com
mailport=25
mailusername=
mailpassword=[/plain]

However, that ends up setting empty strings into the username and password member variables of the MailSession component, and unfortunately the logic which determines whether or not to authenticate with the mail server checks for nulls only. So with empty strings, it attempts to authenticate with the mail server using a blank username and password. Which fails, and causes an unhelpful Faces error (unless you turn on debug on the MailSession component).

I’ve logged a Jira ticket about it here: JBSEAM-4176

You can do a simple workaround by overriding the MailSession component with your own sub-class of the MailSession class. In your sub-class you can override the setUsername and setPassword methods, check for empty strings and set null into the member variable if the parameter is null or empty. Luckily the Seam Install precedence system makes it very easy to override the default Seam component.

[java] package com.myapp.mail;

import static org.jboss.seam.ScopeType.APPLICATION;

import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;

/**
* The Class MailSession. This is an overriding class designed to work around
* https://jira.jboss.org/jira/browse/JBSEAM-4176
*/
@Name(“org.jboss.seam.mail.mailSession”)
@Install(precedence = org.jboss.seam.annotations.Install.APPLICATION, classDependencies = “javax.mail.Session”)
@Scope(APPLICATION)
@BypassInterceptors
public class MailSession extends org.jboss.seam.mail.MailSession {

@Override
public void setPassword(String pPassword) {
if (pPassword == null || pPassword.trim().length() == 0) {
super.setPassword(null);
} else {
super.setPassword(pPassword);
}
}

@Override
public void setUsername(String pUsername) {
if (pUsername == null || pUsername.trim().length() == 0) {
super.setUsername(null);
} else {
super.setUsername(pUsername);
}
}

}[/java]

Make A Custom RichFaces Skin

Using RichFaces in your application makes it easy to build great rich interfaces without spending a ton of time writing custom JavaScript for the front end and the back-end support for the JavaScript calls. It ties into your JSF components easily and makes dynamic interaction easy to build. It also comes with a number of default skins which is great when you’re first starting to build out a new application because it gives it a nice polished look instead of just black and white unstyled elements.

However, once you you get your own site design in place, the RichFaces skins probably won’t match your design perfectly. You can always override any of the particular element styles using CSS, but if you want to quickly change the global look and feel for all the RichFaces components, the easiest thing to do is to create a customized RichFaces skin.

You should start with the RichFaces skin that most closely matches your design and build your custom skin based on that. The skins are defined in properties files in the RichFaces jar file under /META-INF/skins/. You can also just download them from here, to avoid having to unpack the jar file yourself: richfaces-skins.zip.

Copy the skin file that’s closest to your design into your project. If you’re using a Seam project created with seam-gen, you’re in luck because the ant build file is already setup to deploy RichFaces skins if you have them. Just drop the skinname.skin.properties file into the “resources” directory of your Seam project. Rename it to a custom name for your site’s skin, i.e. mysite.skin.properties.

Now you need to configure your application to use the new custom skin. Edit /resources/WEB-INF/web.xml, and change the org.richfaces.SKIN param to the name of your new skin:

[xml] org.richfaces.SKIN mysite [/xml]

Now you can edit the skin file to adjust the colors and look and feel of the skin to match your site’s design. The ant build file will automatically deploy the custom skin file into the war file.

There are also other ways to customize RichFaces and build custom skins including extending an existing skin, or using the new Plug-n-Skin feature, or using XCSS, etc… But this should get you started!

Seam EntityHome Design Pattern

I’ve been using Seam for over a year. At some point the “Home” object was introduced to the documentation (Chapter 11). Reading the documentation didn’t convince me of the point. Being an ATG guy at heart, I still prefer using “form handlers” for managing my important entities. So I haven’t bothered.

However, just recently I ran into a little problem with LazyInitializationExceptions. I’m sure you’ve run into them yourself. Basically, when Hibernate loads an entity for you, it’s loaded by an entity manager which is available to manage that object within a specific scope. This effects persisting changes. Also, if you have properties on that entity that have a fetchType.LAZY, those properties can only be lazily loaded while the same entity manager is available. If it’s not, you get LazyInitializationExceptions. No fun.

So in Seam, what I usually do to avoid this, is to create a long running conversation, and load the entity within the context of that conversation. Then, as long as you’re still in that long running conversation, you can lazily load all the properties you want.

Normally this is fine. However, in my latest project the application will send e-mails to users when they get a new inter-user message. If they click on the link in the e-mail, they come to the site, but without the existing long running conversation query parameter. Their user component is session scoped, so they’re still logged in, but the user object is now outside of it’s conversation, and if you attempt to access lazily loaded properties, for instance the user’s messages they are trying to see based on the e-mail, blammo: exception central. Unhappy users.

I was pointed to this page: Using EntityHome for entities in long-running contexts

Which showed me how to use the EntityHome to avoid the whole problem. Basically it works like this:

When the user logs in, set the user entity’s id into a session scoped component. Don’t bother with long running conversations (at least not for the user). The User Home component’s Factory method creates a user component using the session scoped user id, anytime the user component is referenced. This component entity is loaded within the context of the current conversation (if it hasn’t already been loaded). So, presto-magic, no lazy loading issues.

It let me fix the issue with about 20 lines of code, and little trouble. It’s working perfectly so far.

10MinuteMail Updates

I just pushed a new version of 10MinuteMail. Here are the notable updates:

  1. Removed the Ad-Aware links and text. No one was clicking on them anyhow.
  2. Added some translation fixes.
  3. Implemented AJAX based (RichFaces) refreshing of the list of e-mails in your inbox.
  4. Added smtp client throttling (in Postfix) to limit the number of messages accepted from a single source within 60 seconds. This seems to have already fixed the negative impact of high volume spammers on the function of the site.
  5. Removed the “Get Another E-Mail” feature. While this was a user request, I discovered that it was being abused by spammers.
  6. Added a Forward feature to allow you to forward a received e-mail to your home account for storage.

Enjoy! If you have any issues with the AJAX refreshes, let me know, but I think it should work better now.