Repository: quarkusio/quarkus
Issue: Incorrect behaviour for @ApplicationScoped lifecycle events

To `application-lifecycle-events/src/main/java/org/acme/events/AppLifecycleBean.java` add methods
```
    public void init (@Observes @Initialized(ApplicationScoped.class) Object init) {
        LOGGER.info("Init");
    }

    public void shutdown(@Observes @Destroyed(ApplicationScoped.class) Object init) {
        LOGGER.info("Shutdown");
    }
```

The result of quickstart is
```
2019-03-12 15:31:42,224 INFO  [ListenerBean] (main) Shutdown
2019-03-12 15:31:42,224 INFO  [ListenerBean] (main) Init
2019-03-12 15:31:42,368 INFO  [ListenerBean] (main) Shutdown
2019-03-12 15:31:42,368 INFO  [ListenerBean] (main) Init
2019-03-12 15:31:42,369 INFO  [ListenerBean] (main) The application is starting...hello
```
Please note that both shutdown and init methods were called multiple times and shutdown was call even before the application was started.

Changed files:
extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcAnnotationProcessor.java
independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java
independent-projects/arc/runtime/src/main/java/io/quarkus/arc/ArcContainerImpl.java
independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/contexts/application/ApplicationInitializedTest.java
independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/producer/disposer/DisposerTest.java

diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcAnnotationProcessor.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcAnnotationProcessor.java
index b490d49e5d6..e19e0b1d5d7 100644
--- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcAnnotationProcessor.java
+++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ArcAnnotationProcessor.java
@@ -27,7 +27,6 @@
 import java.util.stream.Collectors;
 
 import javax.enterprise.context.Dependent;
-import javax.enterprise.event.Observes;
 import javax.inject.Inject;
 
 import org.jboss.jandex.AnnotationTarget;
@@ -131,8 +130,6 @@ public BeanContainerBuildItem build(ArcDeploymentTemplate arcTemplate,
         }
         additionalBeans.add(LifecycleEventRunner.class.getName());
 
-        reflectiveClass.produce(new ReflectiveClassBuildItem(true, false, Observes.class.getName())); // graal bug
-
         // Index bean classes registered by quarkus
         Indexer indexer = new Indexer();
         Set<DotName> additionalIndex = new HashSet<>();
diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java
index 14d907574ae..297992939c6 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java
@@ -33,6 +33,9 @@
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
+import javax.enterprise.context.BeforeDestroyed;
+import javax.enterprise.context.Destroyed;
+import javax.enterprise.context.Initialized;
 import javax.enterprise.context.control.ActivateRequestContext;
 import javax.enterprise.inject.Any;
 import javax.enterprise.inject.Default;
@@ -240,6 +243,9 @@ private static IndexView addBuiltinClasses(IndexView index) {
             index(indexer, Default.class.getName());
             index(indexer, Any.class.getName());
             index(indexer, Named.class.getName());
+            index(indexer, Initialized.class.getName());
+            index(indexer, BeforeDestroyed.class.getName());
+            index(indexer, Destroyed.class.getName());
         }
         return CompositeIndex.create(index, indexer.complete());
     }
diff --git a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/ArcContainerImpl.java b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/ArcContainerImpl.java
index 1a71dc2cf82..b0e4717f403 100644
--- a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/ArcContainerImpl.java
+++ b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/ArcContainerImpl.java
@@ -33,7 +33,9 @@
 import java.util.stream.Collectors;
 
 import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.BeforeDestroyed;
 import javax.enterprise.context.Dependent;
+import javax.enterprise.context.Destroyed;
 import javax.enterprise.context.Initialized;
 import javax.enterprise.inject.AmbiguousResolutionException;
 import javax.enterprise.inject.Any;
@@ -247,8 +249,18 @@ synchronized void shutdown() {
                 ArcCDI arcCdi = (ArcCDI) cdi;
                 arcCdi.destroy();
             }
+            // Fire an event with qualifier @BeforeDestroyed(ApplicationScoped.class)
+            Set<Annotation> beforeDestroyQualifiers = new HashSet<>(4);
+            beforeDestroyQualifiers.add(BeforeDestroyed.Literal.APPLICATION);
+            beforeDestroyQualifiers.add(Any.Literal.INSTANCE);
+            EventImpl.createNotifier(Object.class, Object.class, beforeDestroyQualifiers, this).notify(toString());
             // Destroy contexts
             applicationContext.destroy();
+            // Fire an event with qualifier @Destroyed(ApplicationScoped.class)
+            Set<Annotation> destroyQualifiers = new HashSet<>(4);
+            destroyQualifiers.add(Destroyed.Literal.APPLICATION);
+            destroyQualifiers.add(Any.Literal.INSTANCE);
+            EventImpl.createNotifier(Object.class, Object.class, destroyQualifiers, this).notify(toString());
             singletonContext.destroy();
             requestContext.terminate();
             // Clear caches
diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/contexts/application/ApplicationInitializedTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/contexts/application/ApplicationInitializedTest.java
index 3cd9578e4f6..00a8fd80fe9 100644
--- a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/contexts/application/ApplicationInitializedTest.java
+++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/contexts/application/ApplicationInitializedTest.java
@@ -16,35 +16,67 @@
 
 package io.quarkus.arc.test.contexts.application;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.BeforeDestroyed;
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.Destroyed;
 import javax.enterprise.context.Initialized;
 import javax.enterprise.event.Observes;
-import javax.inject.Singleton;
 
-import io.quarkus.arc.test.ArcTestContainer;
 import org.junit.Assert;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import io.quarkus.arc.test.ArcTestContainer;
 
 public class ApplicationInitializedTest {
 
     @Rule
-    public ArcTestContainer container = new ArcTestContainer(Observer.class);
+    public RuleChain chain = RuleChain.outerRule(new TestRule() {
+        @Override
+        public Statement apply(final Statement base, Description description) {
+            return new Statement() {
+
+                @Override
+                public void evaluate() throws Throwable {
+                    base.evaluate();
+                    assertTrue(Observer.DESTROYED.get());
+                    assertTrue(Observer.BEFORE_DESTROYED.get());
+                }
+            };
+        }
+    }).around(new ArcTestContainer(Observer.class));
 
     @Test
     public void testEventWasFired() {
-        Assert.assertTrue(Observer.OBSERVED.get());
+        Assert.assertTrue(Observer.INITIALIZED.get());
     }
 
-    @Singleton
+    @Dependent
     static class Observer {
 
-        static final AtomicBoolean OBSERVED = new AtomicBoolean(false);
+        static final AtomicBoolean INITIALIZED = new AtomicBoolean(false);
+        static final AtomicBoolean DESTROYED = new AtomicBoolean(false);
+        static final AtomicBoolean BEFORE_DESTROYED = new AtomicBoolean(false);
 
         void onStart(@Observes @Initialized(ApplicationScoped.class) Object container) {
-            OBSERVED.set(true);
+            INITIALIZED.set(true);
+        }
+
+        void beforeDestroyed(@Observes @BeforeDestroyed(ApplicationScoped.class) Object container) {
+            BEFORE_DESTROYED.set(true);
+        }
+
+        void destroyed(@Observes @Destroyed(ApplicationScoped.class) Object container) {
+            DESTROYED.set(true);
         }
 
     }
diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/producer/disposer/DisposerTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/producer/disposer/DisposerTest.java
index 59131555e7a..5d59dad5298 100644
--- a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/producer/disposer/DisposerTest.java
+++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/producer/disposer/DisposerTest.java
@@ -71,6 +71,7 @@ public void testDisposers() {
         // A new instance is created for produce and dispose
         assertEquals(2, StringProducer.DESTROYED.get());
         // Both producer and produced bean are application scoped
+        @SuppressWarnings("serial")
         Comparable<BigDecimal> bigDecimal = Arc.container().instance(new TypeLiteral<Comparable<BigDecimal>>() {
         }).get();
         assertEquals(0, bigDecimal.compareTo(BigDecimal.ONE));