You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jo...@apache.org on 2017/12/27 01:14:27 UTC
geronimo-safeguard git commit: GERONIMO-6582 Adding validation of
method signatures via MicroProfile.
Repository: geronimo-safeguard
Updated Branches:
refs/heads/master 5b7ccac68 -> 27626ffdf
GERONIMO-6582 Adding validation of method signatures via MicroProfile.
Upgrading test dependencies.
Project: http://git-wip-us.apache.org/repos/asf/geronimo-safeguard/repo
Commit: http://git-wip-us.apache.org/repos/asf/geronimo-safeguard/commit/27626ffd
Tree: http://git-wip-us.apache.org/repos/asf/geronimo-safeguard/tree/27626ffd
Diff: http://git-wip-us.apache.org/repos/asf/geronimo-safeguard/diff/27626ffd
Branch: refs/heads/master
Commit: 27626ffdfed0f609294b95d790e767e0a1f10daa
Parents: 5b7ccac
Author: John D. Ament <jo...@apache.org>
Authored: Sun Dec 24 21:44:09 2017 -0500
Committer: John D. Ament <jo...@apache.org>
Committed: Tue Dec 26 20:10:12 2017 -0500
----------------------------------------------------------------------
pom.xml | 4 +-
.../impl/cdi/MicroProfileValidator.java | 143 +++++++++++++++++++
.../safeguard/impl/cdi/SafeguardExtension.java | 14 +-
.../MicroprofileAnnotationMapper.java | 3 +
.../safeguard/impl/util/AnnotationUtil.java | 12 ++
safeguard-tck-tests/pom.xml | 17 ---
6 files changed, 170 insertions(+), 23 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/geronimo-safeguard/blob/27626ffd/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index a3f1561..816ee06 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,8 +55,8 @@
<maven.compiler.target>1.8</maven.compiler.target>
<microprofile-fault-tolerance.version>1.0</microprofile-fault-tolerance.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>
+ <arquillian.version>1.1.14.Final</arquillian.version>
+ <arquillian-weld-embedded.version>2.0.0.Final</arquillian-weld-embedded.version>
<cdi2-api.version>2.0</cdi2-api.version>
<weld.version>3.0.1.Final</weld.version>
</properties>
http://git-wip-us.apache.org/repos/asf/geronimo-safeguard/blob/27626ffd/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/MicroProfileValidator.java
----------------------------------------------------------------------
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/MicroProfileValidator.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/MicroProfileValidator.java
new file mode 100644
index 0000000..714818b
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/MicroProfileValidator.java
@@ -0,0 +1,143 @@
+/*
+ * 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.exception.SafeguardException;
+import org.apache.safeguard.impl.util.AnnotationUtil;
+import org.eclipse.microprofile.faulttolerance.Bulkhead;
+import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
+import org.eclipse.microprofile.faulttolerance.ExecutionContext;
+import org.eclipse.microprofile.faulttolerance.Fallback;
+import org.eclipse.microprofile.faulttolerance.Retry;
+import org.eclipse.microprofile.faulttolerance.Timeout;
+
+import javax.enterprise.inject.Vetoed;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedType;
+import java.lang.reflect.Method;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Consumer;
+
+@Vetoed
+final class MicroProfileValidator {
+ private List<Throwable> capturedThrowables = new ArrayList<>();
+
+ void parse(AnnotatedType<?> annotatedType) {
+ for(AnnotatedMethod<?> method : annotatedType.getMethods()) {
+ Retry retry = AnnotationUtil.getAnnotation(method, annotatedType, Retry.class);
+ if (retry != null) {
+ validateRetry(retry, method);
+ }
+ Bulkhead bulkhead = AnnotationUtil.getAnnotation(method, annotatedType, Bulkhead.class);
+ if (bulkhead != null) {
+ validateBulkhead(bulkhead, method);
+ }
+ Timeout timeout = AnnotationUtil.getAnnotation(method, annotatedType, Timeout.class);
+ if (timeout != null) {
+ validateTimeout(timeout, method);
+ }
+ CircuitBreaker circuitBreaker = AnnotationUtil.getAnnotation(method, annotatedType, CircuitBreaker.class);
+ if (circuitBreaker != null) {
+ validateCircuitBreaker(circuitBreaker, method);
+ }
+ Fallback fallback = AnnotationUtil.getAnnotation(method, annotatedType, Fallback.class);
+ if (fallback != null) {
+ validateFallback(fallback, method, annotatedType);
+ }
+ }
+ }
+
+ private void validateFallback(Fallback fallback, AnnotatedMethod<?> method, AnnotatedType<?> annotatedType) {
+ if(fallback.fallbackMethod().equals("") && fallback.value().equals(Fallback.DEFAULT.class)) {
+ capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method));
+ }
+ else if(!fallback.fallbackMethod().equals("") && !fallback.value().equals(Fallback.DEFAULT.class)) {
+ capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method));
+ }
+ else if(!fallback.fallbackMethod().equals("")) {
+ boolean found = false;
+ for(AnnotatedMethod<?> otherMethod : annotatedType.getMethods()) {
+ if(otherMethod.getJavaMember().getName().equals(fallback.fallbackMethod())) {
+ found = true;
+ if(!method.getJavaMember().getReturnType().equals(otherMethod.getJavaMember().getReturnType())) {
+ capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method +
+ " wrong return type"));
+ } else if(!Arrays.equals(method.getJavaMember().getParameterTypes(), otherMethod.getJavaMember().getParameterTypes())) {
+ capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method +
+ " wrong parameters"));
+ }
+ }
+ }
+ if (!found) {
+ capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method +
+ " fallback method not found"));
+ }
+ }
+ else {
+ try {
+ Method methodHandle = fallback.value().getMethod("handle", ExecutionContext.class);
+ if(!methodHandle.getReturnType().equals(method.getJavaMember().getReturnType())) {
+ capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method +
+ " wrong return type"));
+ }
+ } catch (NoSuchMethodException e) {
+ capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method +
+ " fallback method not found"));
+ }
+ }
+ }
+
+ private void validateTimeout(Timeout timeout, AnnotatedMethod<?> method) {
+ if(timeout.value() < 0) {
+ capturedThrowables.add(new SafeguardException("Invalid Timeout definition on method " + method));
+ }
+ }
+
+ private void validateCircuitBreaker(CircuitBreaker circuitBreaker, AnnotatedMethod<?> method) {
+ if(circuitBreaker.requestVolumeThreshold() <= 0 || circuitBreaker.delay() < 0 || circuitBreaker.failureRatio() < 0.0
+ || circuitBreaker.failureRatio() > 1.0 || circuitBreaker.successThreshold() <= 0) {
+ capturedThrowables.add(new SafeguardException("Invalid CircuitBreaker definition on method " + method));
+ }
+ }
+
+ private void validateRetry(Retry retry, AnnotatedMethod<?> method) {
+ if(retry.jitter() < 0 || retry.maxDuration() < 0 || retry.delay() < 0 || retry.maxRetries() < 0) {
+ capturedThrowables.add(new SafeguardException("Invalid Retry definition on method " + method));
+ }
+ Duration delay = Duration.of(retry.delay(), retry.delayUnit());
+ Duration maxDuration = Duration.of(retry.maxDuration(), retry.durationUnit());
+ if(maxDuration.compareTo(delay) < 0) {
+ capturedThrowables.add(new SafeguardException("Invalid Retry definition on method " + method));
+ }
+ }
+
+ private void validateBulkhead(Bulkhead bulkhead, AnnotatedMethod<?> method) {
+ if(bulkhead.value() < 0 || bulkhead.waitingTaskQueue() < 0) {
+ capturedThrowables.add(new SafeguardException("Invalid Bulkhead definition on method " + method));
+ }
+ }
+
+ void forThrowable(Consumer<Throwable> consumer) {
+ capturedThrowables.forEach(consumer);
+ }
+}
http://git-wip-us.apache.org/repos/asf/geronimo-safeguard/blob/27626ffd/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardExtension.java
----------------------------------------------------------------------
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
index c532914..0bd2e9d 100644
--- 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
@@ -26,6 +26,7 @@ import org.eclipse.microprofile.faulttolerance.Retry;
import org.eclipse.microprofile.faulttolerance.Timeout;
import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AnnotatedConstructor;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMethod;
@@ -42,12 +43,17 @@ import java.util.Set;
import static org.apache.safeguard.api.SafeguardEnabled.INSTANCE;
public class SafeguardExtension implements Extension {
- public void findFaultTolerantBeans(@Observes @WithAnnotations({Retry.class, CircuitBreaker.class, Timeout.class,
- Bulkhead.class})
- ProcessAnnotatedType<?> pat) {
+ private MicroProfileValidator microProfileValidator = new MicroProfileValidator();
+ public <X> void findFaultTolerantBeans(@Observes @WithAnnotations({Retry.class, CircuitBreaker.class, Timeout.class,
+ Bulkhead.class}) ProcessAnnotatedType<X> pat) {
if (!pat.getAnnotatedType().isAnnotationPresent(SafeguardEnabled.class)) {
- pat.setAnnotatedType(new SafeguardAnnotatedTypeWrapper(pat.getAnnotatedType()));
+ pat.setAnnotatedType(new SafeguardAnnotatedTypeWrapper<>(pat.getAnnotatedType()));
}
+ microProfileValidator.parse(pat.getAnnotatedType());
+ }
+
+ public void throwExceptions(@Observes AfterBeanDiscovery afterBeanDiscovery) {
+ microProfileValidator.forThrowable(afterBeanDiscovery::addDefinitionError);
}
private static class SafeguardAnnotatedTypeWrapper<X> implements AnnotatedType<X> {
http://git-wip-us.apache.org/repos/asf/geronimo-safeguard/blob/27626ffd/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/MicroprofileAnnotationMapper.java
----------------------------------------------------------------------
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/MicroprofileAnnotationMapper.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/MicroprofileAnnotationMapper.java
index e898875..41921c5 100644
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/MicroprofileAnnotationMapper.java
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/MicroprofileAnnotationMapper.java
@@ -19,6 +19,7 @@
package org.apache.safeguard.impl.executionPlans;
+import org.apache.safeguard.exception.SafeguardException;
import org.apache.safeguard.impl.circuitbreaker.FailsafeCircuitBreakerBuilder;
import org.apache.safeguard.impl.circuitbreaker.FailsafeCircuitBreakerDefinition;
import org.apache.safeguard.impl.retry.FailsafeRetryBuilder;
@@ -30,6 +31,8 @@ import java.time.Duration;
import java.util.concurrent.TimeoutException;
class MicroprofileAnnotationMapper {
+ private static final String RETRY_FORMAT = "%s/Retry/%s";
+ private static final String CIRCUIT_BREAKER_FORMAT = "%s/CircuitBreaker/%s";
static FailsafeRetryDefinition mapRetry(Retry retry, FailsafeRetryBuilder retryBuilder) {
retryBuilder.withMaxRetries(retry.maxRetries())
.withRetryOn(retry.retryOn())
http://git-wip-us.apache.org/repos/asf/geronimo-safeguard/blob/27626ffd/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/AnnotationUtil.java
----------------------------------------------------------------------
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
index 18bacf6..eb3c478 100644
--- 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
@@ -19,6 +19,8 @@
package org.apache.safeguard.impl.util;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedType;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@@ -35,4 +37,14 @@ public final class AnnotationUtil {
return method.getDeclaringClass().getAnnotation(clazz);
}
}
+
+ public static <T extends Annotation> T getAnnotation(AnnotatedMethod<?> method,
+ AnnotatedType<?> type,
+ Class<T> clazz) {
+ T annotation = method.getAnnotation(clazz);
+ if(annotation != null) {
+ return annotation;
+ }
+ return type.getAnnotation(clazz);
+ }
}
http://git-wip-us.apache.org/repos/asf/geronimo-safeguard/blob/27626ffd/safeguard-tck-tests/pom.xml
----------------------------------------------------------------------
diff --git a/safeguard-tck-tests/pom.xml b/safeguard-tck-tests/pom.xml
index 1ec0c6b..580b8a3 100644
--- a/safeguard-tck-tests/pom.xml
+++ b/safeguard-tck-tests/pom.xml
@@ -72,23 +72,6 @@
</dependenciesToScan>
<excludes>
<exclude>org.eclipse.microprofile.fault.tolerance.tck.ConfigTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.illegalConfig.IncompatibleFallbackMethodTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.illegalConfig.IncompatibleFallbackMethodWithArgsTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.illegalConfig.IncompatibleFallbackTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidBulkheadAsynchQueueTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidCircuitBreakerFailureRatioPosTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidCircuitBreakerFailureReqVol0Test</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidRetryJitterTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidCircuitBreakerFailureSuccess0Test</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidCircuitBreakerDelayTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidRetryDelayTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidCircuitBreakerFailureRatioNegTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidBulkheadValueTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidCircuitBreakerFailureReqVolNegTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidRetryDelayDurationTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidTimeoutValueTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidCircuitBreakerFailureSuccessNegTest</exclude>
- <exclude>org.eclipse.microprofile.fault.tolerance.tck.invalidParameters.InvalidRetryMaxRetriesTest</exclude>
</excludes>
</configuration>
</plugin>