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);
Related
I'm currently working with session objects. In service layer I'm autowiring session scoped bean. And I wonder how Spring is able to do this? And more interesting part, even if I use final keyword and use constructor injection, Spring is still able to autowire the object.
#Service
public class SomeServiceImpl implements SomeService {
private final UserSessionDetails userSessionDetails;
#Autowired
public SomeServiceImpl(final UserSessionDetails userSessionDetails) {
this.userSessionDetails = userSessionDetails;
}
}
And my other question is; Is it good practice the using session objects in Service layer? Or am I free to use these objects in Controller and Service layers?
I wonder how Spring is able to do this?
SomeServiceImpl is a singleton, so it should be assembled at startup. Assembling a bean means injecting all required dependencies to it. Although some candidates may have the scope different from the singleton scope, they still have to be provided. For such beans, Spring creates proxies. A proxy is basically a meaningless wrapper until some context comes.
if I use final keyword and use constructor injection, Spring is still able to autowire the object.
Spring supports constructor-based injection. It examines the signature and looks up candidates to inject; the modifiers of a field don't matter.
Is it good practice the using session objects in Service layer? Or am I free to use these objects in Controller and Service layers?
As long as the service is web-oriented and session-concerned, you are free to inject session-scoped beans to it.
You are autowiring by constructor, so the usage of word final does not change anything in this case. By annotating UserSessionDetails as session scoped bean, and injecting it into SomeServiceImpl spring generates a proxy. Any call from your service, is being delegated into UserSessionDetails bean.
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
I'm trying to understand CDI using Weld. Got the next structure:
#ApplicationScoped
public class MainFacade {
#Inject
private FooFacade fooFacade;
private static int ins=0;
public MainFacade() {
super();
ins++;
System.out.println("MainFacade instance = "+ins);
}
public FooFacade getFooFacade() {
return fooFacade;
}
}
Where FooFacade is also #ApplicationScope.
When app is starting I've get a MainFacade instance = 1. When I inject it in other class (GWT RPC servlet) and call mainFacade.getFooFacade() then new instance of MainFacade are created along with a new instance of fooFacade.
Thought that Weld would return me the same instance of application scope bean anywhere I inject it. What I'm doing wrong?
I don't think this test will work well to verify that an application scoped bean is really a "singleton".
If you inject this bean into other beans, Weld will create a proxy which will handle the delegation of all invocations to the correct instance. This is important especially if you inject request scoped bean into session scoped beans for example.
The proxy will basically extend MainFacade which is required because otherwise the proxy cannot be injected into the fields where the injection is happening. When creating an instance of the proxy, the default constructor of you bean will be executed. As Weld will create many proxies, you are seeing multiple logs to the console. You could verify this by adding something like this to your constructor:
System.out.println("Type: "+this.getClass().getName());
When you use #ApplicationScoped Weld creates a proxy that calls constructor too, specification here.
I have an EJB which I don't want anyone to be able to instantiate explicitly. So I have a static method for instantiating it( Factory method) this class is called EmailEJB. It has an interface called EmailService.
Now as I am using jsf, I have a managed bean called EmailMB.
My questions:
Why do I have access only to the interface and not to the bean itself?
How can I instantiate that EmailEJB in EmailMB ? I cannot have an static class inside interface and I cannot instantiate interface.
Thank you.
An EJB is instanciated and its lifecycle is managed by your container.
A Managed Bean is linked to JSF and supposed to contains values from your user.
The role of the EJB is to execute the business job (retrieve data from database, save, update, insert, call another EJB, etc...).
You extract informations from your managed bean and give them to a method of your EJB as parameters. The EJB will do the job and maybe give you some information back which can be stored in the managed bean to go back to the user.
The EJB will never be instanciated in a managed bean. You don't manage the EJB : it is managed by the application server.
Is it possible to make the container inject the same stateful session bean instance into multiple other stateful session beans?
Given the following classes:
#Stateful
public class StatefulTwoBean implements StatefulTwo {
#EJB
private StatefulOne statefulOne;
}
#Stateful
public class StatefulThreeBean implements StatefulThree {
#EJB
private StatefulOne statefulOne;
}
In the above example, StatefulTwoBean and StatefulThreeBean each get injected their own instance of StatefulOneBean.
Is it possible to make the container inject the same instance of StatefulOneBean into both StatefulTwoBean and StatefulThreeBean?
The problem is this - Stateful beans' isntances are allocated by differentiating the clients that call them. Glassfish (and perhaps others) don't propagate this difference on injected beans. The EJB specification, as far as I remember, isn't clear about this.
So your solution is to implement the differentiation yourself. How to achieve this. I'm not pretending this is the most beautiful solution, but it worked. - we did it by putting a Facade (an EJB itself) (I'm calling it a facade, although it does not entirely cover the facade pattern) in front of all our EJBs, with the following code:
public Object call(Object bean,
String methodName,
Object[] args,
Class[] parameterTypes,
UUID sessionId) throws Throwable {
//find the session
SessionContext sessionContext = SessionRegistry.getSession(sessionId);
//set it as current
SessionRegistry.setLocalSession(sessionContext);
.....
}
The important parameter is sessionId - this is something both the client and the server know about, and identifies the current seesion between them.
On the client we used a dynamic proxy to call this facade. So the calls look like this:
getBean(MyConcreteEJB.class).someMethod(), an the getBean method created the proxy, so that callers didn't have to know about the facade bean.
The SessionRegistry had
private static ThreadLocal<SessionContext> localSessionContext = new
ThreadLocal<SessionContext>();
And the SessionContext was simply a Map providing set(key, value) and get(key)
So now, instead of using #Stateful beans to store your state, you could use the SessionContext.
In EJB3.1 you can create your StatefulOne bean as singleton (using the #Singleton annotation) giving you the desired semantics. JBoss should already support this annotation (they've wrote the standard).