I don't understand one thing that I hope someone of you could explain me. I have a maven enterprise project developed with glassfish.
I use the insert code netbeans function (right click) to call bean in a servlet and in particular the annotation
#EJB
I don't understand why when I call a stateful session bean through Insert Code function in netbeans the bean is called through JNDI. Here what I mean
private BookingBeanInterface lookupBookingBeanLocal() {
try {
Context c = new InitialContext();
return (BookingBeanInterface) c.lookup("java:global/it.volaconnoi_volaconnoi-webapp-ear_ear_1.0-SNAPSHOT/it.volaconnoi_volaconnoi-webapp-ejb_ejb_1.0-SNAPSHOT/BookingBean!it.volaconnoi.logic.BookingBeanInterface");
} catch (NamingException ne) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", ne);
throw new RuntimeException(ne);
}
}`
The above function hasn't been wrote by me
I can't inject a stateful session bean through EJB?
Here is the solution to the problem:
As you probably already know a single Servlet instance is used to handle multiple requests from multiple clients so the Stateful EJB should not be injected directly in the Servlet and kept as an instance property, or we will face obvious thread-safety related issues. In our case we are fetching it from JNDI inside doGet method and storing it in the HTTP session so each user will have it's own Sateful EJB instance.
Related
I am migrating Ejb 2.1 to Ejb 3.1. I changed Java Version from 1.6 to 1.8, and Ejb Version from 2.1 to 3.1. Once I made the changes, I am getting problems in the ibm-ejb-jar-bnd.xml and ibm-ejb-jar-ext.xml files.
I am getting these messages:
1: Session EJB with name 'abcEJB' not found
2: Resource reference with name 'ResourceRef_xyz' not found for this EJB or interceptor
Am I missing anything?
I have migrated from EJB 2.1 to EJB 3.1 couple of years back and I recall facing the same issues and error you are facing.
Although I don't remember the exact action that fixed the issue nor other issues I faced along the way, but I will tell you what I did to fix ALL issues, including this one.
Note: It's not an easy task to migrate, but following these next steps as described will save you lots of hassle later on.
Annotate session beans and interfaces with proper annotations:
In my case I had remote interfaces for EJB 2.1 beans. Since I did not need an actual remote interface in my application, I switched them into local interfaces.
Empty ibm-ejb-jar-bnd.xml and ibm-ejb-jar-ext.xml
Change clients to lookup either using DI, JNDI name. In my case I used JNDI lookup.
Now the code should look like this:
Session Bean interface:
#Local
public interface MySessionInterface {
// TODO :: declare business methods
}
Session bean implementation:
#stateless
public interface MySessionBeanImpl implements MySessionInterface {
// TODO :: implement business methods
}
Service Locator to lookup EJBs using JNDI:
public class ServiceLocator {
public final <T> T getLocalSession(Class<T> _class) throws NamingException {
return (T) new InitialContext().lookup("ejblocal:" + _class.getName());
}
}
Client:
public class SessionClient {
public void performOperation() {
try {
MySessionInterface session = ServiceLocator.getLocalSession(MySessionInterface.class);
// TODO :: perform business logic here
} catch (NamingException e) {
// TODO :: handle exception
}
}
}
Of course service locator can have the following improvements but I removed them for brevity:
Cache the result instead of looking it up everytime from the JNDI
Catch the checked exception NamingException and throw your own runtime exception
Hope you find it useful.
In both the ibm-ejb-jar-bnd.xml and ibm-ejb-jar-ext.xml files, the <session> element must contain the name of the EJB that it applies to. That name must match the name of an EJB defined in the corresponding ejb-jar.xml file, specifically the <ejb-name> element, or the name of the EJB identified by either the #Stateless, #Stateful, or #Singleton annotation. When using annotations, the name refers to either the name attribute of the annotation, or the simple class name.
Similarly, the <resource-ref> element must contain the name of the resource references that it applies to. In ejb-jar.xml, this would be the <res-ref-name> element. If the resource reference is defined via annotations, then the name element of the #Resource annotation, or the default name if not specified.
For various reasons I need to perform a manual lookup of SessionContext. In JBoss5, the solution
InitialContext initialContext = new InitialContext();
SessionContext sessionContext = (SessionContext) initialContext.lookup("java:comp/EJBContext");
has served med well, but from JBoss 7 I instead get a
javax.naming.NameNotFoundException: EJBContext -- service jboss.naming.context.java.global.EJBContext
Has something changed in how context is looked up in JBoss 7.2, or is my deployment lacking anything vital? For reference, standard injection works fine, this is the only lookup that fails. Or am I doing something terribly wrong (besides performing a manual lookup of SessionContext)?
According to specification of Java EJB (this one is for EJB 3.2. but nothing changed about EJBContext from previous one, EJB 3.x), you can inject EJBContext into your components either using annotation #Resource or manually via lookup (section 11.15):
The container must make a component’s EJBContext interface available either through injection
using the Resource annotation or in JNDI under the name java:comp/EJBContext
Standard way of looking up for EJB resource is via EJBContext.lookup method but there is also JNDI way which is the only possibilities if you don't have already EJBContext:
Context initCtx = new InitialContext();
EJBContext ejbCtx = (EJBContext) initCtx.lookup("java:comp/EJBContext");
This is exactly what you did, so what is wrong? There are two things, which one I'm not sure about. First, with manually lookup it's sometime needed to assign resource to component with annotation at class level:
#Resource(name = "EJBContext", type = javax.ejb.EJBContext)
public class MyComponent {
...
}
but I'm not sure is it needed for EJBContext as well, I guess not. The second thing, more important and critical - according to specification once again:
EJBContext objects accessed through the naming environment are only valid within the bean
instance that performed the lookup.
this one is section 11.15.1, and the next one, section 11.15.2:
The Container Provider is responsible for providing an appropriate EJBContext object to the refer-
encing component. The object returned must be of the appropriate specific type for the bean requesting
injection or performing the lookup—that is, the Container Provider must return an instance of the SessionContext interface to referencing session beans and an instance of the MessageDrivenCon-
text interface to message-driven beans.
Those both mean that injection and lookup for EJBContext are only valid in Enterprise Java Beans, so those which are annotated with #MessageDriven, #Stateful, #Singleton or #Stateless (or described as EJBs in deployment descriptor file, also as EJB 2.x Specification). Maybe your component isn't valid EJB and it's why lookup isn't working? This is only suggestion of course.
There's one more possibilities to get EJBContext (more correctly SessionContext). Your component should implements SessionBean interface which has setSessionContext(SessionContext sessionContext) method. This method should be invoked by EJB container every time when component is used (injected somewhere, invoked by client or timeout, especially when it's created) and inside this method you should assign sessionContext parameter to bean's field.
Using GlassFish 3.1.2, I try to call a Session Bean from a Netbeans platform module, and I get a null pointer exception. My problem is that I have no trace explaining how / where the NPE is generated.
The code in my Module is simply:
import ejb.MySessionRemote;
import javax.ejb.EJB;
public class TestServer {
#EJB
private static MySessionRemote mySession;
public boolean execute() {
System.out.println("result = " + mySession.getString()); //NPE here: mySession is null
return true;
}
}
The Session bean "My Session", the remote interface and the application deployed on the server side are just the ones from this tutorial: https://netbeans.org/kb/docs/javaee/entappclient.html
Any help greatly appreciated.
Note: I've checked this tutorial, without solving my issue.
If mySession is null, it was probably not injected. You can inject into managed beans (EJBs for example), because these instances are managed (created/removed) by a container, and the container does the injection for you.
You can possibly inject into a POJO, if you use CDI.
If TestServer is part of a stand-alone application for example, try to lookup the EJB using JNDI. This is what your tutorial does as well. It involves setting up the properties to get an InitialContext, and the lookup of the EJB using JNDI.
I am new to Java EE so my question may be very basic. I have built following REST web service with Stateless session bean (simplyfied):
#Path("/list/")
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#Stateless
public class ListResource {
#PersistenceContext(unitName = "unitName")
private EntityManager em;
#GET
#Path("/")
public List<Compound> getCompounds() {
List<Compound> list = tq.getResultList();
if (list.isEmpty()) {
throw new WebApplicationException(Response.status(404).entity("There are no compounds in database.").build());
}
return list;
}
}
It works like charm. Its accessible via URL and return JSON. Problem is that I have another part of the program written in plain Java that needs to use this Session bean as some kind of model to get all Compounds.
Problem is that when I initialize this Session bean somewhere it is outside of persistence context and therefore doesnt know EntityManager to access database. I believe.
I dont know what to do. Can I initialize class ListResource in distant part of code and have Dependency injection of EntityManager working? Or somehow to get persistence context and then initialize this session bean?
I hope it makes sense. Its complicated problem for me to describe.
If you have a web service and a standalone app calling the same bean, I would recommend you to move the functionality in a separate stateless bean and create remote and local interfaces to it. This way you can inject local bean into you web service bean, and call the remote one with jndi.
More about accessing Java EE beans here.
Alternatively, your client java code can call the web service to get all the data. Refer to this question about ways to connect to a RESTful service.
It is continues of question ( struts 2 bean is not created )
I'm using struts2 + toplink in my very simple web application under Tomcat.
On the page I would like use iteration tag. That is why I've declared some factory (SomeFactory) that resolves collection of entities (Entity).
Per article: http://download-uk.oracle.com/docs/cd/B32110_01/web.1013/b28221/usclient005.htm#CIHCEHHG
the only thing I need is declaration:
#PersistenceContext(unitName="name_in_persistence_xml")
public class SomeFactory
{
#PersistenceUnit(unitName="name_in_persistence_xml")
EntityManagerFactory emf;
public EntityManager getEntityManager() {
assert(emf != null); //HERE every time it is null
return emf.createEntityManager();
}
public Collection<Entity> getAll()
{
return getEntityManager().createNamedQuery("Entity.findAll").getResultList();
}
}
What is wrong? May be i miss something in web.xml? How to pre-init toplink for web application to allow injection happen?
You won't get anything injected by Tomcat which is not a Java EE container (and even with a Java EE 5 container, injection only works for managed components like servlets, filters, listeners, EJB, web service endpoints...). So you will have to create the EntityManagerFactory manually (typically in a servlet or a helper class) and get the EntityManager from it:
EntityManagerFactory emf = Persistence.createEntityManagerFactory(PU_NAME);
EntityManager entityManager = emf.createEntityManager();
Note that creating an EntityManagerFactory is a costly operation and should not be done for each request. However, creating an EntityManager is not and you should get one for each thread. But in your case, I'd suggest to use the struts2-persistenceplugin to handle this.
Thanks, but it seems [...] that Java EE is not mandatory to use injection [...] the Spring brings necessary engine for it.
Indeed. But you wrote "NO spring at all" in your other question and you didn't list any piece that could provide injection out of the box. Anyway, check out the struts2-persistenceplugin, it might be enough for your needs.