Package ch.inftec.ju.ee.client

Source Code of ch.inftec.ju.ee.client.ServiceLocatorBuilder

package ch.inftec.ju.ee.client;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.naming.Context;
import javax.naming.InitialContext;

import org.jboss.ejb.client.ContextSelector;
import org.jboss.ejb.client.EJBClientConfiguration;
import org.jboss.ejb.client.EJBClientContext;
import org.jboss.ejb.client.PropertiesBasedEJBClientConfiguration;
import org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.inftec.ju.util.JuRuntimeException;
import ch.inftec.ju.util.JuUtils;
import ch.inftec.ju.util.PropertyChain;

/**
* Builder to create ServiceLocator instances.
* @author Martin
*
*/
public final class ServiceLocatorBuilder {
  /**
   * Gets a builder to create a new Remote ServiceLocator, i.e. a ServiceLocator
   * that will perform remote JBoss lookups.
   * <p>
   * Uses remote-naming for the lookup.
   * @return Builder instance
   */
  public static RemoteServiceLocatorBuilder buildRemote() {
    return new RemoteServiceLocatorBuilder();
  }
 
  /**
   * Builds a remote service locator based on the values of property files on the classpath
   * and system properties, in the following order:
   * <ol>
   *   <li>System property</li>
   *   <li>Optional resource: /ju-remote_user.properties</li>
   *   <li>Default properties: /ju-remote.properties</li>
   * </ol>
   * Check the /ju-remote.properties file for the possible property keys.
   * @return Remote service locator
   */
  public static JndiServiceLocator createRemoteByConfigurationFiles() {
    PropertyChain pc = JuUtils.getJuPropertyChain();
   
    Integer port = pc.get("ju-util-ee.remote.port", Integer.class, true);
    Integer portOffset = pc.get("ju-util-ee.portOffset", Integer.class, true);
   
    return buildRemote()
      .remoteServer(pc.get("ju-util-ee.remote.host", true), port + portOffset)
      .appName(pc.get("ju-util-ee.remote.appName", true))
      .moduleName(pc.get("ju-util-ee.remote.moduleName", true))
      .createServiceLocator();
  }
 
  /**
   * Gets a builder to create a new Local ServiceLocator, i.e. a ServiceLocator
   * that will perform local JNDI and CDI lookups.
   * @return Builder instance
   */
  public static LocalServiceLocatorBuilder buildLocal() {
    return new LocalServiceLocatorBuilder();
  }
 
  /**
   * Helper class to build remote ServiceLocator instances
   * @author Martin
   *
   */
  public static class RemoteServiceLocatorBuilder {
    private Logger logger = LoggerFactory.getLogger(RemoteServiceLocatorBuilder.class);
   
    private String host = "localhost";
    private int port = 4447;
    private String appName;
    private String moduleName;

    /**
     * Sets the remote host and port for the lookup.
     * @param host Remote host. Default is localhost
     * @param port Remote port. Default is 4447
     * @return This builder to allow for chaining
     */
    public RemoteServiceLocatorBuilder remoteServer(String host, int port) {
      this.host = host;
      this.port = port;
      return this;
    }
   
    /**
     * Sets the application name. This is usually the name of the EAR without
     * the .ear suffix, e.g. 'test' for test.ear
     * @param appName Application name
     * @return This builder to allow for chaining
     */
    public RemoteServiceLocatorBuilder appName(String appName) {
      this.appName = appName;
      return this;
    }
   
    /**
     * Sets the module name. This is usually the name of the EJB jar that contains
     * the EJB bean without the .jar suffix, e.g. 'test' for test.jar
     * @param moduleName Module name
     * @return This builder to allow for chaining
     */
    public RemoteServiceLocatorBuilder moduleName(String moduleName) {
      this.moduleName = moduleName;
      return this;
    }
   
    /**
     * Creates a new RemoteServiceLocator instance with the attributes specified
     * to the builder.
     * @return JndiServiceLocator instance
     */
    public JndiServiceLocator createServiceLocator() {
      try {
        // Set EJB Client API properties programmatically instead of using
        // jboss-ejb-client.properties file
        Properties clientProp = new Properties();
        clientProp.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
        clientProp.put("remote.connections", "default");
        clientProp.put("remote.connection.default.port", Integer.toString(this.port)); // Not working if not a String...
        clientProp.put("remote.connection.default.host", this.host);
//        clientProp.put("remote.connection.default.username", "ejbUser");
//        clientProp.put("remote.connection.default.password", "ejbPassword");
        clientProp.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");
       
        EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(clientProp);
        ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc);
        EJBClientContext.setSelector(selector);
       
        logger.debug("JBoss EJB Client Properties (used for remote lookup)" + clientProp);
       
        Properties props = new Properties();
        props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
        Context ctx = new InitialContext(props);
       
//        Properties jndiProps = new Properties();
//        jndiProps.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
//        jndiProps.put(Context.PROVIDER_URL, String.format("remote://%s:%d", this.host, this.port));
//        // create a context passing these properties
//        Context ctx = new InitialContext(jndiProps);
       
        logger.debug("Creating RemoteServiceLocator [host={}:{}, app={} / module={}"
            , new Object[] {this.host, this.port, this.appName, this.moduleName});
       
        return new RemoteServiceLocatorImpl(ctx, this.appName, this.moduleName);
      } catch (Exception ex) {
        throw new JuRuntimeException("Couldn't create ServiceLocator", ex);
      }
    }
  }
 
  /**
   * Helper class to build local ServiceLocator instances
   * @author Martin
   *
   */
  public static class LocalServiceLocatorBuilder {
    private String moduleName;
   
    /**
     * Sets the module name. This is usually the name of the EJB jar that contains
     * the EJB bean without the .jar suffix, e.g. 'test' for test.jar
     * <p>
     * Is used to look up remote interfaces in the same (local) app.
     * @param moduleName Module name
     * @return This builder to allow for chaining
     */
    public LocalServiceLocatorBuilder moduleName(String moduleName) {
      this.moduleName = moduleName;
      return this;
    }
   
    /**
     * Creates a new LocalServiceLocatorBuilder instance with the attributes specified
     * to the builder.
     * @return ServiceLocator instance
     */
    public ServiceLocator createServiceLocator() {
      return new LocalServiceLocatorImpl(this.moduleName);
    }
  }
   
 
  private static abstract class AbstractJndiServiceLocator implements JndiServiceLocator {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
   
    private final Context ctx;
   
    protected AbstractJndiServiceLocator(Context ctx) {
      this.ctx = ctx;
    }
   
    /**
     * Gets the absolute JNDI name (i.e. the JNDI name that will actually be used
     * for the lookup) based on the submitted relative JNDI name.
     * <p>
     * The default implementation just returns the same JNDI
     * @param jndiName (Relative) JNDI name
     * @return Absolute JNDI name used to perform the lookup
     */
    protected String getAbsoluteJndiName(String jndiName) {
      return jndiName;
    }
   
    @Override
    public <T> T lookup(String jndiName) {
      String absoluteJndiName = this.getAbsoluteJndiName(jndiName);
      logger.debug(String.format("JNDI lookup (relative: %s, absolute: %s)", jndiName, absoluteJndiName));
     
      try {
        @SuppressWarnings("unchecked")
        T obj = (T) this.ctx.lookup(absoluteJndiName);
       
        return obj;
      } catch (Exception ex) {
        throw new JuRuntimeException(ex);
      }
    }
  }
 
  private static class RemoteServiceLocatorImpl extends AbstractJndiServiceLocator {
    private final String appName;
    private final String moduleName;
   
    public RemoteServiceLocatorImpl(Context ctx, String appName, String moduleName) {
      super(ctx);

      this.appName = appName;
      this.moduleName = moduleName;
    }

    @Override
    protected String getAbsoluteJndiName(String jndiName) {
      String absoluteJndiName = String.format("ejb:%s/%s/%s"
          , this.appName
          , this.moduleName
          , jndiName);
     
      return absoluteJndiName;
    }
   
    @Override
    public <T> T lookup(Class<T> clazz) {
      String lookupString = String.format("%sBean!%s"
          , clazz.getSimpleName()
          , clazz.getName());
     
      return this.lookup(lookupString);
    }
  }
 
  private static class LocalServiceLocatorImpl extends AbstractJndiServiceLocator implements ServiceLocator {
    private static final String JNDI_NAME_BEAN_MANAGER = "java:comp/BeanManager";
   
    private final String moduleName;
    private BeanManager bm;
   
    private LocalServiceLocatorImpl(String moduleName) {
      super(createInitialContext());

      this.moduleName = moduleName == null ? "" : moduleName;
      this.bm = this.lookup(JNDI_NAME_BEAN_MANAGER);
    }
   
    private static Context createInitialContext() {
      try {
        return new InitialContext();
      } catch (Exception ex) {
        throw new JuRuntimeException("Couldn't create InitialContext", ex);
      }
    }

    @Override
    public <T> T lookup(Class<T> clazz) {
//      java:global/ee-ear-ear/ee-ear-ejb/TestLocalBean!ch.inftec.ju.ee.test.TestLocal
//      java:app/ee-ear-ejb/TestLocalBean!ch.inftec.ju.ee.test.TestLocal
//      java:module/TestLocalBean!ch.inftec.ju.ee.test.TestLocal
//      java:global/ee-ear-ear/ee-ear-ejb/TestLocalBean
//      java:app/ee-ear-ejb/TestLocalBean
//      java:module/TestLocalBean
     
      String jndiName = String.format("java:app/%s/%s!%s"
          , this.moduleName
          , clazz.getSimpleName() + "Bean"
          , clazz.getName());
     
      return this.lookup(jndiName);
    }

    @Override
    public <T> T cdi(Class<T> clazz) {
      Set<Bean<?>> beans = this.bm.getBeans(clazz);
      List<T> instances = this.getInstances(beans, clazz);
      if (instances.size() != 1) {
        throw new JuRuntimeException("Expected exactly one result for CDI lookup of %s, but found %d", clazz, instances.size());
      } else {
        return instances.get(0);
      }
    }
   
    private <T> List<T> getInstances(Set<Bean<?>> beans, Class<T> clazz) {
      List<T> instances = new ArrayList<>();
      for (Bean<?> bean : beans) {
        CreationalContext<?> cont = this.bm.createCreationalContext(bean);
       
        @SuppressWarnings("unchecked")
        T t = (T) this.bm.getReference(bean, clazz, cont);
       
        instances.add(t);
      }
     
      return instances;
    }
  }
}
TOP

Related Classes of ch.inftec.ju.ee.client.ServiceLocatorBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.