SeamFramework.orgCommunity Documentation

Chapter 12. Stereotypes

12.1. Default scope for a stereotype
12.2. Interceptor bindings for stereotypes
12.3. Name defaulting with stereotypes
12.4. Alternative stereotypes
12.5. Stereotype stacking
12.6. Built-in stereotypes

The CDI specification defines a stereotype as follows:

In many systems, use of architectural patterns produces a set of recurring bean roles. A stereotype allows a framework developer to identify such a role and declare some common metadata for beans with that role in a central place.

A stereotype encapsulates any combination of:

  • a default scope, and
  • a set of interceptor bindings.

A stereotype may also specify that:

  • all beans with the stereotype have defaulted bean names, or that
  • all beans with the stereotype are alternatives.

A bean may declare zero, one or multiple stereotypes. Stereotype annotations may be applied to a bean class or producer method or field.

A stereotype is an annotation, annotated @Stereotype, that packages several other annotations. For instance, the following stereotype identifies action classes in some MVC framework:

@Stereotype

@Retention(RUNTIME)
@Target(TYPE)
...
public @interface Action {}

We use the stereotype by applying the annotation to a bean.

@Action

public class LoginAction { ... }

Of course, we need to apply some other annotations to our stereotype or else it wouldn’t be adding much value.

A stereotype may specify a default scope for beans annotated with the stereotype. For example:

@RequestScoped

@Stereotype
@Retention(RUNTIME)
@Target(TYPE)
public @interface Action {}

A particular action may still override this default if necessary:

@Dependent @Action

public class DependentScopedLoginAction { ... }

Naturally, overriding a single default isn’t much use. But remember, stereotypes can define more than just the default scope.

A stereotype may specify a set of interceptor bindings to be inherited by all beans with that stereotype.

@RequestScoped

@Transactional(requiresNew=true)
@Secure
@Stereotype
@Retention(RUNTIME)
@Target(TYPE)
public @interface Action {}

This helps us get technical concerns, like transactions and security, even further away from the business code!

We can specify that all beans with a certain stereotype have a defaulted EL name when a name is not explicitly defined for that bean. All we need to do is add an empty @Named annotation:

@RequestScoped

@Transactional(requiresNew=true)
@Secure
@Named
@Stereotype
@Retention(RUNTIME)
@Target(TYPE)
public @interface Action {}

Now, the LoginAction bean will have the defaulted name loginAction.

A stereotype can indicate that all beans to which it is applied are `@Alternative`s. An alternative stereotype lets us classify beans by deployment scenario.

@Alternative

@Stereotype
@Retention(RUNTIME)
@Target(TYPE)
public @interface Mock {}

We can apply an alternative stereotype to a whole set of beans, and activate them all with one line of code in beans.xml.

@Mock

public class MockLoginAction extends LoginAction { ... }

<beans>
   <alternatives>
      <stereotype>org.mycompany.testing.Mock</stereotype>
   </alternatives>
</beans>

This may blow your mind a bit, but stereotypes may declare other stereotypes, which we’ll call stereotype stacking. You may want to do this if you have two distinct stereotypes which are meaningful on their own, but in other situation may be meaningful when combined.

Here’s an example that combines the @Action and @Auditable stereotypes:

@Auditable

@Action
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface AuditableAction {}

CDI defines one standard stereotype, @Model, which is expected to be used frequently in web applications:

@Named

@RequestScoped
@Stereotype
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface Model {}

Instead of using JSF managed beans, just annotate a bean @Model, and use it directly in your JSF view!