Injecting #EJB into explicitly created object -> NullPointerException - java

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.

Related

How can an injected superclass Bean get the wrong instance ( subclass Bean instance) injected?

Problem:
I had some unexpected behaviour when injecting a Bean(In a filter) with 2 subclasses which I injected in two other classes (Servlets). Now the injected superclass could hold a reference to a subclass instance at runtime (changeing with each container restart).
I must have made a serious mistake but I can't quite figure out what exactly.
Additional information:
I use Java EE6
Class structure:
In the filter I inject the super class which holds a random instance to one of the subclasses or the superclass:
#EJB
private ClientLogger clientLogger;
The super class been starts like this:
#Stateless
#LocalBean
public class ClientLogger implements HcpEntityBeanLogger<Client> {
private Client client;
public ClientLogger(){
}
....
}
This subclass bean I inject in one of my Servlets:
#Stateless
#LocalBean
public class AdminClientLogger extends ClientLogger {
public AdminClientLogger(){
}
...
}
Solution attempt:
So as far as I understand the subclass which gets last injected will be the instance referenced by clientLogger, but why, why can't I have 3 different instances and use inheritance here?
Edit:
I faced this problem again when injecting multiple query beans which all implement the same interface, all of them would hold a reference to the same instance.
The solution was to add beanName wenn injecting the interface with EJB
#EJB(beanName="name of your bean class or name specified in #Stateless(name=".."))
You can use the lookup attribute on the #EJB annotation and get the required subclass injected. E.g.
#EJB(lookup="java:global/rest/AdminClientLogger")
private ClientLogger clientLogger;
Obviously you would have to change the JNDI lookup path in the example above.
So basically this happens when you forget to reference to the concrete sub class. Then the container will apparently just inject the same instance of one of the concrete classes;
There are a number of ways to reference the concrete class:
lookup (example from #NiranjanBhat)
#EJB(lookup="java:global/rest/AdminClientLogger")
private ClientLogger clientLogger;
beanName
#EJB(beanName="name of your bean class or name specified in #Stateless(name=".."))
there is also
name
beanInterface
mappedName
how to use them you can take from the java docs about EJB

Spring Overloaded Constructor Autowiring

I have a class with overloaded constructors, like this:
#Component
public class MyClass {
private ClassA myMemberA;
private ClassA myMemberB;
#Autowire
public MyClass(#Qualifier ("qualifierA") ClassA objectA, ClassA objectB) {
myMemberA = objectA;
myMemberB = objectB;
}
#Autowire
public MyClass(ClassA objectA) {
myMemberA = objectA;
}
}
Basically, one constructor has two arguments of ClassA, and one constructor has just one argument. I have two beans of type ClassA defined.
I would like to have one of the two constructors invoked and autowired accordingly depending on the use case.
When I ran this code, I got the error:
Invalid autowire-marked constructor: ...
Found another constructor with 'required' Autowired annotation: ...
Is it possible to have overloaded autowired constructors? If yes, what is the right way to do it?
Thank you!
You need to define which constructor Spring will be prioritizing by writing something like this: #Autowired(required=true) or #Autowired(required=false). You are only allowed to have one constructor with #Autowired(required=true). By default, if you don't define the required property, it will be set to true, which is the problem in your case.
I don't see the point of having two Autowired constructors if only one of them will be wired anyway. If you're trying to Autowire the two instances of ClassA, it might be better to add the #Autowired annotation to the setters or the variables.

Spring can only register contructor beans?

If let's say I have a class A (#Component) and a class B (#Component). Class A needs an instance of B. If I put class B as a field in A with #Autowired, even though Spring will find the B component (through #ComponentScan), the class A field will be null. However, if I put B as an argument in the A's contructor and annotate the constructor with #Autowired, it will work perfectly.
Is there any way to exclude B from A's constructor?
As #LuiggiMendoza mentioned: Creating a #PostConstruct method is easy: you should only annotate your method with #PostConstruct:
public class A {
#PostConstruct
void init(){
//do smth here
}
}
Or if you use XML configuration you can add init-method parameter to your bean definition.

Can I combine manual instantiation with autowiring?

Ok. I am not sure how to even ask the question, which is the sign I must be missing something. The best I can do is: "Is there a way to instantiate an object manually and still use injection within that object?"
Concretely, say I have:
class A {
public A(MyObject1 obj1, MyObject2 obj2, ..., MyObjectn objn) {
...
}
}
I want to wire all of these objects except MyObjectn. As far as I know, if I use #Autowired in front of that constructor above, then I should only instantiate that object as follows in the code that uses an instance of that class:
#Autowired
A a;
which doesn't allow me to pass in objn in the constructor manually. Is there a way to get around that limitation short of manually initializing A in the code that uses an instance of that class?
Short answer - no.
You either use an IoC or you manually instantiate Objects.
One workaround that comes to my mind:
Create a Service with every MyObject1 being #Autowired
create a method inside this service:
public A createA(MyObjectN objn) {
return new A(object1, object2... objn); //note that object1 .. objectn-1 are autowired.
}
Inject the service with #Autowired ;) and call service.createA()
sunilkumar from vmoksha
NO we cant create like that

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