GERONIMO-6586 - Adding support for retry behavior.
diff --git a/pom.xml b/pom.xml
index 3c7f9a4..33c3da1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,14 +54,105 @@
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
         <microprofile-fault-tolerance.version>1.1-SNAPSHOT</microprofile-fault-tolerance.version>
-        <owb.version>1.7.4</owb.version>
-        <owb2.version>2.0.1</owb2.version>
+        <owb.version>2.0.1</owb.version>
         <arquillian.version>1.1.13.Final</arquillian.version>
         <arquillian-weld-embedded.version>2.0.0.Beta5</arquillian-weld-embedded.version>
         <cdi2-api.version>2.0</cdi2-api.version>
         <weld.version>3.0.1.Final</weld.version>
     </properties>
 
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.apache.geronimo.safeguard</groupId>
+                <artifactId>safeguard-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>net.jodah</groupId>
+                <artifactId>failsafe</artifactId>
+                <version>1.0.4</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.geronimo.specs</groupId>
+                <artifactId>geronimo-jcdi_2.0_spec</artifactId>
+                <version>1.0.1</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.geronimo.specs</groupId>
+                <artifactId>geronimo-annotation_1.3_spec</artifactId>
+                <version>1.0</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.geronimo.specs</groupId>
+                <artifactId>geronimo-atinject_1.0_spec</artifactId>
+                <version>1.0</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.microprofile.fault-tolerance</groupId>
+                <artifactId>microprofile-fault-tolerance-api</artifactId>
+                <version>1.0-SNAPSHOT</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.geronimo.specs</groupId>
+                <artifactId>geronimo-interceptor_1.2_spec</artifactId>
+                <version>1.0</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.geronimo.specs</groupId>
+                <artifactId>geronimo-el_2.2_spec</artifactId>
+                <version>1.0.2</version>
+                <scope>provided</scope>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.openwebbeans</groupId>
+                <artifactId>openwebbeans-spi</artifactId>
+                <version>${owb.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.openwebbeans</groupId>
+                <artifactId>openwebbeans-impl</artifactId>
+                <version>${owb.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.openwebbeans.arquillian</groupId>
+                <artifactId>owb-arquillian-standalone</artifactId>
+                <version>${owb.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.testng</groupId>
+                <artifactId>testng</artifactId>
+                <version>6.9.9</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.assertj</groupId>
+                <artifactId>assertj-core</artifactId>
+                <version>3.8.0</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.weld.se</groupId>
+                <artifactId>weld-se-shaded</artifactId>
+                <version>${weld.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.jboss.arquillian.container</groupId>
+                <artifactId>arquillian-weld-embedded</artifactId>
+                <version>${arquillian-weld-embedded.version}</version>
+                <scope>test</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
     <profiles>
         <profile>
             <id>eclipse-repo</id>
diff --git a/safeguard-api/pom.xml b/safeguard-api/pom.xml
index 7676c35..2f240f6 100644
--- a/safeguard-api/pom.xml
+++ b/safeguard-api/pom.xml
@@ -30,5 +30,18 @@
 
     <artifactId>safeguard-api</artifactId>
 
-
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-jcdi_2.0_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-interceptor_1.2_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.microprofile.fault-tolerance</groupId>
+            <artifactId>microprofile-fault-tolerance-api</artifactId>
+        </dependency>
+    </dependencies>
 </project>
\ No newline at end of file
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/SafeguardEnabled.java b/safeguard-api/src/main/java/org/apache/safeguard/api/SafeguardEnabled.java
new file mode 100644
index 0000000..4396a9b
--- /dev/null
+++ b/safeguard-api/src/main/java/org/apache/safeguard/api/SafeguardEnabled.java
@@ -0,0 +1,36 @@
+/*
+ *  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.safeguard.api;
+
+import javax.enterprise.util.AnnotationLiteral;
+import javax.interceptor.InterceptorBinding;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@InterceptorBinding
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface SafeguardEnabled {
+
+    SafeguardEnabled INSTANCE = new Literal();
+    class Literal extends AnnotationLiteral<SafeguardEnabled> implements SafeguardEnabled {}
+}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryBuilder.java b/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryBuilder.java
new file mode 100644
index 0000000..10228db
--- /dev/null
+++ b/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryBuilder.java
@@ -0,0 +1,34 @@
+/*
+ *  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.safeguard.api.retry;
+
+import java.time.Duration;
+
+public interface RetryBuilder {
+
+    RetryBuilder withMaxRetries(int maxRetries);
+    RetryBuilder withDelay(Duration delay);
+    RetryBuilder withMaxDuration(Duration maxDuration);
+    RetryBuilder withJitter(Duration jitter);
+    RetryBuilder withAbortOn(Class<? extends Throwable>... abortOn);
+    RetryBuilder withRetryOn(Class<? extends Throwable>... retryOn);
+
+    RetryDefinition build();
+}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryDefinition.java b/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryDefinition.java
new file mode 100644
index 0000000..1383e17
--- /dev/null
+++ b/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryDefinition.java
@@ -0,0 +1,39 @@
+/*
+ *  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.safeguard.api.retry;
+
+import java.time.Duration;
+import java.util.Collection;
+
+public interface RetryDefinition {
+
+    int getMaxRetries();
+
+    Duration getDelay();
+
+    Duration getMaxDuration();
+
+    Duration getJitter();
+
+    Collection<Class<? extends Throwable>> getRetryExceptions();
+
+    Collection<Class<? extends Throwable>> getAbortExceptions();
+
+}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryManager.java b/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryManager.java
new file mode 100644
index 0000000..054d8d8
--- /dev/null
+++ b/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryManager.java
@@ -0,0 +1,25 @@
+/*
+ *  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.safeguard.api.retry;
+
+public interface RetryManager {
+    RetryBuilder newRetryDefinition(String name);
+    RetryDefinition getRetryDefinition(String name);
+}
diff --git a/safeguard-impl/pom.xml b/safeguard-impl/pom.xml
index dbc12fa..a94eb64 100644
--- a/safeguard-impl/pom.xml
+++ b/safeguard-impl/pom.xml
@@ -30,5 +30,83 @@
 
     <artifactId>safeguard-impl</artifactId>
 
-
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.geronimo.safeguard</groupId>
+            <artifactId>safeguard-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.jodah</groupId>
+            <artifactId>failsafe</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.arquillian.testng</groupId>
+            <artifactId>arquillian-testng-container</artifactId>
+            <version>${arquillian.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-jcdi_2.0_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-atinject_1.0_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-annotation_1.3_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-interceptor_1.2_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+        </dependency>
+    </dependencies>
+    <profiles>
+        <profile>
+            <id>OWB2</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.apache.geronimo.specs</groupId>
+                    <artifactId>geronimo-el_2.2_spec</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.openwebbeans</groupId>
+                    <artifactId>openwebbeans-spi</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.openwebbeans</groupId>
+                    <artifactId>openwebbeans-impl</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.openwebbeans.arquillian</groupId>
+                    <artifactId>owb-arquillian-standalone</artifactId>
+                </dependency>
+            </dependencies>
+        </profile>
+        <profile>
+            <id>Weld3</id>
+            <dependencies>
+                <dependency>
+                    <groupId>org.jboss.weld.se</groupId>
+                    <artifactId>weld-se-shaded</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.jboss.arquillian.container</groupId>
+                    <artifactId>arquillian-weld-embedded</artifactId>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
 </project>
\ No newline at end of file
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/GuardedExecutions.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/GuardedExecutions.java
new file mode 100644
index 0000000..a1e9a40
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/GuardedExecutions.java
@@ -0,0 +1,82 @@
+/*
+ *  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.safeguard.impl;
+
+import net.jodah.failsafe.Failsafe;
+import org.apache.safeguard.impl.retry.FailsafeRetryBuilder;
+import org.apache.safeguard.impl.retry.FailsafeRetryDefinition;
+import org.apache.safeguard.impl.retry.FailsafeRetryManager;
+import org.apache.safeguard.impl.util.AnnotationUtil;
+import org.apache.safeguard.impl.util.NamingUtil;
+import org.eclipse.microprofile.faulttolerance.Retry;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.interceptor.InvocationContext;
+import java.lang.reflect.Method;
+import java.time.Duration;
+import java.util.concurrent.Callable;
+
+@ApplicationScoped
+public class GuardedExecutions {
+    private FailsafeRetryManager retryManager;
+
+    GuardedExecutions() {
+
+    }
+
+    @Inject
+    public GuardedExecutions(FailsafeRetryManager retryManager) {
+        this.retryManager = retryManager;
+    }
+
+    public Object execute(InvocationContext invocationContext) {
+        Method method = invocationContext.getMethod();
+        String name = NamingUtil.createName(method);
+        FailsafeRetryDefinition failsafeRetryDefinition = retryManager.getRetryDefinition(name);
+        if (failsafeRetryDefinition == null) {
+            failsafeRetryDefinition = createDefinition(name, method);
+        }
+        return Failsafe.with(failsafeRetryDefinition.getRetryPolicy()).get(invocationContext::proceed);
+    }
+
+    public <T> T execute(String name, Callable<T> callable) {
+        FailsafeRetryDefinition failsafeRetryDefinition = retryManager.getRetryDefinition(name);
+        return Failsafe.with(failsafeRetryDefinition.getRetryPolicy()).get(callable);
+    }
+
+    private FailsafeRetryDefinition createDefinition(String name, Method method) {
+        Retry retry = AnnotationUtil.getAnnotation(method, Retry.class);
+        FailsafeRetryBuilder retryBuilder = retryManager.newRetryDefinition(name)
+                .withMaxRetries(retry.maxRetries())
+                .withRetryOn(retry.retryOn())
+                .withAbortOn(retry.abortOn());
+        if (retry.delay() > 0L) {
+            retryBuilder.withDelay(Duration.of(retry.delay(), retry.delayUnit()));
+        }
+        if (retry.jitter() > 0L) {
+            retryBuilder.withJitter(Duration.of(retry.jitter(), retry.jitterDelayUnit()));
+        }
+        if(retry.maxDuration() > 0L) {
+            retryBuilder.withMaxDuration(Duration.of(retry.maxDuration(), retry.durationUnit()));
+        }
+        return retryBuilder.build();
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardExtension.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardExtension.java
new file mode 100644
index 0000000..318a6e6
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardExtension.java
@@ -0,0 +1,108 @@
+/*
+ *  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.safeguard.impl.cdi;
+
+import org.apache.safeguard.api.SafeguardEnabled;
+import org.eclipse.microprofile.faulttolerance.Retry;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AnnotatedConstructor;
+import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.enterprise.inject.spi.WithAnnotations;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static org.apache.safeguard.api.SafeguardEnabled.INSTANCE;
+
+public class SafeguardExtension implements Extension {
+    public void findFaultTolerantBeans(@Observes @WithAnnotations({Retry.class})
+                                               ProcessAnnotatedType<?> pat) {
+        if (!pat.getAnnotatedType().isAnnotationPresent(SafeguardEnabled.class)) {
+            pat.setAnnotatedType(new SafeguardAnnotatedTypeWrapper(pat.getAnnotatedType()));
+        }
+    }
+
+    private static class SafeguardAnnotatedTypeWrapper<X> implements AnnotatedType<X> {
+
+        private final AnnotatedType<X> delegate;
+        private final Set<Annotation> annotations;
+
+        private SafeguardAnnotatedTypeWrapper(AnnotatedType<X> delegate) {
+            this.delegate = delegate;
+            Set<Annotation> annotations = delegate.getAnnotations();
+            Set<Annotation> allAnotations = new LinkedHashSet<>();
+            allAnotations.add(INSTANCE);
+            allAnotations.addAll(annotations);
+            this.annotations = allAnotations;
+        }
+
+        @Override
+        public Class<X> getJavaClass() {
+            return delegate.getJavaClass();
+        }
+
+        @Override
+        public Set<AnnotatedConstructor<X>> getConstructors() {
+            return delegate.getConstructors();
+        }
+
+        @Override
+        public Set<AnnotatedMethod<? super X>> getMethods() {
+            return delegate.getMethods();
+        }
+
+        @Override
+        public Set<AnnotatedField<? super X>> getFields() {
+            return delegate.getFields();
+        }
+
+        @Override
+        public Type getBaseType() {
+            return delegate.getBaseType();
+        }
+
+        @Override
+        public Set<Type> getTypeClosure() {
+            return delegate.getTypeClosure();
+        }
+
+        @Override
+        public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
+            return SafeguardEnabled.class.equals(annotationType) ? (T) INSTANCE : delegate.getAnnotation(annotationType);
+        }
+
+        @Override
+        public Set<Annotation> getAnnotations() {
+            return Collections.unmodifiableSet(annotations);
+        }
+
+        @Override
+        public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
+            return SafeguardEnabled.class.equals(annotationType) || delegate.isAnnotationPresent(annotationType);
+        }
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardInterceptor.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardInterceptor.java
new file mode 100644
index 0000000..156f44d
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardInterceptor.java
@@ -0,0 +1,54 @@
+/*
+ *  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.safeguard.impl.cdi;
+
+import org.apache.safeguard.api.SafeguardEnabled;
+import org.apache.safeguard.impl.GuardedExecutions;
+import org.apache.safeguard.impl.util.AnnotationUtil;
+import org.eclipse.microprofile.faulttolerance.Retry;
+
+import javax.annotation.Priority;
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+import java.lang.reflect.Method;
+
+@Interceptor
+@SafeguardEnabled
+@Priority(400)
+public class SafeguardInterceptor {
+    @Inject
+    private GuardedExecutions guardedExecutions;
+
+    @AroundInvoke
+    public Object runSafeguards(InvocationContext invocationContext) throws Exception{
+        if(isMethodSafeguarded(invocationContext.getMethod())) {
+            return guardedExecutions.execute(invocationContext);
+        }
+        else {
+            return invocationContext.proceed();
+        }
+    }
+
+    private boolean isMethodSafeguarded(Method method) {
+        return AnnotationUtil.getAnnotation(method, Retry.class) != null;
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryBuilder.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryBuilder.java
new file mode 100644
index 0000000..2cf7f07
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryBuilder.java
@@ -0,0 +1,93 @@
+/*
+ *  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.safeguard.impl.retry;
+
+import net.jodah.failsafe.RetryPolicy;
+import org.apache.safeguard.api.retry.RetryBuilder;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+public class FailsafeRetryBuilder implements RetryBuilder{
+    private final List<Class<? extends Throwable>> retryOn;
+    private final List<Class<? extends Throwable>> abortOn;
+    private final RetryPolicy retryPolicy;
+    private final String name;
+    private final FailsafeRetryManager failsafeRetryManager;
+
+    FailsafeRetryBuilder(String name, FailsafeRetryManager failsafeRetryManager) {
+        this.name = name;
+        this.failsafeRetryManager = failsafeRetryManager;
+        this.retryOn = new ArrayList<>();
+        this.abortOn = new ArrayList<>();
+        this.retryPolicy = new RetryPolicy();
+    }
+    @Override
+    public FailsafeRetryBuilder withMaxRetries(int maxRetries) {
+        retryPolicy.withMaxRetries(maxRetries);
+        return this;
+    }
+
+    @Override
+    public FailsafeRetryBuilder withDelay(Duration delay) {
+        retryPolicy.withDelay(delay.toMillis(), TimeUnit.MILLISECONDS);
+        return this;
+    }
+
+    @Override
+    public FailsafeRetryBuilder withMaxDuration(Duration maxDuration) {
+        retryPolicy.withMaxDuration(maxDuration.toMillis(), TimeUnit.MILLISECONDS);
+        return this;
+    }
+
+    @Override
+    public FailsafeRetryBuilder withJitter(Duration jitter) {
+        retryPolicy.withJitter(jitter.toMillis(), TimeUnit.MILLISECONDS);
+        return this;
+    }
+
+    @Override
+    public FailsafeRetryBuilder withAbortOn(Class<? extends Throwable>... abortOn) {
+        this.abortOn.addAll(Arrays.asList(abortOn));
+        return this;
+    }
+
+    @Override
+    public FailsafeRetryBuilder withRetryOn(Class<? extends Throwable>... retryOn) {
+        this.retryOn.addAll(Arrays.asList(retryOn));
+        return this;
+    }
+
+    @Override
+    public FailsafeRetryDefinition build() {
+        if(!this.abortOn.isEmpty()) {
+            retryPolicy.abortOn(this.abortOn);
+        }
+        if(!this.retryOn.isEmpty()) {
+            retryPolicy.retryOn(this.retryOn);
+        }
+        FailsafeRetryDefinition definition = new FailsafeRetryDefinition(retryPolicy, retryOn, abortOn);
+        failsafeRetryManager.register(name, definition);
+        return definition;
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryDefinition.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryDefinition.java
new file mode 100644
index 0000000..916f204
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryDefinition.java
@@ -0,0 +1,75 @@
+/*
+ *  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.safeguard.impl.retry;
+
+import net.jodah.failsafe.RetryPolicy;
+import org.apache.safeguard.api.retry.RetryDefinition;
+
+import java.time.Duration;
+import java.util.Collection;
+
+public class FailsafeRetryDefinition implements RetryDefinition{
+    private final RetryPolicy retryPolicy;
+    private final Collection<Class<? extends Throwable>> retryExceptions;
+    private final Collection<Class<? extends Throwable>> abortExceptions;
+
+    FailsafeRetryDefinition(RetryPolicy retryPolicy, Collection<Class<? extends Throwable>> retryExceptions, Collection<Class<? extends Throwable>> abortExceptions) {
+        this.retryPolicy = retryPolicy;
+        this.retryExceptions = retryExceptions;
+        this.abortExceptions = abortExceptions;
+    }
+
+    @Override
+    public int getMaxRetries() {
+        return retryPolicy.getMaxRetries();
+    }
+
+    @Override
+    public Duration getDelay() {
+        net.jodah.failsafe.util.Duration delay = retryPolicy.getDelay();
+        return Duration.ofMillis(delay.toMillis());
+    }
+
+    @Override
+    public Duration getMaxDuration() {
+        net.jodah.failsafe.util.Duration maxDuration = retryPolicy.getMaxDuration();
+        return Duration.ofMillis(maxDuration.toMillis());
+    }
+
+    @Override
+    public Duration getJitter() {
+        net.jodah.failsafe.util.Duration jitter = retryPolicy.getJitter();
+        return Duration.ofMillis(jitter.toMillis());
+    }
+
+    @Override
+    public Collection<Class<? extends Throwable>> getRetryExceptions() {
+        return this.retryExceptions;
+    }
+
+    @Override
+    public Collection<Class<? extends Throwable>> getAbortExceptions() {
+        return abortExceptions;
+    }
+
+    public RetryPolicy getRetryPolicy() {
+        return retryPolicy;
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryManager.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryManager.java
new file mode 100644
index 0000000..6d1e71f
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryManager.java
@@ -0,0 +1,51 @@
+/*
+ *  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.safeguard.impl.retry;
+
+import org.apache.safeguard.api.retry.RetryManager;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import java.util.HashMap;
+import java.util.Map;
+
+@ApplicationScoped
+public class FailsafeRetryManager implements RetryManager{
+    private Map<String, FailsafeRetryDefinition> retries;
+
+    @PostConstruct
+    public void init() {
+        retries = new HashMap<>();
+    }
+
+    @Override
+    public FailsafeRetryBuilder newRetryDefinition(String name) {
+        return new FailsafeRetryBuilder(name, this);
+    }
+
+    @Override
+    public FailsafeRetryDefinition getRetryDefinition(String name) {
+        return retries.get(name);
+    }
+
+    void register(String name, FailsafeRetryDefinition failsafeRetryDefinition) {
+        this.retries.put(name, failsafeRetryDefinition);
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/AnnotationUtil.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/AnnotationUtil.java
new file mode 100644
index 0000000..18bacf6
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/AnnotationUtil.java
@@ -0,0 +1,38 @@
+/*
+ *  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.safeguard.impl.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+public final class AnnotationUtil {
+    private AnnotationUtil() {
+
+    }
+    public static <T extends Annotation> T getAnnotation(Method method, Class<T> clazz) {
+        T annotation = method.getAnnotation(clazz);
+        if (annotation != null) {
+            return annotation;
+        }
+        else {
+            return method.getDeclaringClass().getAnnotation(clazz);
+        }
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/NamingUtil.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/NamingUtil.java
new file mode 100644
index 0000000..a48a6d7
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/NamingUtil.java
@@ -0,0 +1,32 @@
+/*
+ *  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.safeguard.impl.util;
+
+import java.lang.reflect.Method;
+
+public final class NamingUtil {
+    private NamingUtil() {
+
+    }
+
+    public static String createName(Method method) {
+        return method.getDeclaringClass().getCanonicalName()+"."+method.getName()+"."+method.getParameters();
+    }
+}
diff --git a/safeguard-impl/src/main/resources/META-INF/beans.xml b/safeguard-impl/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..a130381
--- /dev/null
+++ b/safeguard-impl/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,19 @@
+<!--
+  ~  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.
+  -->
+<beans version="1.1" bean-discovery-mode="annotated"/>
diff --git a/safeguard-impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/safeguard-impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
new file mode 100644
index 0000000..0eae66c
--- /dev/null
+++ b/safeguard-impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -0,0 +1 @@
+org.apache.safeguard.impl.cdi.SafeguardExtension
\ No newline at end of file
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/CDIRetryBean.java b/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/CDIRetryBean.java
new file mode 100644
index 0000000..3d69ab0
--- /dev/null
+++ b/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/CDIRetryBean.java
@@ -0,0 +1,41 @@
+/*
+ *  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.safeguard.retry.test;
+
+import org.eclipse.microprofile.faulttolerance.Retry;
+
+import javax.enterprise.context.ApplicationScoped;
+
+@ApplicationScoped
+public class CDIRetryBean {
+    private int calls = 0;
+    @Retry
+    public String doCall() {
+        calls++;
+        if(calls <= 2) {
+            throw new RuntimeException();
+        }
+        return "retried";
+    }
+
+    public int getCalls() {
+        return calls;
+    }
+}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/CDIRetryTest.java b/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/CDIRetryTest.java
new file mode 100644
index 0000000..35586ce
--- /dev/null
+++ b/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/CDIRetryTest.java
@@ -0,0 +1,58 @@
+/*
+ *  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.safeguard.retry.test;
+
+import org.apache.safeguard.impl.GuardedExecutions;
+import org.apache.safeguard.impl.cdi.SafeguardExtension;
+import org.apache.safeguard.impl.cdi.SafeguardInterceptor;
+import org.apache.safeguard.impl.retry.FailsafeRetryManager;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.testng.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.testng.annotations.Test;
+
+import javax.enterprise.inject.spi.Extension;
+import javax.inject.Inject;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CDIRetryTest extends Arquillian{
+    @Deployment
+    public static Archive<?> create() {
+        return ShrinkWrap.create(JavaArchive.class)
+                .addClasses(GuardedExecutions.class, FailsafeRetryManager.class,
+                        SafeguardInterceptor.class, CDIRetryBean.class)
+                .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
+                .addAsServiceProviderAndClasses(Extension.class, SafeguardExtension.class);
+    }
+
+    @Inject
+    private CDIRetryBean cdiRetryBean;
+
+    @Test
+    public void shouldExecuteThreeTimesWithAnnotations() {
+        cdiRetryBean.doCall();
+
+        assertThat(cdiRetryBean.getCalls()).isEqualTo(3);
+    }
+}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/RetryBean.java b/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/RetryBean.java
new file mode 100644
index 0000000..fcadf03
--- /dev/null
+++ b/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/RetryBean.java
@@ -0,0 +1,38 @@
+/*
+ *  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.safeguard.retry.test;
+
+import java.util.concurrent.Callable;
+
+public class RetryBean implements Callable<String> {
+    private int calls = 0;
+    @Override
+    public String call() throws Exception {
+        calls++;
+        if(calls <= 2) {
+            throw new RuntimeException();
+        }
+        return "called";
+    }
+
+    public int getCalls() {
+        return calls;
+    }
+}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/RetryTest.java b/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/RetryTest.java
new file mode 100644
index 0000000..7696534
--- /dev/null
+++ b/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/RetryTest.java
@@ -0,0 +1,53 @@
+/*
+ *  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.safeguard.retry.test;
+
+import org.apache.safeguard.impl.GuardedExecutions;
+import org.apache.safeguard.impl.retry.FailsafeRetryManager;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RetryTest {
+    private GuardedExecutions guardedExecutions;
+    private static final String name = "GUARDED_RETRIES";
+    private FailsafeRetryManager retryManager;
+
+    @BeforeTest
+    public void setupForTest() {
+        this.retryManager = new FailsafeRetryManager();
+        retryManager.init();
+        guardedExecutions = new GuardedExecutions(retryManager);
+    }
+
+    @Test
+    public void testRetryWithManualBuild() {
+        int expectedCalls = 3;
+        retryManager.newRetryDefinition(name)
+                .withMaxRetries(expectedCalls)
+                .build();
+        RetryBean retryBean = new RetryBean();
+
+        guardedExecutions.execute(name, retryBean);
+
+        assertThat(retryBean.getCalls()).isEqualTo(expectedCalls);
+    }
+}