LucidDbAsManagedBean

From Eigenpedia

Jump to: navigation, search

Contents

Introduction

This page explains how to deploy LucidDB as a managed JMX service within a J2EE app server. It uses JBoss as an example; the details vary according to your choice of app server.

Even though LucidDB requires native code for its bottom half, its top half is implemented Java, making J2EE integration easy. There are a number of reasons why embedding it in an application server might be more attractive than running it standalone:

  • one less server process to manage
  • applications running in the same application server can use LucidDB's local JDBC driver for direct access instead of using RMI; this can provide better performance for fetching large result sets
  • even if LucidDB is to be run in isolation (say to avoid the risk of a native code crash affecting other applications), managing it as an mbean may be more attractive than running it in the bare-bones standalone mode, especially in an environment where JMX is already heavily in use

Before reading the rest of this page, be sure to familiarize yourself with the standalone environment. For a full overview of the JBoss JMX implementations, see Chapter 2 of the JBoss 4 Application Server Guide.

Build the Service MBean

Example code for JBoss integration is included with LucidDB releases starting with version 0.7.4. If you are using an earlier version, you can copy and paste from this wiki page instead.

First is the tagging interface for the service mbean (luciddb/examples/jmx/com/yoyodyne/LucidDbServiceMBean.java):

package com.yoyodyne;
import org.jboss.system.*;
public interface LucidDbServiceMBean extends ServiceMBean
{
}

And its implementation (luciddb/examples/jmx/com/yoyodyne/LucidDbService.java):

package com.yoyodyne;
import org.jboss.system.*;
import org.jboss.logging.util.*;
import org.apache.log4j.*;
import com.lucidera.jdbc.*;
import com.lucidera.farrago.*;
public class LucidDbService
    extends ServiceMBeanSupport
    implements LucidDbServiceMBean
{
    private LucidDbServer dbmsServer;
    public void startService() throws Exception
    {
        // Create a driver for loading LucidDB within the same JVM.
        LucidDbLocalDriver jdbcDriver = new LucidDbLocalDriver();
        // Start the LucidDB server
        dbmsServer = new LucidDbServer(
            new LoggerWriter(Logger.getLogger("LucidDB")));
        dbmsServer.start(jdbcDriver);
    }
    public void stopService() throws Exception
    {
        if (dbmsServer != null) {
            if (!dbmsServer.stopSoft()) {
                dbmsServer.getPrintWriter().println("Killing all sessions...");
                dbmsServer.stopHard();
            }
        }
        dbmsServer = null;
    }
}

To compile these, run the commands below from the luciddb/examples/jmx directory after changing the paths to match your JBoss installation locations.

export CLASSPATH="../../lib/farrago.jar"
export CLASSPATH="$CLASSPATH:/path/to/jboss/lib/jboss-system.jar"
export CLASSPATH="$CLASSPATH:/path/to/jboss/lib/jboss-jmx.jar"
export CLASSPATH="$CLASSPATH:/path/to/jboss/lib/jboss-common.jar"
export CLASSPATH="$CLASSPATH:/path/to/jboss/lib/log4j-boot.jar"
javac -cp $CLASSPATH com/yoyodyne/*.java
jar cf luciddb-service-mbean.jar com/yoyodyne/*.class

Deploy

Now, deploy the mbean under your JBoss installation, say in a newly created jboss/server/default/deploy/luciddb-mbean.sar directory, as follows.

(Do this with JBoss stopped since hot deploy is unlikely to work with LucidDB.)

  1. Copy the luciddb-service-mbean.jar compiled above to the jboss/server/default/deploy/luciddb-mbean.sar directory.
  2. Copy the luciddb/plugin/luciddb-mbean.jar (packaged with the LucidDB distribution) to the same directory. This provides additional monitoring and management actions beyond the basic start/stop lifecycle actions.
  3. Create a file luciddb-mbean.sar/META-INF/jboss-service.xml with the contents below (from examples/jmx).
<?xml version="1.0" encoding="UTF-8"?>
<server>
  <mbean code="com.yoyodyne.LucidDbService" name="com.yoyodyne:service=LucidDbService"/>
  <mbean code="com.lucidera.luciddb.mbean.sysviews.SqlStatements" name="com.lucidera.luciddb.mbean:service=SqlStatements"/>
  <mbean code="com.lucidera.luciddb.mbean.sysviews.Sessions" name="com.lucidera.luciddb.mbean:service=Sessions"/>
  <mbean code="com.lucidera.luciddb.mbean.sysviews.SystemParameters" name="com.lucidera.luciddb.mbean:service=SystemParameters"/>
  <mbean code="com.lucidera.luciddb.mbean.sysviews.ObjectsInUse" name="com.lucidera.luciddb.mbean:service=ObjectsInUse"/>
  <mbean code="com.lucidera.luciddb.mbean.sysviews.PerfCounters" name="com.lucidera.luciddb.mbean:service=PerfCounters"/>
  <mbean code="com.lucidera.luciddb.mbean.sysviews.ForeignSources" name="com.lucidera.luciddb.mbean:service=ForeignSources"/>
  <mbean code="com.lucidera.luciddb.mbean.server.PingServer" name="com.lucidera.luciddb.mbean:service=PingServer"/>
</server>

Customize JBoss Startup

Next, create a file named runWithLucidDb.sh in your jboss/bin directory, changing the paths below to match your LucidDB installation location.

#/bin/sh
export LD_LIBRARY_PATH="/path/to/luciddb/lib/fennel"
export JBOSS_CLASSPATH="`cat /path/to/luciddb/bin/classpath.gen`"
export JAVA_OPTS="${JAVA_OPTS} -Dnet.sf.farrago.home=/path/to/luciddb"
export JAVA_OPTS="${JAVA_OPTS} -Djava.util.logging.config.file=/path/to/luciddb/trace/Trace.properties"
export JAVA_OPTS="${JAVA_OPTS} -Dnet.sf.farrago.defaultSessionFactoryLibraryName=class:com.lucidera.farrago.LucidDbSessionFactory"
./run.sh

Note that this configuration uses an existing LucidDB installation, including its catalog and tracing. Consequently, it is very important that you do not run JBoss at the same time as LucidDB standalone (if you do that by accident, one or the other can be expected to fail on startup due to catalog locking).

Also note that injecting the LucidDB libraries onto the system classpath like this is not exactly J2EE best practice. The approach is used for simplicity in this page, but can cause "jar hell" problems in real life. Better solutions exist (such as creating a .ear), with the deployment details varying by application server.

To start JBoss with LucidDB embedded, make your new customized startup script executable, and then run it:

chmod +x runWithLucidDb.sh
./runWithLucidDb.sh

Inside of the JBoss startup output, you should see something like this:

...
16:45:26,532 INFO  [ServiceEndpointManager] WebServices: jbossws-1.0.3.SP1 (date=200609291417)
16:45:27,169 INFO  [LucidDB] Server personality:  LucidDB
16:45:27,169 INFO  [LucidDB] Loading database...
16:45:37,147 INFO  [LucidDB] Starting network...
16:45:37,218 INFO  [LucidDB] Server now listening for RMI connections on port 5434; enter !quit to stop
16:45:39,830 INFO  [StandardService] Starting service jboss.web
...
16:45:53,812 INFO  [Server] JBoss (MX MicroKernel) [4.0.5.GA (build: CVSTag=Branch_4_0 date=200610162339)] Started in 43s:448ms

JMX Console

You can use the JBoss JMX console to check the mbean state. Hit http://yourserver:8080/jmx-console/ and you should see something like this:

Catalina

  • type=Server
  • type=StringCache

JMImplementation

  • name=Default,service=LoaderRepository
  • type=MBeanRegistry
  • type=MBeanServerDelegate

com.lucidera.luciddb.mbean

  • service=ForeignSources
  • service=ObjectsInUse
  • service=PerfCounters
  • service=PingServer
  • service=Sessions
  • service=SqlStatements
  • service=SystemParameters

com.yoyodyne

  • service=LucidDbService

...

You can use the com.lucidera.luciddb.mbean links for monitoring various system views, and the LucidDbService link for starting and stopping LucidDB.

Shutdown

When you shut down JBoss, you should see something like the following (assuming you haven't already explicitly shut down LucidDB first):

16:37:41,553 INFO  [TomcatDeployer] undeploy, ctxPath=/jbossmq-httpil, warUrl=.../deploy/jms/jbossmq-httpil.sar/jbossmq-httpil.war/
16:37:41,601 INFO  [LucidDB] Server shutting down...
16:37:43,212 INFO  [LucidDB] Server shutdown complete
16:37:43,943 INFO  [Server] Shutdown complete
Shutdown complete
Halting VM

Note that unlike in the standalone environment, there is no !quit/!kill distinction; the behavior is always !kill (abruptly terminating any in-progress sessions without warning). Implementing a !quit lifecycle action (attempting stopSoft only) to be invoked from the JMX console should not be difficult.

Connections From Client Applications

For connecting to LucidDB running inside of JBoss, there are three possible scenarios:

  • Applications running in other JVM's have no choice but to use JDBC over RMI.
  • Applications running inside the same application server JVM may be able to use a local JDBC connection instead of RMI. For this to work, they need to be loaded from the same classloader as LucidDB; arranging for this depends on the details of the chosen application server. See JdbcUrlConventions for information on how to construct a local JDBC URL; the monitoring mbeans described above use this approach for querying the system views.
  • Applications running inside the same application server JVM always have usage of RMI as an option.

Quirks

LucidDB uses java.util.logging rather than log4j, so for the most part, the trace output is separated from JBoss. However, there are a few issues:

  • Some other components (such as Catalina) within JBoss may use java.util.logging also, so their output gets redirected into LucidDB's trace file, which may be confusing.
  • During JBoss shutdown, the java.util.logging output seems to get squelched, so you won't see the normal shutdown sequence in LucidDB's trace file. However, if you stop the LucidDB service mbean individually while JBoss stays up, then you will see the sequence as expected.

If you come up with good solutions to these, please add them to this page. (One which is known to work is to write a bridge which redirects java.util.logging output into log4j, providing a unified trace.)

Personal tools