Skip to content

Commit

Permalink
WFLY-412 Add support for @AroundConstruct
Browse files Browse the repository at this point in the history
  • Loading branch information
jharting committed Jul 4, 2013
1 parent dab91e9 commit a27ddc6
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ private Component() {

public static final class AroundConstruct {

public static final int INTERCEPTOR_AROUND_CONSTRUCT = 0xA00;
public static final int WELD_AROUND_CONSTRUCT_INTERCEPTORS = 0xB00;
public static final int CONSTRUCT_COMPONENT = 0xC00;
public static final int TERMINAL_INTERCEPTOR = 0xD00;
public static final int CONSTRUCTION_START_INTERCEPTOR = 0xA00;
public static final int INTERCEPTOR_AROUND_CONSTRUCT = 0xB00;
public static final int WELD_AROUND_CONSTRUCT_INTERCEPTORS = 0xC00;
public static final int CONSTRUCT_COMPONENT = 0xD00;
public static final int TERMINAL_INTERCEPTOR = 0xE00;

private AroundConstruct() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.jboss.as.ee.component.InterceptorDescription;
import org.jboss.as.ee.component.interceptors.InterceptorOrder;
import org.jboss.as.ee.component.interceptors.UserInterceptorFactory;
import org.jboss.as.ee.weld.WeldDeploymentMarker;
import org.jboss.as.ejb3.component.EJBComponentDescription;
import org.jboss.as.ejb3.component.stateful.SerializedCdiInterceptorsKey;
import org.jboss.as.ejb3.component.stateful.StatefulComponentDescription;
Expand All @@ -46,12 +47,12 @@
import org.jboss.as.server.deployment.reflect.ClassIndex;
import org.jboss.as.server.deployment.reflect.DeploymentClassIndex;
import org.jboss.as.weld.WeldBootstrapService;
import org.jboss.as.ee.weld.WeldDeploymentMarker;
import org.jboss.as.weld.WeldMessages;
import org.jboss.as.weld.WeldStartService;
import org.jboss.as.weld.ejb.EjbRequestScopeActivationInterceptor;
import org.jboss.as.weld.ejb.Jsr299BindingsInterceptor;
import org.jboss.as.weld.injection.WeldComponentService;
import org.jboss.as.weld.injection.WeldConstructionStartInterceptor;
import org.jboss.as.weld.injection.WeldInjectionContextInterceptor;
import org.jboss.as.weld.injection.WeldInjectionInterceptor;
import org.jboss.as.weld.injection.WeldInterceptorInjectionInterceptor;
Expand Down Expand Up @@ -175,6 +176,10 @@ public void configureDependency(final ServiceBuilder<?> serviceBuilder, Componen
builder.addDependency(weldServiceName, WeldBootstrapService.class, postConstruct.getWeldContainer());
configuration.addPostConstructInterceptor(postConstruct, InterceptorOrder.ComponentPostConstruct.CDI_INTERCEPTORS);

final Jsr299BindingsInterceptor.Factory aroundConstruct = new Jsr299BindingsInterceptor.Factory(description.getBeanDeploymentArchiveId(), beanName, InterceptionType.AROUND_CONSTRUCT, classLoader);
builder.addDependency(weldServiceName, WeldBootstrapService.class, aroundConstruct.getWeldContainer());
configuration.addAroundConstructInterceptor(aroundConstruct, InterceptorOrder.AroundConstruct.WELD_AROUND_CONSTRUCT_INTERCEPTORS);

/*
* Add interceptor to activate the request scope for the @PostConstruct callback.
* See https://issues.jboss.org/browse/CDI-219 for details
Expand All @@ -186,6 +191,8 @@ public void configureDependency(final ServiceBuilder<?> serviceBuilder, Componen

builder.install();

configuration.addAroundConstructInterceptor(new ImmediateInterceptorFactory(WeldConstructionStartInterceptor.INSTANCE), InterceptorOrder.AroundConstruct.CONSTRUCTION_START_INTERCEPTOR);

configuration.addPostConstructInterceptor(new ImmediateInterceptorFactory(new WeldInjectionContextInterceptor(weldComponentService)), InterceptorOrder.ComponentPostConstruct.WELD_INJECTION_CONTEXT_INTERCEPTOR);
configuration.addPostConstructInterceptor(new WeldInterceptorInjectionInterceptor.Factory(configuration, interceptorClasses), InterceptorOrder.ComponentPostConstruct.INTERCEPTOR_WELD_INJECTION);
configuration.addPostConstructInterceptor(new WeldInjectionInterceptor.Factory(configuration), InterceptorOrder.ComponentPostConstruct.COMPONENT_WELD_INJECTION);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ public Object processInvocation(final InterceptorContext context) throws Excepti
}
case POST_CONSTRUCT:
return doLifecycleInterception(context);
case AROUND_CONSTRUCT:
return doLifecycleInterception(context);
default:
//should never happen
return context.proceed();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.jboss.as.weld.injection;

import java.util.Map;

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.AnnotatedConstructor;

import org.jboss.invocation.Interceptor;
import org.jboss.invocation.InterceptorContext;
import org.jboss.weld.construction.api.AroundConstructCallback;
import org.jboss.weld.construction.api.ConstructionHandle;
import org.jboss.weld.context.CreationalContextImpl;

/**
* Initiates component construction. This interceptor delegates to Weld to start component construction. When Weld resolves the values of constructor
* parameters, it invokes a callback which allows WF to perform AroundConstruct interception. The callback is registered within
* {@link #setupAroundConstructCallback(CreationalContext, InterceptorContext)}
*
* @author Jozef Hartinger
*
*/
public class WeldConstructionStartInterceptor implements Interceptor {

public static final WeldConstructionStartInterceptor INSTANCE = new WeldConstructionStartInterceptor();

private WeldConstructionStartInterceptor() {
}

@Override
public Object processInvocation(InterceptorContext context) throws Exception {
WeldInjectionContext injectionCtx = context.getPrivateData(WeldInjectionContext.class);
setupAroundConstructCallback(injectionCtx.getContext(), context);
/*
* Here we delegate to Weld to start component construction. WF will be called back on the callback registered within #setupAroundConstructCallback.
* The return value of the following call is not important as we get the component reference from ConstructionContext in WeldManagedReferenceFactory.
*/
injectionCtx.produce();
return context.getTarget();
}

private <T> void setupAroundConstructCallback(CreationalContext<T> ctx, final InterceptorContext context) {
CreationalContextImpl<T> ctxImpl = (CreationalContextImpl<T>) ctx;
ctxImpl.setConstructorInterceptionSuppressed(true); // Weld will not try to invoke around construct interceptors on this instance

ctxImpl.registerAroundConstructCallback(new AroundConstructCallback<T>() {
@SuppressWarnings("unchecked")
@Override
public T aroundConstruct(ConstructionHandle<T> ctx, AnnotatedConstructor<T> constructor, Object[] parameters, Map<String, Object> data) throws Exception {
context.putPrivateData(ConstructionHandle.class, ctx);
context.setParameters(parameters);
context.setContextData(data);
context.setConstructor(constructor.getJavaMember());
context.proceed(); // proceed with the WF interceptor chain
return (T) context.getTarget();
}
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.InjectionTarget;

import org.jboss.as.naming.ManagedReference;
import org.jboss.as.weld.WeldMessages;
import org.jboss.weld.bean.ManagedBean;

Expand Down Expand Up @@ -40,13 +39,11 @@ public void inject(Object instance) {
injectionTarget.inject(instance, context);
}

public WeldManagedReference produce() {
public Object produce() {
if (delegateProduce && bean instanceof ManagedBean) {
final Object instance = ((ManagedBean) bean).getInjectionTarget().produce(context);
return new WeldManagedReference(context, instance);
return ((ManagedBean) bean).getInjectionTarget().produce(context);
} else {
final Object instance = injectionTarget.produce(context);
return new WeldManagedReference(context, instance);
return injectionTarget.produce(context);
}
}

Expand All @@ -70,25 +67,4 @@ public InjectionTarget getInjectionTarget() {
public void release() {
context.release();
}

private static final class WeldManagedReference implements ManagedReference, Serializable {
private final CreationalContext<?> context;
private final Object instance;

private WeldManagedReference(final CreationalContext<?> context, final Object instance) {
this.context = context;
this.instance = instance;
}

@Override
public void release() {
context.release();
}

@Override
public Object getInstance() {
return instance;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@
*/
package org.jboss.as.weld.injection;

import java.io.Serializable;

import javax.enterprise.context.spi.CreationalContext;

import org.jboss.as.ee.component.ComponentFactory;
import org.jboss.as.naming.ManagedReference;
import org.jboss.invocation.InterceptorContext;
import org.jboss.weld.construction.api.ConstructionHandle;

/**
* Managed reference factory that can be used to create and inject components.
Expand All @@ -35,13 +40,33 @@ public class WeldManagedReferenceFactory implements ComponentFactory {
public static final WeldManagedReferenceFactory INSTANCE = new WeldManagedReferenceFactory();

private WeldManagedReferenceFactory() {

}

@Override
public ManagedReference create(final InterceptorContext context) {
WeldInjectionContext injectionContext = context.getPrivateData(WeldInjectionContext.class);
return injectionContext.produce();
ConstructionHandle<?> ctx = context.getPrivateData(ConstructionHandle.class);
CreationalContext<?> injectionCtx = context.getPrivateData(WeldInjectionContext.class).getContext();
Object instance = ctx.proceed(context.getParameters(), context.getContextData()); // let Weld create the instance now
return new WeldManagedReference(injectionCtx, instance);
}

private static final class WeldManagedReference implements ManagedReference, Serializable {
private final CreationalContext<?> context;
private final Object instance;

private WeldManagedReference(final CreationalContext<?> context, final Object instance) {
this.context = context;
this.instance = instance;
}

@Override
public void release() {
context.release();
}

@Override
public Object getInstance() {
return instance;
}
}
}

0 comments on commit a27ddc6

Please sign in to comment.