EJB Lookup on remote server then local server
stonesoft May 9, 2014 6:52 AMIf we have 3 jars, Test.jar, Test2.jar, and Test3.jar on our local server running Jboss 7.2. On a remote server we have Test2.jar.
From the local server Test.jar needs to invoke a bean in Test2.jar on the remote server then invoke a bean in Test3.jar on the local server. How can this be done? I have the Remote lookup working thanks to Wolf-Dieter Fink but I cant get the second lookup to work. It gets a "No EJB receiver available" error.
I set up the remote and local servers following the server instance tutorial (added stuff to standalone-full.xml).
I use exclude-local-receivers in my jboss-ejb-client.xml so I lookup Test2 on the remote server instead of the local server. This is what causes me not to be able to lookup Test3.jar but I cant remove it because it also allows me to look up the remote Test2.jar.
BeanClient.java (looks up the remote bean and then the local bean.)
package org.kd.test; import org.kd.test2.Bean; import org.kd.test2.BeanRemote; import org.kd.test3.Bean3; import org.kd.test3.Bean3Remote; import org.kd.utilities.ejb.EjbLookup; import org.apache.log4j.Logger; public class BeanClient { private static final Logger log = Logger.getLogger(BeanClient.class); BeanRemote remoteBean; public void callRemoteBean (String inputString) { BeanRemote remoteBean = null; try { Object returnObj = EjbLookup.lookupEjbWithRetry(Bean.class, BeanRemote.class, 0); remoteBean = (BeanRemote) returnObj; if (remoteBean == null) { log.error("remoteBean not found"); } else { remoteBean.beanTest(inputString); } } catch (Exception ex) { ex.printStackTrace(); } Bean3Remote remoteBean3 = null; try { Object returnObj = EjbLookup.lookupEjbWithRetry(Bean3.class, Bean3Remote.class, 0); remoteBean3 = (Bean3Remote) returnObj; if (remoteBean3 == null) { log.error("remoteBean3 not found"); } else { remoteBean3.beanTest(inputString); } } catch (Exception ex) { ex.printStackTrace(); } } }
EjbLookup.java (does the lookup)
package org.kd.utilities.ejb; import java.lang.annotation.Annotation; import java.nio.file.Paths; import java.util.Properties; import javax.ejb.Local; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import org.apache.log4j.Logger; public class EjbLookup { private static final Logger log = Logger.getLogger(EjbLookup.class); private static Object getEjb (Class<?> remoteBean, Class<?> remoteInterface, String earName) throws NamingException { Properties env = new Properties(); env.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); env.put("jboss.naming.client.ejb.context", "true"); Context context = new InitialContext(env); if (earName == null) { earName = ""; } if (earName.length() > 0) { log.info("The app name is " + earName); } // 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 String moduleName = Paths.get(remoteBean.getProtectionDomain().getCodeSource().getLocation().getFile()).getFileName().toString(); log.info("The module name is " + moduleName); moduleName = moduleName.substring(0, moduleName.lastIndexOf('.')); // Get remote bean name and interface. Set the default lookup string for a remote bean String remoteBeanName = remoteBean.getSimpleName(); String remoteInterfaceName = remoteInterface.getName(); String lookupString = "ejb:" + earName + "/" + moduleName + "//" + remoteBeanName + "!" + remoteInterfaceName; //Check for a local bean annotation in the interface and change the lookup accordingly try { Annotation[] annotations = remoteInterface.getAnnotations(); for (Annotation annotation: annotations) { log.info("Annotation is " + annotation.toString()); if (annotation instanceof Local) { lookupString = "java:global/" + earName + "/" + moduleName + "//" + remoteBeanName + "!" + remoteInterfaceName; break; } } } catch (Exception ex) { log.error("Error getting annotations for " + remoteInterfaceName); } log.info("lookup " + lookupString); // let's do the lookup Object returnObject = null; try { returnObject = context.lookup(lookupString); } catch (Exception ex) { ex.printStackTrace(); } context.close(); log.info("Return the lookup object " + returnObject); return returnObject; } private static Object getEjbWithRetry(Class<?> remoteBean, Class<?> remoteInterface, String earName, Integer maxRetries) throws NamingException{ Object retVal = null; Integer curAttempt = -1; while ((curAttempt < maxRetries) && (retVal == null)) { log.info("Call EJB with " + remoteBean.getName() + " and " + remoteInterface); retVal = getEjb(remoteBean, remoteInterface, earName); curAttempt++; } return retVal; } // Lookup an Stateless EJB that is not in your jar file using the remoteBean class and the remoteInterface class public static Object lookupEjbWithRetry(Class<?> remoteBean, Class<?> remoteInterface, Integer maxRetries) { Object retVal = null; try { retVal = getEjbWithRetry(remoteBean, remoteInterface, "", maxRetries); } catch (Exception ex) { ex.printStackTrace(); } return retVal; } // Lookup an Stateless EJB that is not in your jar file using the remoteBean name and the remoteInterface name // Use this method if if your class is in an EAR public static Object lookupEjbWithRetry(Class<?> remoteBean, Class<?> remoteInterface, String earName, Integer maxRetries) { Object retVal = null; try { retVal = getEjbWithRetry(remoteBean, remoteInterface, earName, maxRetries); } catch (Exception ex) { ex.printStackTrace(); } return retVal; } }
Now the two simple beans, first the remote bean
BeanRemote.java (the interface for the remote bean)
package org.kd.test2; import javax.ejb.Remote; @Remote public interface BeanRemote { public void beanTest(String inputString); }
Bean.java (the remote bean)
package org.kd.test2; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import javax.ejb.Stateless; import org.apache.log4j.Logger; import org.jboss.ejb3.annotation.Pool; @Stateless @Pool(value="mymodel-pool") public class Bean implements BeanRemote { private static final Logger log = Logger.getLogger(Bean.class); public void beanTest(String inputString) { log.info(inputString); Path target = Paths.get("/home/redhat/Test.txt"); try { @SuppressWarnings("unused") Path file = Files.createFile(target); } catch (IOException ex) { ex.printStackTrace(); } } }
And the local bean
Bean3Remote.java
package org.kd.test3; import javax.ejb.Remote; @Remote public interface Bean3Remote { public void beanTest(String inputString); }
Bean3.jara
package org.kd.test3; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import javax.ejb.Stateless; import org.apache.log4j.Logger; import org.jboss.ejb3.annotation.Pool; @Stateless @Pool(value="mymodel-pool") public class Bean3 implements Bean3Remote { private static final Logger log = Logger.getLogger(Bean3.class); public void beanTest(String inputString) { log.info(inputString); Path target = Paths.get("/home/redhat/Test3.txt"); try { @SuppressWarnings("unused") Path file = Files.createFile(target); } catch (IOException ex) { ex.printStackTrace(); } } }