CDI with unmanaged objects - java

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.

Related

Internal working of field injection in spring and why is it not recommended to use

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
}
}

Injecting #EJB into explicitly created object -> NullPointerException

I am trying to figure out how object instantiation works in Java EE. I have noticed that I get a NullPointerException if I try to access a member that is supposed to be injected through #EJB if the Class defining the member has been instantiated explicitly by me rather than the container. My conclusion is that even if a bean is marked to be managed it is not if one doesn't let the container instantiate it. Can we make the container manage such objects?
Let's say that we have the following setup, would it be possible to instantiate (explicitly) ClassB in ClassC and have ClassB invoke a method from ClassA without throwing a NullPointerException?
#Stateless
public class ClassA {
public void bar() {
// Does something fun
}
}
#Stateless
public class ClassB {
#EJB
private ClassA A;
public void foo() {
A.bar(); // throws NullPointerException if ClassB
// is explicitly instantiated works fine
// if injected with #EJB
}
}
public class ClassC {
//#EJB // Only way to go? Can we choose an implementation of ClassB?
private ClassB B;
public ClassC() {
this.B = new ClassB(); // Bad idea? Possible??
this.B.foo();
}
}
The reason I'm looking in to it is because I in my, equivalent of, ClassA need to use an EntityManager to persist some data, at the same time my ClassB is actually an interface so I need to be able to decide at runtime which implementation to instantiate in ClassC. Maybe there are other ways of doing this?
I have noticed that I get a NullPointerException if I try to access a member that is supposed to be injected through #EJB if the Class defining the member has been instantiated explicitly by me rather than the container.
This is obvious as the dependencies are injected by the container. So if you are creating the instance and not setting any value for the dependency, then the dependency will be null. On the other hand, when instances are created by the container, it also sets the values of its dependencies.
My conclusion is that even if a bean is marked to be managed it is not if one doesn't let the container instantiate it.
Yes, that is correct. When you create the instance, the instance is therefore, not managed.
Let's say that we have the following setup, would it be possible to instantiate (explicitly) ClassB in ClassC and have ClassB invoke a method from ClassA without throwing a NullPointerException?
No, when you create the instance, the dependencies will be null.
The reason I'm looking into it is because I in my, equivalent of, ClassA need to use an EntityManager to persist some data, at the same time my ClassB is actually an interface so I need to be able to decide at runtime which implementation to instantiate in ClassC. Maybe there are other ways of doing this?
If you need to inject a specific implementation, the you can do that by specifying bean name.
#EJB(beanName="DefaultService")
private Service defautService;
#EJB(beanName="SpecificService")
private Service specificService;
Refer to this link: http://www.adam-bien.com/roller/abien/entry/injecting_different_implementations_into_an
Alternatively, if you're using CDI you can use #Qualifier
The other way to get an EJB reference if you cannot use injection is to use JNDI to look it up.
Context initialContext = new InitialContext();
ClassB b = (ClassB)initialContext.lookup("java:global/yourappname/ClassB!com.package.containing.ClassB");
Therefore you can use whatever logic you need to determine the JNDI name of the actual ClassB implementation you need and then look it up.

Guice 3 - Automatically building object graph when using assisted inject

Im interested what is the proper manner to construct object with dependencies which themselves have #Assisted params. An example will better illustrate:
Ordinarilly with dependencies that do not have #Assisted params you can simply have a complex heirarchy of objects which all have their dependencies and these get injected no problem, I can just get an instance of an object and all its dependencies will be generated and injected without me having to do anything.
But if I wanted to change it so some of the dependencies in the object hierarchy have #Assisted params then I have to create those instances myself using a factory ie:
public SomeConcreteService(#Assisted String string) {
this.string = string;
}
MyFactory myFactory = injector.getInstance(MyFactory .class);
SomeService myService = factory.getMyService("some string");
This would cause problems for the clean instantiation of the objects because I would have to manually create those instances. and pass them into the required object, which essentially renders the DI for that object redundant I think???? ie I would then need to use the new keyword and pass in all dependencies manually...
new MyComplexObject(myService, myOtherService)
How do I make it so that I don't have to manually build the object graph if one or more of the dependencies uses #Assisted parameters?
The question you need to ask yourself is, "why am I making this #Assisted, and who is going to create these objects?"
If you use the key to get an instance you need, then what you have is fine:
public class YourInjectableClass {
#Inject private MyFactory factory;
public void doStuff(String key) {
// You have a key, and your factory, so you can create the instance yourself.
SomeService service = factory.getMyService(key);
// [...]
}
}
But if you use the key to get an instance create an instance to create an instance to get what you need, then that seems problematic. That might be a better problem for child injectors:
public class YourInjectableClass {
#Inject private Injector injector;
public void doStuff(String key) {
// You need an OuterObject. So rather than calling
// new OuterObject(new InnerObject(factory.getMyService(key))), do:
OuterObject outerObject =
injector.createChildInjector(new OuterObjectModule(key))
.getInstance(OuterObject.class);
// [...]
}
}
Because your value is needed throughout the dependency tree, you can treat it as an injected dependency. This can be a little more confusing, but saves you from letting your dependencies care about instantiation details all the way down the line.
Alternatively, you can create a manual OuterObjectFactory facade which does manually call new. This may be a better solution for legacy code, but can help to follow the Single Responsibility Principle by ensuring that one class is responsible for abstracting away instantiation details.
N.B. I'm assuming that SomeConcreteService takes other dependencies that the object graph can provide. If not, then there's no reason to use injection at all: Give SomeConcreteService a public constructor and call new SomeConcreteService("your value here") where needed. Though Guice takes some pains to abstract away the use of new, it is also unnecessary to create data objects or dependency-light objects like HashMap or Date.

Guice / DI and mixing injection and parameters passed in at runtime

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.

How to setup a non-CDI bean from a 3rd party for #Inject into CDI bean

While I've found examples in CDI where you setup #Produces (kinda factory like) or using the CDI javax.enterprise.inject.spi.Unmanaged concepts, they all seem to presume that CDI will be the one creating the instance of the class on its own terms and lifecycle (which makes sense).
However, there are situations where CDI simply cannot create the instance.
Such as a 3rd party library (that isn't using CDI itself) which is creating the object internally and giving it to you.
Now, how can I take these already instantiated objects (which incidentally are final objects with no default constructor), and make them available for my CDI managed beans to then use?
Here's a simplified example.
public class Foo
{
#Inject
private ByteBuffer buf;
public void go()
{
// do something, with buffer
}
}
public void process() {
ByteBuffer buf = ByteBuffer.allocate(500);
// TODO: how to add "buf" to current context?
Foo foo = CDI.current().select(Foo.class,AnyLiteral.INSTANCE).get();
foo.go();
}
Now, I realize that for this specific example, I could eaily just pass in the ByteBuffer, or setup a #Produces for ByteBuffer, or even have Foo make the ByteBuffer itself. (all of which would be easier). I chose ByteBuffer, because it exhibits the same problems I'm facing with the 3rd party library
The instances are valid beans
I have no control over its source
Instances are created by the library
Those instances are final and cannot be wrapped, overridden, or proxied
The use case also has situations where there are nested CDI references that could also use access to this #Inject ByteBuffer buf;.
Ideally it would be keen to have this be a pure CDI api technique, and not something that is weld or implementation specific.
I've devled into custom Scope creation as well, thinking that might be a solution for this, having a sort of #BufferScope that identifies the start() and end() of this instance. But none of the examples and documentation make this very clear with regards to objects that CDI just cannot call newInstance() or produce() on. The object instantiation is out of my hands, but the ability to present it to a CDI Scope is possible, along with even managing the ultimate death / destruction of that instance.
Proxying is not the same as wrapping. A customary workaround is to create a ByteBufferHolder (insert your class here) that adapts the custom builder flow into a bean that understands that it's inside the DI context.
I'm not sure I agree with the original assertion that CDI assumes it is constructing the instances. For example, I use the following in a JSF application to inject the current FacesContext instance....
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.faces.context.FacesContext;
public class FacesContextProducer {
#Produces #RequestScoped FacesContext getFacesContext() {
return FacesContext.getCurrentInstance();
}
}
At nowhere do I create the FacesContext instance. All that is required is that what has been created by the external framework is accessible.
So, if there is an external source from which you are getting instances, as long as you can get the correct one, the #Produces approach should still work?
There is some fundamental misunderstanding here. CDI is not required to construct the bean instances it can serve through producer methods. A Dependent scope will work just fine if the class is not proxyable. You can also make a wrapper class for the object, and put said class instances in whichever scope you need.
You use a producer method, which can be as simple as something like this:
#Produces
#ApplicationScoped
private Foo produceFoo() {
final Foo instance = // acquire one of those instances you're talking about
return instance;
}
If for whatever reason that doesn't work for you, you can alternatively write a portable extension and programmatically add a Bean that does what you want. So something like this in CDI 2.0+ (untested):
private void afterBeanDiscovery(#Observes final AfterBeanDiscovery event) {
final Foo instance = // acquire one of these final instances you're talking about
event.addBean()
.scope(ApplicationScoped.class)
.qualifiers(whateverYouNeed)
.addTransitiveTypeClosure(instance.getClass())
.createWith(cc -> instance) // you may also need .destroyWith()
;
}
Once you have this "producing side" set up, then in any CDI bean anywhere you can do:
#Inject
private Foo foo;

Categories

Resources