スキル一覧に戻る
cuioss

java-cdi

by cuioss

An orchestration layer for AI coding assistants (currently Claude Code) that enforces consistency, reliability, and more predictable outputs.

0🍴 0📅 2026年1月17日
GitHubで見るManusで実行

SKILL.md


name: java-cdi description: Core CDI patterns including constructor injection, scopes, producers, and container configuration allowed-tools: [Read, Edit, Write, Bash, Grep, Glob]

Java CDI Skill

Core CDI (Contexts and Dependency Injection) standards applicable to any CDI container. This skill covers dependency injection patterns, scopes, and producer methods.

Prerequisites

This skill applies to Jakarta CDI projects:

  • jakarta.inject:jakarta.inject-api
  • jakarta.enterprise:jakarta.enterprise.cdi-api

Required Imports

// CDI Core
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.inject.Singleton;

// CDI Scopes
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.RequestScoped;
import jakarta.enterprise.context.SessionScoped;
import jakarta.enterprise.context.Dependent;

// CDI Producers and Optional Dependencies
import jakarta.enterprise.inject.Produces;
import jakarta.enterprise.inject.Instance;

// Quarkus Configuration
import org.eclipse.microprofile.config.inject.ConfigProperty;

References


Constructor Injection (Mandatory)

REQUIRED: Always use constructor injection instead of field injection.

For foundational constructor injection principles (immutability, testability, fail-fast behavior), see pm-dev-java:java-core skill.

Single Constructor Rule

When a CDI bean has exactly one constructor, CDI automatically treats it as the injection point - no @Inject needed:

@ApplicationScoped
public class OrderService {
    private final PaymentService paymentService;
    private final InventoryService inventoryService;

    // No @Inject needed - only one constructor
    public OrderService(PaymentService paymentService,
                       InventoryService inventoryService) {
        this.paymentService = paymentService;
        this.inventoryService = inventoryService;
    }
}

Multiple Constructors Rule

When a CDI bean has multiple constructors, you MUST explicitly mark the injection constructor with @Inject:

@ApplicationScoped
public class ConfigurableService {
    private final DatabaseService databaseService;
    private final String configValue;

    public ConfigurableService() {
        this.databaseService = null;
        this.configValue = "default";
    }

    @Inject  // REQUIRED - multiple constructors exist
    public ConfigurableService(DatabaseService databaseService,
                              @ConfigProperty(name = "app.config") String configValue) {
        this.databaseService = databaseService;
        this.configValue = configValue;
    }
}

Anti-Patterns

// ❌ Field Injection - FORBIDDEN
@Inject
private UserService userService;

// ❌ Setter Injection - FORBIDDEN
@Inject
public void setUserService(UserService userService) {
    this.userService = userService;
}

CDI Scopes

ScopeLifecycleUse Case
@ApplicationScopedSingle instance per applicationStateless services, most business logic
@RequestScopedNew instance per HTTP requestRequest-specific data
@SessionScopedNew instance per HTTP sessionUser session data
@DependentNew instance per injectionHelpers, utilities
@SingletonSingle instance (eager init)Use sparingly, prefer @ApplicationScoped
@ApplicationScoped
public class UserService { }  // Singleton across application

@RequestScoped
public class RequestContext { }  // New instance per HTTP request

Optional Dependencies

Use Instance<T> when a dependency might not be available:

@ApplicationScoped
public class NotificationService {
    private final EmailService emailService;
    private final SmsService smsService;  // May be null

    public NotificationService(EmailService emailService,
                             Instance<SmsService> smsServiceInstance) {
        this.emailService = emailService;
        this.smsService = smsServiceInstance.isResolvable() ?
                         smsServiceInstance.get() : null;
    }

    public void sendNotification(String message) {
        emailService.send(message);  // Always available
        if (smsService != null) {
            smsService.send(message);  // Optional
        }
    }
}

Producer Methods

Scope and Null Return Rules

CRITICAL: CDI has strict rules about producer methods returning null.

ScopeCan Return Null?Reason
@Dependent✅ YesNo proxy needed
@RequestScoped❌ NoProxy requires target object
@SessionScoped❌ NoProxy requires target object
@ApplicationScoped❌ NoProxy requires target object

@Dependent Scope (Allows null)

@ApplicationScoped
public class ServletObjectsProducer {

    @Produces
    @Dependent  // ✅ REQUIRED for null returns
    public HttpServletRequest produceHttpServletRequest() {
        return getHttpServletRequest().orElse(null);  // Safe with @Dependent
    }
}

Normal Scoped Producers (Cannot return null)

// ❌ ILLEGAL - will throw IllegalProductException
@Produces
@RequestScoped
public SomeService createService() {
    return null;  // CDI will throw exception at runtime
}

// ✅ CORRECT - Use Null Object pattern
@Produces
@RequestScoped
public NotificationService createNotificationService() {
    return notificationEnabled ?
           new EmailNotificationService() :
           new NoOpNotificationService();  // Never null
}
  1. Use Instance at Injection Points (preferred)
  2. Use @Dependent Scope with Null Returns
  3. Use Null Object Pattern

AVOID: Returning Optional<T> from producer methods - goes against CDI design philosophy.


Error Handling

Common CDI Issues

ProblemExceptionSolution
Missing dependencyUnsatisfiedResolutionExceptionEnsure dependency is a CDI bean with appropriate scope
Multiple implementationsAmbiguousResolutionExceptionUse @Named or custom qualifiers
Circular dependenciesDeploymentExceptionRefactor architecture or use Instance<T> for lazy init
// Disambiguate with @Named
@ApplicationScoped
public class PaymentService {
    public PaymentService(@Named("primary") PaymentGateway gateway) {
        // Uses specifically qualified implementation
    }
}

Quality Checklist

  • Constructor injection used (never field/setter injection)
  • Final fields for all injected dependencies
  • Single constructor (no @Inject needed) or @Inject on injection constructor
  • Appropriate scope selected for each bean
  • Instance used for optional dependencies
  • Producer methods use @Dependent if returning null
  • Normal-scoped producers never return null
  • pm-dev-java:java-cdi-quarkus - Quarkus-specific CDI patterns, container/Docker config, security
  • pm-dev-java:java-core - Core Java patterns
  • pm-dev-java:junit-core - CDI testing patterns

スコア

総合スコア

70/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です