Github user bbende commented on a diff in the pull request:
https://github.com/apache/nifi/pull/2735#discussion_r191057795
--- Diff:
nifi-nar-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPConnectionPoolLookup.java
---
@@ -0,0 +1,140 @@
+/*
+ * 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.nifi.dbcp;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.annotation.behavior.DynamicProperty;
+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.components.ValidationContext;
+import org.apache.nifi.components.ValidationResult;
+import org.apache.nifi.controller.AbstractControllerService;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.processor.util.StandardValidators;
+
+import java.sql.Connection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Tags({ "dbcp", "jdbc", "database", "connection", "pooling", "store" })
+@CapabilityDescription("Provides a DBCPService that can be used to
dynamically select another DBCPService. This service " +
+ "requires an attribute named 'database.name' to be passed in when
asking for a connection, and will throw an exception " +
+ "if the attribute is missing. The value of 'database.name' will be
used to select the DBCPService that has been " +
+ "registered with that name. This will allow multiple DBCPServices
to be defined and registered, and then selected " +
+ "dynamically at runtime by tagging flow files with the appropriate
'database.name' attribute.")
+@DynamicProperty(name = "The ", value = "JDBC property value",
expressionLanguageScope = ExpressionLanguageScope.NONE,
+ description = "")
+public class DBCPConnectionPoolLookup extends AbstractControllerService
implements DBCPService {
+
+ public static final String DATABASE_NAME_ATTRIBUTE = "database.name";
+
+ private volatile Map<String,DBCPService> dbcpServiceMap;
+
+ @Override
+ protected PropertyDescriptor
getSupportedDynamicPropertyDescriptor(final String propertyDescriptorName) {
+ return new PropertyDescriptor.Builder()
+ .name(propertyDescriptorName)
+ .description("The DBCPService to return when database.name
= '" + propertyDescriptorName + "'")
+ .identifiesControllerService(DBCPService.class)
+ .addValidator(StandardValidators.NON_BLANK_VALIDATOR)
+ .build();
+ }
+
+ @Override
+ protected Collection<ValidationResult>
customValidate(ValidationContext context) {
+ final List<ValidationResult> results = new ArrayList<>();
+
+ int numDefinedServices = 0;
+ for (final PropertyDescriptor descriptor :
context.getProperties().keySet()) {
+ if (descriptor.isDynamic()) {
+ numDefinedServices++;
+ }
+
+ final String referencedId =
context.getProperty(descriptor).getValue();
+ if (this.getIdentifier().equals(referencedId)) {
+ results.add(new ValidationResult.Builder()
+ .subject(descriptor.getDisplayName())
+ .explanation("the current service cannot be
registered as a DBCPService to lookup")
+ .valid(false)
+ .build());
+ }
+ }
+
+ if (numDefinedServices == 0) {
+ results.add(new ValidationResult.Builder()
+ .subject(this.getClass().getSimpleName())
+ .explanation("at least one DBCPService must be defined
via dynamic properties")
+ .valid(false)
+ .build());
+ }
+
+ return results;
+ }
+
+ @OnEnabled
+ public void onEnabled(final ConfigurationContext context) {
+ final Map<String,DBCPService> serviceMap = new HashMap<>();
+
+ for (final PropertyDescriptor descriptor :
context.getProperties().keySet()) {
+ if (descriptor.isDynamic()) {
+ final DBCPService dbcpService =
context.getProperty(descriptor).asControllerService(DBCPService.class);
+ serviceMap.put(descriptor.getName(), dbcpService);
+ }
+ }
+
+ dbcpServiceMap = Collections.unmodifiableMap(serviceMap);
+ }
+
+ @OnDisabled
+ public void onDisabled() {
+ dbcpServiceMap = null;
+ }
+
+ @Override
+ public Connection getConnection() throws ProcessException {
+ throw new UnsupportedOperationException("Cannot lookup
DBCPConnectionPool without attributes");
--- End diff --
Not opposed to the idea, would it be an optional property or required?
I guess if it's optional then getConnection() can throw exception if no
default is provided otherwise use the default, and getConnection(attributes)
can use the default when the database.name attribute is missing, or if default
isn't provided throw an exception.
---