NIFI-4: Added better support for reporting task and controller service lifecycle via annotations

This commit is contained in:
Mark Payne 2015-01-20 12:59:59 -05:00
parent 53328a4a02
commit b5956709b7
8 changed files with 97 additions and 25 deletions

View File

@ -191,7 +191,6 @@ import org.apache.nifi.web.api.entity.ProvenanceEventEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupsEntity;
import org.apache.nifi.web.util.WebUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -1290,18 +1289,6 @@ public class WebClusterManager implements HttpClusterManager, ProtocolHandler, C
}
}
/**
* Adds an instance of a specified controller service.
*
* @param type
* @param id
* @param properties
* @return
*/
@Override
public ControllerServiceNode createControllerService(String type, String id, Map<String, String> properties) {
return controllerServiceProvider.createControllerService(type, id, properties);
}
@Override
public ControllerService getControllerService(String serviceIdentifier) {
@ -1323,6 +1310,16 @@ public class WebClusterManager implements HttpClusterManager, ProtocolHandler, C
return controllerServiceProvider.isControllerServiceEnabled(serviceIdentifier);
}
@Override
public ControllerServiceNode createControllerService(final String type, final String id, final boolean firstTimeAdded) {
return controllerServiceProvider.createControllerService(type, id, firstTimeAdded);
}
@Override
public void removeControllerService(final ControllerServiceNode serviceNode) {
controllerServiceProvider.removeControllerService(serviceNode);
}
/**
* Handle a bulletins message.
*

View File

@ -73,4 +73,5 @@ public interface ReportingTaskNode extends ConfiguredComponent {
void verifyCanDisable();
void verifyCanEnable();
void verifyCanDelete();
void verifyCanUpdate();
}

View File

@ -43,4 +43,5 @@ public interface ControllerServiceNode extends ConfiguredComponent {
void verifyCanEnable();
void verifyCanDisable();
void verifyCanDelete();
void verifyCanUpdate();
}

View File

@ -19,7 +19,6 @@ package org.apache.nifi.controller.reporting;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.nifi.annotation.lifecycle.OnAdded;
import org.apache.nifi.controller.AbstractConfiguredComponent;
import org.apache.nifi.controller.Availability;
import org.apache.nifi.controller.ConfigurationContext;
@ -27,7 +26,6 @@ import org.apache.nifi.controller.ControllerServiceLookup;
import org.apache.nifi.controller.ProcessScheduler;
import org.apache.nifi.controller.ReportingTaskNode;
import org.apache.nifi.controller.ScheduledState;
import org.apache.nifi.controller.StandardProcessorNode;
import org.apache.nifi.controller.ValidationContextFactory;
import org.apache.nifi.controller.annotation.OnConfigured;
import org.apache.nifi.controller.exception.ProcessorLifeCycleException;
@ -145,6 +143,8 @@ public abstract class AbstractReportingTaskNode extends AbstractConfiguredCompon
}
private void onConfigured() {
// We need to invoke any method annotation with the OnConfigured annotation in order to
// maintain backward compatibility. This will be removed when we remove the old, deprecated annotations.
try (final NarCloseable x = NarCloseable.withNarLoader()) {
final ConfigurationContext configContext = new StandardConfigurationContext(this, serviceLookup);
ReflectionUtils.invokeMethodsWithAnnotation(OnConfigured.class, reportingTask, configContext);
@ -153,11 +153,58 @@ public abstract class AbstractReportingTaskNode extends AbstractConfiguredCompon
}
}
public boolean isDisabled() {
return scheduledState == ScheduledState.DISABLED;
}
@Override
public void verifyCanDelete() {
if (isRunning()) {
throw new IllegalStateException(this + " is running");
throw new IllegalStateException("Cannot delete " + reportingTask + " because it is currently running");
}
}
@Override
public void verifyCanDisable() {
if ( isRunning() ) {
throw new IllegalStateException("Cannot disable " + reportingTask + " because it is currently running");
}
if ( isDisabled() ) {
throw new IllegalStateException("Cannot disable " + reportingTask + " because it is already disabled");
}
}
@Override
public void verifyCanEnable() {
if ( !isDisabled() ) {
throw new IllegalStateException("Cannot enable " + reportingTask + " because it is not disabled");
}
}
@Override
public void verifyCanStart() {
if ( isDisabled() ) {
throw new IllegalStateException("Cannot start " + reportingTask + " because it is currently disabled");
}
if ( isRunning() ) {
throw new IllegalStateException("Cannot start " + reportingTask + " because it is already running");
}
}
@Override
public void verifyCanStop() {
if ( !isRunning() ) {
throw new IllegalStateException("Cannot stop " + reportingTask + " because it is not running");
}
}
@Override
public void verifyCanUpdate() {
if ( isRunning() ) {
throw new IllegalStateException("Cannot update " + reportingTask + " because it is currently running");
}
}
}

View File

@ -123,23 +123,21 @@ public class ControllerServiceLoader {
final List<Element> serviceNodes = DomUtils.getChildElementsByTagName(servicesElement, "service");
for (final Element serviceElement : serviceNodes) {
//add global properties common to all tasks
Map<String, String> properties = new HashMap<>();
//get properties for the specific controller task - id, name, class,
//and schedulingPeriod must be set
final String serviceId = DomUtils.getChild(serviceElement, "identifier").getTextContent().trim();
final String serviceClass = DomUtils.getChild(serviceElement, "class").getTextContent().trim();
//set the class to be used for the configured controller task
final ControllerServiceNode serviceNode = provider.createControllerService(serviceClass, serviceId, false);
//optional task-specific properties
for (final Element optionalProperty : DomUtils.getChildElementsByTagName(serviceElement, "property")) {
final String name = optionalProperty.getAttribute("name").trim();
final String value = optionalProperty.getTextContent().trim();
properties.put(name, value);
serviceNode.setProperty(name, value);
}
//set the class to be used for the configured controller task
final ControllerServiceNode serviceNode = provider.createControllerService(serviceClass, serviceId, properties);
services.add(serviceNode);
serviceNode.setDisabled(false);
}

View File

@ -166,7 +166,30 @@ public class StandardControllerServiceNode extends AbstractConfiguredComponent i
@Override
public void verifyCanDelete() {
if ( !isDisabled() ) {
throw new IllegalStateException(this + " cannot be deleted because it has not been disabled");
throw new IllegalStateException(implementation + " cannot be deleted because it is not disabled");
}
}
@Override
public void verifyCanDisable() {
final ControllerServiceReference references = getReferences();
final int numRunning = references.getRunningReferences().size();
if ( numRunning > 0 ) {
throw new IllegalStateException(implementation + " cannot be disabled because it is referenced by " + numRunning + " components that are currently running");
}
}
@Override
public void verifyCanEnable() {
if ( !isDisabled() ) {
throw new IllegalStateException(implementation + " cannot be enabled because it is not disabled");
}
}
@Override
public void verifyCanUpdate() {
if ( !isDisabled() ) {
throw new IllegalStateException(implementation + " cannot be updated because it is not disabled");
}
}
}

View File

@ -117,6 +117,7 @@ public class StandardControllerServiceProvider implements ControllerServiceProvi
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
final ControllerServiceNode node = serviceNodeHolder.get();
if (node.isDisabled() && !validDisabledMethods.contains(method)) {
// Use nar class loader here because we are implicitly calling toString() on the original implementation.
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
throw new IllegalStateException("Cannot invoke method " + method + " on Controller Service " + originalService + " because the Controller Service is disabled");
} catch (final Throwable e) {

View File

@ -384,8 +384,12 @@ public class ControllerFacade implements ControllerServiceProvider {
}
@Override
public ControllerServiceNode createControllerService(String type, String id, Map<String, String> properties) {
return flowController.createControllerService(type, id, properties);
public ControllerServiceNode createControllerService(String type, String id, boolean firstTimeAdded) {
return flowController.createControllerService(type, id, firstTimeAdded);
}
public void removeControllerService(ControllerServiceNode serviceNode) {
flowController.removeControllerService(serviceNode);
}
@Override