Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Thursday, January 31, 2008

Stripes 1.5 Feature: General Improvements

My last two Stripes articles covered Clean URLs and @StrictBinding. Today I am going a bit more general and discussing several of the smaller improvements.

Disclaimer - We know that other web frameworks have had some of these features in some form or fashion so please don't comment with "ZZZ Framework has been doing that for years.". We know. We get it.

@DontValidate

This annotation has been in Stripes for a while. We would typically use this for cancel events or just any event where you don't want validation to occur. The problem however was that type converting still happens and if it fails errors are generated and your event won't complete. This has been changed in 1.5 so now @DontValidate will also ignore type conversion.

@DontBind


Yesterday I talked about @StrictBinding and how you can control data binding using the annotation and validation. Since @StrictBinding is a class level annotation it makes it nearly impossible to do this on a per event basis. @DontValidate helps but binding still occurs. @DontBind implies @DontValidate and does not attempt any binding of data.

@HttpCache

Back in November of last year I blogged about how easy it is to create an interceptor for Stripes and we created the @NoCache interceptor. This interceptor has been added to Stripes core in 1.5 but with a twist. It is now called @HttpCache and you can control the no-cache and expires parameters via annotation attributes. Lets look at an example.

@HttpCache(expires=600)
public Resolution ajaxUpdate() {

}

The above example will allow caching but expires the document in 10 minutes.

@HttpCache(allow=false)
public Resolution ajaxUpdate() {

}

The above example disables caching and immediately expires the document. This comes in really handy when returning Resolutions to AJAX requests (especially in IE). @HttpCache can be applied at the class or method level. Method level annotations will always override class level annotations.

@Before/@After

These annotations have been available in Stripes for a while but now can be set to run on certain events. Lets look at an example.

@After(on = {"save","edit"}, stages = LifecycleStage.BindingAndValidation)
public Resolution runAfterBinding() {

}

The above method will only execute on the save and edit events. Multiple LifecycleStages can also be specified. @Before works the same way.

There are also quite a few more subtle but significant changes. Here they are in no particular order of importance.

  • When you create a link that doesn't pass validation and there is no _sourcePage to go to, you get a nice validation error report that tells you what you did wrong instead of getting a StripesRuntimeException and having to jump through hoops to figure it out

  • Incoming requests are no longer wrapped multiple times when you map StripesFilter on FORWARD. Solves problems that existed with wrapping multipart requests more than once (big explosion) and other silly issues that would occasionally arise from wrapping multiple times.

  • Enhanced checking of stuff (multiple @Validate, multiple @DefaultHandler) etc. Stripes now does a much better job at notifying you about trivial issues that can be a pain to track down. For example if you annotated two methods with @DefaultHandler Stripes would just pick one and determining why you weren't getting the expected results was time consuming. Now Stripes will throw an exception and tell you exactly what the problem is.

  • Reduced Session use. Stripes used to store encryption keys in the HttpSession. Now that it doesn't stripes doesn't force session creation of any kind.

  • Lots of changes with classpath scanning so that Stripes plays nicer with container/custom class loaders.

  • Most things in Stripes can be easily overridden to support a wide array of scenarios we can come up with as web developers. ActionResolver, ActionBeanContext, TypeConverters, just to name a few. While Stripes prides itself on zero ActionBean configuration you still need to specify init params for the Stripes Filter in the web.xml and that includes any core classes you want replaced with your own custom versions. Stripes now offers an init param, Extension.Packages, that accepts a comma separated list of packages where Stripes will auto discover and load any custom classes that would override Stripes default classes. This can significantly reduce the amount of configuration required in the web.xml


There are a few more enhancements that need to be discusses however they require their own articles respectively. I hope everyone is enjoying these articles. More to come in the days ahead, I assure you.

Wednesday, January 30, 2008

Stripes 1.5 Feature: Control Binding with @StrictBinding

If you missed yesterday's article on Clean URLs you can find it here. Today I want to talk about how we can control what values get bound in an Action Bean when we submit a form. And once again;

Disclaimer - We know that other web frameworks have had some of these features in some form or fashion so please don't comment with "ZZZ Framework has been doing that for years.". We know. We get it.

The Stripes team has added a very useful annotation as well as some supporting changes to an existing annotation to provide a first line of defense against hackers. This annotation is @StrictBinding. This is a class level annotation and uses the @Validate annotation as support. First we can look at a basic example:

@StrictBinding
public class RegisterActionBean extends BaseActionBean {

private User user;
}


In this example any values submitted by a form to this action bean won't be bound at all. Hmm, not very useful. So lets tweak it a bit.

@StrictBinding(allow="*")
public class RegisterActionBean extends BaseActionBean {

private User user;
}


This will allow binding to any top level properties in user. However, nested properties are ignored. Not quite what we need yet. One more modification.

@StrictBinding(allow="**")
public class RegisterActionBean extends BaseActionBean {

private User user;
}


Alright, the double * in the allow attribute says bind everything, no matter how nested. Another way to achieve the same thing is to use defaultPolicy=Policy.ALLOW instead of "allow". If we need finer grained control we can also use the "deny" attribute.

@StrictBinding(allow="**", deny="user.role.id")
public class RegisterActionBean extends BaseActionBean {

private User user;
}


This allows everything to bind except for user.role.id because we don't want a new user to be able to specify their own security level by adding parameters sent to the server. That would be bad. And with that I think you can see the benefit of @StrictBinding. It is a good first line defense mechanism. But we're not done yet.

@StrictBinding all by itself can handle anything you need however the preferred way to control binding is with @StrictBinding + @Validate. Lets look at another example.

@StrictBinding
public class RegisterActionBean extends BaseActionBean {

@ValidateNestedProperties({
@Validate(field="username", required=true),
@Validate(field="password", required=true),
@Validate(field="firstName", required=true),
@Validate(field="lastName", required=true)
})
private User user;
}


First we turn off all binding using the simplest form of @StrictBinding. Then, we control the binding with validation. Any property being validated is bound. Everything else is ignored.

As always data should be sanitized but with the addition of @StrictBinding, Stripes provides a very elegant first line of defense against intruders.

Tuesday, January 29, 2008

Stripes 1.5 Feature: Clean URLs

So I promised a list of some new features coming in Stripes 1.5. Since several of them require some explanation to really get the point across I decided to do a daily article about each of the major feature improvements and then one final article on the smaller things. I finally found a bit of time so here is the first one. Stripes 1.5 is coming along really well. The developers have been committing code like crazy the past month. We should be seeing a beta release really soon.

Disclaimer - We know that other web frameworks have had some of these features in some form or fashion so please don't comment with "ZZZ Framework has been doing that for years.". We know. We get it.

Clean URLs have been possible in Stripes for a while through an add on. However, with Stripes 1.5 they will be an optional feature in the core API. As you may or may not know currently you can define a URL Binding for a Stripes action one of 2 ways. You can let Stripes handle it by inspecting the package and class name and binding it for you or you can explicitly set it using the @UrlBinding annotation. With clean URLs @UrlBinding is required. The format is something like:

@UrlBinding("/action/blog/{$event}/{blog.id}")
public class BlogActionBean...

The resulting URL to edit a blog entry would be:

http://.../app/action/blog/edit/1234

If the event is null it is ignored as well as any given parameter. So a URL like:

http://.../app/action/blog

would result in calling the Default Handler for the BlogActionBean. Support for default parameter values are also available.

@UrlBinding("/action/blog/{$event}/{blog.id=1234")

So accessing the url

http://.../app/action/blog

blog.id will have a value of 1234 however if you pass in a blog.id value it will override the default. Default values for {$event} can also be given. This overrides the @DefaultHandler method if one exists. Otherwise, the @DefaultHandler method is executed.

If you still prefer extensions on your URLs, support for that is also available. The change to the URL binding is trivial:

@UrlBinding("/blog/{$event}/{blog.id}.action")

Stripes JSP tags <s:url />, <s:link />, and <s:form /> all support Clean URLs. For example:

<s:link beanclass="com.app.foo.BlogActionBean" event="edit">
<s:param name="blog.id">1234</s:param>
Edit
</s:link>


Will result in:

<a href="/app/action/blog/edit/1234">Edit</a>

And that is pretty much it for Clean URLs in Stripes 1.5. Very simple, elegant, and as good as the next guys. Possibly better? Let me know.

Friday, November 16, 2007

Stripes TypeConverters: Populating Domain Objects

Most web frameworks today have type converters. Type converters are chunks of code that takes query parameters as Strings and convert them into their appropriate data type. So numbers become Integers, dates become Dates, etc. Most frameworks also allow you to create custom type converters. For example, you might want to convert a currency form field into a Money object. That's all well and good. But we can take it a bit further with Stripes.

A common scenario in the web world is requesting data from the server and displaying it on the page. I mean, really, all web applications do is send data and get data and display the data they got. Nothing too complex. How we populate domain objects based on query parameters is where everyone's code can differ. Most common is for an action to process the query parameters and we get the one(s) we need and use them to lookup information in a database, shove those into some domain objects or properties of some sort, throw them in the request and forward to our view. Again, nothing too complex.

There are many times when we need to populate the same domain object(s) based on the same parameter on many different pages. I'll set up a scenario that we can use throughout the rest of this article. You created a User management screen. Displaying a list of users you want to edit one. The query parameter you pass in is the user.id. So we might have some code in our Stripes action bean that looks something like this:


private User user;
private UserDao userDao;

public User getUser()
{
return this.user;
}

public void setUser(User user)
{
this.user = user;
}

@SpringBean("userDao")
public void setUserDao(UserDao userDao)
{
this.userDao = userDao;
}

public Resolution edit()
{
user = UserDao.getUser(user.getId());
return new ForwardResolution(EDIT_USER_PAGE);
}


We could of course also discuss the pros and cons of doing the same thing in a method annotated with @After/@Before but for the sake of simplicity we'll say that's possible as well and move on.

So the client comes back and decides that they need an additional page where the administrator can click on a product and see all the users that purchased this product. And further more he can click on a user and view some details about that user. We begin to build the new action and view and notice that we've got to duplicate some code we just wrote. We need the UserDao again and we need to do a lookup so we copy and paste, test it, it works. Yea! And then we need another page, and another page, and we copy and paste and copy and paste. At this point we've got the same code written 10 times. That's bad. So we decide hey, we are using Stripes, let's use a TypeConverter to do this.

Stripes has a TypeConverter interface that requires two methods:

convert(String input, Class targetType, Collection errors)
setLocale(Locale locale)

We are only going to worry about convert right now. So we begin our custom type converter:


public class UserTypeConverter implements TypeConverter
{
private UserDao userDAo;

@SpringBean("userDao")
public void setUserDao(UserDao userDao)
{
this.userDao = userDao;
}

public User convert(String id, Class user, Collection error)
{
if (id != null)
{
User user = userDao.getUser(id);
return user;
}
return null;
}
}


This is pretty straightforward. We are just looking the user up from our UserDao using an id. But how does that id get there? Pretty simple as well. Let's look at our action again, only this time using the converter.


User user;

public void setUser(User user)
{
this.user = user;
}

public User getUser()
{
return this.user;
}

public Resolution edit()
{
return new ForwardResolution(EDIT_USER_PAGE);
}


And the URL might looking something like this:

http://localhost:8080/app/User.action?edit=&user=1234

Anytime the id is not null, user gets populated. If it is null, for example when adding a new user, user will only be populated from the normal form to object binding that Stripes normally does. But how does our action know that User is supposed to use the UserTypeConverter? Well, if we weren't needing the Spring Bean injection magic would could have simply done this in our action.

@Validate(converter=UserTypeConverter.class)
User user;

But since we need the Spring Bean magic we need to create our own TypeConverterFactory. Again, another interface. Stripes uses a default to init all the built in type converters. Here is what one might look like:


public class CustomTypeConverterFactory extends DefaultTypeConverterFactory
{
public TypeConverter getInstance(Class clazz, Locale locale) throws Exception
{
TypeConverter tc = super.getInstance(clazz, locale);
ServletContext sc = getConfiguration().getServletContext();

SpringHelper.injectBeans(tc, sc);

return tc;
}

@Override
public void init(Configuration configuration) {
super.init(configuration);
add(User.class, UserTypeConverter.class);
}
}


And then we need to tell Stripes to use our CustomTypeConverterFactory. In the web.xml in the StripesFilter init-params add the following param-name:

TypeConverterFactory.Class

and param-value:

com.app.package.foo.CustomTypeConverterFactory

And we're done. Comments welcome.

Monday, November 12, 2007

Stripes Interceptor Tutorial

Note: I still can't get code to display very well on blogger. Sorry for the formatting issues. If you need to the source code is linked at the bottom of this article if it makes it easier to follow along.

I've been using Stripes for both large and small applications for about a year. While I am of the camp that there is no golden hammer I've not run across a project I am involved with where Stripes doesn't make sense. I've been wanting to write more articles on Stripes. While the documentation on the site is great for folks to get started it is lacking in the area of best practices and general tutorials on different aspects of the framework. One of my favaorite things about Stripes (and there are many) is how easy it is to extend the framework to suit my needs and most of the time I don't even need to dig into the source. A lot of tiimes that power comes in the form of an Interceptor.

Interceptors are not a new concept. I believe my first experince with them in web applications was when working with WebWork several years ago. Stripes has a couple of Interceptors already:

  • SpringInterceptor - Allows you to inject Spring Beans into controllers using the @SpringBean method level annotation.
  • BeforeAfterMethodInterceptor - Allows you to execute methods before and/or after specific Lifecycle Stages using @Before and @After method level annotations (AOP like behavior)

Note: Both the Interceptors mentioned above work in combination with annotations but not all have to.

In this article I want to show how to create an interceptor and we'll also create an annotation that will be used with the interceptor. I'll identify a problem that Stripes by itself doesn't solve and show how to implement the solution with a simple Interceptor. At times you may see mention of concepts that you won't be familiar with if not familiar with Stripes. While I'll try and explain these a bit as I go I may link to the Stripes documentation on the subject so as not to repeat information. I also want to keep this article as concise and to the point as possible.

The Problem

Ajax is everywhere and one common problem I've run into in the past is dealing with the browser caching the response from an ajax request. This seems to happen more often than not in Internet Explorer. What we want is to prevent this as much as possible when needed.

Typical Solutions

Probably the most common talked about solution is appending a random number on the end of the request. This tricks the browser into thinking it is a different response. Wikipedia's entry on XmlHttpRequest offers a different and slightly more complex solution which you can read about here: http://en.wikipedia.org/wiki/Xmlhttprequest#Caching. The problem with that is most of us are using a JavaScript library like jQuery or Prototype and that would cause us to go hacking inside their code. Not ideal. And another approache is to add header information to the response. In java it goes something like this:

HttpServletResponse response = context.getResponse();

response.setDateHeader("Expires", 0);

response.setHeader("Cache-control", "no-cache");

response.setHeader("Pragma", "no-cache");

Finding a centralized place for that code is the key. One solution on the Stripes mailing list was having a disableCaching() method in an ActionBean base class. When you wanted this to execute you would do something like this:

@Before(stages = LifecycleStage.ResolutionExecution)

@Override

protected void disableCaching() {

super.disableCaching();

}

And while that works it is a bit more verbose than need be.

The Interceptor Solution

What we want to do is take the above code and centralize it in an Interceptor that executes on the LifecycleStage.ResolutionExecution stage however we want to be able to control when the code gets executed. To do this we need two things:

  1. @NoCache annotation - We'll use this on methods to denote we want no caching. We'll also allow a boolean argument to indicate whether it should be on or off. This is important if we want to override a class level annotation on one or more methods.
  2. NoCacheInterceptor - We'll use this to check for the @NoCache annotation and shove the no cache header directives into the response.

The @NoCache annotation is pretty straightfoward:

@Retention(RetentionPolicy.RUNTIME)

@Target( {ElementType.METHOD, ElementType.TYPE})

@Documented

public @interface NoCache

{

boolean value() default true;

}

Save that in a file called NoCache.java in whatever package you desire.

Next is the interceptor which requires a bit more discussion. A Stripes interceptor implements an interface called Interceptor. Interceptor requires one method be implemented; public Resolution intercept(ExecutionContext ctx) throws Exception. Stripes will call this method on any configured interceptor during the specified LifecycleStage. Whoa, how do we specify the LifecycleStage? Whoa!!! What's with all this LifecycleStage talk?

Segway..Stripes has five Lifecycle Stages. Instead of repeating what is already well documented I'll let you read about them at your lesiure here.

And we're back...So we need to create this Interceptor and tell it when to execute the intercept method. We do that by specifying an annotation at the class level:

@Intercepts(LifecycleStage.ResolutionExecution)

public class NoCacheInterceptor implements Interceptor {

...

}

Now we should define our intercept method:

public Resolution intercept(ExecutionContext ctx) throws Exception {
...
}

Inside this method we need to define several objects we are going to use:

(1) final Configuration config = StripesFilter.getConfiguration();
(2) final ActionResolver resolver = config.getActionResolver();
(3) final ActionBeanContext context = ctx.getActionBeanContext();
(4) final ActionBean actionBean = resolver.getActionBean(context);
(5) final Class beanClass = actionBean.getClass();
(6) final String eventName = resolver.getEventName(beanClass, context);

  1. The Stripes Configuration class holds all the configuration information passed into Stripes from the web.xml. This includes all configured Interceptors.
  2. The ActionResolver will allows us to get which Method was requested from the ActionBean during the request.
  3. The ActionBeanContext is used to help us get an instance of the requested ActionBean
  4. The requested ActionBean.
  5. We need the actual Class.
  6. The eventName or requested method to call.

The next thing we need to do is get the Method or handler if the eventName doesn't exist. The reason for this is because if you request a URL and there is no eventName specified Stripes will look for a default handler which is a method denoted by the @DefaultHandler annotation. And then if this doesn't exist we need to throw an error and inform the user.

Good Practice: All ActionBeans should have a default handler in case an eventName was not given.

final Method handler;
if (eventName != null) {
handler = resolver.getHandler(beanClass, eventName);
} else {
handler = resolver.getDefaultHandler(beanClass);
if (handler != null) {
context.setEventName(resolver.getHandledEvent(handler));
}
}

// Insist that we have a handler
if (handler == null) {
throw new StripesServletException(
"No handler method found for request with ActionBean ["
+ beanClass.getName() + "] and eventName [ "
+ eventName + "]");
}

Don't worry too much about understanding every bit of that. Just know that we need the handler and we need to throw an error if one doesn't exist. The next thing we need to do is actually look for the @NoCache annotation. If we find it we set the no cache header junk and tell the ExecutionContext to proceed with the request.

if (isCachingDisabled(handler, beanClass)) {
HttpServletResponse response = context.getResponse();
response.setDateHeader("Expires", 0);
response.setHeader("Cache-control", "no-cache");
response.setHeader("Pragma", "no-cache");
}
return ctx.proceed();

Now we'll look at the isCachingDisabled method. We pass this method the handler and also the beanClass.

protected boolean isCachingDisabled(Method method, Class beanClass) {
....
}

To make sure that we are as performant as possible Stripes caches interceptor instances. Because of this we can also cache data within the interceptor. In this case once a @NoCache annotation has been found we want to cache this fact so the next time this interceptor is run with this beanClass we can just check the cache and not have to go through the annotation reflection checks. We first want to check the handler (Method) being called because it override class level annotations. If no annotation is found then we check for a class annotation.

So first, lets check the cache:

CacheKey cacheKey = new CacheKey(method, beanClass);
Boolean disabled = cache.get(cacheKey);
if (disabled != null) {
return disabled;
}

Don't worry about CacheKey yet. It's a simple class and we'll discuss it last. So if we found cache we return the value we found. Otherwise, we need to check for the annotation:

NoCache annotation = method.getAnnotation(NoCache.class);
if (annotation != null) {
disabled = annotation.value();
} else {
// search the method's class and its superclasses
Class clazz = beanClass;
do {
annotation = clazz.getAnnotation(NoCache.class);
clazz = clazz.getSuperclass();
} while (clazz != null && annotation == null);

if (annotation != null) {
disabled = annotation.value();
} else {
disabled = false;
}
}

So basically we look for an annotation on the method. If we find it we return its value. Otherwise, we check the class. We also want to check all super classes incase the user is extending a Base ActionBean of sorts.

Good Practice: Creating a BaseActionBean and having all your ActionBeans extend that base class will save a lot of boilerplace code and make developing with Stripes a lot simpler.

So once we either find an annotation or not we want to cache it and then return what we found:

cache.put(cacheKey, disabled);
return disabled;

The last thing for code is the CacheKey class. We want to make sure that we store unique keys when checking for cache. That way we always know we have the correct cache for the correct beanClass that was requested. Here's the class. I just make it an inner class of the interceptor.

private static final class CacheKey {
private Method method;
private Class beanClass;
private int hashCode;

public CacheKey(Method method, Class beanClass) {
super();
this.method = method;
this.beanClass = beanClass;
this.hashCode = method.hashCode() * 37 + beanClass.hashCode();
}

@Override
public boolean equals(Object obj) {
CacheKey that = (CacheKey) obj;
return this.method.equals(that.method)
&& this.beanClass.equals(that.beanClass);
}

@Override
public int hashCode() {
return hashCode;
}

@Override
public String toString() {
return beanClass.getName() + "." + method.getName();
}
}

Note: In Stripes 1.5, yet to be released, there will be a core set of interceptors on by default. This NoCache interceptor will be one of them along with BeforeAfterMethodInterceptor.

And that's it. Now to use it you might do something like this:

public class SomeActionBean extends BaseActionBean {

@NoCache
public Resolution ajaxEvent() {
// return some ajaxy stuff here
}
}

If you needed all but one method to turn caching off you might do something like this:

@NoCache
public class SomeActionBean extends BaseActionBean {

@NoCache(false)
public Resolution ajaxEvent() {
// return some ajaxy stuff here
}
}

I've included the full source for the interceptor and annotation at the following URL.

NoCache.tar.gz


Tuesday, September 04, 2007

Book Review: Filthy Rich Clients


This review will be in two parts. I was contacted about reviewing Filthy Rich Clients by Chet Haase and Romain Guy and at the same time asked to review Safari's "Rough Cuts" subscription. So first, let's get the not so good out of the way.

Safari's "Rough Cuts" is similar to Manning's MEAP (Manning Early Access Program). If you aren't familiar with either one it's basically a way to read a book as chapters are made available online. The difference, as far as I can tell, between MEAP and Rough Cuts is that chapters released through MEAP are complete whereas chapters released through Rough Cuts often times are incomplete. That isn't to say that reading the final draft of a book versus the Rough Cut version is significantly different but there were things missing like diagrams that are referred to in the text. I may be in the minority here but I actually find them useful in most cases and when a book is talking about a diagram its nice to be able to see it. Add that to my dislike of Safari's interface for reading books online and I give it a thumbs down. I'd rather just read the book when it is complete than have incomplete chapters made available.

And now on to some good news. FRC is a great book. The community has needed a book like this for a long time and I can't think of any better folks to write this kind of book than Chet and Romain. I've been following their blogs for a long time and am a big fan of all the cool things Romain has done with Swing.

FRC is a book about "Developing Animated and Graphical Effects for Desktop Java Applications". Yes, that is on the cover but I couldn't think of a better way to describe this book. FRC gives some much needed insight into the inner workings of Swing, AWT, and Java2D and how they all interact. Sure, you can scour the web and locate a lot of articles and blogs that talk about this but its nice to finally have this in one place. But don't worry, its not that deep. Its just enough to help you understand when things start getting cool later on.

The book does assume a basic understanding of desktop development with Java. If you are new to Swing you might want to get a few basics down before delving into FRC. The book reads very well, even going between the two authors, which you can easily tell who wrote what. If its technical it was probably Chet. If it was pretty it was probably Romain. Not to say that Romain isn't technical in his own right.

There are plenty of code fragments in the book to help convey the author's points. In fact, there is a lot. More than I expected. On a sad note, even though all the examples are available on the book's web site they are Netbeans projects. I download a few and tried to compile them with Ant from the command line but they always complained about Netbeans dependencies. Granted, I didn't research this much so the problem may have easily been resolved.

The book is fun and results are immediate. I've already started trying to come up with a side project for myself just to try out a lot of the techniques described in FRC. I'd recommend this book to anyone looking to spruce up their existing desktop applications or design something entirely new and original. Great work Chet and Romain!!