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();
}
}
}