Java EE inject CDI #SessionScoped into EJB #Stateless session bean - java

How can I inject this class (It's inside the war part of the project):
#Named("user")
#SessionScoped
public class User implements Serializable
{....}
Into this EJB session bean:
#Stateless
#LocalBean
public class testSB
{ inject User here... }
I tried using #Inject but it does not work. It seems that it does not recognize User class.
I tried looking for an example of injecting CDI into EJB, but could not find anything that worked.
Is that even possible? What is the right way to do this? I would like to get data from the User class directly instead of passing the values inside the methods.

Inject a Provider<User> into your stateless bean. Then, when you need the user, do userProdiver.get().

Pay attention to not instantiate a "testSB" object (in this way you can't expect the container to inject an object of class "User" to you). To the container be able to inject one object of class "User" to you, you MUST let the container instantiate the object of class "testSB".
I don't think that there is a problem in injecting a "SessionBean" inside a "RequestBean". All your "RequestBean" objects will share the same object of the "SessionBean" class.

With CDI you should be able to inject anything anywhere, even in EJB SessionScoped.
Try adding an empty beans.xml to your META-INF. Please check my answer here:
Java EE 7 - #Decorator, #Stateless and #PersistenceContext = nullpointerException
Best Regards,
Alexander

Related

Usage of #Component in case of inheritance

I have 2 scenarios where I would like to understand/confirm the usage of #Component:
Extending concrete class:
I have a concrete super class A and its sub-class Aa in my web application. I have annotated with Aa with #Component(value="aa") and #Scope(value=WebApplicationContext.SCOPE_SESSION). Also, I have annotated A class with #Component(value="a") and #Scope(value=WebApplicationContext.SCOPE_SESSION).
My question -> I am only doing applicationContext.getBean("aa"). I can skip the annotations in A class (please correct me if I am wrong), but I don't know why and how? My understanding has been that if a class is not annotated with #Component or defined in bean configuration file then Spring doesn't handle its instance management.
Abstract concrete class:
Same scenario and question as above just that in this case super class is an abstract class.
You have to register the beans via beans in a config or via component annotations (Repo or controller or service). If not the bean is not contained in your application context container.
#Component add a bean in the Spring registry. Then, you can retrieve this bean later.
If you don't use the bean, there is no need to add it to the bean registry. (so just remove #Component(value="a") and #Scope(value=WebApplicationContext.SCOPE_SESSION) )
On your use case, you set a scope to SESSION. It means that every time you create a session, Spring will instantiate your class (A / Aa) and put it on the session. As it is an instance of the class you don't need the super class instance (A) to be able to create the Aa instance.
With A beeing abstract, it is exactly the same thing, except if you try to scan it for Spring to pick it, Spring will throws an error saying A cannot be instantiated.

Can #Inject be used in a pojo

I am trying to use and understand CDI, when I use #Inject in a simple pojo class, it throws me NPE.
example
Greeting.java
public Class Greeting {
public String greet() {
System.out.println("Hello");
}
}
Test.java
import javax.inject.Inject;
public class Test {
#Inject
private Greeting greeting;
public void testGreet() {
greeting.testGreet();
}
}
When I call testGreet() it throws NPE, why is the greeting instance null. Does #Inject way of adding dependency only be used in container managed bean?
Note: jar is not the problem here.
TL;DR:
#Inject-annotated fields are only populated for container-instantiated beans.
Long version:
The CDI container provides you a lot of utilities for easily injecting dependencies to your beans, but it doesn't work by magic. The container can only populate the annotated fields of a client bean if the client bean itself was instantiated by the container. When the container is instantiating the object the sequence of events is as follows:
Your bean's constructor is called.
#Inject-annotated fields (and some other
annotations, #PersistenceContext and #EJB for instance) are
populated.
#PostConstruct-annotated no-args method is called.
Your bean is finished.
You're facing a classic bootstrapping problem, how to move from non-container-managed code into container-managed code. Your options are:
Get access to an instance of BeanManager from your JavaEE container via JNDI lookup. This is technical and a bit clumsy.
Use a CDI extension library such as Apache DeltaSpike. (Example: BeanProvider.getContextualReference(Test.class, false);)
Modify your application to start in a situation where you can inject your Test class rather than calling new Test();. This can be done for example by setting up a startup singleton ejb, which calls your test in it's #PostConstruct-annotated initialisation.
Hope this helps.
You need a JavaEE container, and than you need to define Greeting and Test as managed beans. After that you can inject one in another.
Try to take a look at:
https://docs.oracle.com/javaee/6/tutorial/doc/girch.html
Your class should be implemented from Serializable for being injectable as a "CDI Bean"

JSF : Passing an Object from one backing-bean to another backing-bean

I am trying to figure out a solution for a small problem I have encountered whilst developing a small application. I am trying to pass an object created within one backing-bean and then later using that same object I created within another backing-bean. However, I would not like to make these backing-beans #SessionScoped, and preferably not use the #ManagedBean as I am using CDIfor my JavaEE application.
Is there anyway I could do this using CDI annotations and injecting one backing-bean to another and then have the ability to access that object previously created?
As an example, refer to the below beans:
#Named
#ViewScoped
public RegisterController implements Serializable {
User user = new User();
// Getter and Setter methods which are populated by the JSF page
}
Get Object User created within the above bean and use it within the controller below:
#Named
#ViewScoped
public PaymentController implements Serializable {
#Inject RegisterController registerController; // Injecting bean
registerController.getUser().getName(); //this is null when I try access the properties of the object 'User'. I am assuming this is because #ViewScoped annotated on the 'RegisterController' class?
// I would like to use the User object created in 'RegisterController' here an access properties etc...
}
Could I use the #Inject annotation offered by the CDI?
UPDATE
Ok, so I have got the above working when I annotate the RegisterController with the SessionScoped annotation, however I do not want this Bean annotated SessionScoped as I will probably run into further implications down the track, such as pre-population of fields, etc... Any ideas how to implement this any other way?
Well, #ViewScoped is too short to the purpose and #SessionScoped is too long. Then why not use #ConversationScoped?
See here.
you can use in RegistrationController:
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("user", user);
and in PaymentController:
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user");
this is very useful, you can save the objects you want in the map.

Ejb returns java.lang.NullPointerException

I am newbie in cdi and these are my first steps.
I have a bean in ejb module:
#Stateless
public class TestBean {
public String getIt(){
return "test";
}
}
I have a POJO in war module (I tried with #EJB and #Inject - same result)
public class SaveAction extends Action{
#EJB
private TestBean bean;
#Override
public void execute(){
....
String test = bean.getIt(); //HERE I GET java.lang.NullPointerException
...
}
}
Both war and ejb are inside ear. In log I see
EJB5181:Portable JNDI names for EJB TestBean:
[java:global/example.com/my-ejb/TestBean!com.example.TestBean,
java:global/example.com/my-ejb/TestBean]]]
From that I conclude that bean is initialized - but I can't find it. What am I doing wrong?
CDI and other dependency injection containers don't use magic! It's just ordinary java code that cannot do more or less than any other java code written anywhere. So it is impossible for a framework to do injection when an object is instantiated directly via new:
SaveAction action = new SaveAction();
// don't expect any injection has happened - it can't! no magic!
// action.bean is still null here!
The framework does not have any idea that an object like SaveAction has been instantiated. (Therefore it would be necessary to somehow inform the framework about the newly created object - but neither the constructor nor the 'new' statement do this! Just think one minute about how you would write such a framework code! It's not possible!* ).
To make injection work, the object must be created by the container instead! Otherwise it is NOT managed! (See also chapter 3.7 of the Web Beans specification (JSR 299)).
The best way to do this is to let the container inject the object into another already managed bean. It seems this just deferes the problem, but there are some already managed beans in your application, like the servlet!
Suggestion: Make your SaveAction CDI aware (e.g. annotate it with #Default) and let it be injected into your servlet!
Tutorials:
http://middlewaremagic.com/jboss/?p=1063
http://hudson.jboss.org/jenkins/job/JBoss-AS7-Docs/lastSuccessfulBuild/artifact/guides/developer-getting-started-guide/target/docbook/publish/en-US/html/helloworld.html
*) In theory it should be possible using aspect oriented programming or instrumentation to manipulate the constructors of beans to notify the container if they are invoked. But that's a very complex concept with many unsolved issues I think.

How to invoke method on one #Stateless bean from another #Stateless bean

I have created stateless session bean in Java. Now I want to invoke a method of another stateless session bean. Some things are missing in my code. Usual way of invoking method does not fit here. Being invoked method at another stateless session bean retrieves data from the Internet.
Likewise, how to invoke a method from #Stateless bean of a simple Java class. I build a REST web service with Java and somehow I can't invoke methods being at simple Java class from #Stateless beans.
Cheers
Just inject it with #EJB
#Stateless
public class StatelessBean1 {
#EJB
private StatelessBean2 bean;
}
There's nothing special about invoking methods on a stateless session bean. You use the exact same syntax as with every other kind of bean.
As Bozho indicated, the only thing special about EJBs is that you can't construct an instance using the new operator. You need to inject an instance or alternatively do a JNDI lookup. After that, the normal Java rules apply.
It really shouldn't need to be explained but to be sure, calling a method on a stateless session bean called 'bean':
bean.someMethod(someArgument);

Categories

Resources