开发者

EntityManager injection results in NullPointerException

开发者 https://www.devze.com 2022-12-17 11:17 出处:网络
I\'m writing my first Java EE (EJB + Servlets etc.) application (please note: I\'m using Eclipse). I\'m stuck with a problem with EntityManager injection not working, and having some difficulties find

I'm writing my first Java EE (EJB + Servlets etc.) application (please note: I'm using Eclipse).

I'm stuck with a problem with EntityManager injection not working, and having some difficulties finding why due to my Java EE (and Java in general) noobness.

Here is my persistence.xml file - I think this is mostly correct, since I can launch the HSQL database manager from the JMX console and my PUBLIC.USER table shows up correctly.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="MyPu">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:/DefaultDS</jta-data-source>
        <properties>
    开发者_运维问答        <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
        </properties>
    </persistence-unit>
</persistence>

Here's my servlet code:

[...]
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws      
    String id = request.getParameter("username");
    String password = request.getParameter("password");

    UserManagerBean um = new UserManagerBean();
    um.register(username, password);

    RequestDispatcher dispatcher=getServletContext().getRequestDispatcher("/index.jsp");
    dispatcher.forward(request, response);
}

And here's my UserManagerBean Class:

//bunch of imports

import myPackage.UserManager;

public @Stateful class UserManagerBean implements UserManager {
    @PersistenceContext(unitName="MyPu")
    private EntityManager persistManager;

    public void register(String username, String password) {
        User user = new User(userame, password);
        persistManager.persist(user);
        persistManager.flush();
    }
}

The persistManager.persist(user) line throws a NullPointerException. From my own searching I understood that this is happening because, since I'm calling new() on UserManagerBean the injection from the @PersistenceContext annotation never takes place and persistManager never gets bound.

If so, it is evident that I'm missing something about the proper usage of EJBs.

What is the right way to instantiate my bean? What's with the interfaces? I'm not entirely sure if my bean should be stateful or stateless :\

Additional info:

I changed code in my servlet, from

UserManagerBean um = new UserManagerBean();

to

@EJB
private UserManagerBean um;

in the appropriate place. Now um is the NullPointer.


Quoting Referencing EJB3 Session Beans from non-EJB3 Beans from the JBoss documentation:

JBoss Application Server 4.2.2 implemented EJB3 functionality by way of an EJB MBean container running as a plugin in the JBoss Application Server. This had certain implications for application development.

The EJB3 plugin injects references to an EntityManager and @EJB references from one EJB object to another. However this support is limited to the EJB3 MBean and the JAR files it manages. Any JAR files which are loaded from a WAR (such as Servlets, JSF backing beans, and so forth) do not undergo this processing. The Java 5 Enterprise Edition standard specifies that a Servlet can reference a Session Bean through an @EJB annotated reference, this was not implemented in JBoss Application Server 4.2.2.

So even though the Java EE 5 specification stipulates a wider scope of the @EJB annotation, JBoss 4.2.2 doesn't support it. In fact JBoss 4.2.2 is a transitional version that doesn't claim full Java EE 5 compliance.

Consequently, either:

  • Stick with you actual version of JBoss but use a JDNI lookup to get your bean - or -
  • Swith to JBoss 5 AS that fully supports the entire Java 5 Enterprise Edition specification (but has horrible startup performances) - or -
  • Swith to another Java EE 5 application server like GlassFish v2 (or even v3) or WebLogic 10. I'd go with GFv3.


As Petar Minchev said in the comments above @EJB doesn't work in servlets with JBoss 4.2.

In your WAR (in the WEB-INF directory) you'll need to modify two files:

web.xml:

<ejb-local-ref>
        <ejb-ref-name>ejb/UserManager</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        <local-home/>
        <local>myPackage.UserManager</local>
</ejb-local-ref> 

jboss-web.xml:

<?xml version='1.0' encoding='ISO-8859-1'?>
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.3//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_3_2.dtd">
<jboss-web>

  <ejb-local-ref>
    <ejb-ref-name>ejb/UserManager</ejb-ref-name>
    <local-jndi-name>[earname]/UserManagerBean/local</local-jndi-name>
  </ejb-local-ref>

</jboss-web>

You can then get an instance of your EJB by doing:

UserManagerBean um = (UserManager)new InitialContext().lookup( "java:comp/env/ejb/UserManager" );


As per the comments, it turns out that you indeed are using an appserver which doesn't support it at all -as I expected. To resolve this, you have 3 options:

  1. Use "good old" XML config files.
  2. Upgrade the server (there's already a stable 5.1.0).
  3. Replace the server (I can recommend Glassfish v3 to be the most up-to-date).


To enable dependency injection on your project make sure that you have the file "beans.xml" and it is properly located.

  • For WAR packaging the location is src/main/webapp/WEB-INF/
  • For JAR and EAR packaging the location is src/main/resources/META-INF/

If you have several maven modules you must have it on each module.

More information about beans.xml

0

精彩评论

暂无评论...
验证码 换一张
取 消