Having class like so:
public class A {
#Inject B b;
#Inject C c;
}
is it possible to tell Weld NOT to inject into c? I can veto A class using event:
<T> void processAnnotatedType(#Observes ProcessAnnotatedType<T> pat)
but then also B object would not be injected. I am searching for sth like: "if class name is A and field type is C then omit injection."
To be more specific I want HK2 engine to inject into the "C" field and the problem is that HK2 and Weld are both using #Inject annotation.
Siliarus solution:
I gave a try to Siliarus solution. I found the type that I want add my custom injection implementation to like:
<T> void processIT(#Observes ProcessInjectionTarget<T> pat, BeanManager beanManager) {
Set<InjectionPoint> injectionPoints = pat.getInjectionTarget().getInjectionPoints();
for (InjectionPoint injectionPoint : injectionPoints) {
if (injectionPoint.getType().equals(B.class)) {
l.info("Adding CustomInjection to {}", pat.getAnnotatedType().getJavaClass());
pat.setInjectionTarget(new CustomInjection<T>(pat.getInjectionTarget(), beanManager));
}
}
}
}
}
and after I added overrided inject(...) in CustomInjection
public CustomInjection(InjectionTarget<T> originalInjectionTarget, BeanManager beanManager) {
this.wrappedInjectionTarget = originalInjectionTarget;
this.beanManager = beanManager;
}
like:
#Override
public void inject(T instance, CreationalContext<T> ctx) {
l.trace("Injecting into {}", instance);
//....create my own HK2 object. Can it be just new B() for example ?!
locator =ServiceLocatorUtilities.createAndPopulateServiceLocator();
B b = locator.createAndInitialize(B.class);
l.trace("First injecting standard dependencies {}", instance);
wrappedInjectionTarget.inject(instance, ctx);
// dispose created by CDI B type object ?! - seems messy but works
manageBViaReflection((x, y, z) -> x.set(y, z), instance, b);
}
In manageBViaReflection I just set the object B - b to field X of type B and name b on instance Y - instance.
The delicate inaccuracy is that line:
wrappedInjectionTarget.inject(instance, ctx);
performs and CDI injection on B. I have producer to type B but I want to create it on my own in this particular class - not using a producer. Object B must be disposed and when I override its value using manageBViaReflection then I must dispose it first - its a bit messy but generally that idea works.
Siliarus, jwells131313 - maybe U have any further suggestions ?
Alright, from Weld/CDI point of view, here is how to disable injection into those fields. Note that I don't know HK2 so I don't know how you then want to link it there, but from CDI perspective you need to have the bean as #Dependent (to avoid proxying where things would get nastier). You haven't specified the version for CDI, so I'll make notes for both, 1.x and 2.0.
Actually what comes to me are two things, first, its the ProcessAnnotatedType phase, where you could remove the #Inject annotation so that when CDI takes that annotated type (which it turns into bean), it will no longer see it as injection point. You would do that as follows:
void processAnnotatedType(#Observes ProcessAnnotatedType<T> pat) {
pat.configureAnnotatedType().remove(Inject.class); // CDI 2.0 solution
// for CDI 1.x you need to implement your own AT, which
// will do just the same, the call this:
// pat.setAnnotatedType(yourOwnAT);
}
Second though takes into consideration ProcessInjectionTarget. You would need to wrap InjectionTarget with your own implementation. The strength of this approach is that you can hook HK2 internals here directly. The main idea is to override javax.enterprise.inject.spi.InjectionTarget.inject(T, CreationalContext<T>) and put the HK2 code here, so when CDI actually tries to make injection, it would use HK2.
void processIT(#Observes ProcessInjectionTarget<T> pat) {
pat.setInjectionTarget(myITImpl); // just set your wrapped impl here
// there is no diff here in CDI 1.x and 2.0, no configurator here
}
Whichever way you choose, bear in mind that CDI has a nice huge set of TCK tests which cover all this stuff and hence can be used as an example to see how to implement such wrapper.
Related
As the title suggests , I want to know how does field injection internally works in spring , I read many articles on this and got to know few things like below but didn't understood the exact reason behind it :
-> It should not be used because when you do unit testing then you are dependent upon the spring
container to instantiate the class in case of field injection.
-> You cannot use "final" keyword in case of field injection , means you cannot make the field immutable.
-> It internally uses reflection
I want to know how exactly does #Autowired works internally , how does it uses reflection , I am trying to understand the exact reason behind all the above mentioned points, what happens behind the scenes when we write the below code :
#Component
public class B {
#Autowired
private A a1;
}
I have read similar questions on stack overflow about this topic , but I couldn't find the exact explanation that I am looking.
Spring has a concept of Bean Post Processors.
When spring builds a bean it applies registered bean post processors that help to "initialize" the bean.
So, there is org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor that handles autowiring.
Basically it works with an newly created object. Spring introspects the fields of the beans (by using reflection). The fields that have #Autowired is a subject for processing with this bean post processor. It finds the candidate for injection in the application context and actually injects the value.
Now given this information, its understandable why final fields cannot be autowired. Leave alone spring, In pure Java, final fields must be instantiated directly right during the declaration (final int i = 123) or in the constructor of the class. But the autowiring happens after constructor, so its impossible to autowire the final fields.
As for the unit testing, the private properties must be somehow configured from the test. But since they're encapsulated (yes, spring kind of breaks encapsulation in this case for its usage), its impossible to write a good test for the class that contains fields injection. That's is a reason to switch to constructor injection.
public class FieldInjection {
#Autowired
private A a;
}
VS.
public class ConstructorInjection {
private final A a;
// this can be generated by lombok, you don't have to put #Autowired on constructor in the case of single constructor, spring will use it to create a bean
public ConstructorInjection(A a) {
this.a = a;
}
}
Now the test for FieldInjection class is impossible:
public class FieldInjectionTest {
#Test
void test() {
FieldInjection underTest = new FieldInjection();
how do you know that you should instantiate A a. ????
}
}
However in the case of constructor injection its a trivial task:
public class ConstructorInjectionTest {
#Test
void test() {
A a = mock(A.class);
ConstructorInjection underTest = new ConstructorInjection(a);
// the dependencies must be supplied in the constructor
// otherwise its impossible to create an object under test
}
}
I have a situation where when I initialize some of my classes, some of the fields I need to be injected (e.g. references to factories etc) whereas some others are dynamic and created at runtime (e.g. usernames etc). How do I construct such objects using the GUICE framework?
Simply annotating the fields I need injected as #Inject doesn't work as they seem to not be set up when creating an object using the constructor. For instance:
class C {
#Inject
private FactoryClass toBeInjected;
private ConfigurationField passedIn;
public C(ConfigurationField passedIn) {
this.passedIn = passedIn;
}
}
If my understanding is correct (and I could be wrong), the fact that I'm creating a new instance of C via new and not through Guice means that no injection will take place. I do need to pass these parameters in the constructor, but also want some fields injected -- so how do I solve this problem?
A feature specifically matching "mixing injection and parameters passed" would be Assisted Injection.
class C {
// Guice will automatically create an implementation of this interface.
// This can be defined anywhere, but I like putting it in the class itself.
interface Factory {
C create(ConfigurationField passedIn);
}
#Inject
private FactoryClass toBeInjected;
private ConfigurationField passedIn;
private SomeOtherDepIfYoudLike otherDep;
#Inject public C(#Assisted ConfigurationField passedIn,
SomeOtherDepIfYoudLike otherDep) {
this.passedIn = passedIn;
this.otherDep = otherDep;
}
}
Now in your module:
#Override public void configure() {
install(new FactoryModuleBuilder().build(C.Factory.class));
}
Now when someone wants to create a C, they can avoid calling the constructor directly; instead, they inject a C.Factory into which they pass a ConfigurationField instance of their choice and receive a fully-constructed, fully-injected C instance. (Like with most well-designed DI objects, they can call the constructor directly.)
Note that this design is especially useful in a few ways:
You can use constructor injection, treat all your fields as final, and treat the object as immutable.
If you stick with constructor injection entirely, your object will never be in a partially-initialized state, and your API stays simple (call the constructor and your object is ready).
For testing, you can write any implementation of C.Factory and have it return any instance you want. This can include test doubles of C or its factory: Fakes, mocks, or spies that you create manually or by using Mockito, EasyMock, JMock, or any other mocking framework.
What you are looking for is "On Demand" Injections:
public static void main(String[] args)
{
Injector injector = Guice.createInjector(...);
CreditCardProcessor creditCardProcessor = new PayPalCreditCardProcessor();
injector.injectMembers(creditCardProcessor);
}
or for static things
#Override public void configure() {
requestStaticInjection(ProcessorFactory.class);
...
}
All explained very well https://github.com/google/guice/wiki/Injections#on-demand-injection.
Note:
Both of these things are code smells and should only really be used
for migrating old code over to Guice. New code should not use these
approaches.
I have a class B which implements W interface. It has a default implementation of W's method. class C and D override default implementation for which they need a service whose bean is instantiated by spring. String a and b comes from user and hence there is no way I can create a bean of B/C/D in advance. So I have a factory which creates a new object based on user parameters (it will create B/C/D based on parameters). Is there any clean way I can use service beans(aa/bb/cc/dd etc.) from inside C and D (spring autowires during server startup, at that time parameter required for instantiating B/C/D are not available) or is there any better way to solve the problem ?
Class B implements W{
String a;
String b;
B (String a, String b);
w_method(){
}
}
Class C extends B {
#Autowired
Service aa;
#Autowired
Service bb;
#Autowired
Service cc;
#override
w_method(){
}
}
Class D extends B {
#Autowired
Service dd;
#override
w_method(){
}
}
There are three possible approaches:
The fact that constructor arguments come from user doesn't mean that these objects cannot be created by Spring.
You can declare them as Spring beans of scope prototype and do the following in your factory:
public C createC(String a, String b) {
return applicationContext.getBean("c", a, b);
}
A disadvantage of this method is that your factory depends on ApplicationContext.
You can annotate these classes with #Configurable and enable AspectJ weaving. In this case Spring will configure objects of these classes even if you create them with new. See 7.8.1 Using AspectJ to dependency inject domain objects with Spring.
You can trigger autowiring manually as
applicationContext.getAutowireCapableBeanFactory().autowireBean(...);
This approach is useful when you don't have control over creation of objects that you need to autowire (servlets, etc).
I think the simplest method would be to wire the services into the factory and call setters on the B / C / D objects before you return them, rather than attempting to use #Autowired.
Or use axtavt's constructor argument method. If you want to avoid depending on ApplicationContext, you can use Lookup Method Injection, but you'll have to patch Spring per this blog post: http://nurkiewicz.blogspot.co.uk/2010/08/creating-prototype-spring-beans-on.html
I have a Spring bean, let's say:
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class AImpl implements A {
public void setSomeDependency(D dependency) {
// This setter DOES NOT BELONG to interface A
}
}
<bean id="aImpl" class="AImpl"/>
Now I want to integration test it, but first I need to mock the dependency D, because it does too much stuff. Since the AImpl implements an interface and contains a transactional annotation, the generated proxy is only compatible with the interface A, so I can do this:
#Inject #Named("aImpl")
private A a;
but cannot:
#Inject #Named("aImpl")
private AImpl a;
As a result, I can't mock my dependency.
Please note that adding void setSomeDependency(D dependency) to interface A is not an option, as it has no business meaning. Neither it is using the proxy-target-class="true", as it breaks a whole lot of other beans (this attribute affects all beans in the context).
Is there a way to unproxy the injected bean A, so I could cast it to AImpl?
Try this:
if(AopUtils.isAopProxy(a) && a instanceof Advised) {
Object target = ((Advised)a).getTargetSource().getTarget();
AImpl ai = (AImpl)target;
}
Bonus: in Scala I am using the following equivalent function for the very same purpose:
def unwrapProxy(a: AnyRef) = a match {
case advised: Advised if(AopUtils.isAopProxy(advised)) =>
advised.getTargetSource.getTarget
case notProxy => notProxy
}
With the introduction of Spring 4.2.RC1, there is now a dedicated utility class in the spring-test module that handles this case for you.
The class is called AopTestUtils and provides the methods:
getTargetObject (unwraps only the top-level proxy)
getUltimateTargetObject (unwraps multiple levels of proxies if they exist).
Check out the relevant commit as well as the respective issue.
Suppose that I have two classes, first a class without any properties, fields or annotations:
public class B {}
And a class which gets B injected, like this:
public class A {
#Inject
private B b;
public B getB() {
return b;
}
}
Now class A is pretty useless until we use it, so there are two options:
#Inject it
Construct it manually, using the trusty "new A()"
If A gets injected, CDI manages it and is kind enough to inject B which has the implicit scope of #Dependent. Cool, just what I want.
However, if I manually construct A (let's say in a factory or a builder), CDI completely ignores my object and won't inject an object of type B.
Example I'm talking about when it doesn't work, here object a will always remain null:
public class Builder {
#Inject
private A a;
public static Builder ofTypeSomething() {
// do some magic here
return new Builder();
}
private Builder() {
// and some more here
}
}
Why doesn't this work?
Class A is a valid managed bean and has a valid scope, just like class B. Even if I add #Producer to the static method, it won't change anything (which is fine, cause the idea of the static method is to call it, not to inject Builder anywhere).
Dependency injection, while useful, is not magical. The way DI works is that when you ask the container for an instance of an object the container first constructs it (via new()) and then sets the dependencies (how this happens depends on your framework).
If you construct the entity yourself then the container has no idea you've constructed the entity and can't set the dependencies of the entity.
If you want to use a factory then most frameworks have some way of configuring the entity so that the container knows to make a static factory method call and not call the constructor of the entity. However, you still have to obtain your entity from the container.
Edit: This site seems to demonstrate how to use a factory in CDI.