Jakarta Annotations defines a collection of annotations representing common semantic concepts that enable a declarative style of programming that applies across a variety of Java technologies.
—
Core Jakarta Annotations provide fundamental functionality for lifecycle management, resource injection, nullability constraints, code generation markers, and priority ordering. These annotations form the foundation for dependency injection and container-managed components.
Annotations for controlling component initialization and cleanup phases.
Marks a method to be executed after dependency injection is completed. The method is called before the class is put into service.
/**
* Marks a method for post-construction callback.
* The method is invoked after dependency injection is completed.
* Only one method per class can be annotated with PostConstruct.
*
* Method requirements:
* - void return type
* - no parameters (except InvocationContext for interceptors)
* - can be any access modifier (public, protected, package-private, private)
* - must not be static (except in application client)
* - should not be final
* - if method throws unchecked exception, class must not be put into service
*/
@Target(METHOD)
@Retention(RUNTIME)
public @interface PostConstruct {
}Usage Examples:
import jakarta.annotation.PostConstruct;
public class EmailService {
private ConnectionPool connectionPool;
@PostConstruct
public void initialize() {
connectionPool = new ConnectionPool();
connectionPool.start();
System.out.println("Email service initialized");
}
}
// Private method example
public class DatabaseService {
@PostConstruct
private void setupConnection() {
// Initialization logic
}
}Marks a method to be executed before the instance is removed by the container. Typically used to release resources or perform cleanup.
/**
* Marks a method for pre-destruction callback.
* The method is invoked before the instance is removed by the container.
* Used to release resources or perform cleanup.
*
* Method requirements:
* - void return type
* - no parameters (except InvocationContext for interceptors)
* - can be any access modifier (public, protected, package-private, private)
* - must not be static
* - should not be final
* - if method throws unchecked exception, it is ignored by container
*/
@Target(METHOD)
@Retention(RUNTIME)
public @interface PreDestroy {
}Usage Examples:
import jakarta.annotation.PreDestroy;
public class CacheService {
private CacheManager cacheManager;
@PreDestroy
public void cleanup() {
if (cacheManager != null) {
cacheManager.shutdown();
System.out.println("Cache service cleaned up");
}
}
}Annotations for dependency injection and resource management.
Marks a resource that is needed by the application. Can be applied to fields, methods, or classes for different injection patterns.
Important: Even though not marked @Inherited, deployment tools must examine all superclasses to discover all uses of this annotation, including on private fields and methods of superclasses.
/**
* Marks a resource needed by the application.
* Can be used for field injection, setter injection, or class-level declaration.
*/
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
@Repeatable(Resources.class)
public @interface Resource {
/**
* JNDI name of the resource. Default is field name or JavaBeans property name.
*/
String name() default "";
/**
* Resource reference lookup name (global JNDI names).
*/
String lookup() default "";
/**
* Java type of the resource.
*/
Class<?> type() default Object.class;
/**
* Authentication type for the resource connection.
*/
AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
/**
* Whether the resource can be shared between components.
*/
boolean shareable() default true;
/**
* Product-specific name for resource mapping (not portable).
*/
String mappedName() default "";
/**
* Description of the resource.
*/
String description() default "";
/**
* Authentication type enumeration.
*/
public enum AuthenticationType {
CONTAINER, // Container manages authentication
APPLICATION // Application manages authentication
}
}Usage Examples:
import jakarta.annotation.Resource;
// Field injection
public class OrderService {
@Resource(name = "jdbc/OrderDB")
private DataSource dataSource;
@Resource
private EntityManager entityManager; // Uses field name
@Resource(lookup = "java:global/jms/OrderQueue")
private Queue orderQueue;
}
// Method injection
public class PaymentService {
private DataSource paymentDB;
@Resource(name = "jdbc/PaymentDB")
public void setPaymentDataSource(DataSource ds) {
this.paymentDB = ds;
}
}
// Class-level declaration
@Resource(name = "jdbc/AppDB", type = DataSource.class,
description = "Main application database")
public class Application {
}Container annotation for multiple @Resource declarations on a single class.
/**
* Container for multiple @Resource annotations.
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface Resources {
/**
* Array of Resource annotations.
*/
Resource[] value();
}Usage Examples:
import jakarta.annotation.Resources;
import jakarta.annotation.Resource;
@Resources({
@Resource(name = "jdbc/UserDB", type = DataSource.class),
@Resource(name = "jms/NotificationQueue", type = Queue.class),
@Resource(name = "mail/Session", type = Session.class)
})
public class MultiResourceService {
}Annotations for expressing nullability constraints in APIs.
Indicates that an annotated element must not be null. For fields, the field must not be null after construction. For methods, applies to the return value.
/**
* The annotated element must not be null.
* Annotated fields must not be null after construction has completed.
* When applied to a method, applies to the method return value.
*
* No @Target specified - can be applied to any program element.
*/
@Documented
@Retention(RUNTIME)
public @interface Nonnull {
}Indicates that an annotated element could be null under some circumstances. Useful for overriding @Nonnull assumptions.
/**
* The annotated element could be null under some circumstances.
* Useful mostly for overriding a @Nonnull annotation.
* When applied to a method, applies to the method return value.
*
* No @Target specified - can be applied to any program element.
*/
@Documented
@Retention(RUNTIME)
public @interface Nullable {
}Usage Examples:
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
public class UserService {
@Nonnull
public User createUser(@Nonnull String name, @Nullable String email) {
// Method guarantees non-null return
// name parameter must not be null
// email parameter may be null
return new User(name, email);
}
@Nullable
public User findUser(String id) {
// Method may return null if user not found
return userRepository.findById(id);
}
}Annotations for marking generated code.
Marks source code that has been generated by tools. Used to differentiate user-written code from generated code.
/**
* Marks source code as generated by tools.
* Used to differentiate user-written code from generated code.
*/
@Documented
@Target({PACKAGE, TYPE, ANNOTATION_TYPE, METHOD, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, PARAMETER})
@Retention(SOURCE)
public @interface Generated {
/**
* Name of the code generator (required).
* Recommended: fully qualified class name.
*/
String[] value();
/**
* Date when source was generated.
* ISO 8601 format (e.g., "2001-07-04T12:08:56.235-0700").
*/
String date() default "";
/**
* Comments from the code generator.
*/
String comments() default "";
}Usage Examples:
import jakarta.annotation.Generated;
@Generated(value = "com.example.MyGenerator",
date = "2023-12-01T10:30:00.000Z",
comments = "Generated from schema v2.1")
public class GeneratedEntity {
@Generated("com.example.PropertyGenerator")
private String generatedField;
@Generated(value = "com.example.MethodGenerator",
comments = "Auto-generated getter")
public String getGeneratedField() {
return generatedField;
}
}Annotation for specifying execution priority.
Indicates the priority order in which program elements should be used. The effect is defined by other specifications (e.g., Jakarta Interceptors).
Important: Priority values should generally be non-negative, with negative values reserved for special meanings such as "undefined" or "not specified".
/**
* Indicates priority order for program elements.
* Lower values indicate higher priority.
*/
@Documented
@Retention(RUNTIME)
public @interface Priority {
/**
* Priority value (should generally be non-negative).
* Lower values indicate higher priority.
*/
int value();
}Usage Examples:
import jakarta.annotation.Priority;
@Priority(100)
public class HighPriorityInterceptor {
// Will be executed before lower priority interceptors
}
@Priority(500)
public class LowPriorityInterceptor {
// Will be executed after higher priority interceptors
}
// Common priority constants (from Jakarta Interceptors specification)
@Priority(Interceptor.Priority.PLATFORM_BEFORE) // 0
public class PlatformInterceptor { }
@Priority(Interceptor.Priority.LIBRARY_BEFORE) // 1000
public class LibraryInterceptor { }
@Priority(Interceptor.Priority.APPLICATION) // 2000
public class ApplicationInterceptor { }Install with Tessl CLI
npx tessl i tessl/maven-jakarta-annotation--jakarta-annotation-api