Monday, September 28, 2009

Decorate JSF managed bean with custom Annotations

Java Annotatons  has been widely accepted by enterprise application developers. It really free up developers from writing down tons of boilerplate code which is used for business service invocation or basic infrastructural set up like initializing the service context or getting handle to some core runtime services etc.

This blog post is mainly intended to take you through the possibilities of using annotation while building enterprise solutions. There are definite advantages if you use this tool judiciously. Few highlights are:
  • Reduces the boilerplate code in your business tier.
  • Adds dynamism to your code.
  • Greater control on the implementation part, as the logic is abstracted  from the developers.
  • High Extensibility etc...
JSF managed bean and custom ADF flavored annotations

A closer look at the source code of a typical web application may reveal fair amount of boilerplate code that spread across managed beans on the client tier. This repetitive piece of code mainly does the below tasks.

  • Look up ApplicationModule/DataControl
  • Invoke business service methods
  • Retrieve binding parameter values etc.
Is there any better alternatives available to handle such scenarios?

Answer is 'YES'. One possibility is by using Annotation. If you are building a huge system based on ADF + Java EE technology stack, It's really worth checking possibility of building custom Annotations for your application.

The below diagram clearly depicts how custom Annotation can be leveraged to look up ApplicationModule from a managed bean.





How to build custom Annotations?

I would suggest you to go through this link if you are not familiar with Annotation.

Define custom Annotation

Define custom Annotations based on your system's requirement. The below code snippet shows a custom annotation class (ServiceContext.java) that can be applied to fields of JSF managed bean to inject the reference of underlying ApplictionModule.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)

public @interface ServiceContext {

    /**
     * Purely for extensibility reasons we keep this enum type. As of now
     * we deal with only Application Module
     * */
    public enum Servicable {
        APPLICATION_MODULE;
    }

    public Servicable servicable() default ServiceContext.Servicable.APPLICATION_MODULE;

    public String serviceName(); //DC name if the servicable is of type APPLICATION_MODULE;

}

Processing custom annotation

 Next step is to process the Annotations at runtime. As I stated earlier, the custom Annotation that we are discussing here is purely meant for JSF managed beans. So what we need here is a hook to add the custom AnnotationProcessor so that annotation defined in a managed bean can be processed based on the rule definitions at runtime. Fortunately JSF gives an option to add custom ELResolver where we can listen for bean instantiations and invocations using Expression Language(EL). Please go through this article to learn more about this topic. Annotation processing can be carried out from this custom ELResolver at runtime.

Annotate JSF managed bean

Consider a use case where backing bean of a web application needs to get the reference of underlying ApplicationModule instance. Let us try addressing this use case by introducing the annotation that we generated in the above steps. Now the bean may look like as shown below.

 @ServiceContext(serviceName = "AppModuleDataControl")
 ApplicationModule myAppModule;   
 public String testAMAnnotation() {
        // Add event code here...
        amResult =((AppModuleImpl)myAppModule).getTodaysMessage();
        System.out.println(" Message: " + amResult);
        return null;
    }


That’s it, job is done without writing any sort of boilerplate code. System runtime injects the right ApplicationModule reference to the designated variable at runtime.

More on custom Annotations

Few more ADF Flavored custom annotations are listed below.

Definitions:

 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.FIELD)
 public @interface PageBindingContext {
    public enum BindingType {
        ATTRIBUTE_BINDING,
        ITERATOR_BINDING,
        OPERATION_BINDING,
        VARIABLE_BINDING;
    }
    String name();
    BindingType bindingType();
}

Usage:

    @PageBindingContext(name = "someAttribute",
                        bindingType = BindingType.VARIABLE_BINDING)
    String attribBindingValue;

    @PageBindingContext(name = "someMethod",
                        bindingType = BindingType.OPERATION_BINDING)
    OperationBinding opBinding;

Sample workspace


You can download the sample workspace from here.


Performance Issues

Apparently, Annotation is a very powerful tool. However this needs to be used very judiciously, especially if you are planning to use Annotations at runtime. I would suggest you to go for a strict performance test before releasing the feature to the end users(developers).

Summary

This blog gives you an overview of building custom Annotations for your ADF/Java EE applications. The above example doesn't really replaces the ADF Binding layer, rather tries to make use of the features of binding layer and adds more dynamism to your backing bean.

Annotations can be of great use if it's being used in right way, so be measured and use it judiciously.


4 comments:

Giri SENji said...

Hi Jobinesh,

This is very interesting and valuable. While I certainly understand your suggestion to PERF test before uptaking; do you have a successful usecase where the uses outweigh perf loss?

Jobinesh said...

Thanks Giri for the comments.

Used annotation heavily at compile time mainly for code generation.
Sometime back, when I was working on a proprietary framework, got a chance to implement some 'infrastructural services' initialization part with 'runtime Annotation'. What I’m trying to say here is, eager/greedy initialization using Annotation make sense if it’s being used in all cases, otherwise my humble suggestion is to try out some other smart alternatives. IMHO use annotation to avoid the boilerplate code/configuration, not to over engineer the product

Edi said...

Hi,

There is a link missing regarding the article about the custom ELResolver. As I can figuret out it was either deleted or moved by Oracle while restructuring the Sun site.
Can you please give me a pointer on where I can find some related example.

Thanks.

Jobinesh said...

Sorry Edi, not able to track that specific link. Will update you later if I'm able to find it. btw, noticed another article, hope may help you to get started with -http://docs.sun.com/app/docs/doc/819-3669/bnaif?l=en&a=view