1 Reply Latest reply on Aug 1, 2008 4:47 AM by kconner

    JBoss ESB 4.3.GA and EJBProcessor

    heinzw

      Hello,

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