Skip to content

Commit

Permalink
Arc - fix InvocationContext parameters for around construct intercept…
Browse files Browse the repository at this point in the history
…ors when there are other interceptors in play
  • Loading branch information
manovotn committed Nov 23, 2022
1 parent de814ab commit d5ec1f2
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -956,14 +956,15 @@ protected void implementCreate(ClassOutput classOutput, ClassCreator beanCreator
bridgeCreate.getMethodParam(0)));
}

private List<ResultHandle> newProviderHandles(BeanInfo bean, ClassCreator beanCreator, MethodCreator createMethod,
private void newProviderHandles(BeanInfo bean, ClassCreator beanCreator, MethodCreator createMethod,
Map<InjectionPointInfo, String> injectionPointToProviderField,
Map<InterceptorInfo, String> interceptorToProviderField,
Map<DecoratorInfo, String> decoratorToProviderSupplierField,
Map<InterceptorInfo, ResultHandle> interceptorToWrap,
List<TransientReference> transientReferences) {
List<TransientReference> transientReferences,
List<ResultHandle> injectableParamHandles,
List<ResultHandle> allOtherParamHandles) {

List<ResultHandle> providerHandles = new ArrayList<>();
Optional<Injection> constructorInjection = bean.getConstructorInjection();

if (constructorInjection.isPresent()) {
Expand All @@ -978,7 +979,7 @@ private List<ResultHandle> newProviderHandles(BeanInfo bean, ClassCreator beanCr
providerHandle, createMethod.getMethodParam(0));
ResultHandle referenceHandle = createMethod.invokeInterfaceMethod(MethodDescriptors.INJECTABLE_REF_PROVIDER_GET,
providerHandle, childCtx);
providerHandles.add(referenceHandle);
injectableParamHandles.add(referenceHandle);
if (injectionPoint.isDependentTransientReference()) {
transientReferences.add(new TransientReference(providerHandle, referenceHandle, childCtx));
}
Expand All @@ -988,15 +989,15 @@ private List<ResultHandle> newProviderHandles(BeanInfo bean, ClassCreator beanCr
for (InterceptorInfo interceptor : bean.getBoundInterceptors()) {
ResultHandle wrapped = interceptorToWrap.get(interceptor);
if (wrapped != null) {
providerHandles.add(wrapped);
allOtherParamHandles.add(wrapped);
} else {
ResultHandle interceptorProviderSupplierHandle = createMethod.readInstanceField(
FieldDescriptor.of(beanCreator.getClassName(), interceptorToProviderField.get(interceptor),
Supplier.class),
createMethod.getThis());
ResultHandle interceptorProviderHandle = createMethod.invokeInterfaceMethod(
MethodDescriptors.SUPPLIER_GET, interceptorProviderSupplierHandle);
providerHandles.add(interceptorProviderHandle);
allOtherParamHandles.add(interceptorProviderHandle);
}
}
for (DecoratorInfo decorator : bean.getBoundDecorators()) {
Expand All @@ -1006,10 +1007,9 @@ private List<ResultHandle> newProviderHandles(BeanInfo bean, ClassCreator beanCr
createMethod.getThis());
ResultHandle decoratorProviderHandle = createMethod.invokeInterfaceMethod(
MethodDescriptors.SUPPLIER_GET, decoratorProviderSupplierHandle);
providerHandles.add(decoratorProviderHandle);
allOtherParamHandles.add(decoratorProviderHandle);
}
}
return providerHandles;
}

private ResultHandle newInstanceHandle(BeanInfo bean, ClassCreator beanCreator, BytecodeCreator creator,
Expand Down Expand Up @@ -1402,14 +1402,20 @@ void implementCreateForClassBean(ClassOutput classOutput, ClassCreator beanCreat
}

List<TransientReference> transientReferences = new ArrayList<>();
List<ResultHandle> providerHandles = newProviderHandles(bean, beanCreator, create,
// List of handles representing injectable parameters
List<ResultHandle> injectableCtorParams = new ArrayList<>();
// list of handles representing all other parameters, such as injectable interceptors
List<ResultHandle> allOtherCtorParams = new ArrayList<>();
newProviderHandles(bean, beanCreator, create,
injectionPointToProviderSupplierField, interceptorToProviderSupplierField, decoratorToProviderSupplierField,
interceptorToWrap, transientReferences);
interceptorToWrap, transientReferences, injectableCtorParams, allOtherCtorParams);

// Forwarding function
// Supplier<Object> forward = () -> new SimpleBean_Subclass(ctx,lifecycleInterceptorProvider1)
FunctionCreator func = create.createFunction(Supplier.class);
BytecodeCreator funcBytecode = func.getBytecode();
List<ResultHandle> providerHandles = new ArrayList<>(injectableCtorParams);
providerHandles.addAll(allOtherCtorParams);
ResultHandle retHandle = newInstanceHandle(bean, beanCreator, funcBytecode, create, providerType.className(),
baseName,
providerHandles,
Expand All @@ -1427,11 +1433,10 @@ void implementCreateForClassBean(ClassOutput classOutput, ClassCreator beanCreat
create.writeArrayValue(bindingsArray, bindingsIndex++,
annotationLiterals.create(create, bindingClass, binding));
}

// ResultHandle of Object[] holding all constructor args
ResultHandle ctorArgsArray = create.newArray(Object.class, create.load(providerHandles.size()));
for (int i = 0; i < providerHandles.size(); i++) {
create.writeArrayValue(ctorArgsArray, i, providerHandles.get(i));
ResultHandle ctorArgsArray = create.newArray(Object.class, create.load(injectableCtorParams.size()));
for (int i = 0; i < injectableCtorParams.size(); i++) {
create.writeArrayValue(ctorArgsArray, i, injectableCtorParams.get(i));
}
ResultHandle invocationContextHandle = create.invokeStaticMethod(
MethodDescriptors.INVOCATION_CONTEXTS_AROUND_CONSTRUCT, constructorHandle,
Expand All @@ -1452,11 +1457,13 @@ void implementCreateForClassBean(ClassOutput classOutput, ClassCreator beanCreat

} else {
List<TransientReference> transientReferences = new ArrayList<>();
List<ResultHandle> providerHandles = new ArrayList<>();
newProviderHandles(bean, beanCreator, create, injectionPointToProviderSupplierField,
interceptorToProviderSupplierField, decoratorToProviderSupplierField,
interceptorToWrap, transientReferences, providerHandles, providerHandles);
create.assign(instanceHandle,
newInstanceHandle(bean, beanCreator, create, create, providerType.className(), baseName,
newProviderHandles(bean, beanCreator, create, injectionPointToProviderSupplierField,
interceptorToProviderSupplierField, decoratorToProviderSupplierField,
interceptorToWrap, transientReferences),
providerHandles,
reflectionRegistration, isApplicationClass));
// Destroy injected transient references
destroyTransientReferences(create, transientReferences);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.interceptor.AroundConstruct;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

Expand All @@ -23,7 +24,7 @@ public class AroundConstructTest {

@RegisterExtension
public ArcTestContainer container = new ArcTestContainer(MyTransactional.class, SimpleBean.class,
SimpleInterceptor.class, MyDependency.class);
SimpleInterceptor.class, MyDependency.class, SomeAroundInvokeInterceptor.class);

public static AtomicBoolean INTERCEPTOR_CALLED = new AtomicBoolean(false);

Expand All @@ -43,6 +44,12 @@ static class SimpleBean {

}

// the method has to remain here in order to trigger subclass creation due to at least one around invoke
// intercepted method
public void ping() {

}

}

@Singleton
Expand Down Expand Up @@ -74,4 +81,15 @@ void mySuperCoolAroundConstruct(InvocationContext ctx) throws Exception {
}

}

@MyTransactional
@Interceptor
public static class SomeAroundInvokeInterceptor {

@AroundInvoke
public Object someAroundInvoke(InvocationContext ctx) throws Exception {
return ctx.proceed();
}

}
}

0 comments on commit d5ec1f2

Please sign in to comment.