diff --git a/operator-framework-core/pom.xml b/operator-framework-core/pom.xml
index e46f893d8d..43d3f95758 100644
--- a/operator-framework-core/pom.xml
+++ b/operator-framework-core/pom.xml
@@ -2,72 +2,97 @@
 <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/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>io.javaoperatorsdk</groupId>
-        <artifactId>java-operator-sdk</artifactId>
-        <version>1.7.1-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>io.javaoperatorsdk</groupId>
+    <artifactId>java-operator-sdk</artifactId>
+    <version>1.7.1-SNAPSHOT</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
 
-    <artifactId>operator-framework-core</artifactId>
-    <name>Operator SDK - Framework - Core</name>
-    <description>Core framework for implementing Kubernetes operators</description>
-    <packaging>jar</packaging>
+  <artifactId>operator-framework-core</artifactId>
+  <name>Operator SDK - Framework - Core</name>
+  <description>Core framework for implementing Kubernetes operators</description>
+  <packaging>jar</packaging>
 
-    <properties>
-        <java.version>11</java.version>
-        <maven.compiler.source>11</maven.compiler.source>
-        <maven.compiler.target>11</maven.compiler.target>
-    </properties>
+  <properties>
+    <java.version>11</java.version>
+    <maven.compiler.source>11</maven.compiler.source>
+    <maven.compiler.target>11</maven.compiler.target>
+  </properties>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <version>${surefire.version}</version>
-            </plugin>
-        </plugins>
-    </build>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>${surefire.version}</version>
+      </plugin>
+      <plugin>
+        <!-- Used to generate the version / commit information -->
+        <groupId>pl.project13.maven</groupId>
+        <artifactId>git-commit-id-plugin</artifactId>
+        <version>4.0.3</version>
+        <executions>
+          <execution>
+            <id>get-the-git-infos</id>
+            <goals>
+              <goal>revision</goal>
+            </goals>
+            <phase>initialize</phase>
+          </execution>
+        </executions>
+        <configuration>
+          <generateGitPropertiesFile>true</generateGitPropertiesFile>
+          <generateGitPropertiesFilename>${project.build.outputDirectory}/version.properties
+          </generateGitPropertiesFilename>
+          <includeOnlyProperties>
+            <includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty>
+            <includeOnlyProperty>^git.commit.id.(abbrev|full)$</includeOnlyProperty>
+          </includeOnlyProperties>
+          <commitIdGenerationMode>full</commitIdGenerationMode>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
 
 
-    <dependencies>
-        <dependency>
-            <groupId>io.fabric8</groupId>
-            <artifactId>openshift-client</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
+  <dependencies>
+    <dependency>
+      <groupId>io.fabric8</groupId>
+      <artifactId>openshift-client</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
 
-        <dependency>
-            <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter-api</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter-engine</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.logging.log4j</groupId>
-            <artifactId>log4j-slf4j-impl</artifactId>
-            <version>2.13.3</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.assertj</groupId>
-            <artifactId>assertj-core</artifactId>
-            <version>3.18.0</version>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+      <version>2.13.3</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.assertj</groupId>
+      <artifactId>assertj-core</artifactId>
+      <version>3.18.0</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
 </project>
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/ControllerUtils.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/ControllerUtils.java
index 287312d0e6..55cbe9d6f6 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/ControllerUtils.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/ControllerUtils.java
@@ -1,6 +1,5 @@
 package io.javaoperatorsdk.operator;
 
-import io.fabric8.kubernetes.client.CustomResource;
 import io.javaoperatorsdk.operator.api.Controller;
 import io.javaoperatorsdk.operator.api.ResourceController;
 import java.util.Locale;
@@ -13,11 +12,6 @@ public static String getDefaultFinalizerName(String crdName) {
     return crdName + FINALIZER_NAME_SUFFIX;
   }
 
-  public static boolean hasGivenFinalizer(CustomResource resource, String finalizer) {
-    return resource.getMetadata().getFinalizers() != null
-        && resource.getMetadata().getFinalizers().contains(finalizer);
-  }
-
   public static String getNameFor(Class<? extends ResourceController> controllerClass) {
     // if the controller annotation has a name attribute, use it
     final var annotation = controllerClass.getAnnotation(Controller.class);
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java
index b1e8f25af5..5045eeddcf 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java
@@ -12,7 +12,6 @@
 import io.javaoperatorsdk.operator.processing.event.DefaultEventSourceManager;
 import io.javaoperatorsdk.operator.processing.event.internal.CustomResourceEventSource;
 import io.javaoperatorsdk.operator.processing.retry.GenericRetry;
-import io.javaoperatorsdk.operator.processing.retry.Retry;
 import java.util.Arrays;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -29,11 +28,44 @@ public Operator(KubernetesClient k8sClient, ConfigurationService configurationSe
     this.configurationService = configurationService;
   }
 
+  /**
+   * Finishes the operator startup process. This is mostly used in injection-aware applications
+   * where there is no obvious entrypoint to the application which can trigger the injection process
+   * and start the cluster monitoring processes.
+   */
+  public void start() {
+    final var version = configurationService.getVersion();
+    log.info(
+        "Operator {} (commit: {}) built on {} starting...",
+        version.getSdkVersion(),
+        version.getCommit(),
+        version.getBuiltTime());
+  }
+
+  /**
+   * Registers the specified controller with this operator.
+   *
+   * @param controller the controller to register
+   * @param <R> the {@code CustomResource} type associated with the controller
+   * @throws OperatorException if a problem occurred during the registration process
+   */
   public <R extends CustomResource> void register(ResourceController<R> controller)
       throws OperatorException {
     register(controller, null);
   }
 
+  /**
+   * Registers the specified controller with this operator, overriding its default configuration by
+   * the specified one (usually created via {@link
+   * io.javaoperatorsdk.operator.api.config.ControllerConfigurationOverrider#override(ControllerConfiguration)},
+   * passing it the controller's original configuration.
+   *
+   * @param controller the controller to register
+   * @param configuration the configuration with which we want to register the controller, if {@code
+   *     null}, the controller's orginal configuration is used
+   * @param <R> the {@code CustomResource} type associated with the controller
+   * @throws OperatorException if a problem occurred during the registration process
+   */
   public <R extends CustomResource> void register(
       ResourceController<R> controller, ControllerConfiguration<R> configuration)
       throws OperatorException {
@@ -49,55 +81,57 @@ public <R extends CustomResource> void register(
       if (configuration == null) {
         configuration = existing;
       }
+
       final var retry = GenericRetry.fromConfiguration(configuration.getRetryConfiguration());
       final var targetNamespaces = configuration.getNamespaces().toArray(new String[] {});
-      registerController(controller, configuration.watchAllNamespaces(), retry, targetNamespaces);
-    }
-  }
+      Class<R> resClass = configuration.getCustomResourceClass();
+      String finalizer = configuration.getFinalizer();
+      final var client = k8sClient.customResources(resClass);
+      EventDispatcher dispatcher =
+          new EventDispatcher(
+              controller, finalizer, new EventDispatcher.CustomResourceFacade(client));
 
-  @SuppressWarnings("rawtypes")
-  private <R extends CustomResource> void registerController(
-      ResourceController<R> controller,
-      boolean watchAllNamespaces,
-      Retry retry,
-      String... targetNamespaces)
-      throws OperatorException {
-    final var configuration = configurationService.getConfigurationFor(controller);
-    Class<R> resClass = configuration.getCustomResourceClass();
-    String finalizer = configuration.getFinalizer();
-    MixedOperation client = k8sClient.customResources(resClass);
-    EventDispatcher eventDispatcher =
-        new EventDispatcher(
-            controller, finalizer, new EventDispatcher.CustomResourceFacade(client));
+      // check that the custom resource is known by the cluster
+      final var crdName = configuration.getCRDName();
+      final var crd =
+          k8sClient.apiextensions().v1().customResourceDefinitions().withName(crdName).get();
+      final var controllerName = configuration.getName();
+      if (crd == null) {
+        throw new OperatorException(
+            "'"
+                + crdName
+                + "' CRD was not found on the cluster, controller "
+                + controllerName
+                + " cannot be registered");
+      }
 
-    CustomResourceCache customResourceCache = new CustomResourceCache();
-    DefaultEventHandler defaultEventHandler =
-        new DefaultEventHandler(
-            customResourceCache, eventDispatcher, controller.getClass().getName(), retry);
-    DefaultEventSourceManager eventSourceManager =
-        new DefaultEventSourceManager(defaultEventHandler, retry != null);
-    defaultEventHandler.setEventSourceManager(eventSourceManager);
-    eventDispatcher.setEventSourceManager(eventSourceManager);
+      CustomResourceCache customResourceCache = new CustomResourceCache();
+      DefaultEventHandler defaultEventHandler =
+          new DefaultEventHandler(customResourceCache, dispatcher, controllerName, retry);
+      DefaultEventSourceManager eventSourceManager =
+          new DefaultEventSourceManager(defaultEventHandler, retry != null);
+      defaultEventHandler.setEventSourceManager(eventSourceManager);
+      dispatcher.setEventSourceManager(eventSourceManager);
 
-    controller.init(eventSourceManager);
-    CustomResourceEventSource customResourceEventSource =
-        createCustomResourceEventSource(
-            client,
-            customResourceCache,
-            watchAllNamespaces,
-            targetNamespaces,
-            defaultEventHandler,
-            configuration.isGenerationAware(),
-            finalizer);
-    eventSourceManager.registerCustomResourceEventSource(customResourceEventSource);
+      controller.init(eventSourceManager);
+      final boolean watchAllNamespaces = configuration.watchAllNamespaces();
+      CustomResourceEventSource customResourceEventSource =
+          createCustomResourceEventSource(
+              client,
+              customResourceCache,
+              watchAllNamespaces,
+              targetNamespaces,
+              defaultEventHandler,
+              configuration.isGenerationAware(),
+              finalizer);
+      eventSourceManager.registerCustomResourceEventSource(customResourceEventSource);
 
-    log.info(
-        "Registered Controller: '{}' for CRD: '{}' for namespaces: {}",
-        controller.getClass().getSimpleName(),
-        resClass,
-        targetNamespaces.length == 0
-            ? "[all/client namespace]"
-            : Arrays.toString(targetNamespaces));
+      log.info(
+          "Registered Controller: '{}' for CRD: '{}' for namespaces: {}",
+          controller.getClass().getSimpleName(),
+          resClass,
+          watchAllNamespaces ? "[all namespaces]" : Arrays.toString(targetNamespaces));
+    }
   }
 
   private CustomResourceEventSource createCustomResourceEventSource(
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AbstractConfigurationService.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AbstractConfigurationService.java
index 8d0ccb34e4..6d4e36f067 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AbstractConfigurationService.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AbstractConfigurationService.java
@@ -10,6 +10,11 @@
 public abstract class AbstractConfigurationService implements ConfigurationService {
 
   private final Map<String, ControllerConfiguration> configurations = new ConcurrentHashMap<>();
+  private final Version version;
+
+  public AbstractConfigurationService(Version version) {
+    this.version = version;
+  }
 
   protected <R extends CustomResource> void register(ControllerConfiguration<R> config) {
     final var name = config.getName();
@@ -41,4 +46,9 @@ public <R extends CustomResource> ControllerConfiguration<R> getConfigurationFor
   public Set<String> getKnownControllerNames() {
     return configurations.keySet();
   }
+
+  @Override
+  public Version getVersion() {
+    return version;
+  }
 }
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java
index 952b1c1838..820d1abb28 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java
@@ -5,14 +5,41 @@
 import io.javaoperatorsdk.operator.api.ResourceController;
 import java.util.Set;
 
+/** An interface from which to retrieve configuration information. */
 public interface ConfigurationService {
 
+  /**
+   * Retrieves the configuration associated with the specified controller
+   *
+   * @param controller the controller we want the configuration of
+   * @param <R> the {@code CustomResource} type associated with the specified controller
+   * @return the {@link ControllerConfiguration} associated with the specified controller or {@code
+   *     null} if no configuration exists for the controller
+   */
   <R extends CustomResource> ControllerConfiguration<R> getConfigurationFor(
       ResourceController<R> controller);
 
+  /**
+   * Retrieves the Kubernetes client configuration
+   *
+   * @return the configuration of the Kubernetes client, defaulting to the provided
+   *     auto-configuration
+   */
   default Config getClientConfiguration() {
     return Config.autoConfigure(null);
   }
 
+  /**
+   * Retrieves the set of the names of controllers for which a configuration exists
+   *
+   * @return the set of known controller names
+   */
   Set<String> getKnownControllerNames();
+
+  /**
+   * Retrieves the {@link Version} information associated with this particular instance of the SDK
+   *
+   * @return the version information
+   */
+  Version getVersion();
 }
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Utils.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Utils.java
new file mode 100644
index 0000000000..442b7d47fa
--- /dev/null
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Utils.java
@@ -0,0 +1,51 @@
+package io.javaoperatorsdk.operator.api.config;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.util.Date;
+import java.util.Properties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Utils {
+
+  private static final Logger log = LoggerFactory.getLogger(Utils.class);
+
+  /**
+   * Attempts to load version information from a properties file produced at build time, currently
+   * via the {@code git-commit-id-plugin} maven plugin.
+   *
+   * @return a {@link Version} object encapsulating the version information
+   */
+  public static Version loadFromProperties() {
+    final var is =
+        Thread.currentThread().getContextClassLoader().getResourceAsStream("version.properties");
+
+    final var properties = new Properties();
+    if (is != null) {
+      try {
+        properties.load(is);
+      } catch (IOException e) {
+        log.warn("Couldn't load version information: {}", e.getMessage());
+      }
+    } else {
+      log.warn("Couldn't find version.properties file. Default version information will be used.");
+    }
+
+    Date builtTime;
+    try {
+      builtTime =
+          // RFC 822 date is the default format used by git-commit-id-plugin
+          new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
+              .parse(properties.getProperty("git.build.time"));
+    } catch (ParseException e) {
+      builtTime = Date.from(Instant.EPOCH);
+    }
+    return new Version(
+        properties.getProperty("git.build.version", "unknown"),
+        properties.getProperty("git.commit.id.abbrev", "unknown"),
+        builtTime);
+  }
+}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Version.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Version.java
new file mode 100644
index 0000000000..6af60412b4
--- /dev/null
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Version.java
@@ -0,0 +1,45 @@
+package io.javaoperatorsdk.operator.api.config;
+
+import java.util.Date;
+
+/** A class encapsulating the version information associated with this SDK instance. */
+public class Version {
+
+  private final String sdk;
+  private final String commit;
+  private final Date builtTime;
+
+  public Version(String sdkVersion, String commit, Date builtTime) {
+    this.sdk = sdkVersion;
+    this.commit = commit;
+    this.builtTime = builtTime;
+  }
+
+  /**
+   * Returns the SDK project version
+   *
+   * @return the SDK project version
+   */
+  public String getSdkVersion() {
+    return sdk;
+  }
+
+  /**
+   * Returns the git commit id associated with this SDK instance
+   *
+   * @return the git commit id
+   */
+  public String getCommit() {
+    return commit;
+  }
+
+  /**
+   * Returns the date at which this SDK instance was built
+   *
+   * @return the build time at which this SDK instance was built or the date corresponding to {@link
+   *     java.time.Instant#EPOCH} if the built time couldn't be retrieved
+   */
+  public Date getBuiltTime() {
+    return builtTime;
+  }
+}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/DefaultEventHandler.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/DefaultEventHandler.java
index 5b9fa023e6..92fa88a375 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/DefaultEventHandler.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/DefaultEventHandler.java
@@ -17,7 +17,6 @@
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.locks.ReentrantLock;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -52,13 +51,7 @@ public DefaultEventHandler(
     eventBuffer = new EventBuffer();
     executor =
         new ScheduledThreadPoolExecutor(
-            5,
-            new ThreadFactory() {
-              @Override
-              public Thread newThread(Runnable runnable) {
-                return new Thread(runnable, "EventHandler-" + relatedControllerName);
-              }
-            });
+            5, runnable -> new Thread(runnable, "EventHandler-" + relatedControllerName));
   }
 
   public void setEventSourceManager(DefaultEventSourceManager eventSourceManager) {
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/EventDispatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/EventDispatcher.java
index 9e951e26c2..d79f8677f5 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/EventDispatcher.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/EventDispatcher.java
@@ -3,12 +3,11 @@
 import static io.javaoperatorsdk.operator.EventListUtils.containsCustomResourceDeletedEvent;
 import static io.javaoperatorsdk.operator.processing.KubernetesResourceUtils.getUID;
 import static io.javaoperatorsdk.operator.processing.KubernetesResourceUtils.getVersion;
-import static io.javaoperatorsdk.operator.processing.KubernetesResourceUtils.markedForDeletion;
 
+import io.fabric8.kubernetes.api.model.KubernetesResourceList;
 import io.fabric8.kubernetes.client.CustomResource;
 import io.fabric8.kubernetes.client.dsl.MixedOperation;
 import io.fabric8.kubernetes.client.dsl.Resource;
-import io.javaoperatorsdk.operator.ControllerUtils;
 import io.javaoperatorsdk.operator.api.Context;
 import io.javaoperatorsdk.operator.api.DefaultContext;
 import io.javaoperatorsdk.operator.api.DeleteControl;
@@ -16,7 +15,6 @@
 import io.javaoperatorsdk.operator.api.UpdateControl;
 import io.javaoperatorsdk.operator.processing.event.EventList;
 import io.javaoperatorsdk.operator.processing.event.EventSourceManager;
-import java.util.ArrayList;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -64,8 +62,7 @@ private PostExecutionControl handleDispatch(ExecutionScope executionScope) {
           getVersion(resource));
       return PostExecutionControl.defaultDispatch();
     }
-    if ((markedForDeletion(resource)
-        && !ControllerUtils.hasGivenFinalizer(resource, resourceFinalizer))) {
+    if ((resource.isMarkedForDeletion() && !resource.hasFinalizer(resourceFinalizer))) {
       log.debug(
           "Skipping event dispatching since its marked for deletion but has no finalizer: {}",
           executionScope);
@@ -76,7 +73,7 @@ private PostExecutionControl handleDispatch(ExecutionScope executionScope) {
             eventSourceManager,
             new EventList(executionScope.getEvents()),
             executionScope.getRetryInfo());
-    if (markedForDeletion(resource)) {
+    if (resource.isMarkedForDeletion()) {
       return handleDelete(resource, context);
     } else {
       return handleCreateOrUpdate(executionScope, resource, context);
@@ -85,8 +82,7 @@ private PostExecutionControl handleDispatch(ExecutionScope executionScope) {
 
   private PostExecutionControl handleCreateOrUpdate(
       ExecutionScope executionScope, CustomResource resource, Context context) {
-    if (!ControllerUtils.hasGivenFinalizer(resource, resourceFinalizer)
-        && !markedForDeletion(resource)) {
+    if (!resource.hasFinalizer(resourceFinalizer) && !resource.isMarkedForDeletion()) {
       /*  We always add the finalizer if missing and not marked for deletion.
          We execute the controller processing only for processing the event sent as a results
          of the finalizer add. This will make sure that the resources are not created before
@@ -132,7 +128,7 @@ private PostExecutionControl handleDelete(CustomResource resource, Context conte
         getUID(resource),
         getVersion(resource));
     DeleteControl deleteControl = controller.deleteResource(resource, context);
-    boolean hasFinalizer = ControllerUtils.hasGivenFinalizer(resource, resourceFinalizer);
+    boolean hasFinalizer = resource.hasFinalizer(resourceFinalizer);
     if (deleteControl == DeleteControl.DEFAULT_DELETE && hasFinalizer) {
       CustomResource customResource = removeFinalizer(resource);
       return PostExecutionControl.customResourceUpdated(customResource);
@@ -150,7 +146,7 @@ private PostExecutionControl handleDelete(CustomResource resource, Context conte
   private void updateCustomResourceWithFinalizer(CustomResource resource) {
     log.debug(
         "Adding finalizer for resource: {} version: {}", getUID(resource), getVersion(resource));
-    addFinalizerIfNotPresent(resource);
+    resource.addFinalizer(resourceFinalizer);
     replace(resource);
   }
 
@@ -165,7 +161,7 @@ private CustomResource removeFinalizer(CustomResource resource) {
         "Removing finalizer on resource: {} with version: {}",
         getUID(resource),
         getVersion(resource));
-    resource.getMetadata().getFinalizers().remove(resourceFinalizer);
+    resource.removeFinalizer(resourceFinalizer);
     return customResourceFacade.replaceWithLock(resource);
   }
 
@@ -177,27 +173,17 @@ private CustomResource replace(CustomResource resource) {
     return customResourceFacade.replaceWithLock(resource);
   }
 
-  private void addFinalizerIfNotPresent(CustomResource resource) {
-    if (!ControllerUtils.hasGivenFinalizer(resource, resourceFinalizer)
-        && !markedForDeletion(resource)) {
-      log.info("Adding finalizer to {}", resource.getMetadata());
-      if (resource.getMetadata().getFinalizers() == null) {
-        resource.getMetadata().setFinalizers(new ArrayList<>(1));
-      }
-      resource.getMetadata().getFinalizers().add(resourceFinalizer);
-    }
-  }
-
   // created to support unit testing
-  public static class CustomResourceFacade {
+  public static class CustomResourceFacade<R extends CustomResource> {
 
-    private final MixedOperation<?, ?, Resource<CustomResource>> resourceOperation;
+    private final MixedOperation<R, KubernetesResourceList<R>, Resource<R>> resourceOperation;
 
-    public CustomResourceFacade(MixedOperation<?, ?, Resource<CustomResource>> resourceOperation) {
+    public CustomResourceFacade(
+        MixedOperation<R, KubernetesResourceList<R>, Resource<R>> resourceOperation) {
       this.resourceOperation = resourceOperation;
     }
 
-    public CustomResource updateStatus(CustomResource resource) {
+    public R updateStatus(R resource) {
       log.trace("Updating status for resource: {}", resource);
       return resourceOperation
           .inNamespace(resource.getMetadata().getNamespace())
@@ -205,7 +191,7 @@ public CustomResource updateStatus(CustomResource resource) {
           .updateStatus(resource);
     }
 
-    public CustomResource replaceWithLock(CustomResource resource) {
+    public R replaceWithLock(R resource) {
       return resourceOperation
           .inNamespace(resource.getMetadata().getNamespace())
           .withName(resource.getMetadata().getName())
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/KubernetesResourceUtils.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/KubernetesResourceUtils.java
index 2fd434ce5f..7f617e9705 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/KubernetesResourceUtils.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/KubernetesResourceUtils.java
@@ -1,7 +1,6 @@
 package io.javaoperatorsdk.operator.processing;
 
 import io.fabric8.kubernetes.api.model.HasMetadata;
-import io.fabric8.kubernetes.client.CustomResource;
 
 public class KubernetesResourceUtils {
 
@@ -12,9 +11,4 @@ public static String getUID(HasMetadata customResource) {
   public static String getVersion(HasMetadata customResource) {
     return customResource.getMetadata().getResourceVersion();
   }
-
-  public static boolean markedForDeletion(CustomResource resource) {
-    return resource.getMetadata().getDeletionTimestamp() != null
-        && !resource.getMetadata().getDeletionTimestamp().isEmpty();
-  }
 }
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/internal/CustomResourceEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/internal/CustomResourceEventSource.java
index c8d13a4d4b..55ed716c45 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/internal/CustomResourceEventSource.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/internal/CustomResourceEventSource.java
@@ -2,14 +2,12 @@
 
 import static io.javaoperatorsdk.operator.processing.KubernetesResourceUtils.getUID;
 import static io.javaoperatorsdk.operator.processing.KubernetesResourceUtils.getVersion;
-import static io.javaoperatorsdk.operator.processing.KubernetesResourceUtils.markedForDeletion;
 
 import io.fabric8.kubernetes.client.CustomResource;
 import io.fabric8.kubernetes.client.Watcher;
 import io.fabric8.kubernetes.client.WatcherException;
 import io.fabric8.kubernetes.client.dsl.MixedOperation;
 import io.fabric8.kubernetes.client.dsl.internal.CustomResourceOperationsImpl;
-import io.javaoperatorsdk.operator.ControllerUtils;
 import io.javaoperatorsdk.operator.processing.CustomResourceCache;
 import io.javaoperatorsdk.operator.processing.KubernetesResourceUtils;
 import io.javaoperatorsdk.operator.processing.event.AbstractEventSource;
@@ -115,7 +113,7 @@ public void eventReceived(Watcher.Action action, CustomResource customResource)
   }
 
   private void markLastGenerationProcessed(CustomResource resource) {
-    if (generationAware && ControllerUtils.hasGivenFinalizer(resource, resourceFinalizer)) {
+    if (generationAware && resource.hasFinalizer(resourceFinalizer)) {
       lastGenerationProcessedSuccessfully.put(
           KubernetesResourceUtils.getUID(resource), resource.getMetadata().getGeneration());
     }
@@ -126,7 +124,7 @@ private boolean skipBecauseOfGenerations(CustomResource customResource) {
       return false;
     }
     // if CR being deleted generation is naturally not changing, so we process all the events
-    if (markedForDeletion(customResource)) {
+    if (customResource.isMarkedForDeletion()) {
       return false;
     }
     if (!largerGenerationThenProcessedBefore(customResource)) {
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/EventDispatcherTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/EventDispatcherTest.java
index 2a8bd942ea..643bb5bab3 100644
--- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/EventDispatcherTest.java
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/EventDispatcherTest.java
@@ -33,7 +33,7 @@
 
 class EventDispatcherTest {
 
-  private static final String DEFAULT_FINALIZER = "finalizer";
+  private static final String DEFAULT_FINALIZER = "javaoperatorsdk.io/finalizer";
   private CustomResource testCustomResource;
   private EventDispatcher eventDispatcher;
   private ResourceController<CustomResource> controller = mock(ResourceController.class);
diff --git a/operator-framework-quarkus-extension/deployment/src/main/java/io/javaoperatorsdk/quarkus/extension/deployment/QuarkusExtensionProcessor.java b/operator-framework-quarkus-extension/deployment/src/main/java/io/javaoperatorsdk/quarkus/extension/deployment/QuarkusExtensionProcessor.java
index 446519417b..126ef44446 100644
--- a/operator-framework-quarkus-extension/deployment/src/main/java/io/javaoperatorsdk/quarkus/extension/deployment/QuarkusExtensionProcessor.java
+++ b/operator-framework-quarkus-extension/deployment/src/main/java/io/javaoperatorsdk/quarkus/extension/deployment/QuarkusExtensionProcessor.java
@@ -7,12 +7,14 @@
 import io.javaoperatorsdk.operator.api.config.ConfigurationService;
 import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
 import io.javaoperatorsdk.operator.api.config.RetryConfiguration;
+import io.javaoperatorsdk.operator.api.config.Utils;
 import io.javaoperatorsdk.quarkus.extension.ConfigurationServiceRecorder;
 import io.javaoperatorsdk.quarkus.extension.ExternalConfiguration;
 import io.javaoperatorsdk.quarkus.extension.ExternalControllerConfiguration;
 import io.javaoperatorsdk.quarkus.extension.OperatorProducer;
 import io.javaoperatorsdk.quarkus.extension.QuarkusConfigurationService;
 import io.javaoperatorsdk.quarkus.extension.QuarkusControllerConfiguration;
+import io.javaoperatorsdk.quarkus.extension.Version;
 import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
 import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
 import io.quarkus.deployment.annotations.BuildProducer;
@@ -79,7 +81,12 @@ void createConfigurationServiceAndOperator(
             .map(ci -> createControllerConfiguration(ci, additionalBeans, reflectionClasses))
             .collect(Collectors.toList());
 
-    final var supplier = recorder.configurationServiceSupplier(controllerConfigs);
+    final var version = Utils.loadFromProperties();
+
+    final var supplier =
+        recorder.configurationServiceSupplier(
+            new Version(version.getSdkVersion(), version.getCommit(), version.getBuiltTime()),
+            controllerConfigs);
     syntheticBeanBuildItemBuildProducer.produce(
         SyntheticBeanBuildItem.configure(QuarkusConfigurationService.class)
             .scope(Singleton.class)
diff --git a/operator-framework-quarkus-extension/runtime/src/main/java/io/javaoperatorsdk/quarkus/extension/ConfigurationServiceRecorder.java b/operator-framework-quarkus-extension/runtime/src/main/java/io/javaoperatorsdk/quarkus/extension/ConfigurationServiceRecorder.java
index 8627448bab..d0d6d3dca9 100644
--- a/operator-framework-quarkus-extension/runtime/src/main/java/io/javaoperatorsdk/quarkus/extension/ConfigurationServiceRecorder.java
+++ b/operator-framework-quarkus-extension/runtime/src/main/java/io/javaoperatorsdk/quarkus/extension/ConfigurationServiceRecorder.java
@@ -3,6 +3,7 @@
 import io.fabric8.kubernetes.client.KubernetesClient;
 import io.javaoperatorsdk.operator.api.config.ConfigurationService;
 import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
+import io.javaoperatorsdk.operator.api.config.Version;
 import io.quarkus.arc.Arc;
 import io.quarkus.runtime.annotations.Recorder;
 import java.util.List;
@@ -12,9 +13,9 @@
 public class ConfigurationServiceRecorder {
 
   public Supplier<ConfigurationService> configurationServiceSupplier(
-      List<ControllerConfiguration> controllerConfigs) {
+      Version version, List<ControllerConfiguration> controllerConfigs) {
     return () ->
         new QuarkusConfigurationService(
-            controllerConfigs, Arc.container().instance(KubernetesClient.class).get());
+            version, controllerConfigs, Arc.container().instance(KubernetesClient.class).get());
   }
 }
diff --git a/operator-framework-quarkus-extension/runtime/src/main/java/io/javaoperatorsdk/quarkus/extension/QuarkusConfigurationService.java b/operator-framework-quarkus-extension/runtime/src/main/java/io/javaoperatorsdk/quarkus/extension/QuarkusConfigurationService.java
index 07cfc30fa1..d18a271cec 100644
--- a/operator-framework-quarkus-extension/runtime/src/main/java/io/javaoperatorsdk/quarkus/extension/QuarkusConfigurationService.java
+++ b/operator-framework-quarkus-extension/runtime/src/main/java/io/javaoperatorsdk/quarkus/extension/QuarkusConfigurationService.java
@@ -6,6 +6,7 @@
 import io.javaoperatorsdk.operator.api.ResourceController;
 import io.javaoperatorsdk.operator.api.config.AbstractConfigurationService;
 import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
+import io.javaoperatorsdk.operator.api.config.Version;
 import io.quarkus.arc.runtime.ClientProxyUnwrapper;
 import java.util.List;
 
@@ -14,7 +15,8 @@ public class QuarkusConfigurationService extends AbstractConfigurationService {
   private final KubernetesClient client;
 
   public QuarkusConfigurationService(
-      List<ControllerConfiguration> configurations, KubernetesClient client) {
+      Version version, List<ControllerConfiguration> configurations, KubernetesClient client) {
+    super(version);
     this.client = client;
     if (configurations != null && !configurations.isEmpty()) {
       configurations.forEach(this::register);
diff --git a/operator-framework-quarkus-extension/runtime/src/main/java/io/javaoperatorsdk/quarkus/extension/Version.java b/operator-framework-quarkus-extension/runtime/src/main/java/io/javaoperatorsdk/quarkus/extension/Version.java
new file mode 100644
index 0000000000..354d7628cf
--- /dev/null
+++ b/operator-framework-quarkus-extension/runtime/src/main/java/io/javaoperatorsdk/quarkus/extension/Version.java
@@ -0,0 +1,13 @@
+package io.javaoperatorsdk.quarkus.extension;
+
+import io.quarkus.runtime.annotations.RecordableConstructor;
+import java.util.Date;
+
+/** Re-publish with a recordable constructor so that quarkus can do its thing with it! */
+public class Version extends io.javaoperatorsdk.operator.api.config.Version {
+
+  @RecordableConstructor
+  public Version(String sdkVersion, String commit, Date builtTime) {
+    super(sdkVersion, commit, builtTime);
+  }
+}
diff --git a/operator-framework-spring-boot-starter/src/main/java/io/javaoperatorsdk/operator/springboot/starter/OperatorAutoConfiguration.java b/operator-framework-spring-boot-starter/src/main/java/io/javaoperatorsdk/operator/springboot/starter/OperatorAutoConfiguration.java
index 4a8455b69a..ad6f118aa5 100644
--- a/operator-framework-spring-boot-starter/src/main/java/io/javaoperatorsdk/operator/springboot/starter/OperatorAutoConfiguration.java
+++ b/operator-framework-spring-boot-starter/src/main/java/io/javaoperatorsdk/operator/springboot/starter/OperatorAutoConfiguration.java
@@ -11,6 +11,7 @@
 import io.javaoperatorsdk.operator.api.ResourceController;
 import io.javaoperatorsdk.operator.api.config.AbstractConfigurationService;
 import io.javaoperatorsdk.operator.api.config.RetryConfiguration;
+import io.javaoperatorsdk.operator.api.config.Utils;
 import io.javaoperatorsdk.operator.config.runtime.AnnotationConfiguration;
 import java.util.List;
 import java.util.Optional;
@@ -26,6 +27,10 @@
 public class OperatorAutoConfiguration extends AbstractConfigurationService {
   @Autowired private OperatorConfigurationProperties configuration;
 
+  public OperatorAutoConfiguration() {
+    super(Utils.loadFromProperties());
+  }
+
   @Bean
   @ConditionalOnMissingBean
   public KubernetesClient kubernetesClient() {
diff --git a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationConfiguration.java b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationConfiguration.java
index cce8ac1622..bc2c13ace8 100644
--- a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationConfiguration.java
+++ b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/AnnotationConfiguration.java
@@ -5,17 +5,19 @@
 import io.javaoperatorsdk.operator.api.Controller;
 import io.javaoperatorsdk.operator.api.ResourceController;
 import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
+import java.util.Optional;
 import java.util.Set;
+import java.util.function.Predicate;
 
 public class AnnotationConfiguration<R extends CustomResource>
     implements ControllerConfiguration<R> {
 
   private final ResourceController<R> controller;
-  private final Controller annotation;
+  private final Optional<Controller> annotation;
 
   public AnnotationConfiguration(ResourceController<R> controller) {
     this.controller = controller;
-    this.annotation = controller.getClass().getAnnotation(Controller.class);
+    this.annotation = Optional.ofNullable(controller.getClass().getAnnotation(Controller.class));
   }
 
   @Override
@@ -30,16 +32,15 @@ public String getCRDName() {
 
   @Override
   public String getFinalizer() {
-    final String annotationFinalizerName = annotation.finalizerName();
-    if (!Controller.NULL.equals(annotationFinalizerName)) {
-      return annotationFinalizerName;
-    }
-    return ControllerUtils.getDefaultFinalizerName(getCRDName());
+    return annotation
+        .map(Controller::finalizerName)
+        .filter(Predicate.not(String::isBlank))
+        .orElse(ControllerUtils.getDefaultFinalizerName(getCRDName()));
   }
 
   @Override
   public boolean isGenerationAware() {
-    return annotation.generationAwareEventProcessing();
+    return annotation.map(Controller::generationAwareEventProcessing).orElse(true);
   }
 
   @Override
@@ -49,7 +50,7 @@ public Class<R> getCustomResourceClass() {
 
   @Override
   public Set<String> getNamespaces() {
-    return Set.of(annotation.namespaces());
+    return Set.of(annotation.map(Controller::namespaces).orElse(new String[] {}));
   }
 
   @Override
diff --git a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationService.java b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationService.java
index cadc69b701..73a232c45d 100644
--- a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationService.java
+++ b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationService.java
@@ -5,11 +5,16 @@
 import io.javaoperatorsdk.operator.api.config.AbstractConfigurationService;
 import io.javaoperatorsdk.operator.api.config.ConfigurationService;
 import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
+import io.javaoperatorsdk.operator.api.config.Utils;
 
 public class DefaultConfigurationService extends AbstractConfigurationService {
 
   private static final ConfigurationService instance = new DefaultConfigurationService();
 
+  private DefaultConfigurationService() {
+    super(Utils.loadFromProperties());
+  }
+
   public static ConfigurationService instance() {
     return instance;
   }
diff --git a/samples/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaController.java b/samples/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaController.java
index 26688ff520..4367333ed4 100644
--- a/samples/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaController.java
+++ b/samples/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/SchemaController.java
@@ -6,6 +6,7 @@
 import io.fabric8.kubernetes.api.model.SecretBuilder;
 import io.fabric8.kubernetes.client.KubernetesClient;
 import io.javaoperatorsdk.operator.api.Context;
+import io.javaoperatorsdk.operator.api.Controller;
 import io.javaoperatorsdk.operator.api.DeleteControl;
 import io.javaoperatorsdk.operator.api.ResourceController;
 import io.javaoperatorsdk.operator.api.UpdateControl;
@@ -20,6 +21,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@Controller
 public class SchemaController implements ResourceController<Schema> {
   static final String USERNAME_FORMAT = "%s-user";
   static final String SECRET_FORMAT = "%s-secret";
diff --git a/samples/quarkus/src/main/java/io/javaoperatorsdk/operator/sample/QuarkusOperator.java b/samples/quarkus/src/main/java/io/javaoperatorsdk/operator/sample/QuarkusOperator.java
index 1c0f01953b..9d56fd27ef 100644
--- a/samples/quarkus/src/main/java/io/javaoperatorsdk/operator/sample/QuarkusOperator.java
+++ b/samples/quarkus/src/main/java/io/javaoperatorsdk/operator/sample/QuarkusOperator.java
@@ -1,8 +1,6 @@
 package io.javaoperatorsdk.operator.sample;
 
-import io.fabric8.kubernetes.client.KubernetesClient;
 import io.javaoperatorsdk.operator.Operator;
-import io.javaoperatorsdk.operator.api.config.ConfigurationService;
 import io.quarkus.runtime.Quarkus;
 import io.quarkus.runtime.QuarkusApplication;
 import io.quarkus.runtime.annotations.QuarkusMain;
@@ -11,22 +9,15 @@
 @QuarkusMain
 public class QuarkusOperator implements QuarkusApplication {
 
-  @Inject KubernetesClient client;
-
   @Inject Operator operator;
 
-  @Inject ConfigurationService configuration;
-
-  @Inject CustomServiceController controller;
-
   public static void main(String... args) {
     Quarkus.run(QuarkusOperator.class, args);
   }
 
   @Override
   public int run(String... args) throws Exception {
-    final var config = configuration.getConfigurationFor(controller);
-    System.out.println("CR class: " + config.getCustomResourceClass());
+    operator.start();
     Quarkus.waitForExit();
     return 0;
   }
diff --git a/samples/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/TomcatController.java b/samples/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/TomcatController.java
index c2326e0b53..7fbf54109d 100644
--- a/samples/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/TomcatController.java
+++ b/samples/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/TomcatController.java
@@ -10,6 +10,7 @@
 import io.fabric8.kubernetes.client.dsl.ServiceResource;
 import io.fabric8.kubernetes.client.utils.Serialization;
 import io.javaoperatorsdk.operator.api.Context;
+import io.javaoperatorsdk.operator.api.Controller;
 import io.javaoperatorsdk.operator.api.DeleteControl;
 import io.javaoperatorsdk.operator.api.ResourceController;
 import io.javaoperatorsdk.operator.api.UpdateControl;
@@ -23,6 +24,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@Controller
 public class TomcatController implements ResourceController<Tomcat> {
 
   private final Logger log = LoggerFactory.getLogger(getClass());
diff --git a/samples/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/WebappController.java b/samples/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/WebappController.java
index de32c66fca..b2e4330d5b 100644
--- a/samples/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/WebappController.java
+++ b/samples/tomcat/src/main/java/io/javaoperatorsdk/operator/sample/WebappController.java
@@ -4,6 +4,7 @@
 import io.fabric8.kubernetes.api.model.apps.Deployment;
 import io.fabric8.kubernetes.client.KubernetesClient;
 import io.javaoperatorsdk.operator.api.Context;
+import io.javaoperatorsdk.operator.api.Controller;
 import io.javaoperatorsdk.operator.api.DeleteControl;
 import io.javaoperatorsdk.operator.api.ResourceController;
 import io.javaoperatorsdk.operator.api.UpdateControl;
@@ -15,6 +16,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@Controller
 public class WebappController implements ResourceController<Webapp> {
 
   private KubernetesClient kubernetesClient;