Is it possible to unproxy a Spring bean? - java

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.

Related

Java Dependency Injection - Annotation based setup possible in scenario?

I'm fiddling around with Dependency Injection in Java using simple JUnit tests and javax.inject-Annotations.
I have the following scenario: There's a "top-level"-class (SomeObject) with two dependencies (SomeObjDepA and SomeObjDepB). SomeObjDepB has a dependency to SomeObjDepA too. And this should be the same instance of SomeObjDepA as in the SomeObject-instance. But SomeObjDepA must not be a Singleton, since different SomeObj-instances shall have different instances of SomeObjDepA (and SomeObjDepB). This is where I am stuck.
To be more clear, here's some basic code without any configuration:
public class SomeObject {
#Inject
private SomeObjDepA someObjDepA;
#Inject
private SomeObjDepB someObjDepB;
public SomeObjDepA getSomeObjDepA() {
return someObjDepA;
}
public SomeObjDepB getSomeObjDepB() {
return someObjDepB;
}
}
public class SomeObjDepA {
}
public class SomeObjDepB {
#Inject
private SomeObjDepA someObjDepA;
public SomeObjDepA getSomeObjDepA() {
return someObjDepA;
}
}
public class DependencyInjectionTest {
#Inject
private Provider<SomeObject> someObjProvider;
#Test
public void instancesTest() {
final SomeObject someObjInst1 = this.someObjProvider.get();
final SomeObject someObjInst2 = this.someObjProvider.get();
Assertions.assertNotEquals(someObjInst1, someObjInst2);
Assertions.assertNotEquals(someObjInst1.getSomeObjDepA(), someObjInst2.getSomeObjDepA());
Assertions.assertNotEquals(someObjInst1.getSomeObjDepB(), someObjInst2.getSomeObjDepB());
Assertions.assertEquals(someObjInst1.getSomeObjDepA(), someObjInst1.getSomeObjDepB().getSomeObjDepA());
Assertions.assertEquals(someObjInst2.getSomeObjDepA(), someObjInst2.getSomeObjDepB().getSomeObjDepA());
}
}
Question: How to setup dependency injection to build up a scenario like this? I am looking for a annotation or Java based configuration (if possible)
I am currently using CDI 2.0 (Weld 3.1.5), and JUnit 5 for testing. I prefer a solution using CDI, but any other solution using Spring, Guice, etc. would be nice to.
Many thanks in advance
Depending on what you're looking for, you want to make use of scopes and/or qualifiers.
You can think of a scope as a lifespan. If you don't specify a scope (you don't anywhere above), then the default scope is "create a new one whenever one is called for", which is known as dependent scope. (This is because the thing being injected's lifespan is dependent on the thing that is housing it.)
As #Glains points out above, #ApplicationScoped is one way of indicating that a bean should be in "application scope", which is basically singleton scope with extra goodies. So you can put that on any class that meets the requirements to indicate that its lifespan should be that of the application as a whole.
Next, you talk about distinguishing between two otherwise indistinguishable occurrences of a given object, both of which might be singletons (SomeObjDepA). Qualifiers let you do this.
Let's say that you have a producer method that makes a "yellow" SomeObjDepA and another one that makes a "red" SomeObjDepA. To do this in CDI, you'll need qualifier annotations that express the "red" and "yellow" bits. Then apply them at the site of production. For example:
#ApplicationScoped // producer methods need to be "housed" in a bean
public class Host {
#Produces
#Red // you define this annotation following the spec's rules for qualifier annotations
#ApplicationScoped // ...or whatever scope is called for
public SomeDepA produceRedDepA() {
return new SomeDepA();
}
#Produces
#Yellow // you define this annotation following the spec's rules for qualifier annotations
#ApplicationScoped // ...or whatever scope is called for
public SomeDepA produceYellowDepA() {
return new SomeDepA();
}
}
Here we have two producer methods that will be called by the container appropriately and will "satisfy" relevant injection points elsewhere. For example, in SomeObject, you might have:
#Inject
#Red
private SomeDepA red;
#Inject
#Yellow
private SomeDepA yellow;

CDI Weld omit #Inject

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.

Spring Autowire Annotation with Several Interface Implementations

Suppose you have one interface
public interface A {
public void doSomething();
}
and two implementation classes
#Component(value="aImpl1")
public class AImpl1 implements A {
}
#Component(value="aImpl2")
public class AImpl2 implements A{
}
And finally a class that will use an "A" implementation:
#Component
public class MyClass {
#Autowire
A a;
}
Now if I want to inject AImpl1 I add the #Qualifier("aImpl1") while if I want to inject AImpl2 I add #Qualifier("aImpl2")
The question is: Is it possible to instruct spring somehow to look up all implementations of "A" in this case AImpl1 and AImpl2 and use some application specific conventions to choose the most appropriate implementation? for example in this case my convention could be use the implementation with the greatest suffix (i.e. AImpl2)?
EDIT: the class MyClass should not be aware at all about the implementation lookup logic, it should just find its property "a" set with an object of AImpl2.
You can inject all implentations as List:
#Autowired
List<A> as;
or as Map with bean name as key:
#Autowired
Map<String, A> as;
and then choose proper implementation manually (perhaps, in a setter method):
#Autowired
public void setAs(Map<String, A> as) {
this.a = ...;
}
Assuming you already have hundreds of interfaces and implementations (as you said in a comment), and you do not want to refactor all the code... then is a tricky problem... and this is a tricky solution:
You could create a custom BeanDefinitionRegistryPostProcessor and implement either the method postProcessBeanDefinitionRegistry or postProcessBeanFactory.
This way you have access to all bean definitions before they are instantiated and injected. Do your logic to find which is the preferred implementation for each one of your interfaces, and then, set that one as primary.
#Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanDefinitionRegistry(
BeanDefinitionRegistry registry) throws BeansException {
// this method can be used to set a primary bean, although
// beans defined in a #Configuration class will not be avalable here.
}
#Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
// here, all beans are available including those defined by #configuration, #component, xml, etc.
// do some magic to somehow find which is the preferred bean name for each interface
// you have access to all bean-definition names with: beanFactory.getBeanDefinitionNames()
String beanName = "aImpl2"; // let's say is this one
// get the definition for that bean and set it as primary
beanFactory.getBeanDefinition(beanName).setPrimary(true)
}
}
The hard part is to find the bean name, it depends of the specifics of your application. I guess that having a consistent naming convention will help.
Update:
It seems that both methods in the interface BeanDefinitionRegistryPostProcessor can be used for this purpose. Having in mind that in the postProcessBeanDefinitionRegistry phase, beans configured through #configuration classes are not yet available, as noted in the comments below.
On the other hand they are indeed available in postProcessBeanFactory.
If you have a Configuration class you could use a method in that to make the decision of which implementation of A to return. Then the autowired will inject the appropriate instance for that class.
#Configuration
public class ApplicationConfiguration {
#Bean
A getA() {
// instantiate the implementation of A that you would like to have injected
// or you could use reflection to find the correct class from the classpath.
// return the instance
}
}
This assumes you always want to use the same instance everywhere you are injecting A. If not, then you could have different #Bean annotated methods with names to get different versions.
You can try to use Spring Profiles.

Using autowired beans in an object created at runtime

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

CDI with unmanaged objects

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.

Categories

Resources