Understanding Jakarta EE 8 - C.D.I. (Part 3) - Defining custom CDI annotations.
Tags: programming, tutorial, java, jakartaee
Published: 2021-07-18 00:28:48

![Custom CDI annotations in Jakarta EE 8](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jmpb8em4klbi4mof6bd6.png)[As we continue with this series, we will refer to some content and examples from the [CDI 2.x specification](https://jakarta.ee/specifications/cdi/2.0/cdi-spec-2.0.html)].

The CDI specification allows developers the flexibility to create new types that are within the scopes of the bean type declaration.
In this example we will examine and learn how easy it is to create custom CDI annotations for defining:
 - New qualifier types.
 - New Stereotypes.

## Defining new qualifier types.
A qualifier type is a Java annotation defined as `@Retention(RUNTIME)`. Typically a qualifier type is defined as `@Target({METHOD, FIELD, PARAMETER, TYPE})`.

Defining a qualifier type may be declared by specifying the `@javax.inject.Qualifier` meta-annotation.

In our [example](https://github.com/TheEliteGentleman/jakartaee8-tuts-cdi/tree/master/src/main/java/za/co/sindi/tuts/jakartaee/cdi/example05), we've created 2 service-defined qualifier types, `@Jabbawockee` and `@LesTwins` qualifiers.

```java
@Qualifier
@Documented
@Retention(RUNTIME)
@Target({ TYPE, FIELD, METHOD, PARAMETER })
public @interface Jabbawockee {

}
```

```java
@Qualifier
@Documented
@Retention(RUNTIME)
@Target({ TYPE, FIELD, METHOD, PARAMETER })
public @interface LesTwins {

}
```

And a bean is qualified by annotating the bean class or producer method or field with the qualifier type.

```java
@Jabbawockee
public class JabbawockeeService implements Service {

	public void doWork() {
		System.out.println("Jabbawockee doing the work.");
	}
}
```

## Stereotypes
The [JavaEE specification](https://javaee.github.io/tutorial/cdi-adv008.html) specifies stereotypes as: 

> A **stereotype** is a kind of annotation, applied to a bean, that incorporates other annotations. Stereotypes can be particularly useful in large applications in which
> you have a number of beans that perform similar functions.
> 
A well-known stereotypes, known by Enterprise Java Developers, are from Spring Framework: `@Component`, `@Service` and `@Repository` stereotypes.

A stereotype is an annotation, annotated `@Stereotype`(`@javax.enterprise.inject.Stereotype`), that packages several other annotations. For instance, to recreate the 3 stereotypes from Spring Framework into your JavaEE application:

```java
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
@Documented
@Named
public @interface Component {}
```

Note that our `Component` stereotype has been declared with an empty `@Named` annotation, which specifies that every bean with the stereotype has a defaulted name when a name is not explicitly specified by the bean. A  `@Named`  qualifier declared by a stereotype is not added to the qualifiers of a bean with the stereotype.

If a stereotype declares a non-empty  `@Named`  annotation, the container automatically detects the problem and treats it as a definition error.

```java
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
@Component //Note that Spring specifies that this annotation is a specialization of Component annotation.
public @interface Service {}
```

```java
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface Repository {}
```

Stereotype can be specified with interceptor bindings by annotating the stereotype with interceptor binding types. For example, to have a transactional business service, we can annotate our `Service` stereotype with `@Transactional`.

```java
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
@Transactional
@Component
public @interface Service {}
```

Also, the default scope of a stereotype is defined by annotating the stereotype with a scope type. A stereotype may declare at most one scope. If a stereotype declares more than one scope, the container automatically detects the problem and treats it as a definition error.

For example, in our `Controller` stereotype, we may specify to have a default `@RequestScoped` scope type:
```java
@RequestScoped
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
@Documented
@Named
public @interface Component {}
```

### Built-in stereotype.
The CDI framework provides us with a built-in stereotype `@javax.enterprise.inject.Model` which is intended for use with beans that define the _model_ layer of an MVC web application architecture such as Jakarta Server Faces.

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

In the next article, we will examine Producers (producer method and producer field), injecting using `@Produces` and Decorators, using the `@Decorator` annotation.