@UseDataProvider("success") public void testValidateCorrectFallbackReturnType(Method commandMethod, Method fallbackMethod) { new FallbackMethod(fallbackMethod).validateReturnType(commandMethod); }
private static MetaHolder.Builder setFallbackMethod(MetaHolder.Builder builder, Class<?> declaringClass, Method commandMethod) { FallbackMethod fallbackMethod = MethodProvider.getInstance().getFallbackMethod(declaringClass, commandMethod); if (fallbackMethod.isPresent()) { fallbackMethod.validateReturnType(commandMethod); builder .fallbackMethod(fallbackMethod.getMethod()) .fallbackExecutionType(ExecutionType.getExecutionType(fallbackMethod.getMethod().getReturnType())); } return builder; }
public void validateReturnType(Method commandMethod) throws FallbackDefinitionException { if (isPresent()) { Class<?> commandReturnType = commandMethod.getReturnType(); if (ExecutionType.OBSERVABLE == ExecutionType.getExecutionType(commandReturnType)) { if (ExecutionType.OBSERVABLE != getExecutionType()) { Type commandParametrizedType = commandMethod.getGenericReturnType(); validateCompletableReturnType(commandMethod, method.getReturnType()); return; commandParametrizedType = getFirstParametrizedType(commandMethod); validateParametrizedType(commandParametrizedType, method.getGenericReturnType(), commandMethod, method); } else { validateReturnType(commandMethod, method); if (isCommand() && ExecutionType.ASYNCHRONOUS == getExecutionType()) { validateReturnType(commandMethod, method); if (ExecutionType.ASYNCHRONOUS != getExecutionType()) { Type commandParametrizedType = commandMethod.getGenericReturnType(); if (isReturnTypeParametrized(commandMethod)) { commandParametrizedType = getFirstParametrizedType(commandMethod); validateParametrizedType(commandParametrizedType, method.getGenericReturnType(), commandMethod, method); if (!isCommand() && ExecutionType.ASYNCHRONOUS == getExecutionType()) { throw new FallbackDefinitionException(createErrorMsg(commandMethod, method, "fallback cannot return Future if the fallback isn't command when the command is async.")); if (ExecutionType.ASYNCHRONOUS == getExecutionType()) {
private void validateReturnType(Method commandMethod, Method fallbackMethod) { if (isGenericReturnType(commandMethod)) { List<Type> commandParametrizedTypes = flattenTypeVariables(commandMethod.getGenericReturnType()); List<Type> fallbackParametrizedTypes = flattenTypeVariables(fallbackMethod.getGenericReturnType()); Result result = equalsParametrizedTypes(commandParametrizedTypes, fallbackParametrizedTypes); if (!result.success) { List<String> msg = new ArrayList<String>(); for (Error error : result.errors) { Optional<Type> parentKindOpt = getParentKind(error.commandType, commandParametrizedTypes); String extraHint = ""; if (parentKindOpt.isPresent()) { Type parentKind = parentKindOpt.get(); if (isParametrizedType(parentKind)) { extraHint = "--> " + ((ParameterizedType) parentKind).getRawType().toString() + "<Ooops!>\n"; } } msg.add(String.format(error.reason + "\n" + extraHint + "Command type literal pos: %s; Fallback type literal pos: %s", positionAsString(error.commandType, commandParametrizedTypes), positionAsString(error.fallbackType, fallbackParametrizedTypes))); } throw new FallbackDefinitionException(createErrorMsg(commandMethod, method, StringUtils.join(msg, "\n"))); } } validatePlainReturnType(commandMethod, fallbackMethod); }
fallbackMethod.validateReturnType(metaHolder.getMethod()); CommandAction fallbackAction = null; if (fallbackMethod.isPresent()) { Method fMethod = fallbackMethod.getMethod(); Object[] args = fallbackMethod.isDefault() ? new Object[0] : metaHolder.getArgs(); if (fallbackMethod.isCommand()) { fMethod.setAccessible(true); HystrixCommand hystrixCommand = fMethod.getAnnotation(HystrixCommand.class); .args(args) .fallback(true) .defaultFallback(fallbackMethod.isDefault()) .defaultCollapserKey(metaHolder.getDefaultCollapserKey()) .fallbackMethod(fMethod) .extendedFallback(fallbackMethod.isExtended()) .fallbackExecutionType(fallbackMethod.getExecutionType()) .extendedParentFallback(metaHolder.isExtendedFallback()) .observable(ExecutionType.OBSERVABLE == fallbackMethod.getExecutionType()) .defaultCommandKey(fMethod.getName()) .defaultGroupKey(metaHolder.getDefaultGroupKey()) MetaHolder fmMetaHolder = MetaHolder.builder() .obj(metaHolder.getObj()) .defaultFallback(fallbackMethod.isDefault()) .method(fMethod) .fallbackExecutionType(ExecutionType.SYNCHRONOUS) .extendedFallback(fallbackMethod.isExtended()) .extendedParentFallback(metaHolder.isExtendedFallback())
public void testGetFallbackForExtendedCommandV2_extendedParameterFalse() throws NoSuchMethodException { // given Method extFallback = Service.class.getDeclaredMethod("extCommandV2", String.class, Integer.class, Throwable.class); // when Method fallback = MethodProvider.getInstance().getFallbackMethod(Service.class, extFallback, false).getMethod(); // then assertNull(fallback); }
final ParameterizedType pt1 = (ParameterizedType) commandType; final ParameterizedType pt2 = (ParameterizedType) fallbackType; Result result = regularEquals(pt1.getRawType(), pt2.getRawType()); return result.andThen(new Supplier<Result>() { @Override final TypeVariable tv2 = (TypeVariable) fallbackType; if (tv1.getGenericDeclaration() instanceof Method && tv2.getGenericDeclaration() instanceof Method) { Result result = equals(tv1.getBounds(), tv2.getBounds()); return result.append(new Supplier<List<Error>>() { @Override return regularEquals(tv1, tv2); } else if (isWildcardType(commandType) && isWildcardType(fallbackType)) { final WildcardType wt1 = (WildcardType) commandType; final WildcardType wt2 = (WildcardType) fallbackType; Result result = equals(wt1.getLowerBounds(), wt2.getLowerBounds()); result = result.append(new Supplier<List<Error>>() { @Override result = equals(wt1.getUpperBounds(), wt2.getUpperBounds()); return result.append(new Supplier<List<Error>>() { @Override return regularEquals(commandType, fallbackType);
private void validateCompletableReturnType(Method commandMethod, Class<?> callbackReturnType) { if (Void.TYPE == callbackReturnType) { throw new FallbackDefinitionException(createErrorMsg(commandMethod, method, "fallback cannot return 'void' if command return type is " + Completable.class.getSimpleName())); } }
private FallbackMethod doFind(Class<?> enclosingType, Method commandMethod, boolean extended) { String name = getFallbackName(enclosingType, commandMethod); Class<?>[] fallbackParameterTypes = null; if (isDefault()) { fallbackParameterTypes = new Class[0]; } else { fallbackParameterTypes = commandMethod.getParameterTypes(); } if (extended && fallbackParameterTypes[fallbackParameterTypes.length - 1] == Throwable.class) { fallbackParameterTypes = ArrayUtils.remove(fallbackParameterTypes, fallbackParameterTypes.length - 1); } Class<?>[] extendedFallbackParameterTypes = Arrays.copyOf(fallbackParameterTypes, fallbackParameterTypes.length + 1); extendedFallbackParameterTypes[fallbackParameterTypes.length] = Throwable.class; Optional<Method> exFallbackMethod = getMethod(enclosingType, name, extendedFallbackParameterTypes); Optional<Method> fMethod = getMethod(enclosingType, name, fallbackParameterTypes); Method method = exFallbackMethod.or(fMethod).orNull(); if (method == null) { throw new FallbackDefinitionException("fallback method wasn't found: " + name + "(" + Arrays.toString(fallbackParameterTypes) + ")"); } return new FallbackMethod(method, exFallbackMethod.isPresent(), isDefault()); }
private Result equalsParametrizedTypes(List<Type> commandParametrizedTypes, List<Type> fallbackParametrizedTypes) { if (commandParametrizedTypes.size() != fallbackParametrizedTypes.size()) { return Result.failure(Collections.singletonList( new Error("Different size of types variables.\n" + "Command type literals size = " + commandParametrizedTypes.size() + ": " + commandParametrizedTypes + "\n" + "Fallback type literals size = " + fallbackParametrizedTypes.size() + ": " + fallbackParametrizedTypes + "\n" ))); } for (int i = 0; i < commandParametrizedTypes.size(); i++) { Type commandParametrizedType = commandParametrizedTypes.get(i); Type fallbackParametrizedType = fallbackParametrizedTypes.get(i); Result result = equals(commandParametrizedType, fallbackParametrizedType); if (!result.success) return result; } return SUCCESS; }
fallbackMethod.validateReturnType(metaHolder.getMethod()); CommandAction fallbackAction = null; if (fallbackMethod.isPresent()) { Method fMethod = fallbackMethod.getMethod(); Object[] args = fallbackMethod.isDefault() ? new Object[0] : metaHolder.getArgs(); if (fallbackMethod.isCommand()) { fMethod.setAccessible(true); HystrixCommand hystrixCommand = fMethod.getAnnotation(HystrixCommand.class); .args(args) .fallback(true) .defaultFallback(fallbackMethod.isDefault()) .defaultCollapserKey(metaHolder.getDefaultCollapserKey()) .fallbackMethod(fMethod) .extendedFallback(fallbackMethod.isExtended()) .fallbackExecutionType(fallbackMethod.getExecutionType()) .extendedParentFallback(metaHolder.isExtendedFallback()) .observable(ExecutionType.OBSERVABLE == fallbackMethod.getExecutionType()) .defaultCommandKey(fMethod.getName()) .defaultGroupKey(metaHolder.getDefaultGroupKey()) MetaHolder fmMetaHolder = MetaHolder.builder() .obj(metaHolder.getObj()) .defaultFallback(fallbackMethod.isDefault()) .method(fMethod) .fallbackExecutionType(ExecutionType.SYNCHRONOUS) .extendedFallback(fallbackMethod.isExtended()) .extendedParentFallback(metaHolder.isExtendedFallback())
private void validateReturnType(Method commandMethod, Method fallbackMethod) { if (isGenericReturnType(commandMethod)) { List<Type> commandParametrizedTypes = flattenTypeVariables(commandMethod.getGenericReturnType()); List<Type> fallbackParametrizedTypes = flattenTypeVariables(fallbackMethod.getGenericReturnType()); Result result = equalsParametrizedTypes(commandParametrizedTypes, fallbackParametrizedTypes); if (!result.success) { List<String> msg = new ArrayList<String>(); for (Error error : result.errors) { Optional<Type> parentKindOpt = getParentKind(error.commandType, commandParametrizedTypes); String extraHint = ""; if (parentKindOpt.isPresent()) { Type parentKind = parentKindOpt.get(); if (isParametrizedType(parentKind)) { extraHint = "--> " + ((ParameterizedType) parentKind).getRawType().toString() + "<Ooops!>\n"; } } msg.add(String.format(error.reason + "\n" + extraHint + "Command type literal pos: %s; Fallback type literal pos: %s", positionAsString(error.commandType, commandParametrizedTypes), positionAsString(error.fallbackType, fallbackParametrizedTypes))); } throw new FallbackDefinitionException(createErrorMsg(commandMethod, method, StringUtils.join(msg, "\n"))); } } validatePlainReturnType(commandMethod, fallbackMethod); }
public void testGetFallbackForExtendedCommandV2() throws NoSuchMethodException { // given Method extFallback = Service.class.getDeclaredMethod("extCommandV2", String.class, Integer.class, Throwable.class); // when Method fallback = MethodProvider.getInstance().getFallbackMethod(Service.class, extFallback, true).getMethod(); // then assertParamsTypes(fallback, String.class, Integer.class); }
final ParameterizedType pt1 = (ParameterizedType) commandType; final ParameterizedType pt2 = (ParameterizedType) fallbackType; Result result = regularEquals(pt1.getRawType(), pt2.getRawType()); return result.andThen(new Supplier<Result>() { @Override final TypeVariable tv2 = (TypeVariable) fallbackType; if (tv1.getGenericDeclaration() instanceof Method && tv2.getGenericDeclaration() instanceof Method) { Result result = equals(tv1.getBounds(), tv2.getBounds()); return result.append(new Supplier<List<Error>>() { @Override return regularEquals(tv1, tv2); } else if (isWildcardType(commandType) && isWildcardType(fallbackType)) { final WildcardType wt1 = (WildcardType) commandType; final WildcardType wt2 = (WildcardType) fallbackType; Result result = equals(wt1.getLowerBounds(), wt2.getLowerBounds()); result = result.append(new Supplier<List<Error>>() { @Override result = equals(wt1.getUpperBounds(), wt2.getUpperBounds()); return result.append(new Supplier<List<Error>>() { @Override return regularEquals(commandType, fallbackType);
private void validatePlainReturnType(Class<?> commandReturnType, Class<?> fallbackReturnType, Method commandMethod, Method fallbackMethod) { if (!commandReturnType.isAssignableFrom(fallbackReturnType)) { throw new FallbackDefinitionException(createErrorMsg(commandMethod, fallbackMethod, "Fallback method '" + fallbackMethod + "' must return: " + commandReturnType + " or its subclass")); } }
private FallbackMethod doFind(Class<?> enclosingType, Method commandMethod, boolean extended) { String name = getFallbackName(enclosingType, commandMethod); Class<?>[] fallbackParameterTypes = null; if (isDefault()) { fallbackParameterTypes = new Class[0]; } else { fallbackParameterTypes = commandMethod.getParameterTypes(); } if (extended && fallbackParameterTypes[fallbackParameterTypes.length - 1] == Throwable.class) { fallbackParameterTypes = ArrayUtils.remove(fallbackParameterTypes, fallbackParameterTypes.length - 1); } Class<?>[] extendedFallbackParameterTypes = Arrays.copyOf(fallbackParameterTypes, fallbackParameterTypes.length + 1); extendedFallbackParameterTypes[fallbackParameterTypes.length] = Throwable.class; Optional<Method> exFallbackMethod = getMethod(enclosingType, name, extendedFallbackParameterTypes); Optional<Method> fMethod = getMethod(enclosingType, name, fallbackParameterTypes); Method method = exFallbackMethod.or(fMethod).orNull(); if (method == null) { throw new FallbackDefinitionException("fallback method wasn't found: " + name + "(" + Arrays.toString(fallbackParameterTypes) + ")"); } return new FallbackMethod(method, exFallbackMethod.isPresent(), isDefault()); }
private static Result equals(Type[] t1, Type[] t2) { if (t1 == null && t2 == null) return SUCCESS; if (t1 == null) return Result.failure(); if (t2 == null) return Result.failure(); if (t1.length != t2.length) return Result.failure(new Error(String.format("Different size of type literals. Command size = %d, fallback size = %d", t1.length, t2.length))); Result result = SUCCESS; for (int i = 0; i < t1.length; i++) { result = result.combine(equals(t1[i], t2[i])); if (result.isFailure()) return result; } return result; }
public void validateReturnType(Method commandMethod) throws FallbackDefinitionException { if (isPresent()) { Class<?> commandReturnType = commandMethod.getReturnType(); if (ExecutionType.OBSERVABLE == ExecutionType.getExecutionType(commandReturnType)) { if (ExecutionType.OBSERVABLE != getExecutionType()) { Type commandParametrizedType = commandMethod.getGenericReturnType(); if (isReturnTypeParametrized(commandMethod)) { commandParametrizedType = getFirstParametrizedType(commandMethod); validateParametrizedType(commandParametrizedType, method.getGenericReturnType(), commandMethod, method); } else { validateReturnType(commandMethod, method); if (isCommand() && ExecutionType.ASYNCHRONOUS == getExecutionType()) { validateReturnType(commandMethod, method); if (ExecutionType.ASYNCHRONOUS != getExecutionType()) { Type commandParametrizedType = commandMethod.getGenericReturnType(); if (isReturnTypeParametrized(commandMethod)) { commandParametrizedType = getFirstParametrizedType(commandMethod); validateParametrizedType(commandParametrizedType, method.getGenericReturnType(), commandMethod, method); if (!isCommand() && ExecutionType.ASYNCHRONOUS == getExecutionType()) { throw new FallbackDefinitionException(createErrorMsg(commandMethod, method, "fallback cannot return Future if the fallback isn't command when the command is async.")); if (ExecutionType.ASYNCHRONOUS == getExecutionType()) { throw new FallbackDefinitionException(createErrorMsg(commandMethod, method, "fallback cannot return Future if command isn't asynchronous.")); if (ExecutionType.OBSERVABLE == getExecutionType()) {
builder.observable(observable); FallbackMethod fallbackMethod = MethodProvider.getInstance().getFallbackMethod(obj.getClass(), batchCommandMethod); if (fallbackMethod.isPresent()) { fallbackMethod.validateReturnType(batchCommandMethod); builder .fallbackMethod(fallbackMethod.getMethod()) .fallbackExecutionType(ExecutionType.getExecutionType(fallbackMethod.getMethod().getReturnType()));
@Test(expected = FallbackDefinitionException.class) @UseDataProvider("fail") public void testValidateBadFallbackReturnType(Method commandMethod, Method fallbackMethod) { new FallbackMethod(fallbackMethod).validateReturnType(commandMethod); }