views:

1071

answers:

4

Hi

I am new to Java EE. I tried to get some first examples running (JPA). I am using Glassfish v3. The trouble is that I don't get the App Server injecting the EntityManager. Hear is one example http://www.adam-bien.com/roller/abien/entry/ejb_3_persistence_jpa_for which I extended with a JSP client.

Entity:


package beans;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Book {

    @Id
    @GeneratedValue
    private Long id;
    private String title;
    private String subtitle;

    public Book() {
    }

    public Book(String title) {
        this.title = title;
    }
}

BookService Interface:


package beans;
import javax.ejb.Local;

@Local
public interface BookService {
    Book createOrUpdate(Book book);
    void remove(Book book);
    Book find(Object id);
}

BookServiceBean:


package beans;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class BookServiceBean implements BookService {

    @PersistenceContext
    private EntityManager em;

    public Book createOrUpdate(Book book) {
        return em.merge(book);
    }
    public void remove(Book book) {
        em.remove(em.merge(book));
    }
    public Book find(Object id) {
        return em.find(Book.class, id);
    }
}

persistence.xml:

<persistence>
    <persistence-unit name="sample" transaction-type="JTA">
    <jta-data-source>jdbc/MarcelsDataSource</jta-data-source>
    <properties>
        <property name="eclipselink.ddl-generation" value="create-tables"/>
    </properties>
</persistence-unit>
</persistence>

index.jsp:

<%@ page import="beans.BookServiceBean" %>
<%@ page import="beans.Book" %>
<html>
<body>
<%
    BookServiceBean bs = new BookServiceBean();
    Book b = new Book("Superman");
    bs.createOrUpdate(b);
%>
</body>
</html>

If I run the example I get a java.lang.NullPointerException in the createOrUpdate() method so the entityManager is obviously not injected correctly. I tried to find a remedy for days now and some help would be highly appreciated.

Thanks

Marcel

A: 

Try:

@PersistenceContext(unitName = "sample")
private EntityManager em;
Enno Shioji
That won't help as long as he is using the constructor.
Willi
Thank you. I changed this already and it doesn't seem to be the problem
Marcel Menz
A: 

You are instantiating the service bean directly, when you really need to be having the container inject it (via @EJB). This isn't supported in a JSP, though, so you'll have to switch to a servlet as well.

jsight
Thank you very much. If I use @EJB in a servlet I get a compilation error: The annotation @EJB is disallowed for this location. MMMMMMMMMMarcel
Marcel Menz
Could you mabye post a little example. sorry i am a novice
Marcel Menz
Ok. It has to be outside of the methods now I get a very nice Exception:
Marcel Menz
Exception:javax.naming.NamingException: Lookup failed for 'java:comp/env/controllers.BookController/bs' in SerialContext [Root exception is javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=controllers.BookController/bs,Remote 3.x interface =beans.BookServiceBean,ejb-link=null,lookup=null,mappedName=,jndi-name=beans.BookServiceBean,refType=Session' .
Marcel Menz
Actual (possibly internal) Remote JNDI name used for lookup is 'beans.BookServiceBean#beans.BookServiceBean' [Root exception is javax.naming.NamingException: Lookup failed for 'beans.BookServiceBean#beans.BookServiceBean' in SerialContext [Root exception is javax.naming.NameNotFoundException: beans.BookServiceBean#beans.BookServiceBean not found]]]
Marcel Menz
+3  A: 

You get a NullPointerException because you are instantiating your BookService with a new() - which is basically wrong - and nothing gets injected in the EJB. EJB are component that are managed by the container and should be obtained either via injection or with a lookup.

Here, while the JSP spec allows any code to be run in a scriplet, calling an EJB from a JSP is actually not really encouraged and JSPs don't support injection. In other words, you'll have to use a lookup:

<%@ page import="beans.BookService" %>
<%@ page import="beans.Book" %>
<html>
<body>
<%
    BookService bs = (BookService) new InitialContext().lookup("java:module/BookServiceBean")
    Book b = new Book("Superman");
    bs.createOrUpdate(b);
%>
</body>
</html>

But you should call your EJB from a Servlet or a JSF Managed Bean (and your EJB could be injected in such components).

If you need some samples, have a look at the Java EE Code Samples & Apps.

Update: See How do I access a Local EJB component from a POJO? in the EJB FAQ for more details on JNDI (especially the new portable global JNDI names defined by the EJB 3.1 specification).

Pascal Thivent
Thank you very much. Very good explanation. I get: javax.naming.NameNotFoundException: BookServiceBean not found???
Marcel Menz
@Marcel I was not totally sure about the JNDI name under which the bean would be available. Look at the GlassFish console, the JDNI name should be logged in there.
Pascal Thivent
It worked like this:InitialContext().lookup("java:module/BookServiceBean");Thank you again.Greets
Marcel Menz
@Marcel You're welcome. Have fun with GlassFish :)
Pascal Thivent
A: 
public class BookController extends HttpServlet {

private static final long serialVersionUID = 1L;
@EJB
BookServiceBean bs;

public BookController() {
    super();
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    Book b = new Book("Superman");
    bs.createOrUpdate(b);

}
}

This is what I do now. It leads to:

javax.naming.NamingException: Lookup failed for 'java:comp/env/controllers.BookController/bs' 
in SerialContext  
[Root exception is javax.naming.NamingException: Exception resolving Ejb for 
'Remote ejb-ref name=controllers.BookController/bs,Remote 3.x interface   =beans.BookServiceBean,ejb-link=null,lookup=null,mappedName=,jndi-
name=beans.BookServiceBean,refType=Session' .  
Actual (possibly internal) Remote JNDI name used for lookup is 
'beans.BookServiceBean#beans.BookServiceBean' [Root exception is 
javax.naming.NamingException: Lookup failed for 
'beans.BookServiceBean#beans.BookServiceBean' in SerialContext  [Root exception is 
javax.naming.NameNotFoundException: beans.BookServiceBean#beans.BookServiceBean not found]]]

uppsssss

Marcel Menz
Please post this as a new question (one question = one problem).
Pascal Thivent