Unresolved <ejb-link>

11,363

Solution 1

I had the same issue when trying to deploy my application, NetBeans generated this code in my web.xml on its own.

Check your web.xml and see if you see this:

<ejb-local-ref>
        <ejb-ref-name>appName</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        <ejb-link>AppName#SomeClass</ejb-link>
    </ejb-local-ref>

if so just remove it comepletely, it should deploy after.

Solution 2

What is the name of your EJB module? Unless the jar file is named literally "TaskTool-ejb.jar", then you need to use either:

<ejb-link>TaskTool-ejb.jar#ContextFacade</ejb-link>

or:

<ejb-link>TaskTool-ejb/ContextFacade</ejb-link>

The latter assumes you haven't overridden the module-name in ejb-jar.xml.

Update: Based on your own comment, perhaps you need to use "com.oracle.eas_TaskTool-ejb_ejb_1.0-SNAPSHOT.jar#ContextFacade" or "com.oracle.eas_TaskTool-ejb_ejb_1.0-SNAPSHOT/ContextFacade".

Share:
11,363
retrodev
Author by

retrodev

Updated on June 30, 2022

Comments

  • retrodev
    retrodev almost 2 years

    I'm developing in NetBeans 7, with EJB3.1 and Glassfish 3.1. I am trying to reference the Local Interface of a Session Bean in a JAR from a POJO in a WAR. When I deploy to Glassfish I receive:

    SEVERE: Unresolved <ejb-link>: TaskTool-ejb#ContextFacade
    SEVERE: Exception while deploying the app [com.oracle.eas_TaskTool-ear_ear_1.0-SNAPSHOT]
    SEVERE: Error: Unresolved <ejb-link>: TaskTool-ejb#ContextFacade
    

    I used the NetBeans helper to generate the code to reference the Session Bean's Local Interface and it generated the <ejb-local-ref> section in web.xml for me.

    @Local
    public interface ContextFacadeLocal {
        void create(Context context);
        void edit(Context context);
        void remove(Context context);
        Context find(Object id);
        List<Context> findAll();
        List<Context> findRange(int[] range);
        int count();
        List<Context> findRootContexts();
    }
    
    @Stateless
    public class ContextFacade extends AbstractFacade<Context> implements ContextFacadeLocal {
        @PersistenceContext(unitName = "TaskToolPU")
        private EntityManager em;
    
        protected EntityManager getEntityManager() {
            return em;
        }
    
        public ContextFacade() {
            super(Context.class);
        }
    
        @Override
        public List<Context> findRootContexts() {
            CriteriaBuilder builder = em.getCriteriaBuilder();
            CriteriaQuery<Context> query = builder.createQuery(Context.class);
            Root<Context> c = query.from(Context.class);
            query.select(c).where(builder.isNull(c.get("parent")));
            query.orderBy(builder.asc(c.get("id")));
    
            TypedQuery<Context> q = em.createQuery(query);
            return q.getResultList();
        }
    }
    
    @FacesConverter(value = "contextConverter")
    public class contextConverter implements Converter {
    
        ContextFacadeLocal contextFacade = lookupContextFacadeLocal();
    
        @Override
        public Object getAsObject(FacesContext fc, UIComponent uic, String string) {
            return contextFacade.find(string);
        }
    
        @Override
        public String getAsString(FacesContext fc, UIComponent uic, Object o) {ntityManager() {
            return em;
        }
    
        public ContextFacade() {
            super(Context.class);
        }
    
        @Override
        public List<Context> findRootContexts() {
            CriteriaBuilder builder = em.getCriteriaBuilder();
            CriteriaQuery<Context> query = builder.createQuery(Context.class);
            Root<Context> c = query.from(Context.class);
            query.select(c).where(builder.isNull(c.get("parent")));
            query.orderBy(builder.asc(c.get("id")));
    
            TypedQuery<Context> q = em.createQuery(query);
            return q.getResultList();
        }
    }
    
    @FacesConverter(value = "contextConverter")
    public class contextConverter implements Converter {
    
        ContextFacadeLocal contextFacade = lookupContextFacadeLocal();
    
        @Override
        public Object getAsObject(FacesContext fc, UIComponent uic, String string) {
            return contextFacade.find(string);
        }
    
        @Override
        public String getAsString(FacesContext fc, UIComponent uic, Object o) {
            return ((Context) o).getId().toString();
        }
    
        private ContextFacadeLocal lookupContextFacadeLocal() {
            try {
                javax.naming.Context c = new InitialContext();
                //return (ContextFacadeLocal) c.lookup("java:global/com.oracle.eas_TaskTool-ear_ear_1.0-SNAPSHOT/com.oracle.eas_TaskTool-ejb_ejb_1.0-SNAPSHOT/ContextFacade!com.oracle.eas.ejbs.ContextFacadeLocal");
                return (ContextFacadeLocal) c.lookup("java:comp/env/TaskTool-ejb#ContextFacade");
    
            } catch (NamingException ne) {
                Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", ne);
                throw new RuntimeException(ne);
            }
        }
    }
    
    
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
        <context-param>
            <param-name>javax.faces.PROJECT_STAGE</param-name>
            <param-value>Development</param-value>
        </context-param>
        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>/faces/*</url-pattern>
        </servlet-mapping>
        <session-config>
            <session-timeout>
                30
            </session-timeout>
        </session-config>
        <welcome-file-list>
            <welcome-file>faces/index.xhtml</welcome-file>
        </welcome-file-list>
        <ejb-local-ref>
            <ejb-ref-name>ContextFacade</ejb-ref-name>
            <ejb-ref-type>Session</ejb-ref-type>
            <local>com.oracle.eas.ejbs.ContextFacadeLocal</local>
            <ejb-link>TaskTool-ejb#ContextFacade</ejb-link>
        </ejb-local-ref>
    </web-app>
    

    UPDATE

    For clarity:

    I don't have an ejb-jar.xml at all.

    Using either <ejb-link>TaskTool-ejb/ContextFacade</ejb-link> or <ejb-link>com.oracle.eas_TaskTool-ejb_ejb_1.0-SNAPSHOT/ContextFacade</ejb-link> works.

    Please see bkail answers below for explanation. Many thanks!

  • retrodev
    retrodev almost 13 years
    bkail, I don't have an ejb-jar.xml at all. Using either <ejb-link>TaskTool-ejb/ContextFacade</ejb-link> or <ejb-link>com.oracle.eas_TaskTool-ejb_ejb_1.0-SNAPSHOT/Conte‌​xtFacade</ejb-link> works. Could you explain the difference between using # or / and why I need this section in web.xml at all?
  • Brett Kail
    Brett Kail almost 13 years
    The # syntax is <uri>#<ejb-name>, where uri is the physical JAR name in the EAR, and ejb-name is the bean name (default is the short class name of the annotated EJB). The / syntax is <module-name>/<ejb-name>, where the module-name is specified in ejb-jar.xml (default is the URI without the extension). Can you elaborate on what you mean by "why I need this section in web.xml at all"? Do you mean the whole ejb-local-ref or the ejb-link?
  • retrodev
    retrodev almost 13 years
    I mean the ejb-local-ref. Glassfish 3.1 doesn't seem to need it.
  • Brett Kail
    Brett Kail almost 13 years
    The ejb-local-ref is declaring a reference to allow lookup("java:comp/env/ContextFacade"). If nothing in your code is using that (or you have an @EJB(name="ContextFacade") elsewhere), then you don't need the ejb-local-ref.
  • Twimnox
    Twimnox over 7 years
    Worked for me, I don't know what triggers netbeans to do this, it was the first time it happened when developing webservices...