SessionContext.getBusinessObject() in EJB3 & JNDI lookup - ejb

In EJB2, one needed to use getEJBBusinessObject() method in a EJB to pass reference to itself when calling another (local/remote) bean.
Does the same apply for EJB3?
e.g.
#Stateless
public class MyBean implements MyBeanLocal {
#Resource private SessionContext sessionContext;
public void myMethod() {
OtherBeanLocal otherBean = ...; // getting reference to other local EJB.
MyBeanLocal myBean = sessionContext.getBusinessObject(MyBeanLocal.class);
b.aMethod(myBean);
}
// Edit: calling myMethodTwo() from inside of myMethodOne()
public void myMethodOne() {
MyBeanLocal myBean = sessionContext.getBusinessObject(MyBeanLocal.class);
myBean.myMethodTwo();
}
public void myMethodTwo() {
...
}
...
}
Also, if I fetch my local bean using getBusinessObject() method, is it the same as if I use common JNDI lookup?
I've tested both approach, and both work, but I'm not sure if bean object is processed the same way by the container.
Edit:
Is fetching the reference to ejb itself, when calling myMethodTwo() from inside myMethodOne() of the same ejb, in EJB3, still needed? Is it allowed to call methods inside the same ejb through this reference?
How will this address transactions, if I decide to use some?

Yes, the same applies to EJB 3. Yes, getBusinessObject is the EJB 3 analog to getEJBObject (or getEJBLocalObject). All of those methods return a proxy for the current bean object. For stateless session beans, this is basically the same as looking up through JNDI, though it's likely to perform better since it avoids JNDI overhead.

Related

Access session bean member variable from EJB asynchronous method

I have a #SessionScoped bean (CDI) that I would like to access and update from a EJB #Asynchronous method. If I pass a reference to a member variable in the bean via the #Asynchronous method's parameters and work with it, assuming the object being passed in is made thread safe, is there any other issues I should be aware of?
Is there any different to be aware if a #ViewScoped bean is used instead?
The only one I could think of would be if the CDI Session Bean timed out however that shouldn't be an issue because the object would be retained as the #Asynchronous method still has a reference to it.
I'm trying to pass off a long running task so as not to hold up the user clicking on a button but still update the session model with the result of the job so the user can see the outcome in a "job viewer" type interface.
Never access frontend classes from backend classes.
Just pass a callback to the EJB method.
#Asynchronous
public void asyncDoSomething(SomeInput input, Consumer<SomeResult> callback) {
SomeResult result = doSomethingWith(input);
callback.accept(result);
}
public void yourSessionScopedBeanMethod() {
yourEjb.asyncDoSomething(input, this::setResult);
}
public void setResult(SomeResult result) {
this.result = result;
}

Can't use a session ejb in my managed bean cause i get a Null Pointer Exception

First of all I want to say I'm pretty new in programming with ejb and jsf, and I'm trying to complete a project started by a friend of mine.
I'm getting a NullPointerException caused by the invoke of the method utenteSessionBean.CheckUtentebyId(username) of the session bean object called utenteSessionBean, declared inside the managed bean called Neo4jMBean.
I learned that it's not necessary creating and initializing a session bean (as you must do with a normal java object) in managed bean, but it's enough declaring it.
Here is the code of the session bean, which retrieves data from a DB
#Stateless
#LocalBean
public class UtenteSessionBean {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("EnterpriseApplication2-ejbPU");
public boolean CheckUtentebyId(String username){
EntityManager em = emf.createEntityManager();
Query query = em.createNamedQuery("Utente.findByUsername");
query.setParameter("username", username);
List<Utente> Res=query.getResultList();
//completare funzione ctrl+spazio
System.out.println("pre");
System.out.println("pre"+Res.isEmpty());
em.close();
System.out.println("post");
System.out.println("post"+Res.isEmpty());
if(Res.size()>=1)
{
return true;
}
else
{
return false;
}
}
}
Here's the code of the managed bean:
#ManagedBean
#ViewScoped
public class Neo4jMBean {
#EJB
private UtenteSessionBean utenteSessionBean;
static String SERVER_ROOT_URI = "http://localhost:7474/db/data/";
public Neo4jMBean() {
}
public boolean getUser(String username) {
return utenteSessionBean.CheckUtentebyId(username);
}
}
I've searched on StackOverFlow many times a solution for fixing this problem, but I haven't found something that works for me yet.
I fixed it accessing the EJB Components using JNDI.
In few words, if i use an EJB in a managed bean method, i need to add the next lines of code:
InitialContext ic = new InitialContext();
SessionBeanName = (SessionBeanClass) ic.lookup("java:global/NameOfTheApplication/NameOfTheEJBpackage/NameOfTheSessionBean");
It must be surronded by a try-catch statement
Create empty beans.xml file in your WEB-INF folder to enable CDI

Unknown JNDI Lookup String

I am new to EJB concept. I have seen the following in different website :
Sample 1:
#Stateless
#EJB(name="audit", beanInterface=AnotherEJBLocal.class)
public class EmployeeBean implements EmployeeServiceLocal, EmployeeServiceRemote {
#PersistenceContext(unitName = "EmployeeService")
private EntityManager manager;
public void doAction(){
try {
Context ctx = new InitialContext();
AnotherEJBLocal audit = (AnotherEJBLocal) ctx.lookup("java:comp/env/audit");
audit.doAnother();
} catch (NamingException e) {
throw new EJBException(e);
}
}
}
Sample 2:
public static void main(String[] a) throws Exception {
EmployeeServiceRemote service = null;
service = (EmployeeServiceRemote) new InitialContext().lookup("EmployeeBean/remote");
service.doAction();
}
Sample 3:
obj = ctx.lookup(ejb/CBDWebAppEAR/CBDWebApp.jar/<EJB name>/<Remote Interface Class Name>);
CBDWebApp is the project name in which the bean resides.
My question is:
What is the need & MEANING of java:comp/env/audit
Why same type of string is not used in case of Sample 2. I guess as
it is a remote EJB not local.
Why is the meaning of the EJB look up string in the Sample 3.
The java:comp/env/audit string is looking up the EJB reference that was declared earlier by the #EJB(name="audit", beanInterface=AnotherEJBLocal.class). Names declared by #EJB (and #Resource and all other EE references) are implicitly declared in the java:comp/env context. With this reference, the deployer can retarget the "audit" reference to any EJB in the application that implements the AnotherEJBLocal interface, or if the deployer doesn't specify anything, the javadoc for the #EJB annotation requires it to target a single EJB within the same application that implements the interface.
This main method is (probably) declared by a standalone Java program. In that case, it (probably) is configured via system properties to connect the JNDI server of an application server, which will return the remote reference to the client. The name that is looked up is vendor-specific, and it was probably configured for the EJB during deployment.
This is very similar to #2, the only difference being the specific string being used. In this case, it is probably relying on an application server's "default" binding name if none was configured for the EJB during deployment using the pattern ejb/<app>/<module>/<bean>/<interface>.

Using Spring AOP 3.1.0 to set service instance using method argument

Hi i am new to Annotation and Spring AOP. below is what i am trying to achieve
public interface Service {
public void process(String ServiceName, Bean bean);
}
public class ServiceImpl1 implements Service{
public void process(String ServiceName, Bean bean) {
/// do something here
}
}
public class ServiceImpl2 implements Service{
public void process(String ServiceName, Bean bean) {
/// do something here
}
}
from other class i would be calling something like
...
public void doSomething(String serviceName, Bean bean){
service.process("ServiceImpl1", bean);
}
...
I can achieve the same by using AroundAdvice and Before advice and intercepting my doSomething method and then instantiate the service object after reading the serviceName.
I there is a better approach for this?
I just need a direction and then i will figure this out.
Thanks
Well, I am guessing what you want to do is have a Before advice that takes the passed in service name, creates an object of appropriate class, then calls the appropriate method on that newly created object. It seems like, to me, you are really looking for more of a Factory pattern, but trying to use AOP to accomplish it.
If you took the Factory pattern, you would create a class called ServiceFactory, which takes some parameters and returns the correct Service implementation for those parameters. You calling code would simply use the Factory to get the right Service at runtime.
Another approach, if you want to stick with more of a DI pattern, might be to create a wrapper class that serves as the "conductor". This might have a Map of service names to Service implementation. You could then inject this wrapper into your code, and even inject the Map into the wrapper. Your calling code would call methods on the wrapper, which would locate the correct, singleton implementation and aggrigate the call to it.
I just feel that using AOP for this is asking for trouble.
You can inject the service impl class using the spring #Autowire annotation. Since u have 2 implementation classes, you can use qualifier to specify which impl needs to b injected.

EJB stateless - Private members initialisation

I'm new to EJB and I'm facing my first problem. I'm trying to use an #Schedule method contained in a Stateless EJB. I'd like this method to use a private member variable which would be set at bean creation:
Here's a short example:
#Singleton
#LocalBean
#Startup
public class Starter {
#PostActivate
private void postActivate() {
ScheduleEJB scheduleEjb = new ScheduleEJB("Hello");
}
}
And the schedule bean:
#Stateless
#LocalBean
public class ScheduleEJB {
private String message;
public ScheduleEJB() {
super();
}
public ScheduleEJB(String message) {
super();
this.message= message;
}
#Schedule(second="*/3", minute="*", hour="*", dayOfMonth="*", dayOfWeek="*", month="*", year="*")
private void printMsg() {
System.out.println("MESSAGE : " + message);
}
}
The problem is that my "message" variable is always null when printed in the printMsg() method... What's the best way to achieve this?
Thanks for your help !
You're mixing few things here.
The #PostActivate annotation is to be used on Stateful Session Beans (SFSB), and you use it on the singleton. I guess that you mean the #PostConstruct method which applies to every bean which lifecycle is managed by the container.
You're using a constructor from your EJB. You cannot do:
ScheduleEJB scheduleEjb = new ScheduleEJB("Hello");
as it creates just an instance of this class. It's not an EJB - the container didn't create it, so this class does not have any EJB nature yet.
That's the whole point of dependency injection - you just define what you want and the container is responsible for providing you with an appropriate instance of the resource.
The Stateless Bean (SLSB) is not intented to hold the state. The SFSB is. Even if you would set the message in one SLSB method (i.e. in some ScheduleEJB#setMessage(String) method) than you need to remember that the EJB's are pooled. You don't have any guarantee that the next time you invoke a method on the ScheduleEJB you will get to the same instance.
In your case it would be the easies solution just to add the #Schedule method to your singleton class. Than you can define the variable of your choice in the #PostConstruct method. You can be sure that there is only one Singleton instance per JVM, so your variable will be visible in the Schedule annotated method of the same class.
HTH.

Resources