diff --git a/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/pom.xml b/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/pom.xml
index d06a14cde7..a17ddff533 100644
--- a/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/pom.xml
+++ b/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/pom.xml
@@ -43,7 +43,12 @@
derby
10.11.1.1
-
+
+ org.hamcrest
+ hamcrest-all
+ 1.3
+
+
\ No newline at end of file
diff --git a/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPServiceApacheDBCP14.java b/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPConnectionPool.java
similarity index 76%
rename from nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPServiceApacheDBCP14.java
rename to nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPConnectionPool.java
index eb0a950f13..a80e9bfbc7 100644
--- a/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPServiceApacheDBCP14.java
+++ b/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPConnectionPool.java
@@ -25,6 +25,7 @@ import java.util.List;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnDisabled;
import org.apache.nifi.annotation.lifecycle.OnEnabled;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.controller.AbstractControllerService;
@@ -41,29 +42,28 @@ import org.apache.nifi.reporting.InitializationException;
@Tags({"dbcp", "jdbc", "database", "connection", "pooling", "store"})
@CapabilityDescription("Provides Database Connection Pooling Service. Connections can be asked from pool and returned after usage."
)
-public class DBCPServiceApacheDBCP14 extends AbstractControllerService implements DBCPService {
+public class DBCPConnectionPool extends AbstractControllerService implements DBCPService {
public static final DatabaseSystemDescriptor DEFAULT_DATABASE_SYSTEM = DatabaseSystems.getDescriptor("JavaDB");
public static final PropertyDescriptor DATABASE_SYSTEM = new PropertyDescriptor.Builder()
.name("Database")
.description("Database management system")
-// .allowableValues(POSTGRES, JavaDB, DERBY, MariaDB, OtherDB)
.allowableValues(DatabaseSystems.knownDatabaseSystems)
.defaultValue(DEFAULT_DATABASE_SYSTEM.getValue())
.required(true)
.build();
public static final PropertyDescriptor DB_HOST = new PropertyDescriptor.Builder()
- .name("Database host")
- .description("Database host")
+ .name("Database Host")
+ .description("Database Host")
.defaultValue(null)
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.build();
public static final PropertyDescriptor DB_PORT = new PropertyDescriptor.Builder()
- .name("Database port")
+ .name("Database Port")
.description("Database server port")
.defaultValue(DEFAULT_DATABASE_SYSTEM.defaultPort.toString())
.required(true)
@@ -71,7 +71,7 @@ public class DBCPServiceApacheDBCP14 extends AbstractControllerService implement
.build();
public static final PropertyDescriptor DB_DRIVERNAME = new PropertyDescriptor.Builder()
- .name("Database driver class name")
+ .name("Database Driver Class Name")
.description("Database driver class name")
.defaultValue(DEFAULT_DATABASE_SYSTEM.driverClassName)
.required(true)
@@ -79,7 +79,7 @@ public class DBCPServiceApacheDBCP14 extends AbstractControllerService implement
.build();
public static final PropertyDescriptor DB_NAME = new PropertyDescriptor.Builder()
- .name("Database name")
+ .name("Database Name")
.description("Database name")
.defaultValue(null)
.required(true)
@@ -87,7 +87,7 @@ public class DBCPServiceApacheDBCP14 extends AbstractControllerService implement
.build();
public static final PropertyDescriptor DB_USER = new PropertyDescriptor.Builder()
- .name("Database user")
+ .name("Database User")
.description("Database user name")
.defaultValue(null)
.required(true)
@@ -103,6 +103,26 @@ public class DBCPServiceApacheDBCP14 extends AbstractControllerService implement
.sensitive(true)
.build();
+ public static final PropertyDescriptor MAX_WAIT_MILLIS = new PropertyDescriptor.Builder()
+ .name("Max Wait Millis")
+ .description("The maximum number of milliseconds that the pool will wait (when there are no available connections) "
+ + " for a connection to be returned before throwing an exception, or -1 to wait indefinitely. ")
+ .defaultValue("500")
+ .required(true)
+ .addValidator(StandardValidators.LONG_VALIDATOR)
+ .sensitive(true)
+ .build();
+
+ public static final PropertyDescriptor MAX_TOTAL_CONNECTIONS = new PropertyDescriptor.Builder()
+ .name("Max Total Connections")
+ .description("The maximum number of active connections that can be allocated from this pool at the same time, "
+ + " or negative for no limit.")
+ .defaultValue("8")
+ .required(true)
+ .addValidator(StandardValidators.INTEGER_VALIDATOR)
+ .sensitive(true)
+ .build();
+
private static final List properties;
static {
@@ -125,36 +145,12 @@ public class DBCPServiceApacheDBCP14 extends AbstractControllerService implement
protected List getSupportedPropertyDescriptors() {
return properties;
}
-
- //================================= Apache DBCP pool parameters ================================
-
- /** The maximum number of milliseconds that the pool will wait (when there are no available connections)
- * for a connection to be returned before throwing an exception, or -1 to wait indefinitely.
- */
- static final long maxWaitMillis = 500;
-
- /** The maximum number of active connections that can be allocated from this pool at the same time,
- * or negative for no limit.
- */
- static final int maxTotal = 8;
- //=================================================================================================
-
/**
- * Idea was to dynamically set port, driver and url properties default values after user select database system.
- * As of 01mar2015 such functionality is not supported.
- *
- @Override
- public void onPropertyModified(final PropertyDescriptor descriptor, final String oldValue, final String newValue) {
- super.onPropertyModified(descriptor, oldValue, newValue);
-
- if (descriptor.equals(DATABASE_SYSTEM)) {
-
- DatabaseSystemDescriptor databaseSystemDescriptor = DatabaseSystems.getDescriptor(newValue);
- }
- }
- */
-
+ * Create new pool, open some connections ready to be used
+ * @param context
+ * @throws InitializationException
+ */
@OnEnabled
public void onConfigured(final ConfigurationContext context) throws InitializationException {
configContext = context;
@@ -167,6 +163,8 @@ public class DBCPServiceApacheDBCP14 extends AbstractControllerService implement
String dbname = context.getProperty(DB_NAME).getValue();
String user = context.getProperty(DB_USER).getValue();
String passw = context.getProperty(DB_PASSWORD).getValue();
+ Long maxWaitMillis = context.getProperty(MAX_WAIT_MILLIS).asLong();
+ Integer maxTotal = context.getProperty(MAX_TOTAL_CONNECTIONS).asInteger();
String dburl = dbsystem.buildUrl(host, port, dbname);
@@ -178,6 +176,9 @@ public class DBCPServiceApacheDBCP14 extends AbstractControllerService implement
dataSource.setDriverClassName(drv);
dataSource.setUsername(user);
dataSource.setPassword(passw);
+
+ // That will ensure that you are using the ClassLoader for you NAR.
+ dataSource.setDriverClassLoader(Thread.currentThread().getContextClassLoader());
// verify connection can be established.
try {
@@ -190,6 +191,19 @@ public class DBCPServiceApacheDBCP14 extends AbstractControllerService implement
}
}
+ /**
+ * Shutdown pool, close all open connections.
+ */
+ @OnDisabled
+ public void shutdown() {
+ try {
+ dataSource.close();
+ } catch (SQLException e) {
+ throw new ProcessException(e);
+ }
+ }
+
+
@Override
public Connection getConnection() throws ProcessException {
try {
diff --git a/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService b/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
new file mode 100644
index 0000000000..d022695eed
--- /dev/null
+++ b/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
@@ -0,0 +1,15 @@
+# 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.
+org.apache.nifi.dbcp.DBCPConnectionPool
\ No newline at end of file
diff --git a/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/test/java/org/apache/nifi/dbcp/DBCPServiceTest.java b/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/test/java/org/apache/nifi/dbcp/DBCPServiceTest.java
index 684cc764e7..e93faad0ea 100644
--- a/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/test/java/org/apache/nifi/dbcp/DBCPServiceTest.java
+++ b/nifi/nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/test/java/org/apache/nifi/dbcp/DBCPServiceTest.java
@@ -16,7 +16,8 @@
*/
package org.apache.nifi.dbcp;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import java.io.File;
import java.sql.Connection;
@@ -26,8 +27,6 @@ import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
-import javax.activation.DataSource;
-
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.util.TestRunner;
@@ -46,11 +45,11 @@ public class DBCPServiceTest {
*
*/
@Test
- public void testBad1() throws InitializationException {
+ public void testUnknownDatabaseSystem() throws InitializationException {
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
- final DBCPServiceApacheDBCP14 service = new DBCPServiceApacheDBCP14();
+ final DBCPConnectionPool service = new DBCPConnectionPool();
final Map properties = new HashMap();
- properties.put(DBCPServiceApacheDBCP14.DATABASE_SYSTEM.getName(), "garbage");
+ properties.put(DBCPConnectionPool.DATABASE_SYSTEM.getName(), "garbage");
runner.addControllerService("test-bad2", service, properties);
runner.assertNotValid(service);
}
@@ -59,9 +58,9 @@ public class DBCPServiceTest {
* Missing property values.
*/
@Test
- public void testGood1() throws InitializationException {
+ public void testMissingPropertyValues() throws InitializationException {
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
- final DBCPServiceApacheDBCP14 service = new DBCPServiceApacheDBCP14();
+ final DBCPConnectionPool service = new DBCPConnectionPool();
final Map properties = new HashMap();
runner.addControllerService("test-bad1", service, properties);
runner.assertNotValid(service);
@@ -73,24 +72,24 @@ public class DBCPServiceTest {
*
*/
@Test
- public void testGood2() throws InitializationException, SQLException {
+ public void testCreateInsertSelect() throws InitializationException, SQLException {
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
- final DBCPServiceApacheDBCP14 service = new DBCPServiceApacheDBCP14();
+ final DBCPConnectionPool service = new DBCPConnectionPool();
runner.addControllerService("test-good1", service);
// remove previous test database, if any
File dbLocation = new File(DB_LOCATION);
dbLocation.delete();
- // Should setProperty call also generate DBCPServiceApacheDBCP14.onPropertyModified() method call?
+ // Should setProperty call also generate DBCPConnectionPool.onPropertyModified() method call?
// It does not currently.
// Some properties already should have JavaDB/Derby default values, let's set only missing values.
- runner.setProperty(service, DBCPServiceApacheDBCP14.DB_HOST, "NA"); // Embedded Derby don't use host
- runner.setProperty(service, DBCPServiceApacheDBCP14.DB_NAME, DB_LOCATION);
- runner.setProperty(service, DBCPServiceApacheDBCP14.DB_USER, "tester");
- runner.setProperty(service, DBCPServiceApacheDBCP14.DB_PASSWORD, "testerp");
+ runner.setProperty(service, DBCPConnectionPool.DB_HOST, "NA"); // Embedded Derby don't use host
+ runner.setProperty(service, DBCPConnectionPool.DB_NAME, DB_LOCATION);
+ runner.setProperty(service, DBCPConnectionPool.DB_USER, "tester");
+ runner.setProperty(service, DBCPConnectionPool.DB_PASSWORD, "testerp");
runner.enableControllerService(service);
@@ -117,17 +116,17 @@ public class DBCPServiceTest {
@Test
public void testExhaustPool() throws InitializationException, SQLException {
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
- final DBCPServiceApacheDBCP14 service = new DBCPServiceApacheDBCP14();
+ final DBCPConnectionPool service = new DBCPConnectionPool();
runner.addControllerService("test-exhaust", service);
// remove previous test database, if any
File dbLocation = new File(DB_LOCATION);
dbLocation.delete();
- runner.setProperty(service, DBCPServiceApacheDBCP14.DB_HOST, "NA"); // Embedded Derby don't use host
- runner.setProperty(service, DBCPServiceApacheDBCP14.DB_NAME, DB_LOCATION);
- runner.setProperty(service, DBCPServiceApacheDBCP14.DB_USER, "tester");
- runner.setProperty(service, DBCPServiceApacheDBCP14.DB_PASSWORD, "testerp");
+ runner.setProperty(service, DBCPConnectionPool.DB_HOST, "NA"); // Embedded Derby don't use host
+ runner.setProperty(service, DBCPConnectionPool.DB_NAME, DB_LOCATION);
+ runner.setProperty(service, DBCPConnectionPool.DB_USER, "tester");
+ runner.setProperty(service, DBCPConnectionPool.DB_PASSWORD, "testerp");
runner.enableControllerService(service);
@@ -136,6 +135,7 @@ public class DBCPServiceTest {
Assert.assertNotNull(dbcpService);
exception.expect(ProcessException.class);
+ exception.expectMessage("Cannot get a connection, pool error Timeout waiting for idle object");
for (int i = 0; i < 100; i++) {
Connection connection = dbcpService.getConnection();
Assert.assertNotNull(connection);
@@ -148,19 +148,19 @@ public class DBCPServiceTest {
* and getConnection should not fail.
*/
@Test
- public void testGetMany() throws InitializationException, SQLException {
+ public void testGetManyNormal() throws InitializationException, SQLException {
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
- final DBCPServiceApacheDBCP14 service = new DBCPServiceApacheDBCP14();
+ final DBCPConnectionPool service = new DBCPConnectionPool();
runner.addControllerService("test-exhaust", service);
// remove previous test database, if any
File dbLocation = new File(DB_LOCATION);
dbLocation.delete();
- runner.setProperty(service, DBCPServiceApacheDBCP14.DB_HOST, "NA"); // Embedded Derby don't use host
- runner.setProperty(service, DBCPServiceApacheDBCP14.DB_NAME, DB_LOCATION);
- runner.setProperty(service, DBCPServiceApacheDBCP14.DB_USER, "tester");
- runner.setProperty(service, DBCPServiceApacheDBCP14.DB_PASSWORD, "testerp");
+ runner.setProperty(service, DBCPConnectionPool.DB_HOST, "NA"); // Embedded Derby don't use host
+ runner.setProperty(service, DBCPConnectionPool.DB_NAME, DB_LOCATION);
+ runner.setProperty(service, DBCPConnectionPool.DB_USER, "tester");
+ runner.setProperty(service, DBCPConnectionPool.DB_PASSWORD, "testerp");
runner.enableControllerService(service);
@@ -177,7 +177,7 @@ public class DBCPServiceTest {
@Test
- public void testDriverLaod() throws ClassNotFoundException {
+ public void testDriverLoad() throws ClassNotFoundException {
Class> clazz = Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
assertNotNull(clazz);
}