This is an automated email from the ASF dual-hosted git repository.

jlmonteiro pushed a commit to branch TOMEE-4123_AroundConstruct
in repository https://gitbox.apache.org/repos/asf/tomee.git

commit 4f23fe15685b8b25fcfb3a187e1fcc9f33325ee7
Author: Jean-Louis Monteiro <jlmonte...@tomitribe.com>
AuthorDate: Fri Dec 9 14:09:43 2022 +0100

    Start preparing the model and a basic happy path test to support 
Interceptor 1.2 @AroundConstruct lifecycle callback
---
 .../main/java/org/apache/openejb/BeanContext.java  | 17 +++++++++++++
 .../openejb/assembler/classic/Assembler.java       |  5 ++--
 .../classic/InterceptorBindingBuilder.java         |  3 +++
 .../openejb/assembler/classic/InterceptorInfo.java |  1 +
 .../java/org/apache/openejb/cdi/CdiBeanInfo.java   |  8 ++++++
 .../apache/openejb/config/AnnotationDeployer.java  | 12 +++++++++
 .../apache/openejb/config/EjbJarInfoBuilder.java   |  1 +
 .../java/org/apache/openejb/core/Operation.java    |  1 +
 .../openejb/core/interceptor/InterceptorData.java  | 21 ++++++++++++----
 .../openejb/monitoring/StatsInterceptor.java       | 14 +++++++++++
 .../core/stateful/StatefulInterceptorTest.java     | 29 +++++++++++++++++++++-
 .../java/org/apache/openejb/jee/Interceptor.java   |  9 +++++++
 12 files changed, 113 insertions(+), 8 deletions(-)

diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java 
b/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java
index 44b242d621..4d02f9fd26 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java
@@ -143,8 +143,21 @@ public class BeanContext extends DeploymentContext {
             return;
         }
 
+        final Collection<Interceptor<?>> aroundConstructInterceptors = 
Collection.class.cast(Reflections.get(injectionTarget, 
"aroundConstructInterceptors"));
         final Collection<Interceptor<?>> postConstructInterceptors = 
Collection.class.cast(Reflections.get(injectionTarget, 
"postConstructInterceptors"));
         final Collection<Interceptor<?>> preDestroyInterceptors = 
Collection.class.cast(Reflections.get(injectionTarget, 
"preDestroyInterceptors"));
+
+        if (aroundConstructInterceptors != null) {
+            for (final Interceptor<?> pc : aroundConstructInterceptors) {
+                if (isEjbInterceptor(pc)) {
+                    continue;
+                }
+
+                final InterceptorData interceptorData = 
createInterceptorData(pc);
+                instanceScopedInterceptors.add(interceptorData);
+                cdiInterceptors.add(interceptorData);
+            }
+        }
         if (postConstructInterceptors != null) {
             for (final Interceptor<?> pc : postConstructInterceptors) {
                 if (isEjbInterceptor(pc)) {
@@ -201,6 +214,7 @@ public class BeanContext extends DeploymentContext {
         Map.class.cast(Reflections.get(injectionTarget, 
"methodInterceptors")).clear();
         clear(Collection.class.cast(postConstructInterceptors));
         clear(Collection.class.cast(preDestroyInterceptors));
+        clear(Collection.class.cast(Reflections.get(injectionTarget, 
"aroundConstructMethods")));
         clear(Collection.class.cast(Reflections.get(injectionTarget, 
"postConstructMethods")));
         clear(Collection.class.cast(Reflections.get(injectionTarget, 
"preDestroyMethods")));
         clear(Collection.class.cast(Reflections.get(info, "ejbInterceptors")));
@@ -1594,6 +1608,9 @@ public class BeanContext extends DeploymentContext {
             // Create bean instance
             Object beanInstance;
 
+            // TODO we need to create the interceptor stack for the instance 
and
+            // invoke it to wrap what's bellow to create the beanInstance
+
             final InjectionProcessor injectionProcessor;
             if (!dynamicallyImplemented) {
                 injectionProcessor = new InjectionProcessor(rootInstance, 
getInjections(), InjectionProcessor.unwrap(ctx));
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
index 2bca743fdb..dbc781dee0 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
@@ -17,6 +17,7 @@
 
 package org.apache.openejb.assembler.classic;
 
+import jakarta.interceptor.AroundConstruct;
 import org.apache.geronimo.connector.GeronimoBootstrapContext;
 import org.apache.geronimo.connector.outbound.AbstractConnectionManager;
 import org.apache.geronimo.connector.work.GeronimoWorkManager;
@@ -1285,9 +1286,9 @@ public class Assembler extends AssemblerTool implements 
org.apache.openejb.spi.A
                     final AnnotationFinder finder = Proxy.isProxyClass(clazz) ?
                             null : new AnnotationFinder(new 
ClassesArchive(ancestors(clazz)));
                     final List<Method> postConstructs = finder == null ?
-                            Collections.<Method>emptyList() : 
finder.findAnnotatedMethods(PostConstruct.class);
+                            Collections.emptyList() : 
finder.findAnnotatedMethods(PostConstruct.class);
                     final List<Method> preDestroys = finder == null ?
-                            Collections.<Method>emptyList() : 
finder.findAnnotatedMethods(PreDestroy.class);
+                            Collections.emptyList() : 
finder.findAnnotatedMethods(PreDestroy.class);
 
                     resourceInfo.postConstructMethods = new ArrayList<>();
                     resourceInfo.preDestroyMethods = new ArrayList<>();
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/InterceptorBindingBuilder.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/InterceptorBindingBuilder.java
index d8f27b25d9..4ba00f6319 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/InterceptorBindingBuilder.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/InterceptorBindingBuilder.java
@@ -80,6 +80,7 @@ public class InterceptorBindingBuilder {
             toMethods(clazz, info.aroundInvoke, interceptor.getAroundInvoke());
             toMethods(clazz, info.postActivate, interceptor.getPostActivate());
             toMethods(clazz, info.prePassivate, interceptor.getPrePassivate());
+            toMethods(clazz, info.aroundConstruct, 
interceptor.getAroundConstruct());
             toMethods(clazz, info.postConstruct, 
interceptor.getPostConstruct());
             toMethods(clazz, info.preDestroy, interceptor.getPreDestroy());
             toMethods(clazz, info.afterBegin, interceptor.getAfterBegin());
@@ -272,6 +273,7 @@ public class InterceptorBindingBuilder {
     /**
      * Used for getting the java.lang.reflect.Method objects for the following 
callbacks:
      *
+     * - @AroundConstruct <any-scope> void <method-name>(InvocationContext)
      * - @PostConstruct <any-scope> void <method-name>(InvocationContext)
      * - @PreDestroy <any-scope> void <method-name>(InvocationContext)
      * - @PrePassivate <any-scope> void <method-name>(InvocationContext)
@@ -329,6 +331,7 @@ public class InterceptorBindingBuilder {
     /**
      * Used for getting the java.lang.reflect.Method objects for the following 
callbacks:
      *
+     * - @AroundConstruct <any-scope> void <method-name>()
      * - @PostConstruct <any-scope> void <method-name>()
      * - @PreDestroy <any-scope> void <method-name>()
      * - @PrePassivate <any-scope> void <method-name>()
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/InterceptorInfo.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/InterceptorInfo.java
index 9c6dc58003..715f59a31d 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/InterceptorInfo.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/InterceptorInfo.java
@@ -25,6 +25,7 @@ public class InterceptorInfo extends InfoObject {
 
     public final List<CallbackInfo> aroundInvoke = new ArrayList<>();
 
+    public final List<CallbackInfo> aroundConstruct = new ArrayList<>();
     public final List<CallbackInfo> postConstruct = new ArrayList<>();
     public final List<CallbackInfo> preDestroy = new ArrayList<>();
 
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiBeanInfo.java 
b/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiBeanInfo.java
index 95fb80e416..d641b4d48d 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiBeanInfo.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiBeanInfo.java
@@ -52,6 +52,7 @@ public class CdiBeanInfo implements JndiConsumer {
     protected KeyedCollection<String, MessageDestinationRef> 
messageDestinationRef;
     protected KeyedCollection<String, PersistenceContextRef> 
persistenceContextRef;
     protected KeyedCollection<String, PersistenceUnitRef> persistenceUnitRef;
+    protected List<LifecycleCallback> aroundConstruct;
     protected List<LifecycleCallback> postConstruct;
     protected List<LifecycleCallback> preDestroy;
     protected KeyedCollection<String, DataSource> dataSource;
@@ -227,6 +228,13 @@ public class CdiBeanInfo implements JndiConsumer {
         return this.persistenceUnitRef.toMap();
     }
 
+    public List<LifecycleCallback> getAroundConstruct() {
+        if (aroundConstruct == null) {
+            aroundConstruct = new ArrayList<>();
+        }
+        return this.aroundConstruct;
+    }
+
     public List<LifecycleCallback> getPostConstruct() {
         if (postConstruct == null) {
             postConstruct = new ArrayList<>();
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
index aeef3e57ce..ed7b9032cc 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
@@ -17,6 +17,7 @@
 
 package org.apache.openejb.config;
 
+import jakarta.interceptor.AroundConstruct;
 import org.apache.openejb.BeanContext;
 import org.apache.openejb.OpenEJBException;
 import org.apache.openejb.api.LocalClient;
@@ -2527,6 +2528,7 @@ public class AnnotationDeployer implements 
DynamicDeployer {
                 }
 
                 /*
+                 * @AroundConstruct can't be on the bean itself per spec
                  * @PostConstruct
                  * @PreDestroy
                  * @AroundInvoke
@@ -2983,6 +2985,16 @@ public class AnnotationDeployer implements 
DynamicDeployer {
                  */
                 processCallbacks(interceptor, annotationFinder);
 
+                /*
+                 * @PAroundConstruct can only be on the interceptor itself
+                 */
+                final boolean override = 
"true".equalsIgnoreCase(getProperty("openejb.callbacks.override", "false"));
+                if (apply(override, interceptor.getAroundConstruct())) {
+                    for (final Annotated<Method> method : 
sortMethods(annotationFinder.findMetaAnnotatedMethods(AroundConstruct.class))) {
+                        interceptor.getAroundConstruct().add(new 
LifecycleCallback(method.get()));
+                    }
+                }
+
                 /*
                  * @ApplicationException
                  */
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java
index 874bca4c9f..3f0e0191c6 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java
@@ -449,6 +449,7 @@ public class EjbJarInfoBuilder {
 
             copyCallbacks(s.getAroundInvoke(), info.aroundInvoke);
 
+            copyCallbacks(s.getAroundConstruct(), info.aroundConstruct);
             copyCallbacks(s.getPostConstruct(), info.postConstruct);
             copyCallbacks(s.getPreDestroy(), info.preDestroy);
 
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/core/Operation.java 
b/container/openejb-core/src/main/java/org/apache/openejb/core/Operation.java
index 023023946a..ce0dd9199f 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/core/Operation.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/core/Operation.java
@@ -19,6 +19,7 @@ package org.apache.openejb.core;
 
 public enum Operation {
     INJECTION(true),
+    AROUND_CONSTRUCT(true),
     POST_CONSTRUCT(true),
     BUSINESS(false),
     BUSINESS_WS(false),
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorData.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorData.java
index a7836d8c32..35d73595e6 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorData.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/core/interceptor/InterceptorData.java
@@ -17,11 +17,6 @@
 
 package org.apache.openejb.core.interceptor;
 
-import org.apache.openejb.core.Operation;
-import org.apache.openejb.util.SetAccessible;
-import org.apache.webbeans.component.CdiInterceptorBean;
-import org.apache.xbean.finder.ClassFinder;
-
 import jakarta.annotation.PostConstruct;
 import jakarta.annotation.PreDestroy;
 import jakarta.ejb.AfterBegin;
@@ -30,8 +25,14 @@ import jakarta.ejb.BeforeCompletion;
 import jakarta.ejb.PostActivate;
 import jakarta.ejb.PrePassivate;
 import jakarta.enterprise.inject.spi.InterceptionType;
+import jakarta.interceptor.AroundConstruct;
 import jakarta.interceptor.AroundInvoke;
 import jakarta.interceptor.AroundTimeout;
+import org.apache.openejb.core.Operation;
+import org.apache.openejb.util.SetAccessible;
+import org.apache.webbeans.component.CdiInterceptorBean;
+import org.apache.xbean.finder.ClassFinder;
+
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.util.Collections;
@@ -56,6 +57,7 @@ public class InterceptorData {
 
     private final Set<Method> aroundInvoke = new LinkedHashSet<>();
 
+    private final Set<Method> aroundConstruct = new LinkedHashSet<>();
     private final Set<Method> postConstruct = new LinkedHashSet<>();
     private final Set<Method> preDestroy = new LinkedHashSet<>();
 
@@ -113,6 +115,11 @@ public class InterceptorData {
         return postConstruct;
     }
 
+    // TODO should it return a set of Constructor instead
+    public Set<Method> getAroundConstruct() {
+        return aroundConstruct;
+    }
+
     public Set<Method> getPreDestroy() {
         return preDestroy;
     }
@@ -149,6 +156,8 @@ public class InterceptorData {
                 return getAroundInvoke();
             case REMOVE:
                 return getAroundInvoke();
+            case AROUND_CONSTRUCT:
+                return getAroundConstruct();
             case POST_CONSTRUCT:
                 return getPostConstruct();
             case PRE_DESTROY:
@@ -199,6 +208,7 @@ public class InterceptorData {
         if (model != null) {
             final InterceptorData data = new InterceptorData(clazz);
             data.aroundInvoke.addAll(model.getAroundInvoke());
+            data.aroundConstruct.addAll(model.getAroundConstruct());
             data.postConstruct.addAll(model.getPostConstruct());
             data.preDestroy.addAll(model.getPreDestroy());
             data.postActivate.addAll(model.getPostActivate());
@@ -214,6 +224,7 @@ public class InterceptorData {
         final InterceptorData data = new InterceptorData(clazz);
 
         add(finder, data.aroundInvoke, AroundInvoke.class);
+        add(finder, data.aroundConstruct, AroundConstruct.class);
         add(finder, data.postConstruct, PostConstruct.class);
         add(finder, data.preDestroy, PreDestroy.class);
         add(finder, data.postActivate, PostActivate.class);
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/monitoring/StatsInterceptor.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/monitoring/StatsInterceptor.java
index ec6654a8c7..83107c7d11 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/monitoring/StatsInterceptor.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/monitoring/StatsInterceptor.java
@@ -17,6 +17,7 @@
 
 package org.apache.openejb.monitoring;
 
+import jakarta.interceptor.AroundConstruct;
 import org.apache.openejb.api.Monitor;
 import org.apache.openejb.core.interceptor.InterceptorData;
 import org.apache.openejb.loader.SystemInstance;
@@ -102,6 +103,19 @@ public class StatsInterceptor {
         return record(invocationContext, null);
     }
 
+    public Method AroundConstruct() throws NoSuchMethodException {
+        return this.getClass().getMethod("AroundConstruct");
+    }
+
+    @AroundConstruct
+    public void AroundConstruct(final InvocationContext invocationContext) 
throws Exception {
+        final long start = System.nanoTime();
+        record(invocationContext, AroundConstruct());
+        final long end = System.nanoTime();
+        Logger.getInstance(LogCategory.MONITORING, 
"org.apache.openejb.monitoring")
+              .debug("instance.creating", 
invocationContext.getTarget().getClass().getName(), end - start);
+    }
+
     public Method PostConstruct() throws NoSuchMethodException {
         return this.getClass().getMethod("PostConstruct");
     }
diff --git 
a/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulInterceptorTest.java
 
b/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulInterceptorTest.java
index 0def17e59d..01c0a8210e 100644
--- 
a/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulInterceptorTest.java
+++ 
b/container/openejb-core/src/test/java/org/apache/openejb/core/stateful/StatefulInterceptorTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.openejb.core.stateful;
 
+import jakarta.interceptor.AroundConstruct;
 import junit.framework.TestCase;
 import org.apache.openejb.OpenEJB;
 import org.apache.openejb.assembler.classic.Assembler;
@@ -76,6 +77,7 @@ public class StatefulInterceptorTest extends TestCase {
 
         assertEquals(3, ejbJar.interceptors.size());
         assertEquals(1, ejbJar.interceptors.get(0).aroundInvoke.size());
+        assertEquals(1, ejbJar.interceptors.get(0).aroundConstruct.size());
         assertEquals(1, ejbJar.interceptors.get(0).postConstruct.size());
 
         assertEquals(3, ejbJar.interceptorBindings.size());
@@ -117,7 +119,13 @@ public class StatefulInterceptorTest extends TestCase {
         assertEquals(join("\n", expected), join("\n", calls));
     }
 
-    public static enum Call {
+    public enum Call {
+        Default_AroundConstruct_BEFORE,
+        Class_AroundConstruct_BEFORE,
+        Bean_AroundConstruct,
+        Class_AroundConstruct_AFTER,
+        Default_AroundConstruct_AFTER,
+
         Default_PostConstruct_BEFORE,
         Class_PostConstruct_BEFORE,
         Bean_PostConstruct,
@@ -161,6 +169,10 @@ public class StatefulInterceptorTest extends TestCase {
 
     public static class TargetBean implements Target {
 
+        public TargetBean() {
+            calls.add(Call.Bean_AroundConstruct);
+        }
+
         @PostConstruct
         public void construct() {
             calls.add(Call.Bean_PostConstruct);
@@ -232,6 +244,14 @@ public class StatefulInterceptorTest extends TestCase {
             calls.add(Call.Class_PostConstruct_AFTER);
         }
 
+        @AroundConstruct
+        public void aroundConstruct(final InvocationContext context) throws 
Exception {
+            calls.add(Call.Class_AroundConstruct_BEFORE);
+            context.proceed();
+            calls.add(Call.Class_AroundConstruct_AFTER);
+        }
+
+
         @AroundInvoke
         public Object invoke(final InvocationContext context) throws Exception 
{
             calls.add(Call.Class_Invoke_BEFORE);
@@ -250,6 +270,13 @@ public class StatefulInterceptorTest extends TestCase {
             calls.add(Call.Default_PostConstruct_AFTER);
         }
 
+        @AroundConstruct
+        public void aroundConstruct(final InvocationContext context) throws 
Exception {
+            calls.add(Call.Default_AroundConstruct_BEFORE);
+            context.proceed();
+            calls.add(Call.Default_AroundConstruct_AFTER);
+        }
+
         @AroundInvoke
         public Object invoke(final InvocationContext context) throws Exception 
{
             calls.add(Call.Default_Invoke_BEFORE);
diff --git 
a/container/openejb-jee/src/main/java/org/apache/openejb/jee/Interceptor.java 
b/container/openejb-jee/src/main/java/org/apache/openejb/jee/Interceptor.java
index 7fa68f3218..506ee5b745 100644
--- 
a/container/openejb-jee/src/main/java/org/apache/openejb/jee/Interceptor.java
+++ 
b/container/openejb-jee/src/main/java/org/apache/openejb/jee/Interceptor.java
@@ -118,6 +118,8 @@ public class Interceptor implements JndiConsumer, Session {
     protected KeyedCollection<String, JMSConnectionFactory> 
jmsConnectionFactories;
     @XmlElement(name = "jms-destination")
     protected KeyedCollection<String, JMSDestination> jmsDestinations;
+    @XmlElement(name = "around-construct", required = true)
+    protected List<LifecycleCallback> aroundConstruct;
     @XmlElement(name = "post-construct", required = true)
     protected List<LifecycleCallback> postConstruct;
     @XmlElement(name = "pre-destroy", required = true)
@@ -337,6 +339,13 @@ public class Interceptor implements JndiConsumer, Session {
         return this.dataSource.toMap();
     }
 
+    public List<LifecycleCallback> getAroundConstruct() {
+        if (aroundConstruct == null) {
+            aroundConstruct = new ArrayList<LifecycleCallback>();
+        }
+        return this.aroundConstruct;
+    }
+
     public List<LifecycleCallback> getPostConstruct() {
         if (postConstruct == null) {
             postConstruct = new ArrayList<LifecycleCallback>();

Reply via email to