Search code examples
servletsglassfishejbjndi

EJB JNDI with Glassfish


I'm trying to get EJB to work with Glassfish v3. I'm working on a Java EE Web application with Servlets.

When I deploy this web app to Glassfish, it registers the EJB class into the

java:global JNDI tree. But, when I try to inject an instance of this into my

Servlet I got a NameNotFoundException.

When I look at the logs of my server, the Servlet tries to do the look up in java:comp/env.

Can someone help me to solve this?

Relevant code for the login part:

UserDao.java

@Local
public interface UserDao {
    public User find(Long id);

    public List<User> findAll();

    public List<User> paginate(int offset, int nbentry) throws IllegalArgumentException, IllegalStateException;

    public User findUserByUsernameAndPassword(String username, String password);

    public User create(User user) throws UserException;

    public User update(User user) throws UserException;

    public Boolean delete(User user) throws UserException;

    public int count();
}

JpaUserDao.java

@Stateless
public class JpaUserDao implements UserDao {
    private Logger log = Logger.getLogger(JpaUserDao.class.getSimpleName());
    @PersistenceContext(unitName = "YouFood-PU")
    private EntityManager em;

    @Override
    public User create(User user) throws UserException {
        try {
            em.persist(user);
    } catch (Exception e) {

        throw new UserException("Creation of the user: " + user
                + " failed, please try later or contact the webmaster");
    }

    return user;
}

@Override
public User update(User user) throws UserException {
    try {
        em.persist(em.merge(user));
    } catch (Exception e) {
        throw new UserException("Update of the user: " + user
                + " failed, please try later or contact the webmaster");
    }

    return user;
}

@Override
public Boolean delete(User user) throws UserException {
    try {
        em.remove(em.merge(user));
        return true;
    } catch (Exception e) {
        throw new UserException("Deletion of the user: " + user
                + " failed, please try later or contact the webmaster");
    }
}

@Override
public User find(Long id) {
    User user = new User();

    try {
        user = em.find(User.class, id);
        return user;
    } catch (Exception e) {
        return null;
    }
}

@Override
public User findUserByUsernameAndPassword(String username, String password) {
    User user = null;
    try {
        log.info("findUserByUsernameAndPassword");
        user = (User) em
                .createQuery(
                        "SELECT u FROM User AS u where u.username = :username AND u.password = :password ")
                .setParameter("username", username)
                .setParameter("password", password).getSingleResult();
        return user;
    } catch (Exception e) {
        e.printStackTrace();
        log.severe(e.getStackTrace().toString());
        return null;
    }
}

@SuppressWarnings("unchecked")
@Override
public List<User> findAll() {
    List<User> users = null;
    try {

        users = (List<User>) em.createQuery("SELECT u FROM User u")
                .getResultList();
        return users;
    } catch (Exception e) {
        return null;
    }

}

@SuppressWarnings("unchecked")
@Override
public List<User> paginate(int offset, int nbentry)
        throws IllegalArgumentException, IllegalStateException {
    List<User> users = null;

    users = (List<User>) em.createQuery("FROM User").setFirstResult(offset)
            .setMaxResults(nbentry).getResultList();

    return users;
}

@Override
public int count() {
    Number count;

    count = (Number) em.createQuery("SELECT COUNT(u.id) FROM User")
            .getSingleResult();

    return count.intValue();
}
}

Authenticator.java

@Stateless
public class Authenticator {

private String userFullName;
private Long userId;

@EJB
private JpaUserDao userDao;

public Authenticator() {}

public AuthenticationError connect(String username, String password)
        throws Exception {

    String hashed_password = Authenticator.hash(password, "UTF-8");

    User user = null;

    user = userDao.findUserByUsernameAndPassword(username,
            hashed_password);

    if (user == null) {
        return AuthenticationError.UserNotFound;
    }

    this.userFullName = user.toString();
    this.userId = user.getId();

    return AuthenticationError.Success;
}

public Boolean disconnect(HttpSession session) throws Exception {
    try {
        session.invalidate();
        return true;
    } catch (Exception e) {
        return false;
    }

}

public String getUserFullName() {
    return this.userFullName;
}

public Long getUserId() {
    return this.userId;
}

/**
 * 
 * Static method
 * 
 * @throws Exception
 * 
 */

public static String hash(String data, String charset) throws Exception {
    MessageDigest md = MessageDigest.getInstance("MD5");
    md.reset();
    md.update(data.getBytes(charset), 0, data.length());
    String hash = new BigInteger(1, md.digest()).toString(16);
    return hash;
}

}

LoginServlet.java

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

private static final long serialVersionUID = 1L;
private Logger log = Logger.getLogger(LoginServlet.class.getSimpleName());
@EJB
private Authenticator auth;

/**
 * @see HttpServlet#HttpServlet()
 */
public LoginServlet() {
    super();
    // TODO Auto-generated constructor stub
}

/**
 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
 */
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
    log.info("LoginServlet.deGet() call");
    request.getRequestDispatcher("/jsp/login.jsp").forward(request, response);
}

/**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
 */
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    //auth = new Authenticator();

    log.info("LoginServlet.dePost() call");
    String message = null;
    String username = request.getParameter("username");
    String password = request.getParameter("password");

    log.info("username: " + username);
    log.info("password: " + password);

    try {
        AuthenticationError status = auth.connect(username, password);
        System.out.println(status);
        switch (status) {
            case PasswordMissMatch:
                message = "Password missmatch";
                log.info(message);
                request.setAttribute("error", message);
                request.getRequestDispatcher("/jsp/login.jsp").forward(request, response);
                break;
            case Success:
                message = "Your are successfully logged in";
                log.info(message);
                request.setAttribute("success", message);
                request.getSession().setAttribute("loggedIn", true);
                request.getSession().setAttribute("full_name", auth.getUserFullName());
                request.getSession().setAttribute("user_id", auth.getUserId());
                break;
            case UserNotFound:
                message = "Username provided not found in our record";
                log.info(message);
                request.setAttribute("error", message);
                request.getRequestDispatcher("/jsp/login.jsp").forward(request, response);
                break;
        }
    } catch (GeneralSecurityException e) {

        message = e.getMessage();
        request.setAttribute("error", message);

    } catch (Exception e) {
        message = e.getMessage();
        request.setAttribute("error", message);
    }

    request.getRequestDispatcher("/home").forward(request, response);
}
}

Glassfish Deploy log

INFO: closing
ATTENTION: DPL8027: Ignore WEB-INF/sun-web.xml in archive 
/Users/guillaume/Documents/workspace/Supinfo/YouFood/nbbuild/web/, as GlassFish 
counterpart runtime xml WEB-INF/glassfish-web.xml is present in the same 
archive.

INFO: Processing PersistenceUnitInfo [
    name: YouFood-PU
    ...]
INFO: Binding entity from annotated class: com.youfood.entity.Menu
INFO: Bind entity com.youfood.entity.Menu on table Menu
INFO: Binding entity from annotated class: com.youfood.entity.DinningRoom
INFO: Bind entity com.youfood.entity.DinningRoom on table DinningRoom
INFO: Binding entity from annotated class: com.youfood.entity.Item
INFO: Bind entity com.youfood.entity.Item on table Item
INFO: Binding entity from annotated class: com.youfood.entity.TTable
INFO: Bind entity com.youfood.entity.TTable on table TTable
INFO: Binding entity from annotated class: com.youfood.entity.Zone
INFO: Bind entity com.youfood.entity.Zone on table Zone
INFO: Binding entity from annotated class: com.youfood.entity.Country
INFO: Bind entity com.youfood.entity.Country on table Country
INFO: Binding entity from annotated class: com.youfood.entity.User
INFO: Bind entity com.youfood.entity.User on table User
INFO: Binding entity from annotated class: com.youfood.entity.Order
INFO: Bind entity com.youfood.entity.Order on table OrderTable
INFO: Binding entity from annotated class: com.youfood.entity.Restaurant
INFO: Bind entity com.youfood.entity.Restaurant on table Restaurant
INFO: Mapping collection: com.youfood.entity.DinningRoom.zones -> Zone
INFO: Mapping collection: com.youfood.entity.Zone.tables -> TTable
INFO: Mapping collection: com.youfood.entity.Country.restaurants -> Restaurant
INFO: Mapping collection: com.youfood.entity.Restaurant.dinningRoom -> DinningRoom
INFO: Hibernate Validator not found: ignoring
INFO: Unable to find org.hibernate.search.event.FullTextIndexEventListener on the classpath. Hibernate Search is not enabled.
INFO: Initializing connection provider: org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider
INFO: Using provided datasource
INFO: RDBMS: MySQL, version: 5.1.54
INFO: JDBC driver: MySQL-AB JDBC Driver, version: mysql-connector-java-5.1.13 ( Revision: ${bzr.revision-id} )
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
INFO: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
INFO: Transaction strategy: org.hibernate.ejb.transaction.JoinableCMTTransactionFactory
INFO: instantiating TransactionManagerLookup: org.hibernate.transaction.SunONETransactionManagerLookup
INFO: instantiated TransactionManagerLookup
INFO: Automatic flush during beforeCompletion(): disabled
INFO: Automatic session close at end of transaction: disabled
INFO: JDBC batch size: 15
INFO: JDBC batch updates for versioned data: disabled
INFO: Scrollable result sets: enabled
INFO: JDBC3 getGeneratedKeys(): enabled
INFO: Connection release mode: auto
INFO: Maximum outer join fetch depth: 2
INFO: Default batch fetch size: 1
INFO: Generate SQL with comments: disabled
INFO: Order SQL updates by primary key: disabled
INFO: Order SQL inserts for batching: disabled
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
INFO: Using ASTQueryTranslatorFactory
INFO: Query language substitutions: {}
INFO: JPA-QL strict compliance: enabled
INFO: Second-level cache: enabled
INFO: Query cache: disabled
INFO: Cache region factory : org.hibernate.cache.impl.NoCachingRegionFactory
INFO: Optimize cache for minimal puts: disabled
INFO: Structured second-level cache entries: disabled
INFO: Statistics: disabled
INFO: Deleted entity synthetic identifier rollback: disabled
INFO: Default entity-mode: pojo
INFO: Named query checking : enabled
INFO: Check Nullability in Core (should be disabled when Bean Validation is on): disabled
INFO: building session factory
INFO: Not binding factory to JNDI, no JNDI name configured
INFO: JNDI InitialContext properties:{}
INFO: EJB5181:Portable JNDI names for EJB JpaUserDao: [java:global/YouFood/JpaUserDao, java:global/YouFood/JpaUserDao!com.youfood.dao.UserDao]
INFO: EJB5181:Portable JNDI names for EJB Authenticator: [java:global/YouFood/Authenticator!com.youfood.backoffice.utils.Authenticator, java:global/YouFood/Authenticator]
INFO: WEB0671: Loading application [YouFood] at [/web]
INFO: YouFood a été déployé en 1 279 ms.

Server Log Exception

GRAVE: EJB5070: Exception creating stateless session bean : [Authenticator]
ATTENTION: EJB5184:A system exception occurred during an invocation on EJB Authenticator, method: public com.youfood.backoffice.utils.AuthenticationError com.youfood.backoffice.utils.Authenticator.connect(java.lang.String,java.lang.String) throws java.lang.Exception
ATTENTION: javax.ejb.EJBException: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
    at com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:454)
    at com.sun.ejb.containers.BaseContainer.getContext(BaseContainer.java:2547)
    at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1899)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
    at $Proxy150.connect(Unknown Source)
    at com.youfood.backoffice.utils.__EJB31_Generated__Authenticator__Intf____Bean__.connect(Unknown Source)
    at com.youfood.backoffice.servlet.LoginServlet.doPost(LoginServlet.java:61)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:688)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1542)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
    at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129)
    at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:849)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:746)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1045)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:228)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:680)
Caused by: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
    at com.sun.ejb.containers.StatelessSessionContainer$SessionContextFactory.create(StatelessSessionContainer.java:726)
    at com.sun.ejb.containers.util.pool.NonBlockingPool.getObject(NonBlockingPool.java:247)
    at com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:449)
    ... 39 more
Caused by: javax.ejb.CreateException: Could not create stateless EJB
    at com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:534)
    at com.sun.ejb.containers.StatelessSessionContainer.access$000(StatelessSessionContainer.java:95)
    at com.sun.ejb.containers.StatelessSessionContainer$SessionContextFactory.create(StatelessSessionContainer.java:724)
    ... 41 more
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException: Exception lors de la tentative d'injection de l'élément Remote ejb-ref name=com.youfood.backoffice.utils.Authenticator/userDao,Remote 3.x interface =com.youfood.dao.jpa.JpaUserDao,ejb-link=null,lookup=,mappedName=,jndi-name=com.youfood.dao.jpa.JpaUserDao,refType=Session dans class com.youfood.backoffice.utils.Authenticator : Lookup failed for 'java:comp/env/com.youfood.backoffice.utils.Authenticator/userDao' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming}
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:703)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:470)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:171)
    at com.sun.ejb.containers.BaseContainer.injectEjbInstance(BaseContainer.java:1694)
    at com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:494)
    ... 43 more
Caused by: javax.naming.NamingException: Lookup failed for 'java:comp/env/com.youfood.backoffice.utils.Authenticator/userDao' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=com.youfood.backoffice.utils.Authenticator/userDao,Remote 3.x interface =com.youfood.dao.jpa.JpaUserDao,ejb-link=null,lookup=,mappedName=,jndi-name=com.youfood.dao.jpa.JpaUserDao,refType=Session' .  Actual (possibly internal) Remote JNDI name used for lookup is 'com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao' [Root exception is javax.naming.NamingException: Lookup failed for 'com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao not found]]]
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:518)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455)
    at javax.naming.InitialContext.lookup(InitialContext.java:392)
    at javax.naming.InitialContext.lookup(InitialContext.java:392)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:599)
    ... 47 more
Caused by: javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=com.youfood.backoffice.utils.Authenticator/userDao,Remote 3.x interface =com.youfood.dao.jpa.JpaUserDao,ejb-link=null,lookup=,mappedName=,jndi-name=com.youfood.dao.jpa.JpaUserDao,refType=Session' .  Actual (possibly internal) Remote JNDI name used for lookup is 'com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao' [Root exception is javax.naming.NamingException: Lookup failed for 'com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao not found]]
    at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:191)
    at com.sun.enterprise.container.common.impl.ComponentEnvManagerImpl$EjbReferenceProxy.create(ComponentEnvManagerImpl.java:1109)
    at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:776)
    at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:744)
    at com.sun.enterprise.naming.impl.JavaURLContext.lookup(JavaURLContext.java:169)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:498)
    ... 51 more
Caused by: javax.naming.NamingException: Lookup failed for 'com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao not found]
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:518)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455)
    at javax.naming.InitialContext.lookup(InitialContext.java:392)
    at javax.naming.InitialContext.lookup(InitialContext.java:392)
    at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:186)
    ... 56 more
Caused by: javax.naming.NameNotFoundException: com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao not found
    at com.sun.enterprise.naming.impl.TransientContext.doLookup(TransientContext.java:248)
    at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:215)
    at com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup(SerialContextProviderImpl.java:77)
    at com.sun.enterprise.naming.impl.LocalSerialContextProviderImpl.lookup(LocalSerialContextProviderImpl.java:119)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:505)
    ... 60 more

Solution

  • My guess is that you specified names, mapped names and what have you. This is not needed.

    Something like the following should work:

    EJB:

    @Stateless
    public class MyBean {
        // ...
    }
    

    Servlet:

    @WebServlet(urlPatterns="/someurl")
    public class MyServlet extends HttpServlet {
    
        @EJB
        private MyBean myBean;       
    
        @Override
        public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // ...
        }        
    }
    

    UPDATE:

    After seeing your code, the problem is not the injection of the EJB into the Servlet, but the injection of JpaUserDao in Authenticator.

    You are injecting it by class, but this will not work since JpaUserDao implements a business interface: UserDao. Because it implements such an interface, there will be no local-view created. As a result, you have to inject using the interface:

    @Stateless
    public class Authenticator {
    
        private String userFullName;
        private Long userId;
    
        @EJB
        private UserDao userDao;
    
        // ...
    }
    

    As an extra note, the concept of your Authenticator bean is not going to work. It's a stateless bean and its instance variables will have no meaning to the outside world. Thus, getUserFullName() is not guaranteed to return the result you think it will return. It may happen to work momentarily for you in a test when the container happens to select the same bean instance, but this will not work in general.

    Even when you hold on to the reference of an Authenticator, it will still not work. The thing is you get a proxy, and the container will potentially direct every call to it to another instance. Think of it as a URL to servers in a web farm where a browser does a call to. You have no guarantee that two successive will go to the exact same physical server.

    The authentication that you're trying to do there should be handled by a bean in the web layer and the authentication details put in the HTTP session (additionally, you should maybe use container authentication as well, but that's a whole other thing that's too off-topic here)