make gauge injection working
diff --git a/pom.xml b/pom.xml
index 6bb13ee..0f3cefc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -168,6 +168,10 @@
         <artifactId>maven-surefire-plugin</artifactId>
         <version>2.21.0</version>
         <configuration>
+          <!-- current setup has some leakage it seems
+          <forkCount>1</forkCount>
+          <reuseForks>false</reuseForks>
+          -->
           <dependenciesToScan>
             <dependency>org.eclipse.microprofile.metrics:microprofile-metrics-api-tck</dependency>
             <dependency>org.eclipse.microprofile.metrics:microprofile-metrics-rest-tck</dependency>
diff --git a/src/main/java/org/apache/geronimo/microprofile/metrics/cdi/MetricsExtension.java b/src/main/java/org/apache/geronimo/microprofile/metrics/cdi/MetricsExtension.java
index f5d0fee..87fbb43 100644
--- a/src/main/java/org/apache/geronimo/microprofile/metrics/cdi/MetricsExtension.java
+++ b/src/main/java/org/apache/geronimo/microprofile/metrics/cdi/MetricsExtension.java
@@ -13,6 +13,8 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Function;
 import java.util.stream.Stream;
 
@@ -38,6 +40,7 @@
 import javax.enterprise.util.AnnotationLiteral;
 import javax.enterprise.util.Nonbinding;
 
+import org.apache.geronimo.microprofile.metrics.impl.GaugeImpl;
 import org.apache.geronimo.microprofile.metrics.impl.RegistryImpl;
 import org.eclipse.microprofile.metrics.Counter;
 import org.eclipse.microprofile.metrics.Gauge;
@@ -58,17 +61,17 @@
     private final MetricRegistry vendorRegistry = new RegistryImpl();
 
     private final Map<String, Metadata> registrations = new HashMap<>();
-    private final Map<String, Function<BeanManager, Gauge<?>>> gauges = new HashMap<>();
+    private final Map<String, Function<BeanManager, Gauge<?>>> gaugeFactories = new HashMap<>();
     private final Collection<CreationalContext<?>> creationalContexts = new ArrayList<>();
 
-    void letOtherExtensionUseRegistries(@Observes final BeforeBeanDiscovery beforeBeanDiscovery, final BeanManager beanManager) {
+    void letOtherExtensionsUseRegistries(@Observes final BeforeBeanDiscovery beforeBeanDiscovery, final BeanManager beanManager) {
         beforeBeanDiscovery.addQualifier(RegistryType.class);
         beanManager.fireEvent(applicationRegistry);
         beanManager.fireEvent(applicationRegistry, new RegistryTypeImpl(MetricRegistry.Type.APPLICATION));
         beanManager.fireEvent(baseRegistry, new RegistryTypeImpl(MetricRegistry.Type.BASE));
         beanManager.fireEvent(vendorRegistry, new RegistryTypeImpl(MetricRegistry.Type.VENDOR));
 
-        // we make @Metric(name) binding
+        // we make @Metric.name binding (to avoid to write producers relying on injection point)
         beforeBeanDiscovery.configureQualifier(org.eclipse.microprofile.metrics.annotation.Metric.class)
                 .methods().stream().filter(method -> method.getAnnotated().getJavaMember().getName().equals("name"))
                 .forEach(method -> method.remove(a -> a.annotationType() == Nonbinding.class));
@@ -181,19 +184,12 @@
                     final Metadata metadata = new Metadata(name, gauge.displayName(), gauge.description(), MetricType.GAUGE, gauge.unit());
                     Stream.of(gauge.tags()).forEach(metadata::addTag);
                     addRegistration(method, name, metadata, false, gauge.tags());
-                    gauges.put(name, beanManager -> {
+                    gaugeFactories.put(name, beanManager -> {
                         final CreationalContext<Object> creationalContext = beanManager.createCreationalContext(null);
                         final Bean<?> bean = beanManager.resolve(beanManager.getBeans(javaClass, Default.Literal.INSTANCE));
                         final Object reference = beanManager.getReference(bean, javaClass, creationalContext);
-                        final Gauge<?> instance = () -> {
-                            try {
-                                return Method.class.cast(javaMember).invoke(reference);
-                            } catch (final IllegalAccessException e) {
-                                throw new IllegalStateException(e);
-                            } catch (final InvocationTargetException e) {
-                                throw new IllegalStateException(e.getCause());
-                            }
-                        };
+                        final Method mtd = Method.class.cast(javaMember);
+                        final Gauge<?> instance = new GaugeImpl<>(reference, mtd);
                         if (!beanManager.isNormalScope(bean.getScope())) {
                             creationalContexts.add(creationalContext);
                         }
@@ -203,7 +199,7 @@
             });
     }
 
-    void afterBeanDiscovery(@Observes final AfterBeanDiscovery afterBeanDiscovery) {
+    void afterBeanDiscovery(@Observes final AfterBeanDiscovery afterBeanDiscovery, final BeanManager beanManager) {
         addBean(afterBeanDiscovery, MetricRegistry.Type.APPLICATION.name() + "_@Default", MetricRegistry.class, Default.Literal.INSTANCE, applicationRegistry);
         addBean(afterBeanDiscovery, MetricRegistry.Type.APPLICATION.name(), MetricRegistry.class, new RegistryTypeImpl(MetricRegistry.Type.APPLICATION), applicationRegistry);
         addBean(afterBeanDiscovery, MetricRegistry.Type.BASE.name(), MetricRegistry.class, new RegistryTypeImpl(MetricRegistry.Type.BASE), baseRegistry);
@@ -212,6 +208,20 @@
         // metrics
         registrations.forEach((name, registration) -> {
             switch (registration.getTypeRaw()) {
+                case GAUGE:
+                    addBean(afterBeanDiscovery, name, Gauge.class, new MetricImpl(registration), new Gauge<Object>() {
+                        private final AtomicReference<Gauge<?>> ref = new AtomicReference<>();
+                        @Override
+                        public Object getValue() {
+                            Gauge<?> gauge = ref.get();
+                            if (gauge == null) { // getGauges() is expensive in current form, avoid it
+                                gauge = applicationRegistry.getGauges().get(name);
+                                ref.compareAndSet(null, gauge);
+                            }
+                            return gauge.getValue();
+                        }
+                    });
+                    break;
                 case TIMER:
                     addBean(afterBeanDiscovery, name, Timer.class, new MetricImpl(registration), applicationRegistry.timer(registration));
                     break;
@@ -232,9 +242,12 @@
     void afterDeploymentValidation(@Observes final AfterDeploymentValidation afterDeploymentValidation,
                                    final BeanManager beanManager) {
         registrations.values().stream().filter(m -> m.getTypeRaw() == MetricType.GAUGE)
-                .forEach(registration -> applicationRegistry.register(registration, gauges.get(registration.getName()).apply(beanManager)));
+                .forEach(registration -> {
+                    final Gauge<?> gauge = gaugeFactories.get(registration.getName()).apply(beanManager);
+                    applicationRegistry.register(registration, gauge);
+                });
 
-        gauges.clear();
+        gaugeFactories.clear();
         registrations.clear();
     }
 
diff --git a/src/main/java/org/apache/geronimo/microprofile/metrics/impl/GaugeImpl.java b/src/main/java/org/apache/geronimo/microprofile/metrics/impl/GaugeImpl.java
new file mode 100644
index 0000000..f6f31a6
--- /dev/null
+++ b/src/main/java/org/apache/geronimo/microprofile/metrics/impl/GaugeImpl.java
@@ -0,0 +1,27 @@
+package org.apache.geronimo.microprofile.metrics.impl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.eclipse.microprofile.metrics.Gauge;
+
+public class GaugeImpl<T> implements Gauge<T> {
+    private final Method method;
+    private final Object reference;
+
+    public GaugeImpl(final Object reference, final Method method) {
+        this.method = method;
+        this.reference = reference;
+    }
+
+    @Override
+    public T getValue() {
+        try {
+            return (T) method.invoke(reference);
+        } catch (final IllegalAccessException e) {
+            throw new IllegalStateException(e);
+        } catch (final InvocationTargetException e) {
+            throw new IllegalStateException(e.getCause());
+        }
+    }
+}
diff --git a/src/test/java/org/apache/geronimo/microprofile/metrics/test/ArquillianSetup.java b/src/test/java/org/apache/geronimo/microprofile/metrics/test/ArquillianSetup.java
index e8ccd1f..d11893f 100644
--- a/src/test/java/org/apache/geronimo/microprofile/metrics/test/ArquillianSetup.java
+++ b/src/test/java/org/apache/geronimo/microprofile/metrics/test/ArquillianSetup.java
@@ -2,18 +2,17 @@
 
 import java.lang.reflect.Field;
 
-import javax.enterprise.context.spi.CreationalContext;
-import javax.enterprise.inject.spi.AnnotatedType;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.inject.spi.CDI;
-import javax.enterprise.inject.spi.InjectionTarget;
 
 import org.apache.catalina.Context;
 import org.apache.meecrowave.Meecrowave;
 import org.apache.meecrowave.arquillian.MeecrowaveContainer;
 import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
+import org.jboss.arquillian.container.spi.context.annotation.ContainerScoped;
 import org.jboss.arquillian.container.spi.context.annotation.DeploymentScoped;
 import org.jboss.arquillian.container.spi.event.container.AfterDeploy;
+import org.jboss.arquillian.container.spi.event.container.AfterStart;
 import org.jboss.arquillian.container.spi.event.container.BeforeUnDeploy;
 import org.jboss.arquillian.container.test.impl.client.protocol.local.LocalProtocol;
 import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor;
@@ -49,43 +48,38 @@
         private InstanceProducer<ClassLoader> appClassLoaderInstanceProducer;
 
         @Inject
-        @DeploymentScoped
-        private InstanceProducer<ClassLoader> testClassLoaderInstanceProducer;
+        @ContainerScoped
+        private InstanceProducer<Meecrowave> container;
+
+        public void onDeploy(@Observes final AfterStart afterStart) throws Exception {
+            final DeployableContainer<?> deployableContainer = afterStart.getDeployableContainer();
+            final Field container = MeecrowaveContainer.class.getDeclaredField("container");
+            container.setAccessible(true);
+            final Meecrowave meecrowave = Meecrowave.class.cast(container.get(deployableContainer));
+            this.container.set(meecrowave);
+        }
 
         public void onDeploy(@Observes final AfterDeploy afterDeploy) {
-            final DeployableContainer<?> deployableContainer = afterDeploy.getDeployableContainer();
-            try {
-                final Field container = MeecrowaveContainer.class.getDeclaredField("container");
-                container.setAccessible(true);
-                final Meecrowave meecrowave = Meecrowave.class.cast(container.get(deployableContainer));
-                final ClassLoader appLoader = Context.class.cast(meecrowave.getTomcat().getHost().findChildren()[0]).getLoader().getClassLoader();
-                final Thread thread = Thread.currentThread();
-                appClassLoaderInstanceProducer.set(appLoader);
-                testClassLoaderInstanceProducer.set(meecrowave.getTomcat().getServer().getParentClassLoader());
-                thread.setContextClassLoader(appLoader);
-                beanManagerInstanceProducer.set(CDI.current().getBeanManager());
-            } catch (final Exception e) {
-                // no-op, will not happen and if so it is another container
-            }
+            final Meecrowave meecrowave = container.get();
+            final ClassLoader appLoader = Context.class.cast(meecrowave.getTomcat().getHost().findChildren()[0]).getLoader().getClassLoader();
+            appClassLoaderInstanceProducer.set(appLoader);
+
+            final Thread thread = Thread.currentThread();
+            thread.setContextClassLoader(appLoader);
+            beanManagerInstanceProducer.set(CDI.current().getBeanManager());
         }
 
         public void onUndeploy(@Observes final BeforeUnDeploy beforeUnDeploy) {
-            final ClassLoader cl = testClassLoaderInstanceProducer.get();
+            final ClassLoader cl = container.get().getTomcat().getServer().getParentClassLoader();
             Thread.currentThread().setContextClassLoader(cl);
         }
 
-        public void enrich(@Observes final Before before) {
+        public void enrich(@Observes final Before before) throws Exception {
             final Thread thread = Thread.currentThread();
             final ClassLoader classLoader = thread.getContextClassLoader();
             thread.setContextClassLoader(appClassLoaderInstanceProducer.get());
             try {
-                final BeanManager beanManager = beanManagerInstanceProducer.get();
-                final Object testInstance = before.getTestInstance();
-                final AnnotatedType<?> annotatedType = beanManager.createAnnotatedType(before.getTestClass().getJavaClass());
-                final InjectionTarget injectionTarget = beanManager.createInjectionTarget(annotatedType);
-                final CreationalContext<?> creationalContext = beanManager.createCreationalContext(null);
-                injectionTarget.inject(testInstance, creationalContext);
-                creationalContext.release();
+                container.get().inject(before.getTestInstance()).close();
             } finally {
                 thread.setContextClassLoader(classLoader);
             }