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>.
Related
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
I have to implement two simples java projects ; the first is an EJB projectwho contains a simple service which implement a remote interface, and the second project is a java client which try to call this ejb project ,
so here is what I did until now :
Context context = new InitialContext(jndiProperties);
TestServiceRemote proxy = (TestServiceRemote) context
.lookup("java:global/testEJB/TestService!services.TestServiceRemote");
System.out.println(proxy.showHello());
and this my ejb service :
#Stateless
public class TestService implements TestServiceRemote {
public TestService() {
}
#Override
public String showHello() {
return "Hello";
}
}
finally this my Remote interface :
#Remote
public interface TestServiceRemote {
public String showHello();
}
I had deployed the EJB in WIldfly 9 , but when I launch the java client i get this error shown in console :
Exception in thread "main" javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:350)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at swing.testClient.main(testClient.java:22)
Can someone tell me what I had wrong in my code ?
The java: namespace is not available by default in Java. You can either package your main class as an application client JAR inside an EAR and run it using an application client container launcher, or you can configure the InitialContext to have access to the java: namespace as described in this blog post.
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.
I have 2 POJOs, in which one of them is an EJB and the other is a helper class.
//EJB Bean class
#Singleton
#LocalBean
#Startup
public class EJBBean{
#PostConstruct
public void init(){
HelperClass helper = new HelperClass();
helper.init();
}
}
//Helper class
public class HelperClass{
private static Log LOG = LogFactory.getLog("HelperClass");
private static Long currentTime = new Date().getTime();
public void init(){
//Some statements that use Log and do other Initialization
}
}
When I deploy this EJB jar I am getting an error
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
I have the commons-logging-1.1.1.jar in the classpath; also, I have configured it to use Log4J. As a standalone app that is without EJB meta-data it works fine. Am I missing some EJB config?
BTW I am pretty new to EJB. I am using GlassFish 3.1, Eclipse Helios as IDE and EJB3.1.
This could be because you put the commons-logging-1.1.1.jar into the wrong directory or because your server already provides server-wide library which consists of logging classes.
By the way - I remember a lot of strange 'NoClassDefFoundError' because of mixing commons-logging, log4j and slf4j (especially in mismatching versions).
i have this in the server:
class Person{...}
and
#Stateless
public class HelloServiceBean implements HelloServiceLocal, HelloServiceRemote {
public Person getPerson(String name) {
return new Person(name);
}
}
And i have this in my client (in some different JVM):
public static void main(String[] a) throws Exception{
String name = "java2s";
HelloServiceRemote service = null;
service = (HelloServiceRemote)new InitialContext().lookup("HelloServiceBean/remote");
Person p = service.getPerson(name));
}
When i need to call, for example, getPerson() method from my EJB, which return an object of type of Person, how my client is going to understand that Person is a class ?
Do i have to re-write the Person class another time in my client (and also the HelloServiceRemote class), so it can understand what is a Person ? Or do i have to include the Ejb project into my client project ?
You have to include jar of EJB project at client side containing Interfaces, Entities & other utility classes used.
But exposing Entity Beans at client side is not preferable, you can get more information regarding this at http://www.ibm.com/developerworks/websphere/library/bestpractices/ejbs_access_entity_bean.html