I'm a Java software developer, consultant and architect that focuses on enterprise applications, quality and performance. I gained interest in Java due to it's open nature and community support. Next to Java, I spend most of my time trying to stay up to date with everything that moves inside the software world like Scala and NoSQL db's. Jelle is a DZone MVB and is not an employee of DZone and has posted 12 posts at DZone. You can read more from them at their website. View Full User Profile

Java EE6 Decorators, decorating classes at injection time

06.24.2011
| 9278 views |
  • submit to reddit

A common design pattern in software is the decorator pattern. We take a class and we wrap another class around it. This way, when we call the class, we always pass trough the surrounding class before we reach the inner class

Java EE 6 lets us create decorators through CDI, as part of their AOP features. If we want to implement cross cutting concerns that are still close enough to the business, we can use this feature of Java EE 6.

Let’s say you have a ticket service that lets you order tickets for a certain event. The TicketService handles the registration etc, but we want to add catering. We don’t see this as part of the ticket ordering logic, so we created a decorator.

The decorator will call the TicketService and add catering for the number of tickets.
The interface

public interface TicketService {
    Ticket orderTicket(String name);
}

The implementation of the interface, creates a ticket and persists it.

@Stateless
public class TicketServiceImpl implements TicketService {
 
    @PersistenceContext
    private EntityManager entityManager;
 
    @TransactionAttribute
    @Override
    public Ticket orderTicket(String name) {
        Ticket ticket = new Ticket(name);
        entityManager.persist(ticket);
        return ticket;
    }
}

When we can’t use a decorator, we can create a new implementation of the same interface.

@Decorator
public class TicketServiceDecorator implements TicketService {
 
    @Inject
    @Delegate
    private TicketService ticketService;
    @Inject
    private CateringService cateringService;
 
    @Override
    public Ticket orderTicket(String name) {
        Ticket ticket = ticketService.orderTicket(name);
        cateringService.orderCatering(ticket);
        return ticket;
    }
}

Notice that we apply 2 CDI specific annotations here. The @Decorator marks the implementation as a decorator. A decorator should always have a delegate, a class we want to decorate, marked with the @Delegate annotation (at the injection point). Also take notice of the fact that we use the interface and not the implementation.
Just like the alternative example, when you inject this interface, the normal implementation will be used.

1@Inject private TicketService ticketService;

Instead of using qualifiers, we just have to adjust our beans.xml to mark the TicketServiceDecorator as ‘Decorator’.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
    <decorators>
        <class>be.styledideas.blog.decorator.TicketServiceDecorator</class>
    </decorators>
</beans>

From http://styledideas.be/blog/2011/06/22/java-ee6-decorators-decorating-classes-at-injecting-time/

Published at DZone with permission of Jelle Victoor, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Liam Knox replied on Sat, 2011/06/25 - 6:14pm

I really do not see what this is giving you compared with straight forward IoC and use of the Decorator pattern?

Nicolas Bousquet replied on Mon, 2011/06/27 - 3:14am

Expect the change in the name of your anotations, it give you nothing than straight subclassing.

Reza Rahman replied on Mon, 2011/06/27 - 9:27am in response to: Liam Knox

The big difference is that sub-classing is used to contain your main flow of business logic, while decorators are used to expresss logic that looks a lot more like cross-cutting concerns (it is indeed a relatively rare use case). I had slighly clearer examples/explanation in my much older Interceptors/Decorators tutorial. In particular, it outlines the cases where Decorators make more sense vis-a-vis Interceptors.

Gavin King replied on Mon, 2011/06/27 - 11:56am

I really do not see what this is giving you compared with straight forward IoC and use of the Decorator pattern?

I don't understand this comment.

This is exactly the decorator pattern, in IoC style! I mean, how else would you add a decorator to an object that is being instantiated and injected by the container? In IoC, you don't have control over instantiation of your objects in order to be able to just easily wrap stuff around them.

Furthermore, this facility allows the stack of decorators to be adjusted in the metadata that accompanies the deployment. (The beans.xml file.) Making it easy to add and remove deployment-specific functionality.

 

Expect the change in the name of your anotations, it give you nothing than straight subclassing.

This is definitely not correct. Perhaps you were mislead by the very simple example, which demonstrates only the case of just one decorator.

In fact, you can have the container attach a whole stack of decorators to a class, with the exact list and ordering of the decorators defined in the beans.xml file. You certainly can't do that with subclassing! If there are two decorators, you would need four subclasses which is already much less than ideal. If there are more than two decorators, you get a totally unmanageable combinatorial explosion.

 

Reza Rahman replied on Mon, 2011/06/27 - 2:09pm in response to: Gavin King

Gavin, great to see you on JavaLobby answering CDI/Java EE questions!

Niklas Schlimm replied on Mon, 2011/06/27 - 3:07pm

If the TicketService gets injected I'd expect the di resolution to inject TicketServiceDecorator (if enabled) instead of the TicketServiceImpl. To me that's the feature, so there is more then just the decorator pattern, it just does not come out in this article (which has a focus on the pattern ...). Cheers, Niklas

Liam Knox replied on Mon, 2011/06/27 - 5:26pm in response to: Gavin King

Don't get you. In Spring I simply inject the delegate into the decorating implementation. The order of instantiation is looked after by the nature you have defined this dependency.

All I can see here you have added some annotations that don't pull any weight and more specific XML for not much at all. Not surprising this is J2EE after all.

If I want different decorators or deployment characteristics.

1 I would be very careful in on this
2. I would use Spring profiles as this idea is not confined to this small world of a single design pattern.

Do you really think this Decorator idea is well thought through?

Gavin King replied on Tue, 2011/06/28 - 7:10am

Don't get you. In Spring I simply inject the delegate into the decorating implementation. The order of instantiation is looked after by the nature you have defined this dependency.

 

I admit that this approach might almost work if:

  • you are decorating exactly one bean,
  • your decorator implements *every* method of the bean you are decorating, and
  • you are doing Spring-XML-style injection by name configured in external XML metadata.

 

But in CDI, a decorator may easily:

  • decorate all beans of a certain type (or all beans of a certain type with certain qualifiers),
  • be abstract, intercepting just a subset of the operations of the beans it is decorating, and
  • is intended for use in CDI where candidates for injection are automatically discovered by type instead of explicitly configured by string-based name, and injection points aren't individually configured in XML.

 

i.e. I can *easily* say "intercept just the onGet() method of all Actions in my project" by writing a single abstract class with one method and adding a single line of XML to beans.xml. And all completely typesafe.

 

@Decorator
public abstract class DecorateOnGet implements Action {
    @Inject @Delegate @Any Action action;
    @Override Result onGet(Request req) {
        //do something
        ...
        return action.onGet(req);
    }
}

By adjusting the type and qualifiers of the @Delegate injection point, you can limit the Actions to which the decorator applies.

Again, the power of this facility isn't really visible in extremely simple examples. It's a powerful abstraction for use in more sophisticated usecases.

Do you really think this Decorator idea is well thought through?

I'm very certain of that, yes. You just need to explore CDI a bit further to see it.

Nick Stuart replied on Tue, 2011/06/28 - 8:13am

I'm actually voting this down because (as other comments have pointed out) this example doesn't really express the usefulness of decorators. Gavin's example in the comment above helps illustrate it better (abstract class, not overriding all the methods etc), where the article example really does just look like overriding a class and using that instead! A more thorough example, along with actually showing the use of decorators in action would be much better.

Reza Rahman replied on Tue, 2011/06/28 - 10:00am in response to: Nick Stuart

I posted one of the critiques on the very simple examples, but do want to applaud the author for writing a CDI piece to begin with :-). I voted up :-).

Ivan Lazarte replied on Tue, 2011/06/28 - 10:42am

In spring, I don't have to be in an EE container.

Reza Rahman replied on Tue, 2011/06/28 - 10:49am in response to: Gavin King

I can tell you first hand that CDI was closely scuritized by everyone not just in the CDI, but Java EE, EJB and JSF EGs. It is arguably one of the most closely scrutized JSR ever. To Gavin's credit, he did hold up to it and get elected as star spec lead.

Reza Rahman replied on Tue, 2011/06/28 - 10:55am in response to: Ivan Lazarte

Frankly, this means very little to anyone using a lightweight Java EE container like Resin, Siwpas, TomEE or even GlassFish and JBoss. In fact, using a lightweight Java EE application server means more vendor neutrality and less configuration. I talk about it here: http://blog.caucho.com/2010/02/16/resin-java-ee-6-web-profile-implementation/. It's only a real issue if you choose to continue to use WebSphere and WebLogic -- and the irony is that it is those people that seem to use Spring most frequently :-).

Niklas Schlimm replied on Wed, 2011/06/29 - 12:30am in response to: Liam Knox

Hi Liam! Let's say you inject a TicketService like this into a managed bean:

 @Inject TicketService ticketService;

and you have the above configuration, then I'd expect: the CDI DI resolution will not inject an instance of TicketServiceImpl, but it will inject an instance of TicketServiceDecorator. I did not want to make it a comparison to Spring, all I am saying is, that CDI implements more then just the pattern. It's a good idea to have patterns integrated into the CDI spec, this way it gets more obvious for developers to use patterns in general.

In Spring with @Autowired you'd need to add additional qualification (e.g. name property of @Qualifier) to make sure the container injects the decorator, otherwise you get an ambiguous dependency error.

But let's not argue which way is better, that's the wrong question here (and I am trying to find out every day at the moment - see my blog). There are good ideas in both approaches. I am just saying, that having the decorator pattern in the CDI spec is good and (as I tried to explain) there is more then just the annotations.

Liam Knox replied on Wed, 2011/06/29 - 2:17am in response to: Gavin King

Don't get it. That you need to say so many words to justify this must say something to you?

I can say 2 IoC and AOP.

Can you name one application in production that uses this?

Liam Knox replied on Wed, 2011/06/29 - 2:22am in response to: Niklas Schlimm

Again there are a fantastic amount of words here to describe

A implements B { A delegate; //... } God look at ForwardingCollection in the Google collections if you don't want to get clever. These annotations give you absolutely nothing. I cannot state this enough.

The use of Real Estate pisses me off the most

Liam Knox replied on Wed, 2011/06/29 - 2:30am in response to: Reza Rahman

Reza

All your comments are so J2EE pro but have you actually written an application? Can you understand that the World chose Spring because J2EE was complete rubbish? Why are you and Adam Bien still hyping something that no one buys?

Why is Gavin King even commiting here, has that risible idea of a language he suggested already died so he has reverted to mouth to mouth to the dead J2EE?

PS

I am not pulling punches here. You guys talk a lot of nonsense

Niklas Schlimm replied on Wed, 2011/06/29 - 4:41am in response to: Liam Knox

lol - i thought it would be appropriate to explain it slowly to you :-) i am not the first class CDI fan myself, but just saying "it all sucks" is by far the biggest nonsense in this post. you're saying two words, but if i only take aop then i ask you how often you tried to explain that to the average developer! it's much easier when annotations are more concrete like the ones shown here. you are looking at it with a "little" bias i suppose ;-) again: not comparing spring with cdi here, just saying: doing it that way does also have benefits ... encourage you to read this (to the end): http://www.softwarequalityconnection.com/2011/06/a-call-for-strong-opinions-in-software-development/

Reza Rahman replied on Wed, 2011/06/29 - 1:04pm in response to: Liam Knox

It's really sad that your posts are so full of negativity/personal attacks and so low on actual technical content (and consistently so!). I also find it quite humorous that you accuse others of bias while failing to mention your own involvement with the UK Spring User Group!

I've been developing in Java, J2EE, Java EE, Spring and Seam as long as they have been in existance. I like Java EE because I believe it is a better solution and a pleasure to work with, period (BTW, I was never an advocate of J2EE).

FYI, plenty of people are adopting Java EE, despite all the anti-Java EE propaganda. Besides doing projects myself, I still get offers to do Java EE/Seam projects and we already have early Java EE 6 adopters for Resin 4 (and yes, they do use @Decorator). The best resource that I know of is the list of Java EE/Seam users Gavin made the effort to put together a few years ago: http://seamframework.org/Community/SeamInProduction. If something like that is what you are looking for, it should be possible (albeit take a bit of time/effort) to put together one for the GlassFish and Resin teams as well. Frankly, I think it is a bit silly (which is why most technologies don't bother doing it). Any serious technologist only pays so much attention to adoption rates alone. If that weren' the case, the technology industry would be an awfully boring and stanganted place to work :-).

Reza Rahman replied on Wed, 2011/06/29 - 9:28am in response to: Niklas Schlimm

That is indeed one of the motivations. It would be nice to get some more heavily used patterns standardized in CDI, but they are not as obvious as the decorator pattern.

Jelle Victoor replied on Thu, 2011/06/30 - 2:25am

You are correct that my example in the blogpost is very simple. I will write a new blogpost with the Gavin's feedback, hoping to fully show the power of this new feature.

Reza Rahman replied on Thu, 2011/06/30 - 10:03am in response to: Jelle Victoor

I hope you don't feel discouraged. Writing about any new technology is hard. Writing about anything Java EE is even harder with some of the deliberate negativity/hypercriticism. If you need any help, please do feel free to send me an email/call: http://www.rahmannet.net/contact.jsp.

Jelle Victoor replied on Fri, 2011/07/01 - 4:19am in response to: Reza Rahman

Thanks, I'll send a draft to review when the post is ready!

Jelle Victoor replied on Thu, 2011/08/04 - 2:07pm

I have written a more advanced blogpost, exposing the true power of the decorator pattern in java ee6 http://styledideas.be/blog/2011/08/04/java-ee6-decorators-advanced-usage/

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.