Friday, June 18, 2010

EJB annotations and Stereotyping

Certainly for the EJB-related annotations, I would love to see @Stateless, @Stateful, @Singleton and @MessageDriven be used for stereotyping as well as all the other class level annotations for transactions, security, locking, timeouts and scheduling.

Great security example:

 @RolesAllowed({"SuperUser", "AccountAdmin", "SystemAdmin"})
 @Stereotype
 @Target(METHOD)
 @Retention(RUNTIME)
 public @interface Admins {}
In one swoop all the security rolls become controlled in one spot and there's no need to go changing a million usages to modify the roll names.

Here's a couple great scheduling examples:

 @Schedule(second=”0”, minute=”0”, hour=”0”, month=”*”, dayOfWeek=”*”, year=”*”)
 @Stereotype
 @Target(METHOD)
 @Retention(RUNTIME)
 public @interface Daily {}
 @Schedule(second=”0”, minute=”0”, hour=”0”, month=”*”, dayOfMonth=”15,Last”, year=”*”)
 @Stereotype
 @Target(METHOD)
 @Retention(RUNTIME)
 public @interface BiMonthly {}
The list goes on and on. A much fuller example:
@Stereotype
@Singleton
@TransactionManagement(CONTAINER)
@TransactionAttribute(REQUIRED)
@ConcurrencyManagement(CONTAINER)
@Lock(READ)
@RolesAllowed({"SuperUser", "AccountAdmin", "SystemAdmin"})
@Interceptors({LoggingInterceptor.class, StatisticsInterceptor.class})
@Target(TYPE)
@Retention(RUNTIME)
public @interface SuperBean {}
And to use all that, just:
@SuperBean
public class MyBean {

    public void doSomething() {
        
    }
}

Annotation Scanning Standard

We (the industry) need to get something in place for Java EE 7 to get scanning under control at a platform level. The metadata-complete concept of each individual spec is less helpful given the growing number of specifications that can have class-level "discoverable" annotations.

The rules we have for scanning for ejbs in a webapp are quite unintuitive. And how they relate to the scanning of the new Java EE 6 level annotations are unintuitive to the point that how they are handled, I bet, is rather vendor specific:

  • @DataSourceDefinition(s)
  • @ManagedBean

    The cost of scanning a jar is constant in that it doesn't matter how many annotations you might be looking for or what spec they come from. If each individual spec continues to add spec-specific descriptor support for specifying which jars to scan, we're going to wind up with a rather big mess.

    We should lock this down with a clean and simple file to control which jars.

    Something as simple as the following would be a massive improvement.

    META-INF/scanning.xml

    <scanning>
      <jars>
        <jar>foo.jar</jar>
        <jar>bar.jar</jar>
      </jars>
      <packages>
        <package>org.foo.widgets</package>
        <package>com.bar.components</package>
      </packages>
    </scanning>
    
    I'd love it to have regex support, but even without it there's a big improvement.
  • Saturday, June 12, 2010

    If Software is pizza, EJB is the House Special

    If you can stand terrible food metaphors and have ever been exposed to EJB positively or negatively, keep reading....

    I don't know about you, but I love the simplicity of a good pepperoni pizza now and then. Imagine asking for a plain Pepperoni pizza and being told your only option was to get the House Special and to pick off all the onions, black olives, green pepper and whatever else comes on top. Any person with options would simply go to another pizza shop. Well, that's EJB. Something I hope we can change in EJB 4.0.

    To setup the metaphor a bit more, let's say the dough and cheese is the component itself and the proxy to the component. The toppings are the various QOSs (qualities of service) such as transaction management, interceptors, concurrency management, cron-like scheduling, asynchronous method calls, and other goodness. Each bean type such as Stateful, Stateless, Singleton and Message Driven are certain styles of pizza with a fixed set of toppings; say Meat Lovers, Vegetarian, or Hawaiian. The toppings of each style of pizza have been selected carefully to compliment each other perfectly and guarantee good results.

    Currently though, if you want to start with a plain pizza and add only the toppings you want or need, you cannot do it with EJB. If you want pepperoni, you need to pick a style of pizza that has pepperoni as a topping and deal with the other toppings that come with it, wanted or not. EJB is somewhat flexible and there are usually ways to neutralize some features that amounts to picking off the toppings you don't like, but it's not the same as if they weren't ever there and you are still going to get an odd tasting and odd looking pizza.

    Say you don't really want the transaction management topping. You try to pick off the topping by selecting SUPPORTS as your default transaction attribute so if a transaction is there, your bean participates in it, if not, it still does it's work regardless. All is fine until your bean throws a runtime exception and the container decides to rollback the current transaction on your behalf. Say you instead choose to try and pick off the transactional topping by making your bean use bean-managed transactions. Things work fine except now all transactions are suspended by the container so that the bean cannot mess with the state of what was the current transaction. What you really wanted was your bean to not be transactionally aware in the first place.

    Unfortunately if you want one of the other toppings like container managed concurrency, cron-like scheduling, or asynchronous method calls, you have to learn to like the transaction management topping, period.

    There will always be a need for specific pizza styles with pre-selected toppings -- who doesn't love a good Greek pizza or a Hawaiian now and then. The EJB spec does that well with its perfectly selected bean types, each sprinkled with the select set of QOSs deemed appropriate for that specific bean type. That said, it really should be possible to start with a plain cheese pizza and just add the toppings you want.

    Forget the dough and cheese. EJB should be about the toppings.

    Ideally, every QOS the EJB spec has to offer would be an option that can be applied to a plain component. Imagine if there was a "plain cheese pizza" bean type that would by default have no QOSs at all and for all intense purposes be a true POJO. There's nothing to learn or study to code it or use it. It's just a POJO created by the container. Then one day you decide you'd like it to be transaction aware. At that point you annotate it with @TransactionManagement and then go read the self contained "transaction management" section of the spec to see what is now expected of you and the users of the bean.

    It may be that certain QOSs cannot be combined, which is in fact the case at times. The concept of a container managed persistence context (i.e. a field like "@PersistenceContext EntityManager myEntityManager") cannot be combined with the new @ConcurrencyManagement annotation because EntityManagers themselves are not guaranteed to be capable of concurrency. As a result EJB Singletons are not allowed to use container managed persistence contexts. That may work for some, but maybe you want a Singleton that uses a container managed persistence contexts and do not need concurrency anyway. Such a thing would be possible if you were able to choose the QOSs for your bean regardless of its lifecycle.

    It's time to break up the big specs and let people build their own pizzas.