private ComponentIdentifier getIdentifier(ErrorModel parent) { return buildFromStringRepresentation(parent.getNamespace() + ":" + parent.getType()); } }
/** * @param errorTypeDefinition * @param errorModelMap * @return */ private ErrorModel toErrorModel(ErrorTypeDefinition<?> errorTypeDefinition, Map<String, ErrorModel> errorModelMap) { if (errorModelMap.containsKey(toIdentifier(errorTypeDefinition))) { return errorModelMap.get(toIdentifier(errorTypeDefinition)); } else { ErrorModelBuilder builder = newError(errorTypeDefinition.getType(), getErrorNamespace(errorTypeDefinition)); builder.withParent(toErrorModel(errorTypeDefinition.getParent().orElse(ANY), errorModelMap)); ErrorModel errorModel = builder.build(); errorModelMap.put(toIdentifier(errorTypeDefinition), errorModel); return errorModel; } }
@Test public void orphanErrorsUsesAnyAsParent() { extensionModel = loadExtension(HeisenbergWithOrphanErrors.class); ErrorModel errorModel = extensionModel.getErrorModels().stream().filter(error -> error.getType().equals("HEALTH")).findFirst().get(); assertThat(errorModel.getNamespace(), is(HEISENBERG)); Optional<ErrorModel> anyExtensionError = errorModel.getParent(); assertThat(anyExtensionError.isPresent(), is(true)); assertThat(anyExtensionError.get().getType(), is(ANY.getType())); assertThat(anyExtensionError.get().getNamespace(), is(MULE_NAMESPACE)); }
@Test public void operationInheritsExtensionErrorThrows() { extensionModel = loadExtension(HeisenbergWithExtensionThrows.class); OperationModel someOperation = extensionModel.getOperationModel("someOperation").get(); Optional<ErrorModel> operationError = someOperation.getErrorModels().stream() .filter(errorModel -> errorModel.getType().equals(EXTENSION.getType())).findFirst(); assertThat(operationError.isPresent(), is(true)); }
private ErrorType createErrorType(ErrorModel errorModel, ComponentIdentifier identifier, ExtensionModel extensionModel) { final ErrorType errorType; if (identifier.getNamespace().equals(MULE)) { throw new MuleRuntimeException(createStaticMessage(format("The extension [%s] tried to register the [%s] error with [%s] namespace, which is not allowed.", extensionModel.getName(), identifier, MULE))); } if (errorModel.getParent().isPresent()) { errorType = errorTypeRepository.addErrorType(identifier, getErrorType(errorModel.getParent().get(), extensionModel)); } else { errorType = errorTypeRepository.addErrorType(identifier, null); } return errorType; }
private ErrorTypeRepository mockErrorModel() { final ErrorType parentErrorType = mock(ErrorType.class); ErrorTypeRepository errorTypeRepository = mock(ErrorTypeRepository.class); when(errorTypeRepository.lookupErrorType(any())).thenReturn(Optional.of(ErrorTypeBuilder.builder() .namespace("testNs") .identifier("test") .parentErrorType(parentErrorType) .build())); when(operationModel.getErrorModels()).thenReturn(singleton(new ImmutableErrorModel("test", "testNs", true, null))); return errorTypeRepository; }
DslSyntaxResolver syntaxResolver = DslSyntaxResolver.getDefault(extensionModel, new SingleExtensionImportTypesStrategy()); ErrorModel connectivityErrorModel = newError(CONNECTIVITY_ERROR_IDENTIFIER, errorExtensionNamespace) .withParent(newError(CONNECTIVITY_ERROR_IDENTIFIER, MULE).build()).build(); ErrorModel retryExhaustedError = newError(RETRY_EXHAUSTED_ERROR_IDENTIFIER, errorExtensionNamespace) .withParent(newError(RETRY_EXHAUSTED_ERROR_IDENTIFIER, MULE).build()).build();
@Test public void handleThrowingOfNotRegisteredErrorType() { when(operationModel.getErrorModels()).thenReturn(singleton(newError(CONNECTIVITY_ERROR_IDENTIFIER, ERROR_NAMESPACE).build())); ModuleExceptionHandler handler = new ModuleExceptionHandler(operationModel, extensionModel, typeRepository); ModuleException moduleException = new ModuleException(CONNECTIVITY, new RuntimeException()); assertThatThrownBy(() -> handler.processException(moduleException)) .isInstanceOf(MuleRuntimeException.class) .hasMessage("The component 'testOperation' from the connector 'Test Extension' attempted to throw 'TEST-EXTENSION:CONNECTIVITY'," + " but it was not registered in the Error Repository"); }
private ErrorType getErrorType(ErrorModel errorModel, ExtensionModel extensionModel) { ComponentIdentifier identifier = createIdentifier(errorModel.getType(), errorModel.getNamespace()); Optional<ErrorType> optionalError = errorTypeRepository.getErrorType(identifier); return optionalError.orElseGet(() -> createErrorType(errorModel, identifier, extensionModel)); }
@Test public void extensionErrorsInheritFromMuleErrors() { extensionModel = loadExtension(HeisenbergExtension.class); OperationModel cureCancer = getNamedObject(extensionModel.getOperationModels(), "cureCancer"); assertThat(cureCancer.getErrorModels(), hasItem(hasProperty(TYPE, is(HEALTH.getType())))); Optional<ErrorModel> healthError = extensionModel.getErrorModels().stream() .filter(errorModel -> errorModel.getType().equals(HEALTH.getType())).findFirst(); assertThat(healthError.isPresent(), is(true)); Optional<ErrorModel> optConnectivityError = healthError.get().getParent(); assertThat(optConnectivityError.isPresent(), is(true)); ErrorModel connectivityError = optConnectivityError.get(); assertThat(connectivityError.getType(), is(CONNECTIVITY_ERROR_IDENTIFIER)); assertThat(connectivityError.getNamespace(), is(HEISENBERG)); Optional<ErrorModel> optMuleConnectivityError = connectivityError.getParent(); assertThat(optMuleConnectivityError.isPresent(), is(true)); ErrorModel muleConnectivityError = optMuleConnectivityError.get(); assertThat(muleConnectivityError.getType(), is(CONNECTIVITY_ERROR_IDENTIFIER)); assertThat(muleConnectivityError.getNamespace(), is(MULE_NAMESPACE)); }
@Test public void operationThrowsOverridesExtensionThrows() { extensionModel = loadExtension(HeisenbergWithOperationThrows.class); OperationModel someOperation = extensionModel.getOperationModel("someOperation").get(); Optional<ErrorModel> operationError = someOperation.getErrorModels().stream() .filter(errorModel -> errorModel.getType().equals(OPERATION.getType())).findFirst(); assertThat(operationError.isPresent(), is(true)); }
private void declareErrorModels(OperationDeclarer operationDeclarer, XmlDslModel xmlDslModel, String operationName, ComponentModel operationModel) { Optional<ComponentModel> optionalParametersComponentModel = operationModel.getInnerComponents() .stream() .filter(child -> child.getIdentifier().equals(OPERATION_ERRORS_IDENTIFIER)).findAny(); optionalParametersComponentModel.ifPresent(componentModel -> componentModel.getInnerComponents() .stream() .filter(child -> child.getIdentifier().equals(OPERATION_ERROR_IDENTIFIER)) .forEach(param -> { final String namespace = xmlDslModel.getPrefix().toUpperCase(); final String typeName = param.getParameters().get(ERROR_TYPE_ATTRIBUTE); if (StringUtils.isBlank(typeName)) { throw new IllegalModelDefinitionException(format("The operation [%s] cannot have an <error> with an empty 'type' attribute", operationName)); } if (typeName.contains(NAMESPACE_SEPARATOR)) { throw new IllegalModelDefinitionException(format("The operation [%s] cannot have an <error> [%s] that contains a reserved character [%s]", operationName, typeName, NAMESPACE_SEPARATOR)); } operationDeclarer.withErrorModel(ErrorModelBuilder.newError(typeName, namespace) .withParent(ErrorModelBuilder.newError(ANY).build()) .build()); })); }
@Test public void operationTriesToAddInternalErrorType() { ErrorTypeRepository repository = mock(ErrorTypeRepository.class); when(repository.getErrorType(any())).then((e) -> typeRepository.getErrorType(((ComponentIdentifier) e.getArguments()[0]))); ErrorModel internalRepeatedError = ErrorModelBuilder.newError(SOURCE_RESPONSE_GENERATE).build(); when(operationWithError.getErrorModels()).thenReturn(singleton(internalRepeatedError)); when(extensionModel.getOperationModels()).thenReturn(singletonList(operationWithError)); when(extensionModel.getErrorModels()).thenReturn(singleton(internalRepeatedError)); ErrorTypeLocator mockTypeLocator = mock(ErrorTypeLocator.class); errorsRegistrant = new ExtensionErrorsRegistrant(typeRepository, mockTypeLocator); errorsRegistrant.registerErrors(extensionModel); verify(repository, times(0)).addErrorType(any(), any()); }
private boolean isAllowedError(ErrorType errorType) { return allowedErrorTypes .stream() .anyMatch(errorModel -> { boolean isAllowed = false; ErrorType currentError = errorType; while (currentError != null && !isAllowed) { isAllowed = errorModel.getType().equals(currentError.getIdentifier()) && errorModel.getNamespace().equals(currentError.getNamespace()); currentError = currentError.getParentErrorType(); } return isAllowed; }); }
@Test public void handleThrowingChildErrorsFromTheOneDeclared() { Set<ErrorModel> errors = new HashSet<>(); ErrorModel parent = newError(PARENT.getType(), ERROR_NAMESPACE).build(); ErrorModel child = newError(CHILD.getType(), ERROR_NAMESPACE).withParent(parent).build(); errors.add(parent); ErrorType parentErrorType = typeRepository.addErrorType(getIdentifier(parent), typeRepository.getAnyErrorType()); typeRepository.addErrorType(getIdentifier(child), parentErrorType); when(operationModel.getErrorModels()).thenReturn(errors); ModuleExceptionHandler handler = new ModuleExceptionHandler(operationModel, extensionModel, typeRepository); ModuleException moduleException = new ModuleException(CHILD, new RuntimeException()); Throwable throwable = handler.processException(moduleException); assertThat(throwable, is(instanceOf(TypedException.class))); ErrorType errorType = ((TypedException) throwable).getErrorType(); assertThat(errorType.getIdentifier(), is(CHILD.getType())); assertThat(errorType.getNamespace(), is(ERROR_NAMESPACE)); }
@Test public void handleThrowingOfNotDeclaredErrorType() { typeRepository.addErrorType(buildFromStringRepresentation(ERROR_NAMESPACE + ":" + CONNECTIVITY_ERROR_IDENTIFIER), typeRepository.getAnyErrorType()); when(operationModel.getErrorModels()) .thenReturn(singleton(newError(TRANSFORMATION_ERROR_IDENTIFIER, ERROR_NAMESPACE).build())); ModuleExceptionHandler handler = new ModuleExceptionHandler(operationModel, extensionModel, typeRepository); ModuleException moduleException = new ModuleException(CONNECTIVITY, new RuntimeException()); assertThatThrownBy(() -> handler.processException(moduleException)) .isInstanceOf(MuleRuntimeException.class) .hasMessage("The component 'testOperation' from the connector 'Test Extension' attempted to throw 'TEST-EXTENSION:CONNECTIVITY', " + "but only [TEST-EXTENSION:TRANSFORMATION] errors are allowed."); }
private ErrorModel getErrorModel(ErrorTypeDefinition<?> errorTypeDef, Set<ErrorModel> errors, ComponentDeclaration component) { return errors .stream() .filter(e -> !e.getNamespace().equals(CORE_NAMESPACE_NAME) && e.getType().equals(errorTypeDef.getType())) .findFirst() .orElseThrow(() -> new IllegalModelDefinitionException(format(ERROR_MASK, errorTypeDef, component.getName()))); } }
@Test public void handleTypedException() { when(operationModel.getErrorModels()).thenReturn(singleton(newError(CONNECTIVITY_ERROR_IDENTIFIER, ERROR_NAMESPACE).build())); ModuleExceptionHandler handler = new ModuleExceptionHandler(operationModel, extensionModel, typeRepository); typeRepository.addErrorType(builder() .name(CONNECTIVITY_ERROR_IDENTIFIER) .namespace(ERROR_NAMESPACE) .build(), typeRepository.getAnyErrorType()); ModuleException moduleException = new ModuleException(CONNECTIVITY, new RuntimeException()); Throwable exception = handler.processException(moduleException); assertThat(exception, is(instanceOf(TypedException.class))); ErrorType errorType = ((TypedException) exception).getErrorType(); assertThat(errorType.getIdentifier(), is(CONNECTIVITY_ERROR_IDENTIFIER)); assertThat(errorType.getNamespace(), is(ERROR_NAMESPACE)); }
@Test public void lookupErrorsForOperation() { when(extensionModel.getErrorModels()).thenReturn(singleton(extensionConnectivityError)); errorsRegistrant.registerErrors(extensionModel); ErrorType errorType = typeLocator.lookupComponentErrorType(OPERATION_IDENTIFIER, ConnectionException.class); assertThat(errorType.getIdentifier(), is(CONNECTIVITY_ERROR_IDENTIFIER)); assertThat(errorType.getNamespace(), is(EXTENSION_PREFIX.toUpperCase())); ErrorType muleConnectivityError = errorType.getParentErrorType(); assertThat(muleConnectivityError.getNamespace(), is(MULE_CONNECTIVITY_ERROR.getNamespace())); assertThat(muleConnectivityError.getIdentifier(), is(MULE_CONNECTIVITY_ERROR.getType())); ErrorType anyErrorType = muleConnectivityError.getParentErrorType(); assertThat(anyErrorType.getNamespace(), is(MULE)); assertThat(anyErrorType.getIdentifier(), is(ANY)); assertThat(anyErrorType.getParentErrorType(), is(nullValue())); }