Kabir Khan [
http://community.jboss.org/people/kabir.khan%40jboss.com] created the
discussion
"Weld - pull from MC"
To view the discussion, visit:
http://community.jboss.org/message/549944#549944
--------------------------------------------------------------
I have experimented with an alternate implementation of the weld-mc integration as
discussed in Boston. I still need to write more tests but wanted to let the Weld guys know
where I am at.
The idea is to "pull" data from the MC in special cases, which is different from
the "push" we do at the moment for MC beans annotated with @WeldEnabled. I had a
look at using the InjectionServices interface, but this has the following problems:
-It does not get triggered when calling constructors
-If using a separate @McInject annotation instead of @Inject to do injection the annotated
field does not appear in invocation context's injection points meaning all the fields
etc. need to be parsed from invocation context's target's class (I am not sure if
the target will always be non-null?)
-If using the @Inject annotation with an additional @Mc annotation (to look up the
particular injection point in the MC) falls over when calling proceed(), also again a
problem is that you need to iterate over all fields etc. to look for the members. This
also fails in the validation phase.
As mentioned the ability to do this injection from MC is something that most Weld
applications would not want to do. What I have locally now is an extra service that can
handle this:
package org.jboss.temp.weld.spi;
import java.lang.annotation.Annotation;
import java.util.Iterator;
import org.jboss.weld.bootstrap.api.Service;
public interface ExternalLookupRegistryService extends Service
{
Iterable<ExternalLookup<?>> getExternalLookups();
void addExternalLookup(ExternalLookup<?> externalLookup);
boolean removeExternalLookup(Class<? extends Annotation> clazz);
}
And then a service to handle particular annotations
package org.jboss.temp.weld.spi;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Set;
public interface ExternalLookup<T extends Annotation>
{
Class<T> getAnnotation();
boolean isValid(Type type, Set<Annotation> qualifiers);
Object lookupValue(Type type, Set<Annotation> qualifiers);
}
I'm hoping to be able to push these interfaces into the main spi, the temp location I
am using is just while playing.
Then I have modified the Validator and Field-/ParameterInjectionPoint to look for this
service when validating/injecting:
[kabir ~/sourcecontrol/weld/core/subversion]
$svn diff impl/src/main/java/org/jboss/weld/bootstrap/Validator.java
Index: impl/src/main/java/org/jboss/weld/bootstrap/Validator.java
===================================================================
--- impl/src/main/java/org/jboss/weld/bootstrap/Validator.java (revision 6577)
+++ impl/src/main/java/org/jboss/weld/bootstrap/Validator.java (working copy)
@@ -83,6 +83,8 @@
import javax.inject.Scope;
import org.jboss.interceptor.model.InterceptionModel;
+import org.jboss.temp.weld.spi.ExternalLookup;
+import org.jboss.temp.weld.spi.ExternalLookupRegistryService;
import org.jboss.weld.bean.AbstractClassBean;
import org.jboss.weld.bean.AbstractProducerBean;
import org.jboss.weld.bean.DisposalMethod;
@@ -288,6 +290,16 @@
Set<?> resolvedBeans =
beanManager.getBeanResolver().resolve(beanManager.getBeans(ij));
if (!isInjectionPointSatisfied(ij, resolvedBeans, beanManager))
{
+ ExternalLookupRegistryService service =
beanManager.getServices().get(ExternalLookupRegistryService.class);
+ if (service != null)
+ {
+ for (ExternalLookup<?> lookup : service.getExternalLookups())
+ {
+ if (ij.getAnnotated().isAnnotationPresent(lookup.getAnnotation()))
+ if (lookup.isValid(ij.getType(), ij.getQualifiers()))
+ return;
+ }
+ }
throw new DeploymentException(INJECTION_POINT_HAS_UNSATISFIED_DEPENDENCIES, ij,
Arrays.toString(bindings));
}
if (resolvedBeans.size() > 1 && !ij.isDelegate())
[kabir ~/sourcecontrol/weld/core/subversion]
$svn diff impl/src/main/java/org/jboss/weld/injection/
Index: impl/src/main/java/org/jboss/weld/injection/FieldInjectionPoint.java
===================================================================
--- impl/src/main/java/org/jboss/weld/injection/FieldInjectionPoint.java (revision
6577)
+++ impl/src/main/java/org/jboss/weld/injection/FieldInjectionPoint.java (working
copy)
@@ -36,6 +36,8 @@
import javax.inject.Inject;
import org.jboss.interceptor.util.InterceptionUtils;
+import org.jboss.temp.weld.spi.ExternalLookup;
+import org.jboss.temp.weld.spi.ExternalLookupRegistryService;
import org.jboss.weld.exceptions.IllegalStateException;
import org.jboss.weld.exceptions.InvalidObjectException;
import org.jboss.weld.introspector.ForwardingWeldField;
@@ -114,7 +116,23 @@
// if declaringInstance is a proxy, unwrap it
instanceToInject = InterceptionUtils.getRawInstance(declaringInstance);
}
- delegate().set(instanceToInject, manager.getInjectableReference(this,
creationalContext));
+
+ Object value = null;
+ ExternalLookupRegistryService service =
manager.getServices().get(ExternalLookupRegistryService.class);
+ if (service != null)
+ {
+ for (ExternalLookup<?> lookup : service.getExternalLookups())
+ {
+ if (getAnnotation(lookup.getAnnotation()) != null)
+ value = lookup.lookupValue(getBaseType(), getQualifiers());
+ }
+ }
+
+ if (value == null)
+ value = manager.getInjectableReference(this, creationalContext);
+
+
+ delegate().set(instanceToInject, value);
}
catch (IllegalArgumentException e)
{
Index: impl/src/main/java/org/jboss/weld/injection/ParameterInjectionPoint.java
===================================================================
---
impl/src/main/java/org/jboss/weld/injection/ParameterInjectionPoint.java (revision
6577)
+++ impl/src/main/java/org/jboss/weld/injection/ParameterInjectionPoint.java (working
copy)
@@ -35,6 +35,8 @@
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.Decorator;
+import org.jboss.temp.weld.spi.ExternalLookup;
+import org.jboss.temp.weld.spi.ExternalLookupRegistryService;
import org.jboss.weld.exceptions.IllegalStateException;
import org.jboss.weld.exceptions.InvalidObjectException;
import org.jboss.weld.exceptions.UnsupportedOperationException;
@@ -119,6 +121,15 @@
@SuppressWarnings("unchecked")
public T getValueToInject(BeanManagerImpl manager, CreationalContext<?>
creationalContext)
{
+ ExternalLookupRegistryService service =
manager.getServices().get(ExternalLookupRegistryService.class);
+ if (service != null)
+ {
+ for (ExternalLookup<?> lookup : service.getExternalLookups())
+ {
+ if (getAnnotation(lookup.getAnnotation()) != null)
+ return (T)lookup.lookupValue(getBaseType(), getQualifiers());
+ }
+ }
return (T) manager.getInjectableReference(this, creationalContext);
}
In my test I have this implementation of the service classes
public class TestExternalLookup implements ExternalLookup<External>
{
@Override
public boolean isValid(Type type, Set<Annotation> qualifiers)
{
if (type == Bar.class)
return true;
return false;
}
@Override
public Class<External> getAnnotation()
{
return External.class;
}
@Override
public Object lookupValue(Type type, Set<Annotation> qualifiers)
{
if (type == Bar.class)
return new BarImpl();
return null;
}
}
public class TestExternalLookupRegistryService implements ExternalLookupRegistryService
{
private Map<Class<? extends Annotation>, ExternalLookup<?>> lookups =
Collections.synchronizedMap(new HashMap<Class<? extends Annotation>,
ExternalLookup<?>>());
public void addExternalLookup(ExternalLookup<?> externalLookup)
{
lookups.put(externalLookup.getAnnotation(), externalLookup);
}
public Iterable<ExternalLookup<?>> getExternalLookups()
{
synchronized (lookups)
{
return new HashSet<ExternalLookup<?>>(lookups.values());
}
}
public boolean removeExternalLookup(Class<? extends Annotation> clazz)
{
return lookups.remove(clazz) != null;
}
public void cleanup()
{
lookups.clear();
}
}
I register this service with the deployment and add the TestExternalLookup to it, meaning
that when I create an instance of ExternalConstructorInjected the constructor parameter is
found in TestExternalLookup.
public class ExternalConstructorInjected
{
Bar bar;
@Inject
public ExternalConstructorInjected(@External Bar bar)
{
this.bar = bar;
}
}
I think Pete is on vacation, so after adding a few more tests I'll add this to a
branch somewhere so that it can be included once he okays it.
--------------------------------------------------------------
Reply to this message by going to Community
[
http://community.jboss.org/message/549944#549944]
Start a new discussion in JBoss Microcontainer Development at Community
[
http://community.jboss.org/choose-container!input.jspa?contentType=1&...]