Provide a new way to configure instance by using yaml.

master
David BRASSELY 2014-02-06 10:09:46 +01:00
parent a2dccee0f0
commit b9f8460f16
7 changed files with 297 additions and 124 deletions

View File

@ -39,5 +39,20 @@
<artifactId>transactions-jta</artifactId> <artifactId>transactions-jta</artifactId>
<version>${atomikos.version}</version> <version>${atomikos.version}</version>
</dependency> </dependency>
<!-- Cluster support
<dependency>
<groupId>org.jgroups</groupId>
<artifactId>jgroups</artifactId>
<version>${jgroups.version}</version>
</dependency>
-->
<!-- Config support -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${snakeyaml.version}</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -29,10 +29,15 @@
package net.openesb.standalone.framework; package net.openesb.standalone.framework;
import com.sun.jndi.rmi.registry.RegistryContextFactory; import com.sun.jndi.rmi.registry.RegistryContextFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.rmi.registry.Registry; import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry; import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject; import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -42,189 +47,215 @@ import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL; import javax.management.remote.JMXServiceURL;
//import net.openesb.standalone.node.Node;
//import net.openesb.standalone.node.NodeBuilder;
import net.openesb.standalone.settings.ImmutableSettings;
import net.openesb.standalone.settings.Settings;
import org.yaml.snakeyaml.Yaml;
/** /**
* JBI framework wrapper for Java SE platform. * JBI framework wrapper for Java SE platform.
* <br><br> * <br><br>
* A JSEJBIFramework instance cannot be loaded multiple times in the same * A JSEJBIFramework instance cannot be loaded multiple times in the same VM. If
* VM. If multiple instances of the framework are required in a VM, * multiple instances of the framework are required in a VM, instantiate
* instantiate multiple instances of JSEJBIFramework and load each one * multiple instances of JSEJBIFramework and load each one independently. There
* independently. There is no limit on the number of uniquely named * is no limit on the number of uniquely named JSEJBIFramework instances in the
* JSEJBIFramework instances in the same VM. A specific JSEJBIFramework instance * same VM. A specific JSEJBIFramework instance can be loaded and unloaded
* can be loaded and unloaded multiple times in a VM. * multiple times in a VM.
* *
* @author Sun Microsystems, Inc. * @author Sun Microsystems, Inc.
*/ */
public class JSEJBIFramework public class JSEJBIFramework
extends com.sun.jbi.framework.JBIFramework extends com.sun.jbi.framework.JBIFramework
implements JSEJBIFrameworkMBean implements JSEJBIFrameworkMBean {
{
public static final String CONFIG_FILE = "openesb.config";
public static final String INSTALL_ROOT = "install.root"; public static final String INSTALL_ROOT = "install.root";
public static final String INSTANCE_NAME = "instance.name"; public static final String INSTANCE_NAME = "instance.name";
public static final String CONNECTOR_PORT = "connector.port"; public static final String CONNECTOR_PORT = "instance.port";
/**
/** Configuration defaults. */ * Configuration defaults.
*/
private static final String DEFAULT_INSTALL_ROOT = System.getProperty("user.dir"); private static final String DEFAULT_INSTALL_ROOT = System.getProperty("user.dir");
private static final String DEFAULT_INSTANCE_NAME = "server"; private static final String DEFAULT_INSTANCE_NAME = "server";
private static final String DEFAULT_CONNECTOR_PORT = "8699"; private static final int DEFAULT_CONNECTOR_PORT = 8699;
private JSEPlatformContext mPlatformContext;
private JSEPlatformContext mPlatformContext; private boolean mLoaded;
private boolean mLoaded; private Properties mEnvironment;
private Properties mEnvironment; private JMXConnectorServer mJMXServer;
private JMXConnectorServer mJMXServer; private Registry mRegistry;
private Registry mRegistry; private Logger mLog =
private Logger mLog =
Logger.getLogger(this.getClass().getPackage().getName()); Logger.getLogger(this.getClass().getPackage().getName());
// private Node instanceNode;
/** Creates a new instance of the JBI framework. private Settings settings;
/**
* Creates a new instance of the JBI framework.
*/ */
public JSEJBIFramework(Properties environment) public JSEJBIFramework(Properties environment) {
{
super(); super();
mEnvironment = environment; mEnvironment = environment;
mPlatformContext = new JSEPlatformContext(
mEnvironment.getProperty(INSTANCE_NAME, DEFAULT_INSTANCE_NAME),
mEnvironment.getProperty(INSTALL_ROOT, DEFAULT_INSTALL_ROOT),
mEnvironment.getProperty(CONNECTOR_PORT, DEFAULT_CONNECTOR_PORT));
} }
/** Load the JBI framework with the specified environment. When this method private void init() throws Exception {
* retuns, all public interfaces and system services have completely String installRoot = mEnvironment.getProperty(INSTALL_ROOT, DEFAULT_INSTALL_ROOT);
* initialized. If a connector port is specified in the environment
* properties, a remote JMX connector server is created. String configFile = mEnvironment.getProperty(CONFIG_FILE);
* @throws Exception failed to load JBI framework
*/ if (configFile == null) {
public synchronized void load() configFile = installRoot + File.separatorChar + "config/openesb.yaml";
throws Exception }
{
if (mLoaded) mLog.log(Level.INFO, "Loading configuration from {0}", configFile);
{
throw new IllegalStateException("JBI framework already loaded!"); try {
Yaml yaml = new Yaml();
InputStream input = new FileInputStream(new File(configFile));
settings = new ImmutableSettings((Map) yaml.load(input));
} catch (FileNotFoundException fnfe) {
mLog.log(Level.WARNING, "Unable to load configuration file {0}. Default configuration will be used.", configFile);
settings = new ImmutableSettings(null);
} }
mPlatformContext = new JSEPlatformContext(
installRoot,
settings.get(INSTANCE_NAME, DEFAULT_INSTANCE_NAME),
settings.getAsInt(CONNECTOR_PORT, DEFAULT_CONNECTOR_PORT));
}
/**
* Load the JBI framework with the specified environment. When this method
* retuns, all public interfaces and system services have completely
* initialized. If a connector port is specified in the environment
* properties, a remote JMX connector server is created.
*
* @throws Exception failed to load JBI framework
*/
@Override
public synchronized void load()
throws Exception {
if (mLoaded) {
throw new IllegalStateException("JBI framework already loaded!");
}
this.init();
// Register a management MBean for this framework instance // Register a management MBean for this framework instance
ObjectName fwMBeanName = new ObjectName("com.sun.jbi.jse", ObjectName fwMBeanName = new ObjectName("com.sun.jbi.jse",
"instance", mPlatformContext.getInstanceName()); "instance", mPlatformContext.getInstanceName());
MBeanServer mbs = mPlatformContext.getMBeanServer(); MBeanServer mbs = mPlatformContext.getMBeanServer();
if (mbs.isRegistered(fwMBeanName)) if (mbs.isRegistered(fwMBeanName)) {
{ if (mbs.getAttribute(fwMBeanName, "Loaded").equals(Boolean.TRUE)) {
if (mbs.getAttribute(fwMBeanName, "Loaded").equals(Boolean.TRUE))
{
// Framework already loaded from a separate thread/process // Framework already loaded from a separate thread/process
throw new IllegalStateException("JBI framework instance " + throw new IllegalStateException("JBI framework instance "
mPlatformContext.getInstanceName() + " has already been loaded"); + mPlatformContext.getInstanceName() + " has already been loaded");
} } else {
else
{
// MBean should not be registered - try to clean up // MBean should not be registered - try to clean up
mbs.unregisterMBean(fwMBeanName); mbs.unregisterMBean(fwMBeanName);
} }
} }
mbs.registerMBean(this, fwMBeanName); mbs.registerMBean(this, fwMBeanName);
// Setup the remote JMX connector server // Setup the remote JMX connector server
String portStr = mEnvironment.getProperty(CONNECTOR_PORT); Integer port = null;
if (portStr != null)
{ try {
try port = settings.getAsInt(CONNECTOR_PORT, DEFAULT_CONNECTOR_PORT);
{ createJMXConnectorServer(port);
int port = Integer.parseInt(portStr); } catch (NumberFormatException nfEx) {
createJMXConnectorServer(port); mLog.log(Level.WARNING, "Invalid connector server port: {0}. Remote JMX connector will not be created.", port);
}
catch (NumberFormatException nfEx)
{
mLog.log(Level.WARNING, "Invalid connector server port: {0}. Remote JMX connector will not be created.", portStr);
}
} }
// For stand-alone JBI, JBI_HOME = platform install root // For stand-alone JBI, JBI_HOME = platform install root
mEnvironment.setProperty("com.sun.jbi.home", mEnvironment.setProperty("com.sun.jbi.home",
mPlatformContext.getInstallRoot()); mPlatformContext.getInstallRoot());
init(mPlatformContext, mEnvironment); init(mPlatformContext, mEnvironment);
startup(mPlatformContext.getNamingContext(), ""); startup(mPlatformContext.getNamingContext(), "");
prepare(); prepare();
ready(true); ready(true);
// instanceNode = NodeBuilder.nodeBuilder(settings).build();
// instanceNode.start();
// JBI framework has been loaded // JBI framework has been loaded
mLoaded = true; mLoaded = true;
} }
/** Queries the state of the JBI Framework. /**
* @return true if the JBI framework is loaded, false otherwise. * Queries the state of the JBI Framework.
*
* @return true if the JBI framework is loaded, false otherwise.
*/ */
public boolean isLoaded() @Override
{ public boolean isLoaded() {
return mLoaded; return mLoaded;
} }
/** Unloads the JBI framework. When this method retuns, all /**
* public interfaces, system services, and JMX connector (if configured) * Unloads the JBI framework. When this method retuns, all public
* have been destroyed. * interfaces, system services, and JMX connector (if configured) have been
* @throws javax.jbi.JBIException failed to unload JBI framework * destroyed.
*
* @throws javax.jbi.JBIException failed to unload JBI framework
*/ */
@Override
public void unload() public void unload()
throws Exception throws Exception {
{ if (!mLoaded) {
if (!mLoaded)
{
return; return;
} }
// instanceNode.stop();
shutdown(); shutdown();
terminate(); terminate();
try try {
{
mJMXServer.stop(); mJMXServer.stop();
UnicastRemoteObject.unexportObject(mRegistry, true); UnicastRemoteObject.unexportObject(mRegistry, true);
} } catch (Exception ex) {
catch (Exception ex)
{
mLog.log(Level.SEVERE, "Error during framework shutdown: {0}", ex.toString()); mLog.log(Level.SEVERE, "Error during framework shutdown: {0}", ex.toString());
} }
mLoaded = false; mLoaded = false;
} }
public JMXServiceURL getServiceURL(int port) private JMXServiceURL getServiceURL(int port)
throws java.net.MalformedURLException throws java.net.MalformedURLException {
{
return new JMXServiceURL( return new JMXServiceURL(
"service:jmx:rmi:///jndi/rmi://localhost:" + port + "/jmxrmi"); "service:jmx:rmi:///jndi/rmi://localhost:" + port + "/jmxrmi");
} }
/** Creates a JMX connector server at the specified port. /**
* @param port port for the JMX connector server. * Creates a JMX connector server at the specified port.
*
* @param port port for the JMX connector server.
*/ */
private void createJMXConnectorServer(int port) private void createJMXConnectorServer(int port) {
{
HashMap<String, String> map = new HashMap<String, String>(); HashMap<String, String> map = new HashMap<String, String>();
/* /*
map.put("java.naming.factory.initial", map.put("java.naming.factory.initial",
RegistryContextFactory.class.getName()); RegistryContextFactory.class.getName());
*/ */
try try {
{
// Create the service URL // Create the service URL
JMXServiceURL serviceURL = getServiceURL(port); JMXServiceURL serviceURL = getServiceURL(port);
// Create an RMI registry instance to hold the JMX connector server // Create an RMI registry instance to hold the JMX connector server
mRegistry = LocateRegistry.createRegistry(port); mRegistry = LocateRegistry.createRegistry(port);
// Create and start the connector server // Create and start the connector server
mJMXServer = JMXConnectorServerFactory.newJMXConnectorServer( mJMXServer = JMXConnectorServerFactory.newJMXConnectorServer(
serviceURL, map, mPlatformContext.getMBeanServer()); serviceURL, map, mPlatformContext.getMBeanServer());
mJMXServer.start(); mJMXServer.start();
mLog.log(Level.INFO, "remote JMX connector available at {0}", mJMXServer.getAddress()); mLog.log(Level.INFO, "remote JMX connector available at {0}", mJMXServer.getAddress());
} } catch (Exception ex) {
catch (Exception ex)
{
mLog.log(Level.SEVERE, "Failed to create remote JMX connector: {0}", ex.toString()); mLog.log(Level.SEVERE, "Failed to create remote JMX connector: {0}", ex.toString());
} }
} }
} }

View File

@ -56,13 +56,13 @@ public class JSEPlatformContext implements com.sun.jbi.platform.PlatformContext
private String mInstanceName; private String mInstanceName;
private String mInstanceRoot; private String mInstanceRoot;
private String mInstallRoot; private String mInstallRoot;
private String mConnectorPort; private int mConnectorPort;
private InitialContext mNamingContext; private InitialContext mNamingContext;
private Logger mLog = Logger.getLogger(getClass().getPackage().getName()); private Logger mLog = Logger.getLogger(getClass().getPackage().getName());
public JSEPlatformContext(String instanceName, String installRoot, String connectorPort) { public JSEPlatformContext(String installRoot, String instanceName, int connectorPort) {
mInstanceName = instanceName;
mInstallRoot = installRoot; mInstallRoot = installRoot;
mInstanceName = instanceName;
mInstanceRoot = installRoot + File.separator + instanceName; mInstanceRoot = installRoot + File.separator + instanceName;
mConnectorPort = connectorPort; mConnectorPort = connectorPort;
@ -273,7 +273,7 @@ public class JSEPlatformContext implements com.sun.jbi.platform.PlatformContext
* @return the JMX RMI connector port as a <CODE>String</CODE>. * @return the JMX RMI connector port as a <CODE>String</CODE>.
*/ */
public String getJmxRmiPort() { public String getJmxRmiPort() {
return mConnectorPort; return Integer.toString(mConnectorPort);
} }
/** /**

View File

@ -0,0 +1,72 @@
package net.openesb.standalone.settings;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* An immutable implementation of {@link Settings}.
*
* @author David BRASSELY (brasseld at gmail.com)
* @author OpenESB Community
*/
public class ImmutableSettings implements Settings {
private final Map<String, String> settings;
public ImmutableSettings(Map<String, String> settings) {
if (settings != null) {
this.settings = Collections.unmodifiableMap(settings);
} else {
this.settings = Collections.unmodifiableMap(new HashMap<String, String>());
}
}
@Override
public String get(String setting) {
String retVal = settings.get(setting);
if (retVal != null) {
return retVal;
}
return null;
}
@Override
public String get(String setting, String defaultValue) {
String retVal = get(setting);
return retVal == null ? defaultValue : retVal;
}
@Override
public Boolean getAsBoolean(String setting, Boolean defaultValue) {
return parseBoolean(get(setting), defaultValue);
}
@Override
public Integer getAsInt(String setting, Integer defaultValue) throws SettingsException {
String sValue = get(setting);
if (sValue == null) {
return defaultValue;
}
try {
return Integer.parseInt(sValue);
} catch (NumberFormatException e) {
throw new SettingsException("Failed to parse int setting [" + setting + "] with value [" + sValue + "]", e);
}
}
public static boolean parseBoolean(String value, boolean defaultValue) {
if (value == null) {
return defaultValue;
}
return !(value.equals("false") || value.equals("0") || value.equals("off") || value.equals("no"));
}
public static Boolean parseBoolean(String value, Boolean defaultValue) {
if (value == null) {
return defaultValue;
}
return !(value.equals("false") || value.equals("0") || value.equals("off") || value.equals("no"));
}
}

View File

@ -0,0 +1,35 @@
package net.openesb.standalone.settings;
/**
*
* @author David BRASSELY (brasseld at gmail.com)
* @author OpenESB Community
*/
public interface Settings {
/**
* Returns the setting value associated with the setting key.
*
* @param setting The setting key
* @return The setting value, <tt>null</tt> if it does not exists.
*/
String get(String setting);
/**
* Returns the setting value associated with the setting key. If it does not exists,
* returns the default value provided.
*/
String get(String setting, String defaultValue);
/**
* Returns the setting value (as int) associated with the setting key. If it does not exists,
* returns the default value provided.
*/
Integer getAsInt(String setting, Integer defaultValue) throws SettingsException;
/**
* Returns the setting value (as boolean) associated with the setting key. If it does not exists,
* returns the default value provided.
*/
Boolean getAsBoolean(String setting, Boolean defaultValue) throws SettingsException;
}

View File

@ -0,0 +1,18 @@
package net.openesb.standalone.settings;
/**
* A generic failure to handle settings.
*
* @author David BRASSELY (brasseld at gmail.com)
* @author OpenESB Community
*/
public class SettingsException extends RuntimeException {
public SettingsException(String message) {
super(message);
}
public SettingsException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -32,6 +32,8 @@
<openesb-oeadmin.version>1.0.0-SNAPSHOT</openesb-oeadmin.version> <openesb-oeadmin.version>1.0.0-SNAPSHOT</openesb-oeadmin.version>
<atomikos.version>3.8.0</atomikos.version> <atomikos.version>3.8.0</atomikos.version>
<tomcat.version>7.0.47</tomcat.version> <tomcat.version>7.0.47</tomcat.version>
<snakeyaml.version>1.13</snakeyaml.version>
<!--jgroups.version>3.4.2.Final</jgroups.version-->
</properties> </properties>
<build> <build>