8 Using Jakarta EE Annotations and Dependency Injection

Learn about Jakarta EE metadata annotations and dependency injection (DI) in WebLogic Server.

Annotation Processing

Annotations simplify the application development process by allowing developers to specify within the Java class itself how the application component behaves in the container, requests for dependency injection, and so on. Annotations are an alternative to deployment descriptors that were required by older versions of enterprise applications (J2EE 1.4 and earlier).

Jakarta EE components use Java annotations to declare supported deployment metadata. Servlets execute in the web container; enterprise beans execute in the Jakarta Enterprise Beans container. Depending on the component and the configuration required, standard descriptors such as application.xml and web.xml can be omitted. Supply a descriptor when the application needs configuration that annotations and defaults do not provide. For current annotation packages and types, see the Jakarta EE 11 API documentation. Jakarta EE 11 API documentation

Annotation Parsing

The application components can use annotations to define their needs. Annotations reduce or eliminate the need to deal with deployment descriptors. Annotations simplify the development of application components. The deployment descriptor can still override values defined in the annotation. One usage of annotations is to define fields or methods that need Dependency Injection (DI). Annotations are defined on the POJO (plain old Java object) component classes like the EJB or the servlet.

For @Resource, a field or setter-method annotation declares an injection point. A class-level @Resource declares a named resource reference in the component environment without an injection target; obtain that reference through JNDI or a component-context lookup. On a class-level @Resource, specify both name and type explicitly. See Dependency Injection of Resources.

Deployment View of Annotation Configuration

WebLogic Server provides weblogic.deploy.api.tools.SessionHelper for deployment tools using the Java EE Deployment API (JSR 88). SessionHelper can expose the effective descriptor configuration, including configuration inferred from annotations, even when an input module omits a descriptor. Supported configuration changes can be saved in a deployment plan and applied during deployment. Only properties supported for plan-based configuration can be changed in this way. SessionHelper

Compiling Annotated Classes

The weblogic.appc and weblogic.appmerge command-line utilities process supported annotations in an application or module. Use -writeInferredDescriptors to write descriptors containing inferred deployment metadata. For web and EJB modules, the resulting standard module descriptors are marked metadata-complete="true". This suppresses the deployment-annotation processing governed by those descriptors; it does not disable every annotation facility, such as CDI. The wlappc Ant task supports annotation-aware compilation, but it does not expose a writeInferredDescriptors attribute.

When processing existing web/EJB module descriptors for inferred output, the tools write backup descriptors with the .orig suffix, for example WEB-INF/web.xml.orig or META-INF/ejb-jar.xml.orig. A descriptor absent from the input has no original copy to back up. Preserve an untouched input archive or source tree. To incorporate later annotation changes, run the tools against that original input; if reusing generated output, restore the applicable original descriptors first, and remove any generated descriptor that had no original input counterpart. Do not expect changed deployment annotations to override a previously generated metadata-complete descriptor.

For an enterprise application without application.xml, the tools can infer and write the application descriptor according to the Jakarta EE inference rules.

For more information on using appc, see weblogic.appc Reference. For more information on using appmerge, see Using weblogic.appmerge to Merge Libraries.

Dynamic Annotation Updates

A deployment-plan update changes supported deployment configuration. Use the update operation for plan changes; it is not a general replacement operation for application classes. Whether a configuration property can change dynamically depends on that property and its container. When application classes or their deployment annotations change, rebuild the application and use the applicable redeployment procedure. If using production redeployment, follow Developing Applications for Production Redeployment and its versioning and application-compatibility requirements. If the build uses inferred descriptors, first follow Compiling Annotated Classes so a metadata-complete descriptor does not mask the annotation changes. Developing Applications for Production Redeployment; Compiling Annotated Classes

Dependency Injection of Resources

Dependency injection (DI) allows application components to declare dependencies on external resources and configuration parameters via annotations. The container reads these annotations and injects resources or environment entries into the application components.

For supported container-managed components, resource injection can replace an explicit JNDI lookup in application code. Programmatic JNDI lookup remains available through the Java SE javax.naming APIs.

A field or a method of an application component can be annotated with the @Resource annotation. Note that the container will unbox the environment entry as required to match it to a primitive type used for the injection field or method. Example 8-1 illustrates how an application component uses the @Resource annotation to declare environment entries.

This stateless session bean receives two integer environment entries from the deployer. The numbers below are demonstration values, not tax rules.

Example 8-1 Dependency Injection of Environment Entries

package example;

import jakarta.annotation.Resource;
import jakarta.ejb.Stateless;

@Stateless
public class TaxPolicy {
    @Resource
    private int maxExemptions;

    @Resource
    private int minExemptions;

    public int getMaxExemptions() {
        return maxExemptions;
    }

    public int getMinExemptions() {
        return minExemptions;
    }
}

Supply these demonstration environment entries in META-INF/ejb-jar.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/ejb-jar_4_0.xsd"
         version="4.0">
  <enterprise-beans>
    <session>
      <ejb-name>TaxPolicy</ejb-name>
      <env-entry>
        <env-entry-name>example.TaxPolicy/maxExemptions</env-entry-name>
        <env-entry-type>java.lang.Integer</env-entry-type>
        <env-entry-value>10</env-entry-value>
      </env-entry>
      <env-entry>
        <env-entry-name>example.TaxPolicy/minExemptions</env-entry-name>
        <env-entry-type>java.lang.Integer</env-entry-type>
        <env-entry-value>0</env-entry-value>
      </env-entry>
    </session>
  </enterprise-beans>
</ejb-jar>

Because @Resource does not specify name, the container derives example.TaxPolicy/maxExemptions and example.TaxPolicy/minExemptions from the declaring class and field names. The descriptor supplies Integer values, which are unboxed into the int fields. Obtain the bean through the container; new TaxPolicy() does not request container injection. The field or method may have any access qualifier (public, private, etc.). For all classes except application client main classes, the fields or methods must not be static. The application client container invokes the client main class through its static main method rather than creating an instance of that main class. Injection fields and methods on that main class must therefore be static.

Application Life Cycle Annotation Methods

An application component may need to perform initialization of its own after all resources have been injected. To support this case, one method of the class can be annotated with the @PostConstruct annotation. This method will be called after all injections have occurred and before the class is put into service. This method will be called even if the class doesn't request any resources to be injected. Similarly, for classes whose life cycle is managed by the container, the @PreDestroy annotation can be applied to one method that will be called when the class is taken out of service and will no longer be used by the container. Each class in a class hierarchy may have @PostConstruct and @PreDestroy methods.

The order in which the methods are called matches the order of the class hierarchy, with methods on a superclass being called before methods on a subclass. For an application client main class, the container supports a static @PostConstruct callback before invoking main. It does not support @PreDestroy for the application client.

Standard Jakarta Annotations

The following sections describe the Jakarta Annotations APIs supported by the applicable Jakarta EE component containers.

For information about EJB-specific annotations for WebLogic Server EJBs, see Developing Enterprise JavaBeans for Oracle WebLogic Server.

For information about Web component-specific annotations for WebLogic Server applications, see WebLogic Annotation for Web Components in Developing Web Applications, Servlets, and JSPs for Oracle WebLogic Server.

jakarta.annotation.PostConstruct

Target: Method

Specifies the life cycle callback method that the application component should execute before the first business method invocation and after dependency injection is done to perform any initialization. This method will be called after all injections have occurred and before the class is put into service. This method will be called even if the class doesn't request any resources to be injected.

Declaring a @PostConstruct method is optional. Use it when the component needs initialization after injection. A class may declare at most one @PostConstruct method; different classes in the component’s hierarchy can each declare a callback, subject to the applicable inheritance and overriding rules.

The method annotated with @PostConstruct must follow these requirements:

  • A lifecycle callback declared on the target component class has signature void method() and must not throw checked exceptions. A lifecycle interceptor method declared in an interceptor class has signature void method(jakarta.interceptor.InvocationContext) or Object method(jakarta.interceptor.InvocationContext). A returned Object is ignored for a lifecycle event. A method that also intercepts business or timeout invocations may declare checked exceptions, but must not let a checked exception escape during a post-construct or pre-destroy invocation. See Jakarta Interceptors, Lifecycle Event Callbacks. Jakarta Interceptors 2.2, Lifecycle Event Callbacks

  • The method may be public, protected, package private or private.

  • The method must not be static except for the application client.

  • Use a non-final callback method. A component specification may explicitly relax this restriction.

  • If the method throws an unchecked exception, the class must not be put into service. In the case of EJBs, the method annotated with PostConstruct can handle exceptions and cleanup before the bean instance is discarded.

This annotation does not have any attributes.

jakarta.annotation.PreDestroy

Target: Method

Specifies the life cycle callback method that signals that the application component is about to be destroyed by the container. You typically apply this annotation to methods that release resources that the class has been holding.

Each class may declare at most one @PreDestroy callback. This callback is supported for container-managed objects whose full lifecycle the container controls; it is not supported for application clients.

The method annotated with @PreDestroy must follow these requirements:

  • A lifecycle callback declared on the target component class has signature void method() and must not throw checked exceptions. A lifecycle interceptor method declared in an interceptor class has signature void method(jakarta.interceptor.InvocationContext) or Object method(jakarta.interceptor.InvocationContext). A returned Object is ignored for a lifecycle event. A method that also intercepts business or timeout invocations may declare checked exceptions, but must not let a checked exception escape during a post-construct or pre-destroy invocation. See Jakarta Interceptors, Lifecycle Event Callbacks. Jakarta Interceptors 2.2, Lifecycle Event Callbacks

  • The method may be public, protected, package private or private.

  • The method must not be static.

  • Use a non-final callback method. A component specification may explicitly relax this restriction.

  • An unchecked exception from a @PreDestroy callback is ignored under the Jakarta Annotations contract. For lifecycle interceptor chains, apply the Jakarta Interceptors exception rules; arrange cleanup so that it does not depend on a later callback executing successfully.

This annotation does not have any attributes.

jakarta.annotation.Resource

Target: Class, Method, Field

Specifies a dependence on an external resource, such as a JDBC data source or a JMS destination or connection factory.

If you specify the annotation on a field or method, the container injects an instance of the requested resource into the bean when the bean is initialized. If you apply the annotation to a class, the annotation declares a resource that the component will look up at runtime.

Attributes

Table 8-1 Attributes of the jakarta.annotation.Resource Annotation

Name Description Data Type Required?

name

Names the logical resource reference in the component environment. Relative names are resolved under java:comp/env; lookup identifies the target resource separately.

If you apply the @Resource annotation to a field, the default value of the name attribute is the field name, qualified by the fully qualified class name. If you apply it to a method, the default value is the component property name corresponding to the method, qualified by the fully qualified class name. If you apply the annotation to class, there is no default value and thus you are required to specify the attribute.

String

Yes on a class-level declaration; otherwise inferred when omitted.

lookup

JNDI name of an existing compatible resource to which this reference links. The default is an empty string (no explicit lookup target).

String

No

type

Specifies the Java data type of the resource.

If you apply the @Resource annotation to a field, the default value of the type attribute is the type of the field. If you apply it to a method, the default is the type of the component property. If you apply it to a class, there is no default value and thus you are required to specify this attribute.

Class<?> Yes on a class-level declaration; otherwise inferred when omitted.

authenticationType

Specifies the authentication type to use for the resource.

Valid values for this attribute are:

  • AuthenticationType.CONTAINER

  • AuthenticationType.APPLICATION

Default value is AuthenticationType.CONTAINER

Applies to connection-factory resource references; do not explicitly specify it for other resource types.

AuthenticationType

No

shareable

Indicates whether a resource can be shared between this component and other components.

Valid values for this attribute are true and false. Default value is true.

Applies to connection-factory references; do not explicitly specify it for other resource types.

boolean

No

mappedName

Specifies a WebLogic Server-specific name to which the component reference should be mapped.

For resource references resolved through WebLogic Server’s JNDI-name selection, an explicit JNDI-name mapping in the WebLogic descriptor takes precedence. Without that mapping, a lookup target is used when supplied; mappedName is the fallback when neither supplies a target. A mappedName is product-specific, so prefer lookup when an explicit JNDI reference to a configured compatible resource is appropriate.

These fields belong inside a container-managed component. Import jakarta.annotation.Resource, java.net.URL, javax.sql.DataSource, jakarta.jms.ConnectionFactory and jakarta.jms.Queue. Configure the named JDBC and JMS resources before deployment. The URL is an illustrative value; this example does not open a network connection.

@Resource(mappedName = "https://example.com")
private URL url;

@Resource(mappedName = "customerDB")
private DataSource db;

@Resource(mappedName = "jms/ConnectionFactory")
private ConnectionFactory connectionFactory;

@Resource(mappedName = "jms/Queue")
private Queue queue;

For resource references resolved through WebLogic Server’s JNDI-name selection, an explicit JNDI-name mapping in the WebLogic descriptor takes precedence. Without that mapping, a lookup target is used when supplied; mappedName is the fallback when neither supplies a target. A mappedName is product-specific, so prefer lookup when an explicit JNDI reference to a configured compatible resource is appropriate.

String

No

description

Specifies a description of the resource.

String

No

jakarta.annotation.Resources

Target: Class

@Resources groups multiple @Resource declarations on a class. @Resource is repeatable, so multiple class-level @Resource annotations are also supported; the compiler represents them through the @Resources container.

Attributes

Table 8-2 Attributes of the jakarta.annotation.Resources Annotation

Name Description Data Type Required?

value

Specifies the array of @Resource annotations.

Resource[]

Yes

Standard Jakarta Security Annotations

The following sections describe Jakarta security annotations; support and behavior depend on the component technology.

Support is defined by the component specification. In the enterprise-bean case, @RolesAllowed, @PermitAll and @DenyAll control access to container-invoked business methods. They do not define servlet URL security constraints. For HTTP servlet access, use @ServletSecurity or web.xml security constraints as described in Developing Web Applications, Servlets, and JSPs for Oracle WebLogic Server. @DeclareRoles declares application roles, and @RunAs specifies an application execution identity where supported.

ServletSecurity

Developing Web Applications, Servlets, and JSPs for Oracle WebLogic Server

jakarta.annotation.security.DeclareRoles

Target: Class

Declares logical security roles used by this application component.

You typically use this annotation to define roles that can be tested from within the methods of the annotated class, such as using the isUserInRole method. You can also use the annotation to explicitly declare roles that are implicitly declared if you use the @RolesAllowed annotation on the class or a method of the class.

Declare application roles using the supported annotations or standard deployment descriptor. Configure how users and groups are assigned to those roles through the applicable WebLogic deployment mappings or configured role-mapping policy. Declaring a role does not create a user or group. For administrative role-mapping procedures, see Security Roles in the Oracle WebLogic Remote Console Online Help.

Attributes

Table 8-3 Attributes of the jakarta.annotation.security.DeclareRoles Annotation

Name Description Data Type Required?

value

Array of logical application security role names to declare.

String[]

Yes

jakarta.annotation.security.DenyAll

Target: Class, Method

Excludes the affected container business methods from invocation. On a class, it establishes the default method-access rule for that class; a supported method-level access annotation takes precedence for that method.

This annotation does not have any attributes.

jakarta.annotation.security.PermitAll

Target: Class, Method

Marks the affected container business methods as unchecked for role-based authorization; callers need not belong to an application role. On a class, it establishes the default for that class; a supported method-level access annotation takes precedence for that method. This does not turn off independent authentication, transport or other security requirements.

This annotation does not have any attributes.

jakarta.annotation.security.RolesAllowed

Target: Class, Method

Specifies the list of security roles that are allowed to access methods in the Jakarta EE container.

If you specify it at the class-level, then it applies to all methods in the application component. If you specify it at the method-level, then it only applies to that method. If you specify the annotation at both the class- and method-level, the method value overrides the class value.

Declare application roles using the supported annotations or standard deployment descriptor. Configure how users and groups are assigned to those roles through the applicable WebLogic deployment mappings or configured role-mapping policy. Declaring a role does not create a user or group. For administrative role-mapping procedures, see Security Roles in the Oracle WebLogic Remote Console Online Help.

Attributes

Table 8-4 Attributes of the jakarta.annotation.security.RolesAllowed Annotation

Name Description Data Type Required?

value

Array of logical application security role names permitted to invoke the affected methods.

String[]

Yes

jakarta.annotation.security.RunAs

Target: Class

@RunAs names the logical application security role used to determine a component’s identity when it makes calls to other components. It does not change the identity of the caller being authorized to invoke the component. At deployment, map the run-as role to an appropriate user identity using the applicable WebLogic descriptor or configured role-mapping rules. For an explicit role-to-user mapping, use run-as-role-assignment with role-name and run-as-principal-name in weblogic.xml for a web module or weblogic-ejb-jar.xml for an EJB module. The run-as principal must identify a valid user, not just a group name. Role membership mappings may involve groups, but the effective run-as identity is a user.

Attributes

Table 8-5 Attributes of the jakarta.annotation.security.RunAs Annotation

Name Description Data Type Required?

value

Logical application role name used to determine the component’s run-as identity.

String

Yes