3
votes

I'm using WildFly 8.1.0 Final release.

My application is a JavaEE web app deployed in a WAR (there is no EJB module .ear).

I want to programmatically invoke local EJB with his name using JNDI.

The EJB are just annotated with @Stateless (there is no Local or Remote interfaces)

I try below function:

private <E extends DomainObject> CrudService<E> lookUp(Class<E> cl) {
    try {
        final Hashtable jndiProperties = new Hashtable();
        jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
        final Context context = new InitialContext(jndiProperties);
        // The app name is the application name of the deployed EJBs. This is typically the ear name
        // without the .ear suffix. However, the application name could be overridden in the application.xml of the
        // EJB deployment on the server.
        // Since we haven't deployed the application as a .ear, the app name for us will be an empty string
        final String appName = "";
        // This is the module name of the deployed EJBs on the server. This is typically the jar name of the
        // EJB deployment, without the .jar suffix, but can be overridden via the ejb-jar.xml
        // In this example, we have deployed the EJBs in a jboss-as-ejb-remote-app.jar, so the module name is
        // jboss-as-ejb-remote-app
        final String moduleName = "jboss-as-ejb-remote-app";
        // AS7 allows each deployment to have an (optional) distinct name. We haven't specified a distinct name for
        // our EJB deployment, so this is an empty string
        final String distinctName = "";
        // The EJB name which by default is the simple class name of the bean implementation class
        final String serviceName = cl.getSimpleName() + "Service";
        // let's do the lookup
        return (CrudService<E>) context.lookup("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + serviceName );
        //return (CrudService<E>) context.lookup(serviceName);
    } catch (NamingException e) {
        log.error("NamingException {}",e) ;
        throw new RuntimeException(e) ;
    }
}

but it doesn't work (obviusly it's for remote EJB)

But I don't find any example for local EJB in a WAR with WildFly and I have no idea how to do, I don't use JNDI often...

I found a work arround annotating EJB with @Named(value="EjbClassName") and invoke them using JSF.

FacesContext context = FacesContext.getCurrentInstance() ;
return context.getApplication().evaluateExpressionGet(context, "#{"+cl.getSimpleName()+"Service}", CrudService.class) ;

And it's working,

but I'd prefer not using JSF as it's not related to the view layer.

2
Once you deploy the war, the WildFly server doesn't log the JNDI names that are being loaded? In glassfish I do this to figure out the correct lookup string...Yamada

2 Answers

3
votes

Thank you Yamada the JNDI names appear in the server logs at startup

this solution works:

private <E extends DomainObject> CrudService<E> lookUp(@NonNull Class<E> entityClass) throws NamingException {
    try {
        final Hashtable jndiProperties = new Hashtable();
        jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
        final Context context = new InitialContext(jndiProperties);
        return (CrudService<E>) context.lookup("java:module/"+entityClass.getSimpleName()+"Service");
    } catch (NamingException e) {
        log.error("lookUp({}) throws NamingException {}",entityClass.getSimpleName(),e.getMessage()) ;
        throw e ;
    }
}

without annotate EJB with @LocalBean

0
votes

Just a short answer from mobile: Use @LocalBean for a no-Interface view of your bean. Add this to your stateless session bean and you should find it in the jndi view of your Server.