diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy index 9d790f362..74f5e6d8c 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy @@ -2,7 +2,8 @@ package edu.internet2.tier.shibboleth.admin.ui.controller import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.configuration.CustomAttributesConfiguration -import groovy.json.JsonOutput + +import org.springframework.beans.factory.BeanInitializationException import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.core.io.ResourceLoader @@ -19,6 +20,7 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR * interface in terms of JSON schema. * * @author Dmitriy Kopylenko + * @author Bill Smith (wsmith@unicon.net) */ @RestController('/api/ui/MetadataSources') @ConfigurationProperties('shibui') @@ -64,5 +66,17 @@ class MetadataSourcesUiDefinitionController { @PostConstruct def init() { jsonSchemaUrl = this.resourceLoader.getResource(this.metadataSourcesUiSchemaLocation).getURL() + //Detect malformed JSON schema early, during application start up and fail fast with useful exception message + try { + this.jacksonObjectMapper.readValue(this.jsonSchemaUrl, Map) + } + catch (Exception e) { + def msg = """ + An error is detected during JSON parsing => [${e.message}] + ********************************************************** + Offending resource => [${this.jsonSchemaUrl}] + """ + throw new BeanInitializationException(msg.toString(), e) + } } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionControllerIntegrationTests.groovy index 9d804ad57..2695ac803 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionControllerIntegrationTests.groovy @@ -1,5 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.controller +import org.springframework.beans.factory.BeanInitializationException import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.web.client.TestRestTemplate @@ -23,7 +24,6 @@ class MetadataSourcesUiDefinitionControllerIntegrationTests extends Specificatio def "GET Metadata Sources UI definition schema"() { when: 'GET request is made for metadata source UI definition schema' - def result = this.restTemplate.getForEntity(RESOURCE_URI, Object) then: "Request completed successfully" @@ -33,7 +33,7 @@ class MetadataSourcesUiDefinitionControllerIntegrationTests extends Specificatio def "GET Malformed Metadata Sources UI definition schema"() { when: 'GET request is made for malformed metadata source UI definition schema' - configureMalformedJsonInput() + configureMalformedJsonInput(simulateApplicationStartup { false }) def result = this.restTemplate.getForEntity(RESOURCE_URI, Object) then: "Request results in HTTP 500" @@ -42,8 +42,32 @@ class MetadataSourcesUiDefinitionControllerIntegrationTests extends Specificatio result.body.sourceUiSchemaDefinitionFile } - private configureMalformedJsonInput() { + def "Malformed Metadata Sources UI definition schema is detected during application start up"() { + when: 'Application is starting up and malformed JSON schema is detected' + configureMalformedJsonInput(simulateApplicationStartup { true }) + + then: + def ex = thrown(BeanInitializationException) + ex.message.contains('An error is detected during JSON parsing =>') + ex.message.contains('Offending resource =>') + + } + + private configureMalformedJsonInput(boolean simulateApplicationStartup) { controllerUnderTest.metadataSourcesUiSchemaLocation = 'classpath:metadata-sources-ui-schema_MALFORMED.json' - controllerUnderTest.init() + try { + controllerUnderTest.init() + } + catch (Exception e) { + if (simulateApplicationStartup) { + throw e + } + } + + } + + //Just for the nicer, readable, DSL-like + private static boolean simulateApplicationStartup(Closure booleanFlagSupplier) { + booleanFlagSupplier() } } \ No newline at end of file