You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by jb...@apache.org on 2018/01/19 02:55:23 UTC

[2/2] activemq-artemis git commit: ARTEMIS-1613 Integrating JDBC into CLI (create print-data and exp)

ARTEMIS-1613 Integrating JDBC into CLI (create print-data and exp)


Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/61a1123e
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/61a1123e
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/61a1123e

Branch: refs/heads/master
Commit: 61a1123ee155fd223e29b74e5e735c18b0346f20
Parents: 64424f2
Author: Clebert Suconic <cl...@apache.org>
Authored: Fri Jan 12 14:07:23 2018 -0500
Committer: Justin Bertram <jb...@apache.org>
Committed: Thu Jan 18 20:55:00 2018 -0600

----------------------------------------------------------------------
 .../apache/activemq/artemis/cli/Artemis.java    |   7 +-
 .../artemis/cli/commands/Configurable.java      |  49 ++--
 .../activemq/artemis/cli/commands/Create.java   |  82 ++++++-
 .../artemis/cli/commands/tools/DBOption.java    | 244 +++++++++++++++++++
 .../artemis/cli/commands/tools/PrintData.java   | 201 +++++++++------
 .../cli/commands/tools/xml/XmlDataExporter.java |  81 +++---
 .../artemis/cli/commands/etc/broker.xml         |   1 +
 .../artemis/cli/commands/etc/database-store.txt |  18 ++
 .../apache/activemq/cli/test/ArtemisTest.java   |   7 +
 .../activemq/cli/test/StreamClassPathTest.java  |   1 +
 .../config/ActiveMQDefaultConfiguration.java    |   4 +-
 .../jdbc/store/journal/JDBCJournalImpl.java     |   6 -
 .../activemq/artemis/core/journal/Journal.java  |   9 +-
 .../core/journal/impl/FileWrapperJournal.java   |   3 +-
 .../artemis/core/journal/impl/JournalImpl.java  |   8 +-
 .../artemis/core/config/Configuration.java      |   5 +
 .../impl/journal/DescribeJournal.java           |  26 +-
 .../core/replication/ReplicatedJournal.java     |   5 +-
 .../impl/jdbc/ActiveMQScheduledLeaseLock.java   |   4 +-
 examples/features/standard/database/pom.xml     | 131 ++++++++++
 examples/features/standard/database/readme.md   |   7 +
 .../activemq/artemis/jms/example/DBExample.java |  59 +++++
 examples/features/standard/pom.xml              |   2 +
 .../replication/ReplicationTest.java            |   3 +-
 24 files changed, 784 insertions(+), 179 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java
----------------------------------------------------------------------
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java
index 6abf1b6..e41e629 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java
@@ -19,6 +19,7 @@ package org.apache.activemq.artemis.cli;
 import java.io.File;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.PrintStream;
 import java.util.List;
 
 import io.airlift.airline.Cli;
@@ -176,7 +177,11 @@ public class Artemis {
    }
 
    public static void printBanner() throws Exception {
-      copy(Artemis.class.getResourceAsStream("banner.txt"), System.out);
+      printBanner(System.out);
+   }
+
+   public static void printBanner(PrintStream out) throws Exception {
+      copy(Artemis.class.getResourceAsStream("banner.txt"), out);
    }
 
    private static long copy(InputStream in, OutputStream out) throws Exception {

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Configurable.java
----------------------------------------------------------------------
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Configurable.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Configurable.java
index 9099068..99fb52d 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Configurable.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Configurable.java
@@ -26,6 +26,7 @@ import io.airlift.airline.Option;
 import io.airlift.airline.model.CommandGroupMetadata;
 import io.airlift.airline.model.CommandMetadata;
 import io.airlift.airline.model.GlobalMetadata;
+import org.apache.activemq.artemis.api.core.ActiveMQException;
 import org.apache.activemq.artemis.cli.factory.BrokerFactory;
 import org.apache.activemq.artemis.cli.factory.jmx.ManagementFactory;
 import org.apache.activemq.artemis.core.config.FileDeploymentManager;
@@ -58,6 +59,10 @@ public abstract class Configurable extends ActionAbstract {
       System.err.println();
       System.err.println("Error:" + e.getMessage());
       System.err.println();
+
+      if (!(e instanceof ActiveMQException)) {
+         e.printStackTrace();
+      }
       helpGroup(group, command);
    }
 
@@ -76,25 +81,31 @@ public abstract class Configurable extends ActionAbstract {
 
    protected FileConfiguration getFileConfiguration() throws Exception {
       if (fileConfiguration == null) {
-         if (getBrokerInstance() == null) {
-            final String defaultLocation = "./data";
-            fileConfiguration = new FileConfiguration();
-            // These will be the default places in case the file can't be loaded
-            fileConfiguration.setBindingsDirectory(defaultLocation + "/bindings");
-            fileConfiguration.setJournalDirectory(defaultLocation + "/journal");
-            fileConfiguration.setLargeMessagesDirectory(defaultLocation + "/largemessages");
-            fileConfiguration.setPagingDirectory(defaultLocation + "/paging");
-            fileConfiguration.setBrokerInstance(new File("."));
-         } else {
-            fileConfiguration = new FileConfiguration();
-            FileJMSConfiguration jmsConfiguration = new FileJMSConfiguration();
-
-            String serverConfiguration = getBrokerDTO().server.getConfigurationURI().toASCIIString();
-            FileDeploymentManager fileDeploymentManager = new FileDeploymentManager(serverConfiguration);
-            fileDeploymentManager.addDeployable(fileConfiguration).addDeployable(jmsConfiguration);
-            fileDeploymentManager.readConfiguration();
-            fileConfiguration.setBrokerInstance(new File(getBrokerInstance()));
-         }
+         fileConfiguration = readConfiguration();
+      }
+
+      return fileConfiguration;
+   }
+
+   protected FileConfiguration readConfiguration() throws Exception {
+      FileConfiguration fileConfiguration = new FileConfiguration();
+      if (getBrokerInstance() == null) {
+         final String defaultLocation = "./data";
+         fileConfiguration = new FileConfiguration();
+         // These will be the default places in case the file can't be loaded
+         fileConfiguration.setBindingsDirectory(defaultLocation + "/bindings");
+         fileConfiguration.setJournalDirectory(defaultLocation + "/journal");
+         fileConfiguration.setLargeMessagesDirectory(defaultLocation + "/largemessages");
+         fileConfiguration.setPagingDirectory(defaultLocation + "/paging");
+         fileConfiguration.setBrokerInstance(new File("."));
+      } else {
+         FileJMSConfiguration jmsConfiguration = new FileJMSConfiguration();
+
+         String serverConfiguration = getBrokerDTO().server.getConfigurationURI().toASCIIString();
+         FileDeploymentManager fileDeploymentManager = new FileDeploymentManager(serverConfiguration);
+         fileDeploymentManager.addDeployable(fileConfiguration).addDeployable(jmsConfiguration);
+         fileDeploymentManager.readConfiguration();
+         fileConfiguration.setBrokerInstance(new File(getBrokerInstance()));
       }
 
       return fileConfiguration;

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java
----------------------------------------------------------------------
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java
index 400bdc3..5fe281e 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java
@@ -103,6 +103,7 @@ public class Create extends InputAbstract {
    public static final String ETC_STOMP_ACCEPTOR_TXT = "etc/stomp-acceptor.txt";
    public static final String ETC_PING_TXT = "etc/ping-settings.txt";
    public static final String ETC_COMMENTED_PING_TXT = "etc/commented-ping-settings.txt";
+   public static final String ETC_DATABASE_STORE_TXT = "etc/database-store.txt";
 
    public static final String ETC_GLOBAL_MAX_SPECIFIED_TXT = "etc/global-max-specified.txt";
    public static final String ETC_GLOBAL_MAX_DEFAULT_TXT = "etc/global-max-default.txt";
@@ -261,6 +262,40 @@ public class Create extends InputAbstract {
    @Option(name = "--global-max-size", description = "Maximum amount of memory which message data may consume (Default: Undefined, half of the system's memory)")
    private String globalMaxSize;
 
+
+   @Option(name = "--jdbc", description = "It will activate jdbc")
+   boolean jdbc;
+
+   @Option(name = "--jdbc-bindings-table-name", description = "Name of the jdbc bindigns table")
+   private String jdbcBindings = ActiveMQDefaultConfiguration.getDefaultBindingsTableName();
+
+   @Option(name = "--jdbc-message-table-name", description = "Name of the jdbc messages table")
+   private String jdbcMessages = ActiveMQDefaultConfiguration.getDefaultMessageTableName();
+
+   @Option(name = "--jdbc-large-message-table-name", description = "Name of the large messages table")
+   private String jdbcLargeMessages = ActiveMQDefaultConfiguration.getDefaultLargeMessagesTableName();
+
+   @Option(name = "--jdbc-page-store-table-name", description = "Name of the page sotre messages table")
+   private String jdbcPageStore = ActiveMQDefaultConfiguration.getDefaultPageStoreTableName();
+
+   @Option(name = "--jdbc-connection-url", description = "The connection used for the database")
+   private String jdbcURL = null;
+
+   @Option(name = "--jdbc-driver-class-name", description = "JDBC driver classname")
+   private String jdbcClassName = ActiveMQDefaultConfiguration.getDefaultDriverClassName();
+
+   @Option(name = "--jdbc-network-timeout", description = "Network timeout")
+   long jdbcNetworkTimeout = ActiveMQDefaultConfiguration.getDefaultJdbcNetworkTimeout();
+
+   @Option(name = "--jdbc-lock-acquisition-timeout", description = "Lock acquisition timeout")
+   long jdbcLockAcquisitionTimeout = ActiveMQDefaultConfiguration.getDefaultJournalLockAcquisitionTimeout();
+
+   @Option(name = "--jdbc-lock-renew-period", description = "Lock Renew Period")
+   long jdbcLockRenewPeriod = ActiveMQDefaultConfiguration.getDefaultJdbcLockRenewPeriodMillis();
+
+   @Option(name = "--jdbc-lock-expiration", description = "Lock expiration")
+   long jdbcLockExpiration = ActiveMQDefaultConfiguration.getDefaultJdbcLockExpirationMillis();
+
    private boolean IS_WINDOWS;
    private boolean IS_CYGWIN;
 
@@ -557,6 +592,25 @@ public class Create extends InputAbstract {
          filters.put("${global-max-section}", readTextFile(ETC_GLOBAL_MAX_SPECIFIED_TXT, filters));
       }
 
+      if (jdbc) {
+         if (jdbcURL == null) {
+            jdbcURL = "jdbc:derby:" + getInstance().getAbsolutePath() + "/data/derby/db;create=true";
+         }
+         filters.put("${jdbcBindings}", jdbcBindings);
+         filters.put("${jdbcMessages}", jdbcMessages);
+         filters.put("${jdbcLargeMessages}", jdbcLargeMessages);
+         filters.put("${jdbcPageStore}", jdbcPageStore);
+         filters.put("${jdbcURL}", jdbcURL);
+         filters.put("${jdbcClassName}", jdbcClassName);
+         filters.put("${jdbcNetworkTimeout}", "" + jdbcNetworkTimeout);
+         filters.put("${jdbcLockAcquisitionTimeout}", "" + jdbcLockAcquisitionTimeout);
+         filters.put("${jdbcLockRenewPeriod}", "" + jdbcLockRenewPeriod);
+         filters.put("${jdbcLockExpiration}", "" + jdbcLockExpiration);
+         filters.put("${jdbc}", readTextFile(ETC_DATABASE_STORE_TXT, filters));
+      } else {
+         filters.put("${jdbc}", "");
+      }
+
 
       if (clustered) {
          filters.put("${host}", getHostForClustered());
@@ -682,6 +736,13 @@ public class Create extends InputAbstract {
 
       filters.put("${auto-create}", isAutoCreate() ? "true" : "false");
 
+      if (jdbc) {
+         noAutoTune = true;
+         System.out.println();
+         printStar("Copy a jar containing the JDBC Driver '" + jdbcClassName + "' into " + directory.getAbsolutePath() + "/lib");
+         System.out.println();
+      }
+
       performAutoTune(filters, journalType, dataFolder);
 
       write(ETC_BROKER_XML, filters, false);
@@ -725,6 +786,19 @@ public class Create extends InputAbstract {
       return null;
    }
 
+   private void printStar(String message) {
+      int size = Math.min(message.length(), 80);
+      StringBuffer buffer = new StringBuffer(size);
+      for (int i = 0; i < size; i++) {
+         buffer.append("*");
+      }
+      System.out.println(buffer.toString());
+      System.out.println();
+      System.out.println(message);
+      System.out.println();
+      System.out.println(buffer.toString());
+   }
+
    private void setupJournalType() {
 
       if (noJournalSync && !mapped) {
@@ -935,7 +1009,13 @@ public class Create extends InputAbstract {
 
       if (filters != null) {
          for (Map.Entry<String, String> entry : filters.entrySet()) {
-            content = replace(content, entry.getKey(), entry.getValue());
+            try {
+               content = replace(content, entry.getKey(), entry.getValue());
+            } catch (Throwable e) {
+               System.out.println("Error on " + entry.getKey());
+               e.printStackTrace();
+               System.exit(-1);
+            }
          }
       }
       return content;

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DBOption.java
----------------------------------------------------------------------
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DBOption.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DBOption.java
new file mode 100644
index 0000000..044d179
--- /dev/null
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DBOption.java
@@ -0,0 +1,244 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.activemq.artemis.cli.commands.tools;
+
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
+
+import io.airlift.airline.Option;
+import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
+import org.apache.activemq.artemis.cli.commands.ActionContext;
+import org.apache.activemq.artemis.core.config.Configuration;
+import org.apache.activemq.artemis.core.config.impl.FileConfiguration;
+import org.apache.activemq.artemis.core.config.storage.DatabaseStorageConfiguration;
+import org.apache.activemq.artemis.core.paging.PagingManager;
+import org.apache.activemq.artemis.core.paging.PagingStoreFactory;
+import org.apache.activemq.artemis.core.paging.impl.PagingManagerImpl;
+import org.apache.activemq.artemis.core.paging.impl.PagingStoreFactoryDatabase;
+import org.apache.activemq.artemis.core.paging.impl.PagingStoreFactoryNIO;
+import org.apache.activemq.artemis.core.persistence.impl.journal.JDBCJournalStorageManager;
+import org.apache.activemq.artemis.core.persistence.impl.journal.JournalStorageManager;
+import org.apache.activemq.artemis.core.settings.HierarchicalRepository;
+import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
+import org.apache.activemq.artemis.core.settings.impl.HierarchicalObjectRepository;
+import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
+import org.apache.activemq.artemis.utils.ExecutorFactory;
+import org.apache.activemq.artemis.utils.actors.OrderedExecutorFactory;
+import org.apache.activemq.artemis.utils.critical.EmptyCriticalAnalyzer;
+
+public class DBOption extends OptionalLocking {
+
+   protected JournalStorageManager storageManager;
+
+   protected Configuration config;
+
+   protected ExecutorService executor;
+
+   protected ExecutorFactory executorFactory;
+
+   protected ScheduledExecutorService scheduledExecutorService;
+
+   @Option(name = "--output", description = "Output name for the file")
+   private String output;
+
+   @Option(name = "--jdbc", description = "It will activate jdbc")
+   Boolean jdbc;
+
+   @Option(name = "--jdbc-bindings-table-name", description = "Name of the jdbc bindigns table")
+   private String jdbcBindings = ActiveMQDefaultConfiguration.getDefaultBindingsTableName();
+
+   @Option(name = "--jdbc-message-table-name", description = "Name of the jdbc messages table")
+   private String jdbcMessages = ActiveMQDefaultConfiguration.getDefaultLargeMessagesTableName();
+
+   @Option(name = "--jdbc-large-message-table-name", description = "Name of the large messages table")
+   private String jdbcLargeMessages = ActiveMQDefaultConfiguration.getDefaultLargeMessagesTableName();
+
+   @Option(name = "--jdbc-page-store-table-name", description = "Name of the page sotre messages table")
+   private String jdbcPageStore = ActiveMQDefaultConfiguration.getDefaultPageStoreTableName();
+
+   @Option(name = "--jdbc-connection-url", description = "The connection used for the database")
+   private String jdbcURL = null;
+
+   @Option(name = "--jdbc-driver-class-name", description = "JDBC driver classname")
+   private String jdbcClassName = ActiveMQDefaultConfiguration.getDefaultDriverClassName();
+
+   public boolean isJDBC() throws Exception {
+      parseDBConfig();
+      return jdbc;
+   }
+
+   public String getJdbcBindings() throws Exception {
+      parseDBConfig();
+      return jdbcBindings;
+   }
+
+   public DBOption setJdbcBindings(String jdbcBindings) {
+      this.jdbcBindings = jdbcBindings;
+      return this;
+   }
+
+   public String getJdbcMessages() throws Exception {
+      parseDBConfig();
+      return jdbcMessages;
+   }
+
+   public DBOption setJdbcMessages(String jdbcMessages) {
+      this.jdbcMessages = jdbcMessages;
+      return this;
+   }
+
+   public String getJdbcLargeMessages() throws Exception {
+      parseDBConfig();
+      return jdbcLargeMessages;
+   }
+
+   public DBOption setJdbcLargeMessages(String jdbcLargeMessages) {
+      this.jdbcLargeMessages = jdbcLargeMessages;
+      return this;
+   }
+
+   public String getJdbcPageStore() throws Exception {
+      parseDBConfig();
+      return jdbcPageStore;
+   }
+
+   public DBOption setJdbcPageStore(String jdbcPageStore) {
+      this.jdbcPageStore = jdbcPageStore;
+      return this;
+   }
+
+   public String getJdbcURL() throws Exception {
+      parseDBConfig();
+      return jdbcURL;
+   }
+
+   public DBOption setJdbcURL(String jdbcURL) {
+      this.jdbcURL = jdbcURL;
+      return this;
+   }
+
+   public String getJdbcClassName() throws Exception {
+      parseDBConfig();
+      return jdbcClassName;
+   }
+
+   public DBOption setJdbcClassName(String jdbcClassName) {
+      this.jdbcClassName = jdbcClassName;
+      return this;
+   }
+
+
+   @Override
+   public Object execute(ActionContext context) throws Exception {
+      super.execute(context);
+
+      if (output != null) {
+         FileOutputStream fileOutputStream = new FileOutputStream(output);
+         PrintStream printStream = new PrintStream(fileOutputStream);
+         context.out = printStream;
+
+         Runtime.getRuntime().addShutdownHook(new Thread(printStream::close));
+      }
+      return null;
+   }
+
+   private void parseDBConfig() throws Exception {
+      if (jdbc == null) {
+         FileConfiguration fileConfiguration = getFileConfiguration();
+         jdbc = fileConfiguration.isJDBC();
+         if (jdbc) {
+            DatabaseStorageConfiguration storageConfiguration = (DatabaseStorageConfiguration) fileConfiguration.getStoreConfiguration();
+            jdbcBindings = storageConfiguration.getBindingsTableName();
+            jdbcMessages = storageConfiguration.getMessageTableName();
+            jdbcLargeMessages = storageConfiguration.getLargeMessageTableName();
+            jdbcPageStore = storageConfiguration.getPageStoreTableName();
+            jdbcURL = storageConfiguration.getJdbcConnectionUrl();
+            jdbcClassName = storageConfiguration.getJdbcDriverClassName();
+         }
+      }
+   }
+
+   // Get a new configuration based on the passed parameters and not on the parsed configuration
+   public Configuration getParameterConfiguration() throws Exception {
+      Configuration configuration = readConfiguration();
+      if (isJDBC()) {
+         DatabaseStorageConfiguration storageConfiguration = new DatabaseStorageConfiguration();
+         storageConfiguration.setJdbcConnectionUrl(getJdbcURL());
+         storageConfiguration.setJdbcDriverClassName(getJdbcClassName());
+         storageConfiguration.setBindingsTableName(getJdbcBindings());
+         storageConfiguration.setMessageTableName(getJdbcMessages());
+         storageConfiguration.setLargeMessageTableName(getJdbcLargeMessages());
+         storageConfiguration.setPageStoreTableName(getJdbcPageStore());
+         configuration.setStoreConfiguration(storageConfiguration);
+      } else {
+         configuration.setBindingsDirectory(getBinding());
+         configuration.setJournalDirectory(getJournal());
+         configuration.setPagingDirectory(getPaging());
+         configuration.setLargeMessagesDirectory(getLargeMessages());
+      }
+
+      return configuration;
+   }
+
+   protected PagingManager pagingmanager;
+
+   protected void initializeJournal(Configuration configuration) throws Exception {
+      this.config = configuration;
+      executor = Executors.newFixedThreadPool(5, ActiveMQThreadFactory.defaultThreadFactory());
+      executorFactory = new OrderedExecutorFactory(executor);
+
+      scheduledExecutorService = new ScheduledThreadPoolExecutor(configuration.getScheduledThreadPoolMaxSize(), new ThreadFactory() {
+         @Override
+         public Thread newThread(Runnable r) {
+            return new Thread(r);
+         }
+      });
+
+      HierarchicalRepository<AddressSettings> addressSettingsRepository = new HierarchicalObjectRepository<>(config.getWildcardConfiguration());
+      addressSettingsRepository.setDefault(new AddressSettings());
+
+      if (configuration.isJDBC()) {
+         storageManager = new JDBCJournalStorageManager(config, null, scheduledExecutorService, executorFactory, executorFactory, null);
+
+         PagingStoreFactory pageStoreFactory = new PagingStoreFactoryDatabase((DatabaseStorageConfiguration) configuration.getStoreConfiguration(),
+                                                                              storageManager, 1000L,
+                                                                              scheduledExecutorService, executorFactory,
+                                                                             false, null);
+         pagingmanager = new PagingManagerImpl(pageStoreFactory, addressSettingsRepository);
+      } else {
+         storageManager = new JournalStorageManager(config, EmptyCriticalAnalyzer.getInstance(), executorFactory, executorFactory);
+         PagingStoreFactory pageStoreFactory = new PagingStoreFactoryNIO(storageManager, config.getPagingLocation(), 1000L, scheduledExecutorService, executorFactory, true, null);
+         pagingmanager = new PagingManagerImpl(pageStoreFactory, addressSettingsRepository);
+
+      }
+
+   }
+
+   protected void cleanup() throws Exception {
+      executor.shutdown();
+      scheduledExecutorService.shutdown();
+
+      storageManager.stop();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java
----------------------------------------------------------------------
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java
index cf9c9c4..9771c5e 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java
@@ -17,6 +17,7 @@
 package org.apache.activemq.artemis.cli.commands.tools;
 
 import java.io.File;
+import java.io.PrintStream;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -32,6 +33,7 @@ import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
 import org.apache.activemq.artemis.api.core.SimpleString;
 import org.apache.activemq.artemis.cli.Artemis;
 import org.apache.activemq.artemis.cli.commands.ActionContext;
+import org.apache.activemq.artemis.core.config.Configuration;
 import org.apache.activemq.artemis.core.journal.RecordInfo;
 import org.apache.activemq.artemis.core.message.impl.CoreMessagePersister;
 import org.apache.activemq.artemis.core.paging.PagedMessage;
@@ -60,8 +62,10 @@ import org.apache.activemq.artemis.utils.ExecutorFactory;
 import org.apache.activemq.artemis.utils.actors.ArtemisExecutor;
 
 @Command(name = "print", description = "Print data records information (WARNING: don't use while a production server is running)")
-public class PrintData extends OptionalLocking {
+public class PrintData extends DBOption {
 
+   private static final String BINDINGS_BANNER = "B I N D I N G S  J O U R N A L";
+   private static final String MESSAGES_BANNER = "M E S S A G E S   J O U R N A L";
    static {
       MessagePersister.registerPersister(CoreMessagePersister.getInstance());
    }
@@ -69,18 +73,49 @@ public class PrintData extends OptionalLocking {
    @Override
    public Object execute(ActionContext context) throws Exception {
       super.execute(context);
+
+      Configuration configuration = getParameterConfiguration();
+
       try {
-         printData(new File(getBinding()), new File(getJournal()), new File(getPaging()));
+         if (configuration.isJDBC()) {
+            printDataJDBC(configuration, context.out);
+         } else {
+            printData(new File(getBinding()), new File(getJournal()), new File(getPaging()), context.out);
+         }
       } catch (Exception e) {
          treatError(e, "data", "print");
       }
       return null;
    }
 
+
+   public void printDataJDBC(Configuration configuration, PrintStream out) throws Exception {
+      initializeJournal(configuration);
+
+      Artemis.printBanner(out);
+
+      printBanner(out, BINDINGS_BANNER);
+
+      DescribeJournal.printSurvivingRecords(storageManager.getBindingsJournal(), out);
+
+      printBanner(out, MESSAGES_BANNER);
+
+      DescribeJournal describeJournal = DescribeJournal.printSurvivingRecords(storageManager.getMessageJournal(), out);
+
+      printPages(describeJournal, storageManager, pagingmanager, out);
+
+      cleanup();
+
+   }
+
    public static void printData(File bindingsDirectory, File messagesDirectory, File pagingDirectory) throws Exception {
-      // Having the version on the data report is an information very useful to understand what happened
+      printData(bindingsDirectory, messagesDirectory, pagingDirectory, System.out);
+   }
+
+   public static void printData(File bindingsDirectory, File messagesDirectory, File pagingDirectory, PrintStream out) throws Exception {
+         // Having the version on the data report is an information very useful to understand what happened
       // When debugging stuff
-      Artemis.printBanner();
+      Artemis.printBanner(out);
 
       File serverLockFile = new File(messagesDirectory, "server.lock");
 
@@ -88,45 +123,35 @@ public class PrintData extends OptionalLocking {
          try {
             FileLockNodeManager fileLock = new FileLockNodeManager(messagesDirectory, false);
             fileLock.start();
-            System.out.println("********************************************");
-            System.out.println("Server's ID=" + fileLock.getNodeId().toString());
-            System.out.println("********************************************");
+            printBanner(out, "Server's ID=" + fileLock.getNodeId().toString());
             fileLock.stop();
          } catch (Exception e) {
             e.printStackTrace();
          }
       }
 
-      System.out.println("********************************************");
-      System.out.println("B I N D I N G S  J O U R N A L");
-      System.out.println("********************************************");
+      printBanner(out, BINDINGS_BANNER);
 
       try {
-         DescribeJournal.describeBindingsJournal(bindingsDirectory);
+         DescribeJournal.describeBindingsJournal(bindingsDirectory, out);
       } catch (Exception e) {
          e.printStackTrace();
       }
 
-      System.out.println();
-      System.out.println("********************************************");
-      System.out.println("M E S S A G E S   J O U R N A L");
-      System.out.println("********************************************");
+      printBanner(out, MESSAGES_BANNER);
 
       DescribeJournal describeJournal = null;
       try {
-         describeJournal = DescribeJournal.describeMessagesJournal(messagesDirectory);
+         describeJournal = DescribeJournal.describeMessagesJournal(messagesDirectory, out);
       } catch (Exception e) {
          e.printStackTrace();
          return;
       }
 
       try {
-         System.out.println();
-         System.out.println("********************************************");
-         System.out.println("P A G I N G");
-         System.out.println("********************************************");
+         printBanner(out, "P A G I N G");
 
-         printPages(pagingDirectory, describeJournal);
+         printPages(pagingDirectory, describeJournal, out);
       } catch (Exception e) {
          e.printStackTrace();
          return;
@@ -134,12 +159,15 @@ public class PrintData extends OptionalLocking {
 
    }
 
-   private static void printPages(File pageDirectory, DescribeJournal describeJournal) {
-      try {
-
-         PageCursorsInfo cursorACKs = calculateCursorsInfo(describeJournal.getRecords());
+   protected static void printBanner(PrintStream out, String x2) {
+      out.println();
+      out.println("********************************************");
+      out.println(x2);
+      out.println("********************************************");
+   }
 
-         Set<Long> pgTXs = cursorACKs.getPgTXs();
+   private static void printPages(File pageDirectory, DescribeJournal describeJournal, PrintStream out) {
+      try {
 
          ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1, ActiveMQThreadFactory.defaultThreadFactory());
          final ExecutorService executor = Executors.newFixedThreadPool(10, ActiveMQThreadFactory.defaultThreadFactory());
@@ -155,69 +183,80 @@ public class PrintData extends OptionalLocking {
          addressSettingsRepository.setDefault(new AddressSettings());
          PagingManager manager = new PagingManagerImpl(pageStoreFactory, addressSettingsRepository);
 
-         manager.start();
+         printPages(describeJournal, sm, manager, out);
+      } catch (Exception e) {
+         e.printStackTrace();
+      }
+   }
 
-         SimpleString[] stores = manager.getStoreNames();
+   private static void printPages(DescribeJournal describeJournal,
+                                  StorageManager sm,
+                                  PagingManager manager,
+                                  PrintStream out) throws Exception {
+      PageCursorsInfo cursorACKs = calculateCursorsInfo(describeJournal.getRecords());
 
-         for (SimpleString store : stores) {
-            PagingStore pgStore = manager.getPageStore(store);
-            File folder = null;
+      Set<Long> pgTXs = cursorACKs.getPgTXs();
 
-            if (pgStore != null) {
-               folder = pgStore.getFolder();
-            }
-            System.out.println("####################################################################################################");
-            System.out.println("Exploring store " + store + " folder = " + folder);
-            int pgid = (int) pgStore.getFirstPage();
-            for (int pg = 0; pg < pgStore.getNumberOfPages(); pg++) {
-               System.out.println("*******   Page " + pgid);
-               Page page = pgStore.createPage(pgid);
-               page.open();
-               List<PagedMessage> msgs = page.read(sm);
-               page.close();
-
-               int msgID = 0;
-
-               for (PagedMessage msg : msgs) {
-                  msg.initMessage(sm);
-                  System.out.print("pg=" + pgid + ", msg=" + msgID + ",pgTX=" + msg.getTransactionID() + ",userMessageID=" + (msg.getMessage().getUserID() != null ? msg.getMessage().getUserID() : "") + ", msg=" + msg.getMessage());
-                  System.out.print(",Queues = ");
-                  long[] q = msg.getQueueIDs();
-                  for (int i = 0; i < q.length; i++) {
-                     System.out.print(q[i]);
-
-                     PagePosition posCheck = new PagePositionImpl(pgid, msgID);
-
-                     boolean acked = false;
-
-                     Set<PagePosition> positions = cursorACKs.getCursorRecords().get(q[i]);
-                     if (positions != null) {
-                        acked = positions.contains(posCheck);
-                     }
-
-                     if (acked) {
-                        System.out.print(" (ACK)");
-                     }
-
-                     if (cursorACKs.getCompletePages(q[i]).contains(Long.valueOf(pgid))) {
-                        System.out.println(" (PG-COMPLETE)");
-                     }
-
-                     if (i + 1 < q.length) {
-                        System.out.print(",");
-                     }
+      manager.start();
+
+      SimpleString[] stores = manager.getStoreNames();
+
+      for (SimpleString store : stores) {
+         PagingStore pgStore = manager.getPageStore(store);
+         File folder = null;
+
+         if (pgStore != null) {
+            folder = pgStore.getFolder();
+         }
+         out.println("####################################################################################################");
+         out.println("Exploring store " + store + " folder = " + folder);
+         int pgid = (int) pgStore.getFirstPage();
+         for (int pg = 0; pg < pgStore.getNumberOfPages(); pg++) {
+            out.println("*******   Page " + pgid);
+            Page page = pgStore.createPage(pgid);
+            page.open();
+            List<PagedMessage> msgs = page.read(sm);
+            page.close();
+
+            int msgID = 0;
+
+            for (PagedMessage msg : msgs) {
+               msg.initMessage(sm);
+               out.print("pg=" + pgid + ", msg=" + msgID + ",pgTX=" + msg.getTransactionID() + ",userMessageID=" + (msg.getMessage().getUserID() != null ? msg.getMessage().getUserID() : "") + ", msg=" + msg.getMessage());
+               out.print(",Queues = ");
+               long[] q = msg.getQueueIDs();
+               for (int i = 0; i < q.length; i++) {
+                  out.print(q[i]);
+
+                  PagePosition posCheck = new PagePositionImpl(pgid, msgID);
+
+                  boolean acked = false;
+
+                  Set<PagePosition> positions = cursorACKs.getCursorRecords().get(q[i]);
+                  if (positions != null) {
+                     acked = positions.contains(posCheck);
                   }
-                  if (msg.getTransactionID() >= 0 && !pgTXs.contains(msg.getTransactionID())) {
-                     System.out.print(", **PG_TX_NOT_FOUND**");
+
+                  if (acked) {
+                     out.print(" (ACK)");
                   }
-                  System.out.println();
-                  msgID++;
+
+                  if (cursorACKs.getCompletePages(q[i]).contains(Long.valueOf(pgid))) {
+                     out.println(" (PG-COMPLETE)");
+                  }
+
+                  if (i + 1 < q.length) {
+                     out.print(",");
+                  }
+               }
+               if (msg.getTransactionID() >= 0 && !pgTXs.contains(msg.getTransactionID())) {
+                  out.print(", **PG_TX_NOT_FOUND**");
                }
-               pgid++;
+               out.println();
+               msgID++;
             }
+            pgid++;
          }
-      } catch (Exception e) {
-         e.printStackTrace();
       }
    }
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataExporter.java
----------------------------------------------------------------------
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataExporter.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataExporter.java
index 7a59c00..85eac4a 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataExporter.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataExporter.java
@@ -32,9 +32,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
 
 import io.airlift.airline.Command;
 import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
@@ -45,31 +42,24 @@ import org.apache.activemq.artemis.api.core.Message;
 import org.apache.activemq.artemis.api.core.RoutingType;
 import org.apache.activemq.artemis.api.core.SimpleString;
 import org.apache.activemq.artemis.cli.commands.ActionContext;
-import org.apache.activemq.artemis.cli.commands.tools.OptionalLocking;
-import org.apache.activemq.artemis.core.config.Configuration;
+import org.apache.activemq.artemis.cli.commands.tools.DBOption;
 import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
 import org.apache.activemq.artemis.core.journal.Journal;
 import org.apache.activemq.artemis.core.journal.PreparedTransactionInfo;
 import org.apache.activemq.artemis.core.journal.RecordInfo;
 import org.apache.activemq.artemis.core.journal.TransactionFailureCallback;
-import org.apache.activemq.artemis.core.journal.impl.JournalImpl;
 import org.apache.activemq.artemis.core.message.LargeBodyEncoder;
 import org.apache.activemq.artemis.core.paging.PagedMessage;
-import org.apache.activemq.artemis.core.paging.PagingManager;
 import org.apache.activemq.artemis.core.paging.PagingStore;
-import org.apache.activemq.artemis.core.paging.PagingStoreFactory;
 import org.apache.activemq.artemis.core.paging.cursor.PagePosition;
 import org.apache.activemq.artemis.core.paging.cursor.impl.PagePositionImpl;
 import org.apache.activemq.artemis.core.paging.impl.Page;
 import org.apache.activemq.artemis.core.paging.impl.PageTransactionInfoImpl;
-import org.apache.activemq.artemis.core.paging.impl.PagingManagerImpl;
-import org.apache.activemq.artemis.core.paging.impl.PagingStoreFactoryNIO;
 import org.apache.activemq.artemis.core.persistence.impl.journal.AckDescribe;
 import org.apache.activemq.artemis.core.persistence.impl.journal.DescribeJournal;
 import org.apache.activemq.artemis.core.persistence.impl.journal.DescribeJournal.MessageDescribe;
 import org.apache.activemq.artemis.core.persistence.impl.journal.DescribeJournal.ReferenceDescribe;
 import org.apache.activemq.artemis.core.persistence.impl.journal.JournalRecordIds;
-import org.apache.activemq.artemis.core.persistence.impl.journal.JournalStorageManager;
 import org.apache.activemq.artemis.core.persistence.impl.journal.codec.CursorAckRecordEncoding;
 import org.apache.activemq.artemis.core.persistence.impl.journal.codec.PageUpdateTXEncoding;
 import org.apache.activemq.artemis.core.persistence.impl.journal.codec.PersistentAddressBindingEncoding;
@@ -77,24 +67,11 @@ import org.apache.activemq.artemis.core.persistence.impl.journal.codec.Persisten
 import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
 import org.apache.activemq.artemis.core.server.JournalType;
 import org.apache.activemq.artemis.core.server.LargeServerMessage;
-import org.apache.activemq.artemis.core.settings.HierarchicalRepository;
-import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
-import org.apache.activemq.artemis.core.settings.impl.HierarchicalObjectRepository;
-import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
-import org.apache.activemq.artemis.utils.ExecutorFactory;
-import org.apache.activemq.artemis.utils.actors.ArtemisExecutor;
-import org.apache.activemq.artemis.utils.actors.OrderedExecutorFactory;
-import org.apache.activemq.artemis.utils.critical.EmptyCriticalAnalyzer;
 
 @Command(name = "exp", description = "Export all message-data using an XML that could be interpreted by any system.")
-public final class XmlDataExporter extends OptionalLocking {
+public final class XmlDataExporter extends DBOption {
 
    private static final Long LARGE_MESSAGE_CHUNK_SIZE = 1000L;
-
-   private JournalStorageManager storageManager;
-
-   private Configuration config;
-
    private XMLStreamWriter xmlWriter;
 
    // an inner map of message refs hashed by the queue ID to which they belong and then hashed by their record ID
@@ -120,32 +97,52 @@ public final class XmlDataExporter extends OptionalLocking {
       super.execute(context);
 
       try {
-         process(context.out, getBinding(), getJournal(), getPaging(), getLargeMessages());
+         config = getParameterConfiguration();
+         process(context.out);
       } catch (Exception e) {
          treatError(e, "data", "exp");
       }
       return null;
    }
 
+   /**
+    * Use setConfiguration and process(out) instead.
+    *
+    * @param out
+    * @param bindingsDir
+    * @param journalDir
+    * @param pagingDir
+    * @param largeMessagesDir
+    * @throws Exception
+    */
+   @Deprecated
    public void process(OutputStream out,
                        String bindingsDir,
                        String journalDir,
                        String pagingDir,
                        String largeMessagesDir) throws Exception {
       config = new ConfigurationImpl().setBindingsDirectory(bindingsDir).setJournalDirectory(journalDir).setPagingDirectory(pagingDir).setLargeMessagesDirectory(largeMessagesDir).setJournalType(JournalType.NIO);
-      final ExecutorService executor = Executors.newFixedThreadPool(5, ActiveMQThreadFactory.defaultThreadFactory());
-      ExecutorFactory executorFactory = new OrderedExecutorFactory(executor);
+      initializeJournal(config);
+      writeOutput(out);
+      cleanup();
+   }
 
-      storageManager = new JournalStorageManager(config, EmptyCriticalAnalyzer.getInstance(), executorFactory, executorFactory);
+   public void process(OutputStream out) throws Exception {
 
+      initializeJournal(config);
+
+      writeOutput(out);
+
+      cleanup();
+   }
+
+   protected void writeOutput(OutputStream out) throws Exception {
       XMLOutputFactory factory = XMLOutputFactory.newInstance();
       XMLStreamWriter rawXmlWriter = factory.createXMLStreamWriter(out, "UTF-8");
       PrettyPrintHandler handler = new PrettyPrintHandler(rawXmlWriter);
       xmlWriter = (XMLStreamWriter) Proxy.newProxyInstance(XMLStreamWriter.class.getClassLoader(), new Class[]{XMLStreamWriter.class}, handler);
 
       writeXMLData();
-
-      executor.shutdown();
    }
 
    private void writeXMLData() throws Exception {
@@ -209,7 +206,7 @@ public final class XmlDataExporter extends OptionalLocking {
          }
       };
 
-      ((JournalImpl) messageJournal).load(records, preparedTransactions, transactionFailureCallback, false);
+      messageJournal.load(records, preparedTransactions, transactionFailureCallback, false);
 
       // Since we don't use these nullify the reference so that the garbage collector can clean them up
       preparedTransactions = null;
@@ -303,7 +300,7 @@ public final class XmlDataExporter extends OptionalLocking {
 
       ActiveMQServerLogger.LOGGER.debug("Reading bindings journal from " + config.getBindingsDirectory());
 
-      ((JournalImpl) bindingsJournal).load(records, null, null, false);
+      bindingsJournal.load(records, null, null);
 
       for (RecordInfo info : records) {
          if (info.getUserRecordType() == JournalRecordIds.QUEUE_BINDING_RECORD) {
@@ -384,25 +381,13 @@ public final class XmlDataExporter extends OptionalLocking {
     */
    private void printPagedMessagesAsXML() {
       try {
-         ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1, ActiveMQThreadFactory.defaultThreadFactory());
-         final ExecutorService executor = Executors.newFixedThreadPool(10, ActiveMQThreadFactory.defaultThreadFactory());
-         ExecutorFactory executorFactory = new ExecutorFactory() {
-            @Override
-            public ArtemisExecutor getExecutor() {
-               return ArtemisExecutor.delegate(executor);
-            }
-         };
-         PagingStoreFactory pageStoreFactory = new PagingStoreFactoryNIO(storageManager, config.getPagingLocation(), 1000L, scheduled, executorFactory, true, null);
-         HierarchicalRepository<AddressSettings> addressSettingsRepository = new HierarchicalObjectRepository<>(config.getWildcardConfiguration());
-         addressSettingsRepository.setDefault(new AddressSettings());
-         PagingManager manager = new PagingManagerImpl(pageStoreFactory, addressSettingsRepository);
 
-         manager.start();
+         pagingmanager.start();
 
-         SimpleString[] stores = manager.getStoreNames();
+         SimpleString[] stores = pagingmanager.getStoreNames();
 
          for (SimpleString store : stores) {
-            PagingStore pageStore = manager.getPageStore(store);
+            PagingStore pageStore = pagingmanager.getPageStore(store);
 
             if (pageStore != null) {
                File folder = pageStore.getFolder();

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/broker.xml
----------------------------------------------------------------------
diff --git a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/broker.xml b/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/broker.xml
index 013b911..4ab1660 100644
--- a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/broker.xml
+++ b/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/broker.xml
@@ -27,6 +27,7 @@ under the License.
 
       <name>${name}</name>
 
+${jdbc}
       <persistence-enabled>${persistence-enabled}</persistence-enabled>
 
       <!-- this could be ASYNCIO, MAPPED, NIO

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/database-store.txt
----------------------------------------------------------------------
diff --git a/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/database-store.txt b/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/database-store.txt
new file mode 100644
index 0000000..57197e3
--- /dev/null
+++ b/artemis-cli/src/main/resources/org/apache/activemq/artemis/cli/commands/etc/database-store.txt
@@ -0,0 +1,18 @@
+      <store>
+         <database-store>
+            <!-- The most efficient persistent layer for Artemis is the file-store,
+                 however if you require a database please refer to your database provider
+                 for any database specific questions.
+                 We don't endorse any specific JDBC provider. Derby is provided by default for demonstration purposes. -->
+            <jdbc-driver-class-name>${jdbcClassName}</jdbc-driver-class-name>
+            <jdbc-connection-url>${jdbcURL}</jdbc-connection-url>
+            <message-table-name>${jdbcMessages}</message-table-name>
+            <bindings-table-name>${jdbcBindings}</bindings-table-name>
+            <large-message-table-name>${jdbcLargeMessages}</large-message-table-name>
+            <page-store-table-name>${jdbcPageStore}</page-store-table-name>
+            <jdbc-lock-acquisition-timeout>${jdbcLockAcquisitionTimeout}</jdbc-lock-acquisition-timeout>
+            <jdbc-lock-expiration>${jdbcLockExpiration}</jdbc-lock-expiration>
+            <jdbc-lock-renew-period>${jdbcLockRenewPeriod}</jdbc-lock-renew-period>
+            <jdbc-network-timeout>${jdbcNetworkTimeout}</jdbc-network-timeout>
+         </database-store>
+      </store>

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
----------------------------------------------------------------------
diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
index 5f7254e..711f780 100644
--- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
+++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
@@ -141,6 +141,13 @@ public class ArtemisTest extends CliTestBase {
 
 
    @Test
+   public void testCreateDB() throws Exception {
+      File instance1 = new File(temporaryFolder.getRoot(), "instance1");
+      Artemis.internalExecute("create", instance1.getAbsolutePath(), "--silent", "--jdbc");
+   }
+
+
+   @Test
    public void testSimpleCreateMapped() throws Throwable {
       try {
          //instance1: default using http

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-cli/src/test/java/org/apache/activemq/cli/test/StreamClassPathTest.java
----------------------------------------------------------------------
diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/StreamClassPathTest.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/StreamClassPathTest.java
index fcf1e67..f965c77 100644
--- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/StreamClassPathTest.java
+++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/StreamClassPathTest.java
@@ -60,6 +60,7 @@ public class StreamClassPathTest {
       openStream(Create.ETC_GLOBAL_MAX_SPECIFIED_TXT);
       openStream(Create.ETC_GLOBAL_MAX_DEFAULT_TXT);
       openStream(Create.ETC_JOLOKIA_ACCESS_XML);
+      openStream(Create.ETC_DATABASE_STORE_TXT);
 
    }
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
----------------------------------------------------------------------
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
index fecf71c..fe7e1bf 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
@@ -423,8 +423,8 @@ public final class ActiveMQDefaultConfiguration {
    // Default database url.  Derby database is used by default.
    private static String DEFAULT_DATABASE_URL = null;
 
-   // Default JDBC Driver class name
-   private static String DEFAULT_JDBC_DRIVER_CLASS_NAME = null;
+   // Default JDBC Driver class name, derby by default just for demo purposes
+   private static String DEFAULT_JDBC_DRIVER_CLASS_NAME = "org.apache.derby.jdbc.EmbeddedDriver";
 
    // Default message table name, used with Database storage type
    private static String DEFAULT_MESSAGE_TABLE_NAME = "MESSAGES";

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/journal/JDBCJournalImpl.java
----------------------------------------------------------------------
diff --git a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/journal/JDBCJournalImpl.java b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/journal/JDBCJournalImpl.java
index f6922bd..7340959 100644
--- a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/journal/JDBCJournalImpl.java
+++ b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/journal/JDBCJournalImpl.java
@@ -881,12 +881,6 @@ public class JDBCJournalImpl extends AbstractJDBCDriver implements Journal {
    }
 
    @Override
-   public JournalLoadInformation load(List<RecordInfo> committedRecords,
-                                      List<PreparedTransactionInfo> preparedTransactions,
-                                      TransactionFailureCallback transactionFailure) throws Exception {
-      return load(committedRecords, preparedTransactions, transactionFailure, true);
-   }
-
    public synchronized JournalLoadInformation load(final List<RecordInfo> committedRecords,
                                                    final List<PreparedTransactionInfo> preparedTransactions,
                                                    final TransactionFailureCallback failureCallback,

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/Journal.java
----------------------------------------------------------------------
diff --git a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/Journal.java b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/Journal.java
index 3da17fe..6844614 100644
--- a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/Journal.java
+++ b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/Journal.java
@@ -194,9 +194,16 @@ public interface Journal extends ActiveMQComponent {
 
    void lineUpContext(IOCompletion callback);
 
+   default JournalLoadInformation load(List<RecordInfo> committedRecords,
+                               List<PreparedTransactionInfo> preparedTransactions,
+                               TransactionFailureCallback transactionFailure) throws Exception {
+      return load(committedRecords, preparedTransactions, transactionFailure, true);
+   }
+
    JournalLoadInformation load(List<RecordInfo> committedRecords,
                                List<PreparedTransactionInfo> preparedTransactions,
-                               TransactionFailureCallback transactionFailure) throws Exception;
+                               TransactionFailureCallback transactionFailure,
+                               boolean fixBadTx) throws Exception;
 
    int getAlignment() throws Exception;
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/FileWrapperJournal.java
----------------------------------------------------------------------
diff --git a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/FileWrapperJournal.java b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/FileWrapperJournal.java
index 7354067..6a5ebbd 100644
--- a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/FileWrapperJournal.java
+++ b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/FileWrapperJournal.java
@@ -269,7 +269,8 @@ public final class FileWrapperJournal extends JournalBase {
    @Override
    public JournalLoadInformation load(List<RecordInfo> committedRecords,
                                       List<PreparedTransactionInfo> preparedTransactions,
-                                      TransactionFailureCallback transactionFailure) throws Exception {
+                                      TransactionFailureCallback transactionFailure,
+                                      boolean fixbadtx) throws Exception {
       throw new ActiveMQUnsupportedPacketException();
    }
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java
----------------------------------------------------------------------
diff --git a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java
index 77bf9da..88204d4 100644
--- a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java
+++ b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java
@@ -1367,16 +1367,10 @@ public class JournalImpl extends JournalBase implements TestableJournal, Journal
       return load(DummyLoader.INSTANCE, true, syncState);
    }
 
-   @Override
-   public JournalLoadInformation load(final List<RecordInfo> committedRecords,
-                                      final List<PreparedTransactionInfo> preparedTransactions,
-                                      final TransactionFailureCallback failureCallback) throws Exception {
-      return load(committedRecords, preparedTransactions, failureCallback, true);
-   }
-
    /**
     * @see JournalImpl#load(LoaderCallback)
     */
+   @Override
    public synchronized JournalLoadInformation load(final List<RecordInfo> committedRecords,
                                                    final List<PreparedTransactionInfo> preparedTransactions,
                                                    final TransactionFailureCallback failureCallback,

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
index f052248..27cdba2 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
@@ -1044,6 +1044,11 @@ public interface Configuration {
     */
    File getBrokerInstance();
 
+   default boolean isJDBC() {
+      StoreConfiguration configuration = getStoreConfiguration();
+      return (configuration != null && configuration.getStoreType() == StoreConfiguration.StoreType.DATABASE);
+   }
+
    StoreConfiguration getStoreConfiguration();
 
    Configuration setStoreConfiguration(StoreConfiguration storeConfiguration);

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/DescribeJournal.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/DescribeJournal.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/DescribeJournal.java
index 698978b..bfabc25 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/DescribeJournal.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/DescribeJournal.java
@@ -31,6 +31,7 @@ import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
 import org.apache.activemq.artemis.core.io.SequentialFileFactory;
 import org.apache.activemq.artemis.core.io.nio.NIOSequentialFileFactory;
 import org.apache.activemq.artemis.core.journal.EncodingSupport;
+import org.apache.activemq.artemis.core.journal.Journal;
 import org.apache.activemq.artemis.core.journal.PreparedTransactionInfo;
 import org.apache.activemq.artemis.core.journal.RecordInfo;
 import org.apache.activemq.artemis.core.journal.TransactionFailureCallback;
@@ -105,15 +106,22 @@ public final class DescribeJournal {
    }
 
    public static void describeBindingsJournal(final File bindingsDir) throws Exception {
+      describeBindingsJournal(bindingsDir, System.out);
+   }
+
+   public static void describeBindingsJournal(final File bindingsDir, PrintStream out) throws Exception {
 
       SequentialFileFactory bindingsFF = new NIOSequentialFileFactory(bindingsDir, null, 1);
 
       JournalImpl bindings = new JournalImpl(1024 * 1024, 2, 2, -1, 0, bindingsFF, "activemq-bindings", "bindings", 1);
-      describeJournal(bindingsFF, bindings, bindingsDir);
+      describeJournal(bindingsFF, bindings, bindingsDir, out);
    }
 
    public static DescribeJournal describeMessagesJournal(final File messagesDir) throws Exception {
+      return describeMessagesJournal(messagesDir, System.out);
+   }
 
+   public static DescribeJournal describeMessagesJournal(final File messagesDir, PrintStream out) throws Exception {
       SequentialFileFactory messagesFF = new NIOSequentialFileFactory(messagesDir, null, 1);
 
       // Will use only default values. The load function should adapt to anything different
@@ -121,7 +129,7 @@ public final class DescribeJournal {
 
       JournalImpl messagesJournal = new JournalImpl(defaultValues.getJournalFileSize(), defaultValues.getJournalMinFiles(), defaultValues.getJournalPoolFiles(), 0, 0, messagesFF, "activemq-data", "amq", 1);
 
-      return describeJournal(messagesFF, messagesJournal, messagesDir);
+      return describeJournal(messagesFF, messagesJournal, messagesDir, out);
    }
 
    /**
@@ -131,11 +139,10 @@ public final class DescribeJournal {
     */
    private static DescribeJournal describeJournal(SequentialFileFactory fileFactory,
                                                   JournalImpl journal,
-                                                  final File path) throws Exception {
+                                                  final File path,
+                                                  PrintStream out) throws Exception {
       List<JournalFile> files = journal.orderFiles();
 
-      final PrintStream out = System.out;
-
       final Map<Long, PageSubscriptionCounterImpl> counters = new HashMap<>();
 
       out.println("Journal path: " + path);
@@ -246,6 +253,13 @@ public final class DescribeJournal {
          printCounters(out, counters);
       }
 
+      return printSurvivingRecords(journal, out);
+   }
+
+   public static DescribeJournal printSurvivingRecords(Journal journal,
+                                                       PrintStream out) throws Exception {
+
+      final Map<Long, PageSubscriptionCounterImpl> counters = new HashMap<>();
       out.println("### Surviving Records Summary ###");
 
       List<RecordInfo> records = new LinkedList<>();
@@ -277,8 +291,6 @@ public final class DescribeJournal {
          }
       }, false);
 
-      counters.clear();
-
       for (RecordInfo info : records) {
          PageSubscriptionCounterImpl subsCounter = null;
          long queueIDForCounter = 0;

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-server/src/main/java/org/apache/activemq/artemis/core/replication/ReplicatedJournal.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/replication/ReplicatedJournal.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/replication/ReplicatedJournal.java
index 83112d5..7ad06f5 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/replication/ReplicatedJournal.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/replication/ReplicatedJournal.java
@@ -426,8 +426,9 @@ public class ReplicatedJournal implements Journal {
    @Override
    public JournalLoadInformation load(final List<RecordInfo> committedRecords,
                                       final List<PreparedTransactionInfo> preparedTransactions,
-                                      final TransactionFailureCallback transactionFailure) throws Exception {
-      return localJournal.load(committedRecords, preparedTransactions, transactionFailure);
+                                      final TransactionFailureCallback transactionFailure,
+                                      final boolean fixbadTX) throws Exception {
+      return localJournal.load(committedRecords, preparedTransactions, transactionFailure, fixbadTX);
    }
 
    /**

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/jdbc/ActiveMQScheduledLeaseLock.java
----------------------------------------------------------------------
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/jdbc/ActiveMQScheduledLeaseLock.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/jdbc/ActiveMQScheduledLeaseLock.java
index f2f0c94..ce91d70 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/jdbc/ActiveMQScheduledLeaseLock.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/jdbc/ActiveMQScheduledLeaseLock.java
@@ -111,9 +111,9 @@ final class ActiveMQScheduledLeaseLock extends ActiveMQScheduledComponent implem
       }
       final long measuredRenewPeriodNanos = renewStart - lastRenewStart;
       final long measuredRenewPeriodMillis = TimeUnit.NANOSECONDS.toMillis(measuredRenewPeriodNanos);
-      if (measuredRenewPeriodMillis > expirationMillis) {
+      if (measuredRenewPeriodMillis - expirationMillis > 100) {
          LOGGER.error(lockName + " lock renew period lasted " + measuredRenewPeriodMillis + " ms instead of " + expectedRenewPeriodMillis + " ms");
-      } else if (measuredRenewPeriodMillis > expectedRenewPeriodMillis) {
+      } else if (measuredRenewPeriodMillis - expectedRenewPeriodMillis > 100) {
          LOGGER.warn(lockName + " lock renew period lasted " + measuredRenewPeriodMillis + " ms instead of " + expectedRenewPeriodMillis + " ms");
       }
    }

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/examples/features/standard/database/pom.xml
----------------------------------------------------------------------
diff --git a/examples/features/standard/database/pom.xml b/examples/features/standard/database/pom.xml
new file mode 100644
index 0000000..51a5db0
--- /dev/null
+++ b/examples/features/standard/database/pom.xml
@@ -0,0 +1,131 @@
+<?xml version='1.0'?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+   <modelVersion>4.0.0</modelVersion>
+
+   <parent>
+      <groupId>org.apache.activemq.examples.broker</groupId>
+      <artifactId>jms-examples</artifactId>
+      <version>2.5.0-SNAPSHOT</version>
+   </parent>
+
+   <artifactId>datatabase</artifactId>
+   <packaging>jar</packaging>
+   <name>ActiveMQ Artemis JMS Expiry Example</name>
+
+   <properties>
+      <activemq.basedir>${project.basedir}/../../../..</activemq.basedir>
+   </properties>
+
+   <dependencies>
+      <dependency>
+         <groupId>org.apache.activemq</groupId>
+         <artifactId>artemis-jms-client-all</artifactId>
+         <version>${project.version}</version>
+      </dependency>
+   </dependencies>
+
+   <build>
+      <plugins>
+         <plugin>
+            <groupId>org.apache.activemq</groupId>
+            <artifactId>artemis-maven-plugin</artifactId>
+            <executions>
+               <execution>
+                  <id>create</id>
+                  <goals>
+                     <goal>create</goal>
+                  </goals>
+                  <configuration>
+                     <ignore>${noServer}</ignore>
+                     <libList>
+                        <!-- adding derby for the example -->
+                        <arg>org.apache.derby:derby:${apache.derby.version}</arg>
+                     </libList>
+                     <args>
+                        <arg>--jdbc</arg>
+                     </args>
+                  </configuration>
+               </execution>
+               <execution>
+                  <id>start</id>
+                  <goals>
+                     <goal>cli</goal>
+                  </goals>
+                  <configuration>
+                     <ignore>${noServer}</ignore>
+                     <spawn>true</spawn>
+                     <testURI>tcp://localhost:61616</testURI>
+                     <args>
+                        <param>run</param>
+                     </args>
+                  </configuration>
+               </execution>
+               <execution>
+                  <id>runClient</id>
+                  <goals>
+                     <goal>runClient</goal>
+                  </goals>
+                  <configuration>
+                     <clientClass>org.apache.activemq.artemis.jms.example.DBExample</clientClass>
+                  </configuration>
+               </execution>
+               <execution>
+                  <id>stop</id>
+                  <goals>
+                     <goal>cli</goal>
+                  </goals>
+                  <configuration>
+                     <ignore>${noServer}</ignore>
+                     <args>
+                        <param>stop</param>
+                     </args>
+                  </configuration>
+               </execution>
+            </executions>
+            <dependencies>
+               <dependency>
+                  <groupId>org.apache.activemq.examples.broker</groupId>
+                  <artifactId>datatabase</artifactId>
+                  <version>${project.version}</version>
+               </dependency>
+            </dependencies>
+         </plugin>
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-clean-plugin</artifactId>
+         </plugin>
+      </plugins>
+   </build>
+   <profiles>
+      <profile>
+         <id>release</id>
+         <build>
+            <plugins>
+               <plugin>
+                  <groupId>com.vladsch.flexmark</groupId>
+                  <artifactId>markdown-page-generator-plugin</artifactId>
+               </plugin>
+            </plugins>
+         </build>
+      </profile>
+   </profiles>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/examples/features/standard/database/readme.md
----------------------------------------------------------------------
diff --git a/examples/features/standard/database/readme.md b/examples/features/standard/database/readme.md
new file mode 100644
index 0000000..d32f727
--- /dev/null
+++ b/examples/features/standard/database/readme.md
@@ -0,0 +1,7 @@
+# Database example
+
+To run the example, simply type **mvn verify** from this directory, or **mvn -PnoServer verify** if you want to start and create the broker manually.
+
+This example shows you how to configure ActiveMQ Artemis to run with a database.
+
+Notice this is not making any assumption of what is the recommended database to be used with Artemis. After all we recommend the artemis journal to be used, however in certain environments users will prefer databases for specific reasons.

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/examples/features/standard/database/src/main/java/org/apache/activemq/artemis/jms/example/DBExample.java
----------------------------------------------------------------------
diff --git a/examples/features/standard/database/src/main/java/org/apache/activemq/artemis/jms/example/DBExample.java b/examples/features/standard/database/src/main/java/org/apache/activemq/artemis/jms/example/DBExample.java
new file mode 100644
index 0000000..359467b
--- /dev/null
+++ b/examples/features/standard/database/src/main/java/org/apache/activemq/artemis/jms/example/DBExample.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.jms.example;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.naming.InitialContext;
+
+import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
+
+/**
+ * An example showing how messages are moved to an expiry queue when they expire.
+ */
+public class DBExample {
+
+   public static void main(final String[] args) throws Exception {
+      InitialContext initialContext = null;
+      ConnectionFactory cf = new ActiveMQConnectionFactory();
+      try (Connection connection = cf.createConnection()) {
+         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+         Queue queue = session.createQueue("queue1");
+
+         MessageProducer producer = session.createProducer(queue);
+
+         TextMessage message = session.createTextMessage("this is a text message");
+
+         producer.send(message);
+         System.out.println("Sent message to " + queue.getQueueName() + ": " + message.getText());
+
+         MessageConsumer messageConsumer = session.createConsumer(queue);
+
+         connection.start();
+
+         TextMessage messageReceived = (TextMessage) messageConsumer.receive(5000);
+         System.out.println("Received message from " + queue.getQueueName() + ": " + messageReceived);
+
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/examples/features/standard/pom.xml
----------------------------------------------------------------------
diff --git a/examples/features/standard/pom.xml b/examples/features/standard/pom.xml
index 0d77a4e..b4d0f67 100644
--- a/examples/features/standard/pom.xml
+++ b/examples/features/standard/pom.xml
@@ -47,6 +47,7 @@ under the License.
             <module>cdi</module>
             <module>client-kickoff</module>
             <module>consumer-rate-limit</module>
+            <module>database</module>
             <module>dead-letter</module>
             <module>delayed-redelivery</module>
             <module>divert</module>
@@ -114,6 +115,7 @@ under the License.
             <module>cdi</module>
             <module>client-kickoff</module>
             <module>consumer-rate-limit</module>
+            <module>database</module>
             <module>dead-letter</module>
             <module>delayed-redelivery</module>
             <module>divert</module>

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/61a1123e/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/replication/ReplicationTest.java
----------------------------------------------------------------------
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/replication/ReplicationTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/replication/ReplicationTest.java
index d35174b..07c02c3 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/replication/ReplicationTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/replication/ReplicationTest.java
@@ -813,7 +813,8 @@ public final class ReplicationTest extends ActiveMQTestBase {
       @Override
       public JournalLoadInformation load(final List<RecordInfo> committedRecords,
                                          final List<PreparedTransactionInfo> preparedTransactions,
-                                         final TransactionFailureCallback transactionFailure) throws Exception {
+                                         final TransactionFailureCallback transactionFailure,
+                                         final boolean fixbadtx) throws Exception {
 
          return new JournalLoadInformation();
       }