Github user markap14 commented on a diff in the pull request: https://github.com/apache/nifi/pull/3005#discussion_r218438047 --- Diff: nifi-nar-bundles/nifi-jms-bundle/nifi-jms-processors/src/main/java/org/apache/nifi/jms/cf/JndiJmsConnectionFactoryProvider.java --- @@ -0,0 +1,165 @@ +/* + * 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.jms.cf; + +import org.apache.nifi.annotation.behavior.DynamicProperty; +import org.apache.nifi.annotation.documentation.CapabilityDescription; +import org.apache.nifi.annotation.documentation.SeeAlso; +import org.apache.nifi.annotation.documentation.Tags; +import org.apache.nifi.annotation.lifecycle.OnDisabled; +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.components.PropertyDescriptor.Builder; +import org.apache.nifi.components.Validator; +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 javax.jms.ConnectionFactory; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import java.util.Arrays; +import java.util.Hashtable; +import java.util.List; + +import static org.apache.nifi.processor.util.StandardValidators.NON_EMPTY_VALIDATOR; + +@Tags({"jms", "jndi", "messaging", "integration", "queue", "topic", "publish", "subscribe"}) +@CapabilityDescription("Provides a service to lookup an existing JMS ConnectionFactory using the Java Naming and Directory Interface (JNDI).") +@DynamicProperty( + description = "In order to perform a JNDI Lookup, an Initial Context must be established. When this is done, an Environment can be established for the context. Any dynamic/user-defined property" + + " that is added to this Controller Service will be added as an Environment configuration/variable to this Context.", + name = "The name of a JNDI Initial Context environment variable.", + value = "The value of the JNDI Initial Context Environment variable.", + expressionLanguageScope = ExpressionLanguageScope.VARIABLE_REGISTRY) +@SeeAlso(classNames = {"org.apache.nifi.jms.processors.ConsumeJMS", "org.apache.nifi.jms.processors.PublishJMS", "org.apache.nifi.jms.cf.JMSConnectionFactoryProvider"}) +public class JndiJmsConnectionFactoryProvider extends AbstractControllerService implements JMSConnectionFactoryProviderDefinition{ + + static final PropertyDescriptor INITIAL_NAMING_FACTORY_CLASS = new Builder() + .name("java.naming.factory.initial") + .displayName("Initial Naming Factory Class") + .description("The fully qualified class name of the Java Initial Naming Factory (java.naming.factory.initial).") + .addValidator(NON_EMPTY_VALIDATOR) + .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY) + .required(true) + .build(); + static final PropertyDescriptor NAMING_PROVIDER_URL = new Builder() + .name("java.naming.provider.url") + .displayName("Naming Provider URL") + .description("The URL of the JNDI Naming Provider to use") + .required(true) + .addValidator(NON_EMPTY_VALIDATOR) + .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY) + .build(); + static final PropertyDescriptor CONNECTION_FACTORY_NAME = new Builder() + .name("connection.factory.name") + .displayName("Connection Factory Name") + .description("The name of the JNDI Object to lookup for the Connection Factory") + .required(true) + .addValidator(NON_EMPTY_VALIDATOR) + .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY) + .build(); + static final PropertyDescriptor NAMING_FACTORY_LIBRARIES = new Builder() + .name("naming.factory.libraries") + .displayName("Naming Factory Libraries") + .description("Specifies .jar files or directories to add to the ClassPath in order to find the Initial Naming Factory Class") + .required(false) + .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY) + .addValidator(StandardValidators.createListValidator(true, true, StandardValidators.createURLorFileValidator())) + .dynamicallyModifiesClasspath(true) + .build(); + + private static final List<PropertyDescriptor> PROPERTY_DESCRIPTORS = Arrays.asList( + INITIAL_NAMING_FACTORY_CLASS, + NAMING_PROVIDER_URL, + CONNECTION_FACTORY_NAME, + NAMING_FACTORY_LIBRARIES); + + private ConnectionFactory connectionFactory; + + @Override + protected List<PropertyDescriptor> getSupportedPropertyDescriptors() { + return PROPERTY_DESCRIPTORS; + } + + @Override + protected PropertyDescriptor getSupportedDynamicPropertyDescriptor(final String propertyDescriptorName) { + return new Builder() + .name(propertyDescriptorName) + .displayName(propertyDescriptorName) + .description("JNDI Initial Context Environment configuration for '" + propertyDescriptorName + "'") + .required(false) + .dynamic(true) + .addValidator(Validator.VALID) + .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY) + .build(); + } + + @OnDisabled + public void shutdown() { + connectionFactory = null; + } + + @Override + public synchronized ConnectionFactory getConnectionFactory() { --- End diff -- No, the above code is not thread safe. All access to the member variable must be protected. Synchronization is not a concern here. Either the method returns immediately or blocks while creating the connection factory, which is the desired behavior.
---