CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-jakarta-annotation--jakarta-annotation-api

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.

Pending
Overview
Eval results
Files

sql-annotations.mddocs/

SQL Annotations

Jakarta SQL Annotations provide declarative database DataSource configuration and JNDI registration. These annotations enable database setup without external configuration files, allowing developers to define DataSource properties directly in code.

Capabilities

DataSource Configuration

Annotations for defining and configuring database connections with JNDI registration.

@DataSourceDefinition

Defines a container DataSource to be registered with JNDI. Configures all DataSource properties including connection details, pool settings, and transaction behavior.

Important: DataSource properties should not be specified more than once. If the URL contains properties that are also specified using annotation elements, the precedence order is undefined and implementation-specific. If properties are specified in both the properties array and as annotation elements, the annotation element value takes precedence.

/**
 * Defines a container DataSource for JNDI registration.
 * Configures database connection and pooling properties.
 */
@Target(TYPE)
@Retention(RUNTIME)
@Repeatable(DataSourceDefinitions.class)
public @interface DataSourceDefinition {
    /**
     * JNDI name by which the data source will be registered (required).
     */
    String name();
    
    /**
     * DataSource implementation class name (required).
     * Must implement DataSource, XADataSource, or ConnectionPoolDataSource.
     */
    String className();
    
    /**
     * Description of the data source.
     */
    String description() default "";
    
    /**
     * JDBC URL for the database connection.
     */
    String url() default "";
    
    /**
     * User name for database authentication.
     */ 
    String user() default "";
    
    /**
     * Password for database authentication.
     */
    String password() default "";
    
    /**
     * Database name on the server.
     */
    String databaseName() default "";
    
    /**
     * Port number where database server is listening.
     */
    int portNumber() default -1;
    
    /**
     * Database server name.
     */
    String serverName() default "localhost";
    
    /**
     * Transaction isolation level.
     * Values from Connection interface: TRANSACTION_READ_UNCOMMITTED,
     * TRANSACTION_READ_COMMITTED, TRANSACTION_REPEATABLE_READ, TRANSACTION_SERIALIZABLE.
     */
    int isolationLevel() default -1;
    
    /**
     * Whether connections participate in transactions.
     */
    boolean transactional() default true;
    
    /**
     * Initial number of connections in the pool.
     */
    int initialPoolSize() default -1;
    
    /**
     * Maximum number of concurrent connections in the pool.
     */
    int maxPoolSize() default -1;
    
    /**
     * Minimum number of connections in the pool.
     */
    int minPoolSize() default -1;
    
    /**
     * Maximum time (seconds) unused connection remains in pool.
     */
    int maxIdleTime() default -1;
    
    /**
     * Total number of statements the connection pool should keep open.
     */
    int maxStatements() default -1;
    
    /**
     * Vendor-specific properties in "propertyName=propertyValue" format.
     */
    String[] properties() default {};
    
    /**
     * Maximum time (seconds) to wait while connecting to database.
     */
    int loginTimeout() default 0;
}

Usage Examples:

import jakarta.annotation.sql.DataSourceDefinition;
import java.sql.Connection;

// Basic MySQL DataSource
@DataSourceDefinition(
    name = "java:global/MyAppDataSource",
    className = "com.mysql.cj.jdbc.MysqlDataSource",
    url = "jdbc:mysql://localhost:3306/myapp",
    user = "appuser",
    password = "secret123"
)
public class DatabaseConfig {
}

// Advanced PostgreSQL configuration with connection pooling
@DataSourceDefinition(
    name = "java:app/PostgresDS",
    className = "org.postgresql.ds.PGPoolingDataSource",
    serverName = "db.example.com",
    portNumber = 5432,
    databaseName = "production",
    user = "produser",
    password = "prodpass",
    description = "Production PostgreSQL database",
    isolationLevel = Connection.TRANSACTION_READ_COMMITTED,
    transactional = true,
    initialPoolSize = 5,
    maxPoolSize = 20,
    minPoolSize = 2,
    maxIdleTime = 300,
    maxStatements = 100,
    loginTimeout = 10,
    properties = {
        "ssl=true",
        "sslmode=require",
        "prepareThreshold=3"
    }
)
public class ProductionDatabaseConfig {
}

// H2 in-memory database for testing
@DataSourceDefinition(
    name = "java:comp/env/TestDB",
    className = "org.h2.jdbcx.JdbcDataSource", 
    url = "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1",
    user = "sa",
    password = "",
    description = "In-memory H2 database for testing"
)
public class TestConfiguration {
}

// Oracle with XA support
@DataSourceDefinition(
    name = "java:global/OracleXADS",
    className = "oracle.jdbc.xa.client.OracleXADataSource",
    url = "jdbc:oracle:thin:@oracle.example.com:1521:ORCL",
    user = "appuser", 
    password = "oraclepass",
    transactional = true,
    isolationLevel = Connection.TRANSACTION_SERIALIZABLE,
    properties = {
        "oracle.jdbc.implicitStatementCacheSize=20",
        "oracle.jdbc.fanEnabled=false"
    }
)
public class OracleConfig {
}

@DataSourceDefinitions

Container annotation for multiple @DataSourceDefinition declarations. Allows defining multiple DataSources on a single class.

/**
 * Container for multiple @DataSourceDefinition annotations.
 * Allows multiple DataSource definitions on a single class.
 */
@Target(TYPE)
@Retention(RUNTIME)
public @interface DataSourceDefinitions {
    /**
     * Array of DataSourceDefinition annotations.
     */
    DataSourceDefinition[] value();
}

Usage Examples:

import jakarta.annotation.sql.DataSourceDefinitions;
import jakarta.annotation.sql.DataSourceDefinition;

// Multiple DataSources for microservice architecture
@DataSourceDefinitions({
    @DataSourceDefinition(
        name = "java:global/UserDB",
        className = "com.mysql.cj.jdbc.MysqlDataSource",
        url = "jdbc:mysql://userdb:3306/users",
        user = "userservice",
        password = "userpass",
        description = "User management database"
    ),
    @DataSourceDefinition(
        name = "java:global/OrderDB", 
        className = "org.postgresql.ds.PGSimpleDataSource",
        url = "jdbc:postgresql://orderdb:5432/orders",
        user = "orderservice",
        password = "orderpass",
        description = "Order processing database"
    ),
    @DataSourceDefinition(
        name = "java:global/InventoryDB",
        className = "com.mysql.cj.jdbc.MysqlDataSource", 
        url = "jdbc:mysql://inventorydb:3306/inventory",
        user = "inventoryservice",
        password = "invpass",
        description = "Inventory tracking database"
    )
})
public class MultiDatabaseApplication {
}

// Read/Write split configuration
@DataSourceDefinitions({
    @DataSourceDefinition(
        name = "java:comp/env/ReadOnlyDB",
        className = "com.mysql.cj.jdbc.MysqlDataSource",
        url = "jdbc:mysql://slave.db.example.com:3306/myapp",
        user = "readonly",
        password = "readpass",
        description = "Read-only slave database",
        maxPoolSize = 10,
        properties = {"readOnly=true"}
    ),
    @DataSourceDefinition(
        name = "java:comp/env/ReadWriteDB",
        className = "com.mysql.cj.jdbc.MysqlDataSource", 
        url = "jdbc:mysql://master.db.example.com:3306/myapp",
        user = "readwrite",
        password = "writepass",
        description = "Read-write master database",
        maxPoolSize = 5,
        transactional = true
    )
})
public class ReadWriteSplitConfig {
}

// Development vs Production configurations
@DataSourceDefinitions({
    @DataSourceDefinition(
        name = "java:global/DevDB",
        className = "org.h2.jdbcx.JdbcDataSource",
        url = "jdbc:h2:~/devdb",
        user = "dev",
        password = "dev",
        description = "Development H2 database"
    ),
    @DataSourceDefinition(
        name = "java:global/ProdDB",
        className = "org.postgresql.ds.PGPoolingDataSource",
        serverName = "prod.db.company.com",
        portNumber = 5432,
        databaseName = "production",
        user = "produser",
        password = "prodpass",
        description = "Production PostgreSQL database",
        initialPoolSize = 10,
        maxPoolSize = 50,
        minPoolSize = 5
    )
})
public class EnvironmentDatabaseConfig {
}

DataSource Integration Patterns

Using Defined DataSources

import jakarta.annotation.Resource;
import jakarta.annotation.sql.DataSourceDefinition;
import javax.sql.DataSource;

@DataSourceDefinition(
    name = "java:app/MyDS",
    className = "com.mysql.cj.jdbc.MysqlDataSource",
    url = "jdbc:mysql://localhost:3306/mydb",
    user = "user",
    password = "pass"
)
public class DatabaseService {
    
    // Injecting the defined DataSource
    @Resource(lookup = "java:app/MyDS")
    private DataSource dataSource;
    
    public List<User> getUsers() {
        try (Connection conn = dataSource.getConnection();
             PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users")) {
            
            ResultSet rs = stmt.executeQuery();
            List<User> users = new ArrayList<>();
            while (rs.next()) {
                users.add(mapToUser(rs));
            }
            return users;
        } catch (SQLException e) {
            throw new RuntimeException("Database error", e);
        }
    }
}

Connection Pool Configuration

// High-performance production setup
@DataSourceDefinition(
    name = "java:global/HighPerformanceDB",
    className = "com.zaxxer.hikari.HikariDataSource",
    url = "jdbc:postgresql://db.example.com:5432/app",
    user = "appuser",
    password = "apppass",
    initialPoolSize = 10,     // Start with 10 connections
    maxPoolSize = 50,         // Max 50 concurrent connections  
    minPoolSize = 5,          // Keep minimum 5 connections
    maxIdleTime = 600,        // 10 minutes idle timeout
    maxStatements = 250,      // Statement cache size
    loginTimeout = 5,         // 5 second connection timeout
    properties = {
        "maximumPoolSize=50",
        "minimumIdle=5", 
        "connectionTimeout=5000",
        "idleTimeout=600000",
        "maxLifetime=1800000",   // 30 minutes max connection lifetime
        "leakDetectionThreshold=60000"  // 1 minute leak detection
    }
)
public class HighPerformanceConfig {
}

Multi-Tenant Database Configuration

@DataSourceDefinitions({
    @DataSourceDefinition(
        name = "java:global/TenantA_DB",
        className = "com.mysql.cj.jdbc.MysqlDataSource",
        url = "jdbc:mysql://tenant-a.db.example.com:3306/tenant_a",
        user = "tenant_a_user",
        password = "tenant_a_pass",
        description = "Tenant A dedicated database"
    ),
    @DataSourceDefinition(
        name = "java:global/TenantB_DB", 
        className = "com.mysql.cj.jdbc.MysqlDataSource",
        url = "jdbc:mysql://tenant-b.db.example.com:3306/tenant_b",
        user = "tenant_b_user", 
        password = "tenant_b_pass",
        description = "Tenant B dedicated database"
    ),
    @DataSourceDefinition(
        name = "java:global/SharedDB",
        className = "com.mysql.cj.jdbc.MysqlDataSource",
        url = "jdbc:mysql://shared.db.example.com:3306/shared",
        user = "shared_user",
        password = "shared_pass", 
        description = "Shared tenant database"
    )
})
public class MultiTenantConfiguration {
}

Install with Tessl CLI

npx tessl i tessl/maven-jakarta-annotation--jakarta-annotation-api

docs

core-annotations.md

index.md

security-annotations.md

sql-annotations.md

tile.json