CDI Decorators tutorial

A decorator is a Java class that is annotated javax.decorator.Decorator and that has a corresponding decorators element in the beans.xml file.

The decorator bean class implements an interface and defines, through a delegate injection point (annotated with @Delegate), which field, method or constructor needs to be decorated.

Let's take as example the MemberRegistration Bean which stores on the DB every user which registers.

Here's the core part of it:

@Stateless
public class MemberRegistration implements MemberRegistrationInt {
. . .

    public void register(Member member) throws Exception {
        log.info("Registering " + member.getName());
        em.persist(member);
        memberEventSrc.fire(member);
    }

Now we want to "decorate" the register method so that we can provide an alternate execution and (if needed) invoke as well the main method. Here we will trace on the application server data directory, each user that registered:
@Decorator
public class RegistrationDecorator implements MemberRegistrationInt{
    @Inject @Delegate MemberRegistrationInt registration;

    @Override
    public void register(Member member) throws Exception {

         BufferedWriter bw = null;

         try {
                 // Writes into the AS data dir a log of all users registered.
           bw = new BufferedWriter(new FileWriter(System.getProperty("jboss.server.data.dir") +"/kitchensink.dat", true));
           bw.write("Registering User "+member.toString());
           bw.newLine();
           bw.flush();
          } catch (IOException ioe) {
              ioe.printStackTrace();
          } finally {
              if (bw != null) try {
              bw.close();
         } catch (IOException ioe2) {  ioe2.printStacktrace();  }
         }
              // Now calls the Member registration method
         registration.register(member);

    }

}

Notice the usage of the @Decorator class which declares it as a Decorator.  The annotation:
    @Inject @Delegate MemberRegistrationInt registration;
Specifies the injection point, which will be on the MemberRegistrationInt interface. In order to activate decorators you need to declare them in your beans.xml file:


<decorators>
    <class>org.jboss.as.quickstarts.kitchensink.decorator.RegistrationDecorator</class>
</decorators>

Decorators vs Interceptors vs Alternatives

Decorators bear some similarities with Interceptors and with  Alternatives as well.

Decorators and Interceptors are similar because they can be both used to "enrich" or "decorate" one method call with additional tasks. However Interceptors are used for general tasks, which are not related with your class in particular (e.g. auditing). On the other hand, Decorators, do bear with them the Bean attributes/operations so they can actually specialize or override a specific business functionality

Decorators and Alternatives are similar as well because they can be used to provide different implementations for your use cases. However Alternative beans can be used to provide a whole different bean implementation, while decorators can be used to further specialize a single method/attribute and they allow as well interacting with the method/attribute we are going to specialize.

 

Download the code

The source code for this example can be downloaded from my fork of Jboss AS 7 quickstart, available at: https://github.com/fmarchioni/jboss-as-quickstart/tree/master/kitchensink-cdi-listener-decorator
0
0
0
s2smodern