Sample Facade Bean Invocation

Here is an example of invoking a facade bean that is created by the Cram modeling and build environments. This could be utilized in a context where you are implementing an alternative web services implementation. In this particular example the code is specific to a WebLogic Server application server, but could easily be modified for WebSphere as shown in the commented section.

package webservice;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;


public class FacadeUsageDemo {

  /**
   * Illustrates how a Curam facade can be invoked from a client.
   */
  private void invokeFacade() throws NamingException,
    ClassNotFoundException, SecurityException,
    NoSuchMethodException, IllegalArgumentException,
    IllegalAccessException, InvocationTargetException {

    final String sUser = "tester";
    final String sPassword = "password";

    // TODO: Change for non-WebLogic application server.
    final String initialCtxFactory =
      "weblogic.jndi.WLInitialContextFactory";
    final String providerUrl = "t3://localhost:7001";

    // Authenticate and get an initial context.
    final Properties properties = new Properties();
    properties.setProperty(Context.SECURITY_PRINCIPAL, sUser);
    properties.setProperty(Context.SECURITY_CREDENTIALS,
      sPassword);
    properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
      initialCtxFactory);
    properties.setProperty(Context.PROVIDER_URL, providerUrl);
    final Context initialContext =
      new InitialContext(properties);

    // Lookup the facade bean.
    final Object o =
      initialContext.
      lookup("java:comp/env/curamejb/MyFacadeBeanClass");


    // Load the home interface class so that we can narrow to it.
    final Class<?> cls = getContextClassLoader().loadClass(
      "my.custom.remote.MyFacadeHome");
    final Object ehome =
      javax.rmi.PortableRemoteObject.narrow(o, cls);

    // Get and invoke the 'create' method of the home interface
    // to give us a reference to the facade bean.
    final Method createMethod =
      cls.getMethod("create", new Class[0]);
    final Object facadeObj =
      createMethod.invoke(ehome, new Object[0]);

    // Use reflection to get and invoke the method
    // 'myMethod' of our interface.
    final Class<?> facadeObjClass = facadeObj.getClass();
    final Method myMethod =
      facadeObjClass.getMethod("myMethod", new Class[0]);
    // Pass arguments to invoke based on the method signature:
    myMethod.invoke(facadeObj, new Object[0]);
    initialContext.close();

    // Note: once the initialContext object has been obtained,
    // the remainder of this method could be written like this.
    // However due to problems experienced with loading classes
    // in WebLogic, the above workaround is necessary so that a
    // classloader could be explicitly specified.
    //try {
    //  final custom.webservice.remote.MyFacadeBeanClassHome
    //    ehome =
    //      (custom.webservice.remote.MyFacadeBeanClassHome)
    //      javax.rmi.PortableRemoteObject.narrow(
    //      o,
    //    custom.webservice.remote.MyFacadeBeanClassHome.class);
    //  custom.webservice.remote.MyFacadeBeanClass facadeObj =
    //    ehome.create();
    //  // Assumes a void method here; otherwise, arguments
    //  // would be needed:
    //  facadeObj.myMethod();
    //  initialContext.close();
    //} catch (Throwable t) {
    //  t.printStackTrace();
    //}

  }

  /**
   * Gets the class loader for the context.
   *
   * @return ClassLoader for the context.
   */
  private ClassLoader getContextClassLoader() {
    return AccessController.doPrivileged(
      new PrivilegedAction<ClassLoader>() {
        /**
         * PrvilegedAction subclass.
         *
         * @return ClassLoader for the context.
         */
        public ClassLoader run() {
          return Thread.currentThread().getContextClassLoader();
        }
      }
    );
  }

}