JBoss ESB 4.3.GA and EJBProcessor
heinzw Jul 31, 2008 4:02 PMHello,
we use in a project the jboss esb 4.3.GA. We try to invoke a method of a Stateless EJB 3.0 SessionBean with the EJBProcessor implementation of the esb. We got an ClassCastException because the Remote Interface of the SessionBean can't Cast to a EJBHome Interface. We fixed the problem with the folling code and we want to give it back to the community.
import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Map.Entry; import javax.naming.ConfigurationException; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import org.apache.log4j.Logger; import org.jboss.soa.esb.actions.AbstractActionLifecycle; import org.jboss.soa.esb.actions.ActionLifecycleException; import org.jboss.soa.esb.actions.ActionProcessingException; import org.jboss.soa.esb.helpers.ConfigTree; import org.jboss.soa.esb.message.Body; import org.jboss.soa.esb.message.Message; /** * * @author Akquinet AG * */ public class EJBProcessor extends AbstractActionLifecycle { private static final Logger log = Logger.getLogger(EJBProcessor.class); public static final String EJB_NAME = "ejb-name"; public static final String JNDI_NAME = "jndi-name"; public static final String EJB_METHOD = "method"; public static final String JAVA_TYPE = "type"; public static final String INICTXFACTORY = "initial-context-factory"; public static final String PROVIDERURL = "provider-url"; public static final String OUT_VAR = "esb-out-var"; public static final String DEFAULT_OUT = "DEFAULT_EJB_OUT"; public static final int ARG_PREFIX_LENGTH = 3; private final ConfigTree configTree; private Map<String, String> ejbRef; private Map<Integer, Argument> ejbParams; private List<String> ejbParamTypeNames; private Properties props; public EJBProcessor(ConfigTree config) { assert config != null; configTree = config; } @Override public void initialise() throws ActionLifecycleException { ejbRef = new HashMap<String, String>(); ejbParams = new HashMap<Integer, Argument>(); ejbParamTypeNames = new ArrayList<String>(); // Get the configuration from jboss-esb.xml ejbRef.put(EJB_NAME, configTree.getAttribute(EJB_NAME)); ejbRef.put(JNDI_NAME, configTree.getAttribute(JNDI_NAME)); ejbRef.put(EJB_METHOD, configTree.getAttribute(EJB_METHOD)); ejbRef.put(INICTXFACTORY, configTree.getAttribute(INICTXFACTORY)); ejbRef.put(PROVIDERURL, configTree.getAttribute(PROVIDERURL)); if (configTree.getAttribute(OUT_VAR) != null) { ejbRef.put(OUT_VAR, configTree.getAttribute(OUT_VAR)); } else { ejbRef.put(OUT_VAR, DEFAULT_OUT); } log.debug("ejbRef = " + ejbRef); // Get all parameters for the EJB method, defined in jboss-esb.xml ConfigTree[] subElements = configTree.getAllChildren(); for (ConfigTree child : subElements) { Integer argNum; String jType; String esbLocation; argNum = Integer.parseInt(child.getName().substring(ARG_PREFIX_LENGTH)); jType = child.getAttribute(JAVA_TYPE); esbLocation = child.getWholeText(); ejbParams.put(argNum, new Argument(jType, esbLocation)); ejbParamTypeNames.add(jType); } log.debug("ejbParams = " + ejbParams); log.debug("ejbParamTypeNames = " + ejbParamTypeNames); // Check for missing configuration values for (Entry<String, String> entry : ejbRef.entrySet()) { if (entry.getValue() == null) { throw new ActionLifecycleException("Value for key '" + entry.getKey() + "' may not be null"); } } // Build Properties for InitialContext lookup props = new Properties(); props.put(Context.INITIAL_CONTEXT_FACTORY, ejbRef.get(INICTXFACTORY)); props.put(Context.PROVIDER_URL, ejbRef.get(PROVIDERURL)); log.debug("jndi-props = " + props); } public Message process(Message msg) throws ActionProcessingException, ConfigurationException { assert ejbRef != null; assert ejbParams != null; assert ejbParamTypeNames != null; log.debug("process message " + msg); try { final Object service = lookupTarget(); final Body body = msg.getBody(); log.debug("looked up service = " + service); // Assemble parameter array Object[] param = new Object[ejbParams.size()]; for (int i = 0; i < ejbParams.size(); i++) { // get the parameter from the esb message and // cast it to the in the jboss-esb.xml specified type final String type = ejbParams.get(i).getType(); final String value = ejbParams.get(i).getLoc(); param = Class.forName(type).cast(body.get(value)); } final Object result = this.invoke(service, ejbRef.get(EJB_METHOD), param); if (result != null) { log.debug("result is " + result); body.add(ejbRef.get(OUT_VAR), result); } log.debug("###########################################"); log.debug(msg); log.debug("###########################################"); } catch (Exception e) { log.error("Got an error while processing EJB", e); throw new ActionProcessingException("Got an error while processing EJB " + ejbRef.get(EJB_NAME), e); } return msg; } protected Object lookupTarget() throws NamingException { // Get the InitialContext final InitialContext iniCtx = new InitialContext(props); final Object service; try { service = iniCtx.lookup(ejbRef.get(JNDI_NAME)); } finally { iniCtx.close(); } return service; } @SuppressWarnings("unchecked") private Object invoke(final Object target, final String methodName, final Object[] params) throws Exception { // Assemble method signature array final Class[] sigArray = new Class[ejbParams.size()]; for (int i = 0; i < ejbParams.size(); i++) { sigArray = Class.forName(ejbParams.get(i).getType()); } try { // Get the specified method Method method = target.getClass().getMethod(methodName, sigArray); log.debug("before invoke " + method); // finally invoke it... final Object result = method.invoke(target, params); log.debug("after invoke " + method + " result " + result); return result; } catch (NoSuchMethodException e) { log.error("unable to locate method " + methodName + "(" + Arrays.asList(params) + ") on target " + target); throw e; } } // Helper inner class for method arguments and where to find it in the esb // message class Argument { private String type; private String loc; public Argument(String javaType, String esbLoc) { type = javaType; loc = esbLoc; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getLoc() { return loc; } public void setLoc(String loc) { this.loc = loc; } } }