From 108011551bb81e3465d1bd6087a81110967df9e0 Mon Sep 17 00:00:00 2001 From: Piotr Stanior Date: Wed, 9 Dec 2020 09:36:03 +0100 Subject: CDS add Swagger annotations for Resource, Template, Dictionary and Config API Issue-ID: CCSDK-3014 Change-Id: I380c38cde52a748a9b797c573b7651a766e8b496 Signed-off-by: Piotr Stanior --- ms/blueprintsprocessor/application/pom.xml | 2 +- .../config/snapshots/db/ResourceConfigSnapshot.kt | 4 +- .../resource/dict/ResourceDefinition.kt | 8 +++ .../api/ResourceConfigSnapshotController.kt | 19 +++-- .../designer/api/ResourceDictionaryController.kt | 81 ++++++++++++++++++++-- .../designer/api/domain/ResourceDictionary.kt | 17 +++-- .../resource/api/ResourceController.kt | 8 +-- .../resource/api/TemplateController.kt | 8 +-- 8 files changed, 110 insertions(+), 37 deletions(-) (limited to 'ms') diff --git a/ms/blueprintsprocessor/application/pom.xml b/ms/blueprintsprocessor/application/pom.xml index 2b144338a..76d301338 100755 --- a/ms/blueprintsprocessor/application/pom.xml +++ b/ms/blueprintsprocessor/application/pom.xml @@ -335,9 +335,9 @@ true org.onap.ccsdk.cds.blueprintsprocessor.designer.api.BlueprintModelController - diff --git a/ms/blueprintsprocessor/functions/config-snapshots/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/config/snapshots/db/ResourceConfigSnapshot.kt b/ms/blueprintsprocessor/functions/config-snapshots/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/config/snapshots/db/ResourceConfigSnapshot.kt index 7df5ea144..a260d32bc 100644 --- a/ms/blueprintsprocessor/functions/config-snapshots/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/config/snapshots/db/ResourceConfigSnapshot.kt +++ b/ms/blueprintsprocessor/functions/config-snapshots/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/config/snapshots/db/ResourceConfigSnapshot.kt @@ -50,7 +50,7 @@ class ResourceConfigSnapshot : Serializable { @Column(name = "resource_type", nullable = false) var resourceType: String? = null - @get:ApiModelProperty(value = "ID associated with the resource type in the inventory system.", required = true) + @get:ApiModelProperty(value = "ID associated with the resource type in the inventory system.", required = true, example = "\"1\"") @Column(name = "resource_id", nullable = false) var resourceId: String? = null @@ -58,7 +58,7 @@ class ResourceConfigSnapshot : Serializable { @Column(name = "status", nullable = false) var status: Status? = null - @get:ApiModelProperty(value = "Snapshot of the resource as retrieved from resource.", required = true) + @get:ApiModelProperty(value = "Snapshot of the resource as retrieved from resource.", required = true, example = "\"config_snapshot\"") @Lob @Column(name = "config_snapshot", nullable = false) var config_snapshot: String? = null diff --git a/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt b/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt index 556f4a3da..2e7e18258 100644 --- a/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt +++ b/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt @@ -20,29 +20,37 @@ package org.onap.ccsdk.cds.controllerblueprints.resource.dict import com.fasterxml.jackson.annotation.JsonFormat import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.JsonNode +import io.swagger.annotations.ApiModel +import io.swagger.annotations.ApiModelProperty import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeTemplate import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition import java.io.Serializable import java.util.Date +@ApiModel open class ResourceDefinition { @JsonProperty(value = "name", required = true) + @ApiModelProperty(value = "Name", required = true, example = "\"default-source\"") lateinit var name: String @JsonProperty(value = "property", required = true) + @ApiModelProperty(value = "Property", required = true) lateinit var property: PropertyDefinition var tags: String? = null /** The default group for Resource Definition is "default" */ @JsonProperty(value = "group", required = true) + @ApiModelProperty(value = "Group", required = true, example = "\"default\"") var group: String = "default" @JsonProperty(value = "updated-by") + @ApiModelProperty(value = "Updated by", required = true, example = "\"example@onap.com\"") lateinit var updatedBy: String @JsonProperty(value = "sources", required = true) + @ApiModelProperty(value = "Sources", required = true, example = "\"sources\"") lateinit var sources: MutableMap } diff --git a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotController.kt b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotController.kt index d285fe52d..584df27ed 100644 --- a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotController.kt +++ b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotController.kt @@ -48,7 +48,7 @@ import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping("/api/v1/configs") @Api( - value = "/api/v1/configs", + value = "Resource configuration", description = "Interaction with stored configurations." ) open class ResourceConfigSnapshotController(private val resourceConfigSnapshotService: ResourceConfigSnapshotService) { @@ -67,7 +67,6 @@ open class ResourceConfigSnapshotController(private val resourceConfigSnapshotSe } @RequestMapping( - path = [""], method = [RequestMethod.GET], produces = [MediaType.TEXT_PLAIN_VALUE, MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE] ) @@ -79,10 +78,10 @@ open class ResourceConfigSnapshotController(private val resourceConfigSnapshotSe @ResponseBody @PreAuthorize("hasRole('USER')") fun get( - @ApiParam(value = "Resource Type associated of the resource configuration snapshot.", required = false) + @ApiParam(value = "Resource Type associated of the resource configuration snapshot.", required = false, example = "\"PNF\"") @RequestParam(value = "resourceType", required = true) resourceType: String, - @ApiParam(value = "Resource Id associated of the resource configuration snapshot.", required = false) + @ApiParam(value = "Resource Id associated of the resource configuration snapshot.", required = false, example = "\"1\"") @RequestParam(value = "resourceId", required = true) resourceId: String, @ApiParam(value = "Status of the snapshot being retrieved.", defaultValue = "RUNNING", required = false) @@ -142,18 +141,18 @@ open class ResourceConfigSnapshotController(private val resourceConfigSnapshotSe value = "Store a resource configuration snapshot identified by resourceId, resourceType, status.", notes = "Store a resource configuration snapshot, identified by its resourceId and resourceType, " + "and optionally its status, either RUNNING or CANDIDATE.", - response = ResourceConfigSnapshot::class, produces = MediaType.APPLICATION_JSON_VALUE + response = ResourceConfigSnapshot::class ) @ResponseBody @PreAuthorize("hasRole('USER')") fun postWithResourceIdAndResourceType( - @ApiParam(value = "Resource Type associated with the resolution.", required = false) + @ApiParam(value = "Resource Type associated with the resolution.", required = false, example = "\"PNF\"") @PathVariable(value = "resourceType", required = true) resourceType: String, - @ApiParam(value = "Resource Id associated with the resolution.", required = false) + @ApiParam(value = "Resource Id associated with the resolution.", required = false, example = "\"1\"") @PathVariable(value = "resourceId", required = true) resourceId: String, @ApiParam(value = "Status of the snapshot being retrieved.", defaultValue = "RUNNING", required = true) @PathVariable(value = "status", required = true) status: String, - @ApiParam(value = "Config snapshot to store.", required = true) + @ApiParam(value = "Config snapshot to store.", required = true, example = "\"config_snapshot\"") @RequestBody snapshot: String ): ResponseEntity = runBlocking { @@ -178,7 +177,7 @@ open class ResourceConfigSnapshotController(private val resourceConfigSnapshotSe @ResponseBody @PreAuthorize("hasRole('USER')") fun getAllByID( - @ApiParam(value = "Resource Id associated of the resource configuration snapshots.", required = false) + @ApiParam(value = "Resource Id associated of the resource configuration snapshots.", required = false, example = "\"1\"") @RequestParam(value = "resourceId", required = true) resourceId: String, @ApiParam(value = "Status of the snapshot being retrieved.", defaultValue = "ANY", required = false) @RequestParam(value = "status", required = false, defaultValue = "ANY") status: String @@ -223,7 +222,7 @@ open class ResourceConfigSnapshotController(private val resourceConfigSnapshotSe @ResponseBody @PreAuthorize("hasRole('USER')") fun getAllByType( - @ApiParam(value = "Resource Type associated of the resource configuration snapshot.", required = false) + @ApiParam(value = "Resource Type associated of the resource configuration snapshot.", required = false, example = "\"PNF\"") @RequestParam(value = "resourceType", required = true) resourceType: String, @ApiParam(value = "Status of the snapshot being retrieved.", defaultValue = "ANY", required = false) @RequestParam(value = "status", required = false, defaultValue = "ANY") status: String diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/ResourceDictionaryController.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/ResourceDictionaryController.kt index 7f569cfba..1dcfa2ff1 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/ResourceDictionaryController.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/ResourceDictionaryController.kt @@ -16,6 +16,9 @@ package org.onap.ccsdk.cds.blueprintsprocessor.designer.api +import io.swagger.annotations.Api +import io.swagger.annotations.ApiOperation +import io.swagger.annotations.ApiParam import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.domain.ResourceDictionary import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler.ResourceDictionaryHandler import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.mdcWebCoroutineScope @@ -34,24 +37,43 @@ import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping(value = ["/api/v1/dictionary"]) +@Api( + value = "Resource dictionary", + description = "Interaction with stored dictionaries." +) open class ResourceDictionaryController(private val resourceDictionaryHandler: ResourceDictionaryHandler) { @GetMapping(path = ["/{name}"], produces = [MediaType.APPLICATION_JSON_VALUE]) + @ApiOperation( + value = "Retrieve a resource dictionary.", + notes = "Retrieve a resource dictionary by name provided.", + response = ResourceDictionary::class + ) @ResponseBody @Throws(BluePrintException::class) - suspend fun getResourceDictionaryByName(@PathVariable(value = "name") name: String): ResourceDictionary = + suspend fun getResourceDictionaryByName( + @ApiParam(value = "Name of the resource.", required = true, example = "\"hostname\"") + @PathVariable(value = "name") name: String + ): ResourceDictionary = mdcWebCoroutineScope { resourceDictionaryHandler.getResourceDictionaryByName(name) } @PostMapping( - path = [""], produces = [MediaType.APPLICATION_JSON_VALUE], consumes = [MediaType.APPLICATION_JSON_VALUE] ) + @ApiOperation( + value = "Saves a resource dictionary.", + notes = "Saves a resource dictionary by dictionary provided.", + response = ResourceDictionary::class + ) @ResponseBody @Throws(BluePrintException::class) - suspend fun saveResourceDictionary(@RequestBody dataDictionary: ResourceDictionary): ResourceDictionary = + suspend fun saveResourceDictionary( + @ApiParam(value = "Resource dictionary to store.", required = true) + @RequestBody dataDictionary: ResourceDictionary + ): ResourceDictionary = mdcWebCoroutineScope { resourceDictionaryHandler.saveResourceDictionary(dataDictionary) } @@ -61,15 +83,31 @@ open class ResourceDictionaryController(private val resourceDictionaryHandler: R produces = [MediaType.APPLICATION_JSON_VALUE], consumes = [MediaType.APPLICATION_JSON_VALUE] ) + @ApiOperation( + value = "Saves a resource dictionary.", + notes = "Saves a resource dictionary by resource definition provided.", + nickname = "ResourceDictionaryController_saveResourceDictionary_1_POST.org.onap.ccsdk.cds.blueprintsprocessor.designer.api", + response = ResourceDefinition::class + ) @ResponseBody @Throws(BluePrintException::class) - suspend fun saveResourceDictionary(@RequestBody resourceDefinition: ResourceDefinition): ResourceDefinition = + suspend fun saveResourceDictionary( + @ApiParam(value = "Resource definition to generate.", required = true) + @RequestBody resourceDefinition: ResourceDefinition + ): ResourceDefinition = mdcWebCoroutineScope { resourceDictionaryHandler.saveResourceDefinition(resourceDefinition) } @DeleteMapping(path = ["/{name}"]) - suspend fun deleteResourceDictionaryByName(@PathVariable(value = "name") name: String) = mdcWebCoroutineScope { + @ApiOperation( + value = "Removes a resource dictionary.", + notes = "Removes a resource dictionary by name provided." + ) + suspend fun deleteResourceDictionaryByName( + @ApiParam(value = "Name of the resource.", required = true) + @PathVariable(value = "name") name: String + ) = mdcWebCoroutineScope { resourceDictionaryHandler.deleteResourceDictionary(name) } @@ -78,26 +116,55 @@ open class ResourceDictionaryController(private val resourceDictionaryHandler: R produces = [MediaType.APPLICATION_JSON_VALUE], consumes = [MediaType.APPLICATION_JSON_VALUE] ) + @ApiOperation( + value = "Searches for a resource dictionary.", + notes = "Searches for a resource dictionary by names provided.", + responseContainer = "List", + response = ResourceDictionary::class + ) @ResponseBody - suspend fun searchResourceDictionaryByNames(@RequestBody names: List): List = + suspend fun searchResourceDictionaryByNames( + @ApiParam(value = "List of names.", required = true) + @RequestBody names: List + ): List = mdcWebCoroutineScope { resourceDictionaryHandler.searchResourceDictionaryByNames(names) } @GetMapping(path = ["/search/{tags}"], produces = [MediaType.APPLICATION_JSON_VALUE]) + @ApiOperation( + value = "Searches for a resource dictionary.", + notes = "Searches for a resource dictionary by tags provided.", + responseContainer = "List", + response = ResourceDictionary::class + ) @ResponseBody - suspend fun searchResourceDictionaryByTags(@PathVariable(value = "tags") tags: String): List = + suspend fun searchResourceDictionaryByTags( + @ApiParam(value = "Tags list.", required = true, example = "\"status\"") + @PathVariable(value = "tags") tags: String + ): List = mdcWebCoroutineScope { resourceDictionaryHandler.searchResourceDictionaryByTags(tags) } @GetMapping(path = ["/source-mapping"], produces = [MediaType.APPLICATION_JSON_VALUE]) + @ApiOperation( + value = "Searches for a source mapping.", + notes = "Searches for a source mapping.", + response = ResourceSourceMapping::class + ) @ResponseBody suspend fun getResourceSourceMapping(): ResourceSourceMapping = mdcWebCoroutineScope { resourceDictionaryHandler.getResourceSourceMapping() } @GetMapping(path = ["/resource_dictionary_group"], produces = [MediaType.APPLICATION_JSON_VALUE]) + @ApiOperation( + value = "Retrieve all resource dictionary groups.", + notes = "Retrieve all resource dictionary groups.", + responseContainer = "List", + response = String::class + ) @ResponseBody suspend fun getResourceDictionaryDistinct(): List = mdcWebCoroutineScope { resourceDictionaryHandler.getResourceDictionaryDistinct() diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/domain/ResourceDictionary.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/domain/ResourceDictionary.kt index eaa63ddee..5dac6b5e5 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/domain/ResourceDictionary.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/domain/ResourceDictionary.kt @@ -17,6 +17,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.designer.api.domain import com.fasterxml.jackson.annotation.JsonFormat +import io.swagger.annotations.ApiModel import io.swagger.annotations.ApiModelProperty import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition import org.springframework.data.annotation.LastModifiedDate @@ -40,40 +41,42 @@ import javax.persistence.TemporalType * @version 1.0 */ @EntityListeners(AuditingEntityListener::class) +@ApiModel @Entity @Table(name = "RESOURCE_DICTIONARY") class ResourceDictionary : Serializable { @Id @Column(name = "name", nullable = false) - @ApiModelProperty(required = true) + @ApiModelProperty(value = "Name", required = true, example = "\"sample-db-source\"") lateinit var name: String @Column(name = "data_type", nullable = false) - @ApiModelProperty(required = true) + @ApiModelProperty(value = "Data type", required = true, example = "\"string\"") lateinit var dataType: String @Column(name = "entry_schema") + @ApiModelProperty(value = "Entry schema", required = true, example = "\"dt-license-key\"") var entrySchema: String? = null @Column(name = "resource_dictionary_group") - @ApiModelProperty(required = true) + @ApiModelProperty(value = "Resource dictionary group", required = true, example = "\"default\"") var resourceDictionaryGroup: String? = null @Lob @Convert(converter = JpaResourceDefinitionConverter::class) @Column(name = "definition", nullable = false) - @ApiModelProperty(required = true) + @ApiModelProperty(value = "Definition", required = true) lateinit var definition: ResourceDefinition @Lob @Column(name = "description", nullable = false) - @ApiModelProperty(required = true) + @ApiModelProperty(value = "Description", required = true, example = "\"demo_artifacts_version\"") lateinit var description: String @Lob @Column(name = "tags", nullable = false) - @ApiModelProperty(required = true) + @ApiModelProperty(value = "Tags", required = true, example = "\"hostname\"") lateinit var tags: String @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") @@ -83,7 +86,7 @@ class ResourceDictionary : Serializable { var creationDate: Date? = null @Column(name = "updated_by", nullable = false) - @ApiModelProperty(required = true) + @ApiModelProperty(value = "Updated by", required = true, example = "\"username\"") lateinit var updatedBy: String override fun toString(): String { diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt index e7c11e306..3c18ba4f9 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt @@ -38,7 +38,7 @@ import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping("/api/v1/resources") @Api( - value = "/api/v1/resources", + value = "Resources", description = "Interaction with resolved resources." ) open class ResourceController(private var resourceResolutionDBService: ResourceResolutionDBService) { @@ -116,8 +116,7 @@ open class ResourceController(private var resourceResolutionDBService: ResourceR ) @ApiOperation( value = "Delete resources using resolution key", - notes = "Delete all the resources associated to a resolution-key using blueprint metadata, artifact name and the resolution-key.", - produces = MediaType.APPLICATION_JSON_VALUE + notes = "Delete all the resources associated to a resolution-key using blueprint metadata, artifact name and the resolution-key." ) @PreAuthorize("hasRole('USER')") fun deleteByBlueprintNameAndBlueprintVersionAndArtifactNameAndResolutionKey( @@ -148,8 +147,7 @@ open class ResourceController(private var resourceResolutionDBService: ResourceR ) @ApiOperation( value = "Fetch a resource value using resolution key.", - notes = "Retrieve a stored resource value using the blueprint metadata, artifact name, resolution-key along with the name of the resource value to retrieve.", - produces = MediaType.APPLICATION_JSON_VALUE + notes = "Retrieve a stored resource value using the blueprint metadata, artifact name, resolution-key along with the name of the resource value to retrieve." ) @ResponseBody @PreAuthorize("hasRole('USER')") diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt index b56a63b17..b80e81ca0 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt @@ -47,7 +47,7 @@ import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping("/api/v1/template") @Api( - value = "/api/v1/template", + value = "Resource template", description = "Interaction with resolved template." ) open class TemplateController(private val templateResolutionService: TemplateResolutionService) { @@ -146,8 +146,7 @@ open class TemplateController(private val templateResolutionService: TemplateRes value = "Store a resolved template w/ resolution-key", notes = "Store a template for a given CBA's action, identified by its blueprint name, blueprint version, " + "artifact name and resolution key.", - response = TemplateResolution::class, - produces = MediaType.APPLICATION_JSON_VALUE + response = TemplateResolution::class ) @ResponseBody @PreAuthorize("hasRole('USER')") @@ -178,8 +177,7 @@ open class TemplateController(private val templateResolutionService: TemplateRes value = "Store a resolved template w/ resourceId and resourceType", notes = "Store a template for a given CBA's action, identified by its blueprint name, blueprint version, " + "artifact name, resourceId and resourceType.", - response = TemplateResolution::class, - produces = MediaType.APPLICATION_JSON_VALUE + response = TemplateResolution::class ) @ResponseBody @PreAuthorize("hasRole('USER')") -- cgit 1.2.3-korg