Java EE Bean inject into another Bean - java

I'm making two beans say ABean and BBean. I want to inject BBean into ABean but this is causing null pointer errors, likely because the bean has yet to be instantiated. How can I inject beans in beans as such:
#Singleton
public class ABean {
#Inject
BBean bean;
....
}
I'm using java ee 7 with wildfly server. Both beans are singletons so BBean is also declared as:
public class BBean {
#PostConstruct
public void startup() {
..
}
..
}
With out the dependency, I'm able to create both beans as I do have the necessary META-INF folder and beans.xml file with in it. I'm however coming to the conclusion that this might be bad practice/ anti-pattern. Anyway I'm not using this approach anymore.

Perhaps you forgot to add the beans.xml file, in order to enable CDI in your application. This is what the Java EE 6 Tutorial says http://docs.oracle.com/javaee/6/tutorial/doc/gjbnz.html:
An application that uses CDI must have a file named beans.xml. The file can be completely empty (it has content only in certain limited situations), but it must be present. For a web application, the beans.xml file must be in the WEB-INF directory. For EJB modules or JAR files, the beans.xml file must be in the META-INF directory.

did you remember to include a setter so the bean can be injected? #Inject does not work like #EJB.
also, like previously indicated, do not try to use the bean until after the owning bean is instantiated (not in constructor, only in #PostConstruct'ed method)
hope that helps.

Related

Can I set properties toward beans in an imported library?

I have a main Micronaut service. I also have a library project which houses some beans. One such bean (reduced) is:
#Singleton
public class Testo {
#Value("${testo}")
public int testo;
}
I am successfully "importing" this bean and #Injecting it as described in the documentation. However, I cannot for the life of me set this "testo" property from the main service. System properties, Environment variables, PropertyResource files (application.yml), at any level -> nothing works.
I check this through both a printout of the variable in the terminal, or debugging using IDEA.
Is it possible to set properties of beans that are housed in a library project?
Micronaut v3.1.3
Java 11
Is it possible to set properties of beans that are housed in a library
project?
It is. If you have #Value("${some.config.value}") on a property in a bean that is defined in your application or a bean that is defined in a properly compiled Micronaut bean provided by a library, then you can provide a value for some.config.value through any of the supported config source mechanism and that value will be used to initialize the property marked with #Value.
Of course that only works if the bean is being managed by the Micronaut context. If you are doing something like new Testo() then the #Value annotation will have no effect.

Access an injected Stateful Session Bean over a looked up Stateful Session Bean

I was wondering if EJB specifications allow to access a stateful session bean over a looked up stateful session bean.
The reason why I'm asking is, that Jboss EAP 7.0 has no problems with it, but Websphere throws a NullPointerException when I try to access the bean.
For example:
#Stateful
public class SampleServiceRoot implements SampleServiceRootRemote {
#EJB
protected SampleServiceChildLocal servicechild;
#Override
public SampleServiceChildLocal getServiceChild(){
return servicechild;
}
}
#Stateful
public class SampleServiceChild implements SampleServiceChildLocal,SampleServiceChildRemote{
#Override
public void anyMethod(){
//DO Anything
}
}
When I do a remote lookup to the SampleServiceRootRemote and call "getServiceChild()" and try to call "anyMethod()" on it, it works on JBoss EAP 7.0 but on Websphere I get a NullPointerException.
So I was wondering if this is a Bug in Websphere or is it forbidden by EJB Specification and I was just lucky with JBoss EAP 7.0?
The EJB specification does require this scenario to work, depending on some configuration options; there are configuration options that may disable it.
The fact that you are seeing a NullPointerException indicates that WebSphere is not aware of the #EJB annotation on the field in the SampleServiceRoot class. Per the EJB specification, an instance of SampleServiceRoot cannot be created if the #EJB annotation cannot be resolved. Since an instance of SampleServiceRoot has been created, then one of the following has likely occurred:
1 - The application performed a new SampleServiceRoot rather than looking it up in JNDI. This doesn't sound like your problem, but good to double check.
2 - The application contains an ejb-jar.xml with the setting metadata-complete="true". When this is set, WebSphere will not look for annotations, and so will not see or process the #EJB annotation. Either change the setting to "false" or add the <ejb-ref> or <ejb-local-ref> to the ejb-jar.xml file.
3 - The application does not have metadata-complete="true", however when the application is deployed to WebSphere the option to set metadata-complete was selected.
This option will change the metadata-complete setting to "true". Stop using this option, or add the <ejb-ref> or <ejb-local-ref> to the ejb-jar.xml file.
4 - The EJB is contained in a WAR module at level 2.4 or older. In WebSphere, annotations for older modules are not processed.
5 - The application includes a copy of the javax.ejb.EJB class. WebSphere provides the javax.ejb.EJB class, and it is loaded by the WebSphere runtime classloader. If the application also contains the javax.ejb.EJB class on the application classpath, then another instance will be loaded by the application classloader, and it will not match the instance used by the EJB Container. There should be a warning in the logs if this has occurred.
So yes, your scenario is required to be supported; however the specification does allow configurations that disable it. You just need to identify which configuration / packaging option has caused WebSphere to not see the #EJB annotation.
Thanks for the answer,
we tried to move the declarations of the Local-Interface to the Remote Interface of the SampleServiceChild. Also we did not use #EJB annotation. We managed it with doing a lookup of the SampleServiceChild over the InitialContext.
Now it works

Advantage of using #EJB to inject #Stateless Bean or using directly #inject

I am working on an old project developed in EJB.
I have serviceImpl as #Stateless(mappedName = "adminService"). I have seen in my project injecting this class in other classes by
#EJB(mappedName = "java:app/adminServices/adminServiceImpl")
and other classes are part of the same EAR but different modules. This serviceImpl class is being used only in this EAR.
So my question is if we have a class that is declared as #Stateless and is not being used in other EAR. This class is being used in same EAR modules. So can't we directly use #Inject without declaring it #Stateless?
I have known for three JNDI syntax for EJB
java:global[/application name]/module name/enterprise bean name[/interface name]
java:module/enterprise bean name/[interface name]
java:app[/module name]/enterprise bean name[/interface name]
Can't I use #Inject for java:app?
Why do I need java:module in the same modules, I can directly create an object or use #Inject.
In case of java:global I can understand if you are in other JVM then you need to make RMI call to get an object if stateless bean instance is in other JVM. So I have to use java:global syntax to get stateless bean instance from other JVM even in same JVM. Because I don't think We can use #Inject to get the instance from another EAR project into your EAR.
But in same JVM and same EAR, what is need of java:app and java:module JNDI syntax to get the instance by #EJB annotation if the bean is not singleton.
I can directly use #Inject.

usage of cdi's in a ejb project without jsf

I am learning javaEE and I read somewhere about the main usage of cdi's was back then first in jsf-managed beans with annotations like #requestscope, #applicationscope, etc.. now in newer javaEE versions the cdi got available everywhere (even in ejb beans) so the question is, how do I have to annotate a class which shall be injected inside my local stateless ejb? I am asking this because the annotations like #RequestScope and all those are from jsf but I am not using jsf. Is #Default enough since its marked as default anyway? Is #Dependent better choice?
#Stateless
public class FooEjb{
#Inject Bar b;
}
// what annotation to put here?
public class Bar {
...
}
Yes you don't need JSF to use CDI in JavaEE.
If you are using CDI without using JSF, use the scope annotations from the javax.enterprise.context package.
#Default is a qualifier which as the name suggests the default qualifier. If you have multiple implementations/instances of the same class in your container, then you can use qualifiers to distinguish.
#Dependent is a scope which is the default scope. This means it will depend on the scope of the class it's injected in. A new instance of a #Dependent class will be injected every time a new instance of the class in which it is injected is created.
To enable CDI you need to put a beans.xml file in WEB-INF directory of your web project or META-INF directory of your EAR or EJB project.
According to the java ee documentation, no annotation is required in your case. A simple POJO is an injectable bean and receive the #Default annotation. No need to use JSF.

How to use #Resource annotation in servlet (or in any other Java class)?

I am experimenting with Java Dependency Injection. Many questions here on SO talk about jndi resources being wired. But I think, a java class can be wired using #Resource annotation. I have a simple servlet in which I have two properties to be wired using CDI. I am using Tomcat6, Servlet 2.5, and Weld configuration.
The servlet code:
#Inject
private HikariConnectionProperties hikariConnectionProperties;
#Resource(name = "connectionProvider")
private IConnectionProvider connectionProvider;
However I get the code compiled, deployed. But, when there is a request for the corresponding servlet I get javax.naming.NameNotFoundException: Name connectionProvider is not bound in this Context.
But, I have #Named annotation for the ConnectionProvider class. The same configuration works with #Inject for both the fields.
So, my first question is how can I fix this issue? And is there any way that I can specify scope for a particular injection(using only annotations of JSR) without using Spring's #Scope? Any example is a great help as I am a newbie to CDI.
#Resource only works in Tomcat when you set up a resource in your container. Here's a reference for your own sake: http://tomcat.apache.org/tomcat-6.0-doc/jndi-resources-howto.html
It expects that you're binding a JNDI entry called "connectionProvider" in Tomcat. CDI does not bind elements to JNDI, it has its own internal mapping of objects to scopes. #Inject works here as you likely have not setup a resource for this class in your resource configuration.

Categories

Resources