Tuesday, August 5, 2008

Beginning Groovy & Grails on Sale today only!!

Well i am assuming Apress has the most random site in the world at times.

But today only they have our recent book, Beginning Groovy & Grails for $10 (ebook)

Click here - http://www.apress.com/info/dailydeal

If you want to purchase it i suggest going before midnight tonight.

Tuesday, June 10, 2008

Authentication With Seam

One characteristics of modern web frameworks is to provide lots of functionality out of the box. This functionality ranges from authentication, to batch processing, to validation. For those of you who have used Seam's authentication framework, you know it is extremely easy to use. However, if you want to add some custom messaging in there, it is NOT as easy to use. We will go over here a work around to that issue. But first let's discuss how to create Seam authentication in general.

The main component to remember is the `Identiy` class. This will store the user, password, and provides the methods on it for logging in and out. This class is provided by Seam out of the box. In the first part we will create the login itself.

The login can be fairly simple and will use the `Identity` object. Here is a simple login form.

Partial of login.xhtml

<h:form id="login">
<h:inputText id="username" size="20" value="#{identity.username}" required="true"/>
<h:inputSecret id="password" size="22" value="#{identity.password}" required="true"/>
<h:selectBooleanCheckbox id="rememberMe" value="#{identity.rememberMe}"/>
<h:commandButton value="Login" action="#{identity.login}"/>


As you see everything here references the `Identity`, now thats just the first part. We need to tell Seam what class/method to use for authentication.
In your *components.xml* you will define an authentication method and class to call when `#{identity.login}` is called.

components.xml

<security:identity
authenticate-method="#{authenticator.authenticate}"/>


Then you simply define a Seam component named "authenticator" with a method "authenticate". By default Seam allows you to inject an object called `Identity` ( a Seam Session scoped component). The `Identity` object contains the username, password, and roles associated with the user, the first two will be used for logging in. A base skeleton of this code is here:

Authenticator.java


@Name("authenticator")
public class Authenticator
{
@In
Identity identity;

public boolean authenticate() {
// Do your database, ldap, etc lookup
// then return true/false based on if it was successful
}
}



Simple enough eh? It's simple and straight to the point. However, there is one **IMPORANT** thing to remember when using Seam Security. And that is Authentication != Login. This distinction will for the most part not effect you unless you want to start dealing with error messages.

By default there are two messages, a failure or successful login that are displayed by Seam automatically when an authentication passes/fails. Both of these are defined in the `message.resources` file as :

message_en.properties

org.jboss.seam.loginFailed=Login failed!
org.jboss.seam.loginSuccessful=Welcome


You can change the messages there. However, what if your requirements are more complex. What if you want to display a message that specifically the username or password is in correct, or if you are using something like LDAP or CAS, and you want to report that their servers are down. Simple enough right? Just do a `FacesMessage` context look up and add to it? Right? Wrong! What's the problem with this? You run a good chance that the error message will show up twice on the screen. While this isn't the worse thing to happen, it is a bit annoying. So why does this happen? The authenticator is just that its "authentication" it is NOT logging in. Meaning that the authenticator is actually called multiple times depending on the scenario and you do not necessarily have control over when and how often the authenticator is called.

So how do we fix this? Well the answer is, we do not write messages directly inside the authenticator. Instead, we will write login messages where they should be written, at login. So how do we do this while still using Seam's login? One way is to use a combination of the Seam Events/Observers and to write a "custom login".

The purpose of the Events/Observer, is actually quite interesting. You can write an event in one area of the code, and the Observer can pick it up based on a keyword in a separate class and process it. So in the authenticator you can add this line of code whenever you want to raise a specific message.


Events.instance().raiseEvent("invalidLogin", "Invalid password!!");


The first part of the method contains the key "invalidLogin", the second part displays whatever string we want to display to the front end. Please note, the actual method takes an array of Objects for it's second parameter, so you could pass as many strings, or whatever object you want to it.

We have now saved this event, now comes the part of retrieving it and storing it to the `FacesMessages`, this part is a BIT trickier, but not that bad. We need to create our own `Identity` class. The `Identity`, as I explained is the component that actually performs the logging in. But wait just earlier i said that `Identity` is a Seam level component. What we are going to do is basically extend the `Identity` class and then replace the component with ours. Lets take a look at our custom identity component.

CustomIdentity.java


@Name("org.jboss.seam.security.identity")
@Scope(ScopeType.SESSION)
@Install(precedence = Install.APPLICATION)
@BypassInterceptors
@Startup
public class CustomIdentity extends Identity {
private static final long serialVersionUID = -9154737979944336061L;

@Override
public String login() {
String retVal = "";
try {
// clear out the login message in case it was triggered
// by an authenticate occurring outside the login
loginErrorMessage = null;
retVal = super.login();
} finally {
// check if any error messages were registered from
// this logging., if they are write them out
if (StringUtils.isNotBlank(loginErrorMessage)) {
FacesMessages.instance().add(loginErrorMessage);
}
}
return retVal;
}

private String loginErrorMessage;

/**
* This is used to save off an error message in case of a login.
* @param message
*/
@Observer("invalidLogin")
public void writeInvalidLogin(String message) {
loginErrorMessage = message;
}
}



This code is a bit of a mouthful, but really not that hard to implement. The class level annotations are similar to the ones by default with `Identity` except we change the precedence to a later time. By default `Identity` has a `BUILT_IN` precedence. By changing it to `APPLICATION` we guarantee that our custom component will be the one used by Seam instead of Seam's `Identity` component.

The last method in the code defines the `Observer`. The `Observer` is called when the event is raised, so we are going to set it to a class level string.

Finally, you will see the login. It again is fairly straight forward as well. We are going to call the parent's login method (which is Seam's Identity login method) but after the login call we will check to see if any messages were saved by our Events/Observer pattern and if they are we will add them to the `FacesMessages`.

And that is it. You now will display errors the screen without them displaying multiple times.

While this is not the MOST straight forward way to add messages, it unfortunately is one of the ways you can do it in Seam. I have seen quite a few questions in the past at conferences and message boards about why dual messages are sent back. I hope this help explains it and shows you a way around the issue.

Saturday, April 26, 2008

Grails - Perfect for College Students


My three co-authors are starting to put the finishing touches on our Groovy and Grails book, which is out in June. Today we had to design the cover letter (which goes on the back) that tells the audience what this book is about and who its intended for.

Well it struck me as I was helping to write the how perfect Grails is not only for advanced Java users but for extremely basic Java users. The FACT remains despite what many might tell you, Java is strong in the work place and growing even stronger. And there is very good reasons for this, the Java stack can do things that some of the smaller more flexible dynamic stacks just can't do. For example one of the systems I am helping to write right now contains an extreme amount of nightly processing, this system is managed for its starts, the amount of beans running at a time, etc. My point is ... Java is needed for the system.

So where does Grails play into all this? Learning Java is actually fairly easy. Using it properly a bit harder, understanding the components used for applications and how to set up and create a Web 2.0 framework MUCH harder. (this is one are that Java gets rightfully dinged) Its quite the effort and beginners WILL get lost. Enter Grails. It not only sets everything up for you, but makes it easy to run and deploy, you don't even need to configure a database.

But not only that. It uses Spring and Hibernate, tools many Java developers use in their daily work. Now while it wraps much of the pains of both, the general ideas will still be there. Not to mention the clear separation of MVC and Services exists as well. In the end what Grails will give you an easier route to learn more advance items, and when it comes time to use any other Java framework out there you will have an easier time ramping up than your peers. Not to mention you will be able to intelligently talk about Web 2.0 Java development in interviews.


Wednesday, February 13, 2008

JBoss World Day 1


Today is the first day of JBoss World, I survived the first three presentations and waiting for the keynote to be  complete to do some of the "socializing" / "networking" aspect of this conference. Has gone very well so far. The first session on JBoss Clustering was quite interesting. Also attended Big Lots session. I was not going to at first, but it is always interesting to see what others are doing in the technologies one works with. I also even met two people from the company I used to work at when I was in Georgia (I knew one of the guys but did not recognize him at first)

All in all good soo far. I do find it weird how many of their sessions someone duplicate (like Seam). I hope by the time they get to my session people are not thinking, you know i am tired of Seam now.

At any rate, will post more later.


Thursday, January 10, 2008

Codemash Day #1


 Codemash has started and we are half way through the day. This morning I attended two Ruby talks (one on Facebook and the other on Flexmocks) that were both interesting.

The Facebook one really fascinated me, because their is soo much potential and money for those kind of applications. Not only that but tease to create an application that uses Facebook is much more trivial than I originally thought it'd be. I am quite frankly surprised their aren't more applications out there for it from big businesses. 

Well looking forward to the Grails presentation from my co-author at 3:30, then off to finish up my presentation for tomorrow.