-
Notifications
You must be signed in to change notification settings - Fork 480
Description
Description
Implement CDI interceptor bindings for all 6 ByteBuddy Advice annotations to make them work correctly on CDI beans.
Background
ByteBuddy annotations currently fail silently on @ApplicationScoped CDI beans because Weld proxies do not copy method annotations. ByteBuddy's class matcher uses declaresMethod(isAnnotatedWith(...)) which cannot see annotations on proxy classes. This was the root cause of the connection leak fixed in #34134.
Current ByteBuddy Annotations (from ByteBuddyFactory):
- @CloseDB → CloseDBAdvice - Closes and commits DB connection at method exit
- @CloseDBIfOpened → CloseDBIfOpenedAdvice - Closes DB connection only if opened during method
- @WrapInTransaction → WrapInTransactionAdvice - Wraps method in database transaction
- @ExternalTransaction → ExternalTransactionAdvice - Creates separate transaction context
- @logtime → LogTimeAdvice - Logs method execution time with configurable level
- @EnterpriseFeature → EnterpriseFeatureAdvice - Validates enterprise license level before execution
Implementation Approach
For each annotation, implement CDI interceptor:
1. Database Connection/Transaction Annotations (@CloseDB, @CloseDBIfOpened, @WrapInTransaction, @ExternalTransaction):
- Add
@InterceptorBindingmeta-annotation to each - Create corresponding interceptor classes with
@AroundInvoke - Replicate ByteBuddy advice logic in interceptor methods
- Handle connection lifecycle, transaction boundaries, and cleanup
2. Performance/Observability Annotations (@logtime):
- Add
@InterceptorBindingmeta-annotation - Create LogTimeInterceptor with
@AroundInvoke - Use StopWatch to measure execution time
- Support configurable logging level (INFO/DEBUG)
3. Security/License Annotations (@EnterpriseFeature):
- Add
@InterceptorBindingmeta-annotation - Create EnterpriseFeatureInterceptor with
@AroundInvoke - Validate license level before method execution
- Throw DotInvalidLicenseException if requirements not met
4. Enable interceptors in beans.xml:
<interceptors>
<class>com.dotcms.business.interceptor.CloseDBInterceptor</class>
<class>com.dotcms.business.interceptor.CloseDBIfOpenedInterceptor</class>
<class>com.dotcms.business.interceptor.WrapInTransactionInterceptor</class>
<class>com.dotcms.business.interceptor.ExternalTransactionInterceptor</class>
<class>com.dotcms.business.interceptor.LogTimeInterceptor</class>
<class>com.dotcms.business.interceptor.EnterpriseFeatureInterceptor</class>
</interceptors>Technical Details
Why Both ByteBuddy and CDI Interceptors Can Coexist:
- ByteBuddy: Fires on non-CDI classes (instrumented at class load time)
- CDI Interceptors: Fire on CDI beans at proxy boundary (runtime)
- Both use same lifecycle guards (e.g.,
isNewConnection) to prevent double-processing - Result: Annotations work correctly everywhere with backward compatibility
Priority Order (Critical → Nice-to-Have):
- @CloseDBIfOpened - Connection leak prevention (showstopper bug)
- @WrapInTransaction - Data integrity (high priority)
- @CloseDB - Resource management (high priority)
- @ExternalTransaction - Transaction isolation (medium priority)
- @EnterpriseFeature - License enforcement (medium priority)
- @logtime - Observability (low priority)
Benefits
- Fixes 7+ known legacy violations in UniqueFieldDataBaseUtil, JobQueueManagerAPIImpl, MetricsAPIImpl, CustomAttributeAPIImpl, HostWebAPIImpl, DBUniqueFieldValidationStrategy
- Eliminates manual wrapping - No more
LocalTransaction.wrapReturn()boilerplate - Prevents future leaks - Annotations work correctly on CDI beans
- Backward compatible - Non-CDI code continues to use ByteBuddy
- Consistent behavior - Same semantics across CDI and non-CDI classes
Acceptance Criteria
- All 6 annotations converted to
@InterceptorBinding(backward compatible) - CDI interceptor classes implemented for each annotation
- Interceptors enabled in beans.xml
- Unit tests verify interceptors fire correctly on CDI beans
- Integration tests verify no double-processing (ByteBuddy + CDI)
- ArchUnit test updated to allow annotations on CDI beans after interceptors enabled
- Known legacy violations migrated or documented
- Performance impact measured (interceptor overhead vs ByteBuddy)
Testing Strategy
- Unit Tests: Mock CDI context, verify interceptor invocation
- Integration Tests: Real CDI beans with annotations, verify behavior
- Compatibility Tests: Ensure ByteBuddy still works on non-CDI classes
- Performance Tests: Measure overhead of CDI interceptors vs ByteBuddy
- Leak Tests: Run MetricsStatsCollector repeatedly, verify no connection leaks
References
- Root cause analysis: [DEFECT] Default site not being selected on login. #34134 (MetricStatsCollector connection leak)
- ByteBuddy implementation:
com.dotcms.business.bytebuddy.ByteBuddyFactory - ArchUnit test:
CodingStandardsArchTest.applicationScopedBeansCannotUseByteBuddyAnnotations()
Metadata
Metadata
Assignees
Labels
Type
Projects
Status