Tuesday, January 4, 2011

Groovy MetaClassing Issue?

Does someone want to explain this to me?

Or can?

Here is my basic problem. I have a class, it takes a method, i want to intercept it and depending on the object do something with it.

It can accept some kind of Collection usually.

Now here is the problem. You can use the object fine. But when you do something like "list as Set" ... when it hits the invokeMethod the arg is a PojoWrapper and NOT a Set object. Note if you called the method directly it is a Set.

This provides all sorts of problems, for one you cant do args[0].getClass() or it will thrown an NPE.

I tried to do just about anything to determine the variable when it is a PojoWrapper but everything threw an NPE.

Using groovy 1.7.5 ... cut and paste this into your groovy console and you will see


def a = [1,2,3]

def b = a as Set

t = new Temp()
t.stuff(a as Set)
println "*******"

t.metaClass.invokeMethod {String name, args ->
def ourVar = args[0]
println "name : $name / args : " + args[0]
if (ourVar instanceof Set) {
println "its a set"
}
else if (ourVar instanceof Collection) {
println "its a collection"
}
else if (ourVar instanceof org.codehaus.groovy.runtime.wrappers.PojoWrapper) {
println "Wrapper"
println ourVar
def list = []
list.addAll(ourVar)
println list.getClass()
}
//println ourVar.class
println "----"
}

t.joe(a)
t.joe(b)
t.joe(a as Set)

class Temp {

def stuff(t) {
println t
println t.getClass()
}

def invokeMethod(String name, args) {
println "huhg:: " + args
}
}


Tweak it, to me its pretty odd, i am using something similair in my code, and i can come up with a few hacks but none that are good. I'd really like to be able to determine what that PojoWrapper is.

Note if u do the as Set and set to a variable before hand it works fine.

Thursday, August 6, 2009

When NOT to use Injection in Seam

Seam has a very interesting and quite frankly very powerful and unique methodology for injection in the Java world. There injection methodology is a bit different in Spring in that it is done at method level (and the fact that Seam supports bi-jection as well). The injection works for services and for properties. So take the example below:



@Name("foo")
@Session
public class Foo implements FooService {

@In
UserTO user;

@In
UserService service;

public void process() {
service.run(user);
}
}



Here we are injecting a user and a service and can now have a seam component or a JSF page call this class. In fact they can both call this easily since there is nothing web specific in the definitions by having the transfer object "user" defined on there pages and then calling: foo.process(). The user being used will be injected as well as the service so they both will be accessible by the method.

This class can be a Stateless Session Bean or a POJO, which under normal circumstances could never handle a user specific class level variable. But with Seam it can. Why is this?

Method Level Injection
Simple. Seam intercepts everything at method invocation time. That way this code can work on classes that are usually stateless. Every time this method is called the bi-jection happens. So one can guarantee that multiple calls to the class will have access to the right user object. (based on scope)

Well that's great for transfer objects and domain objects, but what about that service up there? It's getting injected EACH time as well, which is fairly unnecessary. And each time you do it you are adding to the time it takes to run this method. For most web based applications that small overhead of injecting it will not be felt. However, what if you are using Seam to do some batch processing where you want to process multiple items per second. And what if the class you are using injects multiple services. That is where this scenario starts to show fatigue, and takes more time. This is the problem we were recently having at a client, we noticed an appreciable slowness due to this constant bi-jection of services. The time was enough we were processing 5 items per second instead of 10. so what's the answer?

Not Using @In
The answer is relatively simple. If the bean in question is a Stateless Session bean then use the normal @EJB for your services. Remember when using Seam we either define in the ejb-jar.xml or the Session Bean itself that Seam will be intercepting the Session bean. So when you use @EJB your service will still get injected with all the normal Seam bells and whistles; however, this will occur before the bean is given to the caller and not at method invocation time. The previous code would now look like this:




@Name("foo")
@Session
public class Foo implements FooService {

@In
UserTO user;

@EJB
UserService service;

public void process() {
service.run(user);
}
}



And if you using straight POJOs you can still make use of the @Create annotation and do a bit of coding to set the component yourself then. Just use the following to set the service:



Component.getInstance("serviceName")



Using the @EJB annotation not only helps performance but cleans up the code so that you know if you see @In it's for a transfer object that could be changing.

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.