This closes #380

This commit is contained in:
Clebert Suconic 2016-02-08 11:23:38 -05:00
commit 8d275de12d
13 changed files with 66 additions and 31 deletions

View File

@ -403,7 +403,10 @@ public final class ActiveMQDefaultConfiguration {
private static String DEFAULT_STORE_TYPE = "FILE"; private static String DEFAULT_STORE_TYPE = "FILE";
// Default database url. Derby database is used by default. // Default database url. Derby database is used by default.
private static String DEFAULT_DATABASE_URL = "jdbc:derby:data/derby;create=true"; private static String DEFAULT_DATABASE_URL = null;
// Default JDBC Driver class name
private static String DEFAULT_JDBC_DRIVER_CLASS_NAME = null;
// Default message table name, used with Database storage type // Default message table name, used with Database storage type
private static String DEFAULT_MESSAGE_TABLE_NAME = "MESSAGES"; private static String DEFAULT_MESSAGE_TABLE_NAME = "MESSAGES";
@ -1096,4 +1099,8 @@ public final class ActiveMQDefaultConfiguration {
public static String getDefaultBindingsTableName() { public static String getDefaultBindingsTableName() {
return DEFAULT_BINDINGS_TABLE_NAME; return DEFAULT_BINDINGS_TABLE_NAME;
} }
public static String getDefaultDriverClassName() {
return DEFAULT_JDBC_DRIVER_CLASS_NAME;
}
} }

View File

@ -56,6 +56,7 @@
<dependency> <dependency>
<groupId>org.apache.derby</groupId> <groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId> <artifactId>derby</artifactId>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -22,26 +22,16 @@ import java.sql.DriverManager;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.Collections;
import java.util.List;
import org.apache.derby.jdbc.AutoloadedDriver;
public class JDBCUtils { public class JDBCUtils {
public static Driver getDriver() throws Exception { public static Driver getDriver(String className) throws Exception {
Driver dbDriver = null;
// Load Database driver, sets Derby Autoloaded Driver as lowest priority.
List<Driver> drivers = Collections.list(DriverManager.getDrivers());
if (drivers.size() <= 2 && drivers.size() > 0) {
dbDriver = drivers.get(0);
boolean isDerby = dbDriver instanceof AutoloadedDriver;
if (drivers.size() > 1 && isDerby) { try {
dbDriver = drivers.get(1); Driver driver = (Driver) Class.forName(className).newInstance();
}
if (isDerby) { // Shutdown the derby if using the derby embedded driver.
if (className.equals("org.apache.derby.jdbc.EmbeddedDriver")) {
Runtime.getRuntime().addShutdownHook(new Thread() { Runtime.getRuntime().addShutdownHook(new Thread() {
@Override @Override
public void run() { public void run() {
@ -53,12 +43,14 @@ public class JDBCUtils {
} }
}); });
} }
return driver;
} }
else { catch (ClassNotFoundException cnfe) {
String error = drivers.isEmpty() ? "No DB driver found on class path" : "Too many DB drivers on class path, not sure which to use"; throw new RuntimeException("Could not find class: " + className);
throw new RuntimeException(error); }
catch (Exception e) {
throw new RuntimeException("Unable to instantiate driver class: ", e);
} }
return dbDriver;
} }
public static void createTableIfNotExists(Connection connection, String tableName, String sql) throws SQLException { public static void createTableIfNotExists(Connection connection, String tableName, String sql) throws SQLException {

View File

@ -56,6 +56,8 @@ public class JDBCJournalImpl implements Journal {
private final String tableName; private final String tableName;
private final String jdbcDriverClass;
private Connection connection; private Connection connection;
private List<JDBCJournalRecord> records; private List<JDBCJournalRecord> records;
@ -88,9 +90,10 @@ public class JDBCJournalImpl implements Journal {
// Sequence ID for journal records // Sequence ID for journal records
private AtomicLong seq = new AtomicLong(0); private AtomicLong seq = new AtomicLong(0);
public JDBCJournalImpl(String jdbcUrl, String tableName) { public JDBCJournalImpl(String jdbcUrl, String tableName, String jdbcDriverClass) {
this.tableName = tableName; this.tableName = tableName;
this.jdbcUrl = jdbcUrl; this.jdbcUrl = jdbcUrl;
this.jdbcDriverClass = jdbcDriverClass;
timerThread = "Timer JDBC Journal(" + tableName + ")"; timerThread = "Timer JDBC Journal(" + tableName + ")";
records = new ArrayList<>(); records = new ArrayList<>();
@ -98,8 +101,15 @@ public class JDBCJournalImpl implements Journal {
@Override @Override
public void start() throws Exception { public void start() throws Exception {
dbDriver = JDBCUtils.getDriver(); dbDriver = JDBCUtils.getDriver(jdbcDriverClass);
connection = dbDriver.connect(jdbcUrl, new Properties());
try {
connection = dbDriver.connect(jdbcUrl, new Properties());
}
catch (SQLException e) {
ActiveMQJournalLogger.LOGGER.error("Unable to connect to database using URL: " + jdbcUrl);
throw new RuntimeException("Error connecting to database", e);
}
JDBCUtils.createTableIfNotExists(connection, tableName, JDBCJournalRecord.createTableSQL(tableName)); JDBCUtils.createTableIfNotExists(connection, tableName, JDBCJournalRecord.createTableSQL(tableName));
@ -109,8 +119,8 @@ public class JDBCJournalImpl implements Journal {
deleteJournalRecords = connection.prepareStatement(JDBCJournalRecord.deleteRecordsSQL(tableName)); deleteJournalRecords = connection.prepareStatement(JDBCJournalRecord.deleteRecordsSQL(tableName));
deleteJournalTxRecords = connection.prepareStatement(JDBCJournalRecord.deleteJournalTxRecordsSQL(tableName)); deleteJournalTxRecords = connection.prepareStatement(JDBCJournalRecord.deleteJournalTxRecordsSQL(tableName));
syncTimer = new Timer(timerThread, true);
syncTimer.scheduleAtFixedRate(new JDBCJournalSync(this), SYNC_DELAY * 2, SYNC_DELAY); syncTimer.schedule(new JDBCJournalSync(this), SYNC_DELAY * 2, SYNC_DELAY);
started = true; started = true;
} }

View File

@ -27,6 +27,7 @@ public class DatabaseStorageConfiguration implements StoreConfiguration {
private String jdbcConnectionUrl = ActiveMQDefaultConfiguration.getDefaultDatabaseUrl(); private String jdbcConnectionUrl = ActiveMQDefaultConfiguration.getDefaultDatabaseUrl();
private String jdbcDriverClassName = ActiveMQDefaultConfiguration.getDefaultDriverClassName();
@Override @Override
public StoreType getStoreType() { public StoreType getStoreType() {
return StoreType.DATABASE; return StoreType.DATABASE;
@ -55,4 +56,12 @@ public class DatabaseStorageConfiguration implements StoreConfiguration {
public String getJdbcConnectionUrl() { public String getJdbcConnectionUrl() {
return jdbcConnectionUrl; return jdbcConnectionUrl;
} }
public void setJdbcDriverClassName(String jdbcDriverClassName) {
this.jdbcDriverClassName = jdbcDriverClassName;
}
public String getJdbcDriverClassName() {
return jdbcDriverClassName;
}
} }

View File

@ -1150,6 +1150,7 @@ public final class FileConfigurationParser extends XMLConfigurationUtil {
conf.setBindingsTableName(getString(storeNode, "bindings-table-name", conf.getBindingsTableName(), Validators.NO_CHECK)); conf.setBindingsTableName(getString(storeNode, "bindings-table-name", conf.getBindingsTableName(), Validators.NO_CHECK));
conf.setMessageTableName(getString(storeNode, "message-table-name", conf.getMessageTableName(), Validators.NO_CHECK)); conf.setMessageTableName(getString(storeNode, "message-table-name", conf.getMessageTableName(), Validators.NO_CHECK));
conf.setJdbcConnectionUrl(getString(storeNode, "jdbc-connection-url", conf.getJdbcConnectionUrl(), Validators.NO_CHECK)); conf.setJdbcConnectionUrl(getString(storeNode, "jdbc-connection-url", conf.getJdbcConnectionUrl(), Validators.NO_CHECK));
conf.setJdbcDriverClassName(getString(storeNode, "jdbc-driver-class-name", conf.getJdbcDriverClassName(), Validators.NO_CHECK));
return conf; return conf;
} }

View File

@ -42,10 +42,10 @@ public class JDBCJournalStorageManager extends JournalStorageManager {
protected void init(Configuration config, IOCriticalErrorListener criticalErrorListener) { protected void init(Configuration config, IOCriticalErrorListener criticalErrorListener) {
DatabaseStorageConfiguration dbConf = (DatabaseStorageConfiguration) config.getStoreConfiguration(); DatabaseStorageConfiguration dbConf = (DatabaseStorageConfiguration) config.getStoreConfiguration();
Journal localBindings = new JDBCJournalImpl(dbConf.getJdbcConnectionUrl(), dbConf.getBindingsTableName()); Journal localBindings = new JDBCJournalImpl(dbConf.getJdbcConnectionUrl(), dbConf.getBindingsTableName(), dbConf.getJdbcDriverClassName());
bindingsJournal = localBindings; bindingsJournal = localBindings;
Journal localMessage = new JDBCJournalImpl(dbConf.getJdbcConnectionUrl(), dbConf.getMessageTableName()); Journal localMessage = new JDBCJournalImpl(dbConf.getJdbcConnectionUrl(), dbConf.getMessageTableName(), dbConf.getJdbcDriverClassName());
messageJournal = localMessage; messageJournal = localMessage;
} }

View File

@ -1516,6 +1516,13 @@
<xsd:complexType name="databaseStoreType"> <xsd:complexType name="databaseStoreType">
<xsd:all> <xsd:all>
<xsd:element name="jdbc-driver-class-name" type="xsd:string" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
The JDBC Driver class name
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="jdbc-connection-url" type="xsd:string" minOccurs="1" maxOccurs="1"> <xsd:element name="jdbc-connection-url" type="xsd:string" minOccurs="1" maxOccurs="1">
<xsd:annotation> <xsd:annotation>
<xsd:documentation> <xsd:documentation>

View File

@ -395,6 +395,7 @@ public abstract class ActiveMQTestBase extends Assert {
dbStorageConfiguration.setJdbcConnectionUrl(getTestJDBCConnectionUrl()); dbStorageConfiguration.setJdbcConnectionUrl(getTestJDBCConnectionUrl());
dbStorageConfiguration.setBindingsTableName("BINDINGS"); dbStorageConfiguration.setBindingsTableName("BINDINGS");
dbStorageConfiguration.setMessageTableName("MESSAGES"); dbStorageConfiguration.setMessageTableName("MESSAGES");
dbStorageConfiguration.setJdbcDriverClassName("org.apache.derby.jdbc.EmbeddedDriver");
configuration.setStoreConfiguration(dbStorageConfiguration); configuration.setStoreConfiguration(dbStorageConfiguration);

View File

@ -24,6 +24,7 @@
<jdbc-connection-url>jdbc:derby:target/derby/database-store;create=true</jdbc-connection-url> <jdbc-connection-url>jdbc:derby:target/derby/database-store;create=true</jdbc-connection-url>
<bindings-table-name>BINDINGS_TABLE</bindings-table-name> <bindings-table-name>BINDINGS_TABLE</bindings-table-name>
<message-table-name>MESSAGE_TABLE</message-table-name> <message-table-name>MESSAGE_TABLE</message-table-name>
<jdbc-driver-class-name>org.apache.derby.jdbc.EmbeddedDriver</jdbc-driver-class-name>
</database-store> </database-store>
</store> </store>
</core> </core>

View File

@ -376,6 +376,7 @@ To configure Apache ActiveMQ Artemis to use a database for persisting messages a
<jdbc-connection-url>jdbc:derby:target/derby/database-store;create=true</jdbc-connection-url> <jdbc-connection-url>jdbc:derby:target/derby/database-store;create=true</jdbc-connection-url>
<bindings-table-name>BINDINGS_TABLE</bindings-table-name> <bindings-table-name>BINDINGS_TABLE</bindings-table-name>
<message-table-name>MESSAGE_TABLE</message-table-name> <message-table-name>MESSAGE_TABLE</message-table-name>
<jdbc-driver-class-name>org.apache.derby.jdbc.EmbeddedDriver</jdbc-driver-class-name>
</database-store> </database-store>
</store> </store>
``` ```
@ -392,6 +393,11 @@ To configure Apache ActiveMQ Artemis to use a database for persisting messages a
The name of the table in which messages and related data will be persisted for the ActiveMQ Artemis server. Specifying table names allows users to share single database amongst multiple servers, without interference. The name of the table in which messages and related data will be persisted for the ActiveMQ Artemis server. Specifying table names allows users to share single database amongst multiple servers, without interference.
- `jdbc-driver-class-name`
The fully qualified class name of the desired database Driver.
## Configuring Apache ActiveMQ Artemis for Zero Persistence ## Configuring Apache ActiveMQ Artemis for Zero Persistence
In some situations, zero persistence is sometimes required for a In some situations, zero persistence is sometimes required for a

View File

@ -208,6 +208,7 @@
<groupId>org.apache.derby</groupId> <groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId> <artifactId>derby</artifactId>
<version>${apache.derby.version}</version> <version>${apache.derby.version}</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.paho</groupId> <groupId>org.eclipse.paho</groupId>

View File

@ -18,7 +18,6 @@ package org.apache.activemq.artemis.tests.integration.jdbc.store.journal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -41,16 +40,16 @@ public class JDBCJournalTest {
private static final String JOURNAL_TABLE_NAME = "MESSAGE_JOURNAL"; private static final String JOURNAL_TABLE_NAME = "MESSAGE_JOURNAL";
private static final String DRIVER_CLASS = "org.apache.derby.jdbc.EmbeddedDriver";
private JDBCJournalImpl journal; private JDBCJournalImpl journal;
private String jdbcUrl; private String jdbcUrl;
private Properties jdbcConnectionProperties;
@Before @Before
public void setup() throws Exception { public void setup() throws Exception {
jdbcUrl = "jdbc:derby:target/data;create=true"; jdbcUrl = "jdbc:derby:target/data;create=true";
journal = new JDBCJournalImpl(jdbcUrl, JOURNAL_TABLE_NAME); journal = new JDBCJournalImpl(jdbcUrl, JOURNAL_TABLE_NAME, DRIVER_CLASS);
journal.start(); journal.start();
} }