Scopes

CDI has a number of scope annotations. Every managed bean either explicitly or implicitly defines the scope, and the scope specifies the life cycle of all the instances of the beans.
For example, we have an EJB session bean of an application with a stateless scope, as shown in the following code:

@Stateless
class App {
@Inject
private lateinit var identityCreator: IdentityCreator
@Inject
private lateinit var identityRepository: IdentityRepository

fun createIdentity(inputData: InputData): Identity {
val person = identityCreator.createPerson(inputData)
identityRepository.store(person)
return person

}
}

Stateless beans are pooled by the application server. We have several instances of the bean, which is the concern of the application server. When we want to invoke a business function such as createPerson(), we receive an instance of the bean, execute the function, and the instance is returned back into the pool. We must not store any states in these instances as we don't know which instance we will get each time.

There are also other instance scopes, such as @Stateful. Stateful session beans are bound to a user's HTTP session. All the business functions we invoke will be invoked on the same instance. We could, therefore, store some state information in these instances. These are not shared with other users' sessions. An example of a stateful bean is shown here:

@Stateful
class App {
@Inject
private lateinit var identityCreator: IdentityCreator
@Inject
private lateinit var identityRepository: IdentityRepository

fun createResource(inputData: InputData): Identity {
val person = identityCreator.createPerson(inputData)
identityRepository.store(person)
return person
}
}

There is a third scope, the @Singleton EJB scope. A singleton EJB is a bean that exists only once within a Java EE application. All invocations of the business functions will be invoked on the same instance, as shown in the following code:

@Singleton
class App {
//..
}

Context-managed beans, or CDI-managed beans, also have scopes. For example, IdentityCreator and IdentityRepository are CDI-managed beans and they don't have any annotations, as shown in the following code:

package org.rao.kotlin.cdi

class
IdentityCreator {
//..
}
package org.rao.kotlin.cdi

class
IdentityRepository {
//..
}

CDI actually defines several scopes, more than the EJB. By default, CDI-managed beans have the @Dependent scope, even if we don't specify the @Dependent annotation:

@Dependent
class IdentityCreator {
@Inject
@NativeEnglishSpeaker
private lateinit var defaultPreferredLanguage: PreferredLanguage

fun createPerson(inputData: InputData): Person {
val person = Person()
person.preferredLanguage = if (inputData.preferredLanguage == null)
defaultPreferredLanguage
else
inputData.preferredLanguage
return person
}
}

Beans annotated with @Dependent are the same as if we don't specify any annotation. By default, beans are dependent-scoped.

This means that the life cycle of these beans depends on the injection point at which the beans are injected. This is demonstrated in the following code:

@Stateless
class App {
@Inject
private lateinit var identityCreator: IdentityCreator
@Inject
private lateinit var identityRepository: IdentityRepository

fun createResource(inputData: InputData): Identity {
val person = resourceCreator.createPerson(inputData)
resourceRepository.store(person)
return person

}
}

Here, for the stateless EJB, we want to inject CDI-managed beans. This EJB instance will get one dedicated IdentityCreator bean and one dedicated IdentityRepository bean, which are active during the life cycle of EJB beans. These beans are not shared with any other managed beans. This means that the IdentityCreator class and the IdentityRepository bean are dependent on the EJB bean App.

In this case, the life cycle of the identityCreator class and the identityRepository bean is decided by the EJB bean App. As it is stateless, its life cycle lasts until the instance is returned to the pool. In the case of the stateful bean, the life cycle lasts for the duration of the particular HTTP session of the requesting client.

Similarly, we could define the CDI-managed bean that itself injects other dependent CDI beans. If we have all the dependent beans, the first one will specify the life cycle for the dependent objects.

An @ApplicationScoped CDI bean is similar to singleton EJBs—only one instance of the bean exists within the whole application. This means we only have one instance and everything will be invoked on the same instance of the bean. Consider the following code:

@ApplicationScoped
class IdentityCreator {
@Inject
@NativeEnglishSpeaker
private lateinit var defaultPreferredLanguage: PreferredLanguage

//..
}

There are two more CDI beans—@RequestScoped and @SessionScoped. A RequestScoped CDI bean has a life cycle that is limited to a particular request. A SessionScoped CDI bean, on the other hand, has a life cycle that lasts for the duration of the active HTTP session and is managed by the CDI.

We can use different scopes within a Java EE application. The overall platform will make sure everything works as expected. We can define a bean with a larger scope and inject a smaller scoped bean in it. We can have, for example, a stateful session bean, into which we can then inject other stateless EJBs. This is possible because although we don't directly hold a reference to an IdentityCreator dependent bean, the reference to its proxy object and the framework will take care of managing the beans.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset