From 2371fe79fe36a6629810b6dcfd435a95ce0fd54d Mon Sep 17 00:00:00 2001 From: Rishi Chail Date: Fri, 30 Oct 2020 12:58:54 +0000 Subject: IS: Remove Jersey and Use Spring Framework Issue-ID: CCSDK-2959 Issue-Link: https://jira.onap.org/browse/CCSDK-2959 Signed-off-by: Rishi Chail Change-Id: Ie87d2fe53bffcaf2af0229961139910faeb36e26 --- cps/cps-rest/pom.xml | 52 +----- .../org/onap/cps/rest/config/JerseyConfig.java | 72 ------- .../cps/rest/controller/CpsRestController.java | 153 +++++++++++++++ .../onap/cps/rest/controller/ModelController.java | 36 ---- .../onap/cps/rest/controller/RestController.java | 206 --------------------- cps/cps-rest/src/main/resources/application.yml | 2 + 6 files changed, 156 insertions(+), 365 deletions(-) delete mode 100644 cps/cps-rest/src/main/java/org/onap/cps/rest/config/JerseyConfig.java create mode 100644 cps/cps-rest/src/main/java/org/onap/cps/rest/controller/CpsRestController.java delete mode 100644 cps/cps-rest/src/main/java/org/onap/cps/rest/controller/ModelController.java delete mode 100644 cps/cps-rest/src/main/java/org/onap/cps/rest/controller/RestController.java diff --git a/cps/cps-rest/pom.xml b/cps/cps-rest/pom.xml index 3cecc5f73..ed896a82f 100644 --- a/cps/cps-rest/pom.xml +++ b/cps/cps-rest/pom.xml @@ -23,19 +23,9 @@ ${project.version} - - org.glassfish.jersey.media - jersey-media-multipart - - - - org.springframework - spring-webmvc - - org.springframework.boot - spring-boot-starter-jersey + spring-boot-starter-web org.springframework.boot @@ -73,20 +63,6 @@ - - - org.apache.cxf - cxf-bundle-jaxrs - ${cxf-bundle-jaxrs.version} - - - - - org.apache.cxf - cxf-rt-rs-service-description - ${cxf-rt-rs-service.version} - - @@ -104,32 +80,6 @@ - - io.swagger.codegen.v3 - swagger-codegen-maven-plugin - ${swagger-codegen.version} - - - - generate - - - ${project.basedir}/docs/api/swagger/openapi.yml - org.onap.cps.rest.controller - org.onap.cps.rest.model - org.onap.cps.rest.controller - jaxrs-cxf - true - - src/gen/java - java8 - jersey2 - true - - - - - org.apache.maven.plugins diff --git a/cps/cps-rest/src/main/java/org/onap/cps/rest/config/JerseyConfig.java b/cps/cps-rest/src/main/java/org/onap/cps/rest/config/JerseyConfig.java deleted file mode 100644 index 553c16b55..000000000 --- a/cps/cps-rest/src/main/java/org/onap/cps/rest/config/JerseyConfig.java +++ /dev/null @@ -1,72 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. All rights reserved. - * ================================================================================ - * Licensed 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. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.rest.config; - -import io.swagger.v3.jaxrs2.integration.JaxrsOpenApiContextBuilder; -import io.swagger.v3.jaxrs2.integration.resources.AcceptHeaderOpenApiResource; -import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource; -import io.swagger.v3.oas.integration.OpenApiConfigurationException; -import javax.annotation.PostConstruct; -import javax.ws.rs.ApplicationPath; -import org.glassfish.jersey.media.multipart.MultiPartFeature; -import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.servlet.ServletProperties; -import org.onap.cps.rest.controller.ModelController; -import org.onap.cps.rest.controller.RestController; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ApplicationPath("api") -public class JerseyConfig extends ResourceConfig { - - /** - * This method is used to setup Jersey related configuration. - */ - @PostConstruct - public void init() { - register(MultiPartFeature.class); - register(OpenApiResource.class); - register(AcceptHeaderOpenApiResource.class); - - // Register controllers - register(ModelController.class); - register(RestController.class); - - configureSwagger(); - configureSwaggerUI(); - } - - private void configureSwagger() { - try { - new JaxrsOpenApiContextBuilder<>().buildContext(true).read(); - } catch (final OpenApiConfigurationException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - private void configureSwaggerUI() { - // Enable Jersey filter forwarding to next filter for 404 responses. - // This configuration lets Jersey servlet container forwarding static swagger ui requests to spring mvc filter - // to be handle by spring mvc dispatcher servlet. - property(ServletProperties.FILTER_FORWARD_ON_404, true); - } - -} diff --git a/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/CpsRestController.java b/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/CpsRestController.java new file mode 100644 index 000000000..a577af70e --- /dev/null +++ b/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/CpsRestController.java @@ -0,0 +1,153 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation + * Modifications Copyright (C) 2020 Bell Canada. All rights reserved. + * ================================================================================ + * Licensed 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.rest.controller; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import javax.persistence.PersistenceException; +import org.hibernate.exception.ConstraintViolationException; +import org.onap.cps.api.CpService; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.parser.api.YangParserException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +@RestController +public class CpsRestController { + + @Autowired + private CpService cpService; + + /* + Old rest endpoints before contract first approach (Need to be removed). + */ + + /** + * Upload a yang model file. + * + * @param uploadedFile the yang model Multipart File. + * @param dataspaceName the dataspace name linked to the model. + * @return a ResponseEntity. + */ + @PostMapping("/dataspaces/{dataspace_name}/modules") + public final ResponseEntity uploadYangModelFile( + @RequestParam("file") MultipartFile uploadedFile, + @PathVariable("dataspace_name") String dataspaceName) { + try { + final File fileToParse = saveToFile(uploadedFile); + final SchemaContext schemaContext = cpService.parseAndValidateModel(fileToParse); + cpService.storeSchemaContext(schemaContext, dataspaceName); + return new ResponseEntity("Resource successfully created", HttpStatus.CREATED); + } catch (final YangParserException | ConstraintViolationException e) { + return new ResponseEntity(e.getMessage(), HttpStatus.BAD_REQUEST); + } catch (final Exception e) { + return new ResponseEntity(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + /** + * Upload a JSON file. + * + * @param uploadedFile the JSON Multipart file. + * @return a ResponseEntity. + */ + @PostMapping("/upload-yang-json-data-file") + public final ResponseEntity uploadYangJsonDataFile( + @RequestParam("file") MultipartFile uploadedFile) { + try { + validateJsonStructure(uploadedFile); + final int persistenceObjectId = cpService.storeJsonStructure(new String(uploadedFile.getBytes())); + return new ResponseEntity( + "Object stored in CPS with identity: " + persistenceObjectId, HttpStatus.OK); + } catch (final JsonSyntaxException e) { + return new ResponseEntity(e.getMessage(), HttpStatus.BAD_REQUEST); + } catch (final Exception e) { + return new ResponseEntity(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + /** + * Read a JSON Object using the object identifier. + * + * @param jsonObjectId the JSON object identifier. + * @return a ResponseEntity. + */ + @GetMapping("/json-object/{id}") + public final ResponseEntity getJsonObjectById( + @PathVariable("id") final int jsonObjectId) { + try { + return new ResponseEntity(cpService.getJsonById(jsonObjectId), HttpStatus.OK); + } catch (final PersistenceException e) { + return new ResponseEntity(e.getMessage(), HttpStatus.NOT_FOUND); + } catch (final Exception e) { + return new ResponseEntity(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + /** + * Delete a JSON Object using the object identifier. + * + * @param jsonObjectId the JSON object identifier. + * @return a ResponseEntity. + */ + @DeleteMapping("json-object/{id}") + public final ResponseEntity deleteJsonObjectById( + @PathVariable("id") final int jsonObjectId) { + try { + cpService.deleteJsonById(jsonObjectId); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } catch (final EmptyResultDataAccessException e) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND.toString(), HttpStatus.NOT_FOUND); + } catch (final Exception e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + private static final void validateJsonStructure(final MultipartFile jsonFile) + throws JsonSyntaxException, IOException { + final Gson gson = new Gson(); + gson.fromJson(new String(jsonFile.getBytes()), Object.class); + } + + private static final File saveToFile(final MultipartFile multipartFile) + throws IOException { + final File file = File.createTempFile("tempFile", ".yang"); + file.deleteOnExit(); + + try (OutputStream outputStream = new FileOutputStream(file)) { + outputStream.write(multipartFile.getBytes()); + } + return file; + } +} \ No newline at end of file diff --git a/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/ModelController.java b/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/ModelController.java deleted file mode 100644 index e155aa94c..000000000 --- a/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/ModelController.java +++ /dev/null @@ -1,36 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. All rights reserved. - * ================================================================================ - * Licensed 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. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.rest.controller; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - -@Path("/hi") -public class ModelController { - - @GET - @Produces(MediaType.TEXT_PLAIN) - public String sayHello() { - return "Hi"; - } -} diff --git a/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/RestController.java b/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/RestController.java deleted file mode 100644 index d3ff91b07..000000000 --- a/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/RestController.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation - * Modifications Copyright (C) 2020 Bell Canada. All rights reserved. - * ================================================================================ - * Licensed 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. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.rest.controller; - -import com.google.gson.Gson; -import com.google.gson.JsonSyntaxException; -import java.io.File; -import javax.persistence.PersistenceException; -import javax.validation.Valid; -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import org.apache.cxf.jaxrs.ext.multipart.Attachment; -import org.glassfish.jersey.media.multipart.FormDataParam; -import org.hibernate.exception.ConstraintViolationException; -import org.onap.cps.api.CpService; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.model.parser.api.YangParserException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.dao.EmptyResultDataAccessException; - -@Path("cps") -public class RestController implements CpsResourceApi { - - @Autowired - private CpService cpService; - - @Override - public Object createAnchor(final Attachment fileDetail, final String dataspaceName) { - return null; - } - - @Override - public Object createModules(final Attachment fileDetail, final String dataspaceName) { - return null; - } - - @Override - public Object createNode(final Attachment fileDetail, final String dataspaceName) { - return null; - } - - @Override - public Object deleteAnchor(final String dataspaceName, final String anchorName) { - return null; - } - - @Override - public Object deleteDataspace(final String dataspaceName) { - return null; - } - - @Override - public Object getAnchor(final String dataspaceName, final String anchorName) { - return null; - } - - @Override - public Object getAnchors(final String dataspaceName) { - return null; - } - - @Override - public Object getModule(final String dataspaceName, final String namespaceName, final String revision) { - return null; - } - - @Override - public Object getNode(@Valid final String body, final String dataspaceName) { - return null; - } - - @Override - public Object getNodeByDataspaceAndAnchor(@Valid final String body, final String dataspaceName, - final String anchorName) { - return null; - } - - /* - Old rest endpoints before contract first approach (Need to be removed). - */ - - /** - * Upload a yang model file. - * - * @param uploadedFile the yang model file. - * @param dataspaceName the dataspace name linked to the model. - * @return a http response code. - */ - @POST - @Path("/dataspaces/{dataspace_name}/modules") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.MULTIPART_FORM_DATA) - public final Response uploadYangModelFile(@FormDataParam("file") File uploadedFile, - @PathParam("dataspace_name") String dataspaceName) { - try { - final File fileToParse = renameFileIfNeeded(uploadedFile); - final SchemaContext schemaContext = cpService.parseAndValidateModel(fileToParse); - cpService.storeSchemaContext(schemaContext, dataspaceName); - return Response.status(Status.CREATED).entity("Resource successfully created").build(); - } catch (final YangParserException | ConstraintViolationException e) { - return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); - } catch (final Exception e) { - return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); - } - } - - /** - * Upload a JSON file. - * - * @param uploadedFile the JSON file. - * @return a http response code. - */ - @POST - @Path("/upload-yang-json-data-file") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.MULTIPART_FORM_DATA) - public final Response uploadYangJsonDataFile(@FormDataParam("file") final String uploadedFile) { - try { - validateJsonStructure(uploadedFile); - final int persistenceObjectId = cpService.storeJsonStructure(uploadedFile); - return Response.status(Status.OK).entity("Object stored in CPS with identity: " + persistenceObjectId) - .build(); - } catch (final JsonSyntaxException e) { - return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); - } catch (final Exception e) { - return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); - } - } - - /** - * Read a JSON Object using the object identifier. - * - * @param jsonObjectId the JSON object identifier. - * @return a HTTP response. - */ - @GET - @Path("/json-object/{id}") - public final Response getJsonObjectById(@PathParam("id") final int jsonObjectId) { - try { - return Response.status(Status.OK).entity(cpService.getJsonById(jsonObjectId)).build(); - } catch (final PersistenceException e) { - return Response.status(Status.NOT_FOUND).entity(e.getMessage()).build(); - } catch (final Exception e) { - return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); - } - } - - /** - * Delete a JSON Object using the object identifier. - * - * @param jsonObjectId the JSON object identifier. - * @return a HTTP response. - */ - @DELETE - @Path("json-object/{id}") - public final Response deleteJsonObjectById(@PathParam("id") final int jsonObjectId) { - try { - cpService.deleteJsonById(jsonObjectId); - return Response.status(Status.OK).entity(Status.OK.toString()).build(); - } catch (final EmptyResultDataAccessException e) { - return Response.status(Status.NOT_FOUND).entity(Status.NOT_FOUND.toString()).build(); - } catch (final Exception e) { - return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); - } - } - - private static final void validateJsonStructure(final String jsonFile) { - final Gson gson = new Gson(); - gson.fromJson(jsonFile, Object.class); - } - - private static final File renameFileIfNeeded(final File originalFile) { - if (originalFile.getName().endsWith(".yang")) { - return originalFile; - } - final File renamedFile = new File(originalFile.getName() + ".yang"); - originalFile.renameTo(renamedFile); - return renamedFile; - } -} \ No newline at end of file diff --git a/cps/cps-rest/src/main/resources/application.yml b/cps/cps-rest/src/main/resources/application.yml index c9154ba1f..8e2aee043 100644 --- a/cps/cps-rest/src/main/resources/application.yml +++ b/cps/cps-rest/src/main/resources/application.yml @@ -1,5 +1,7 @@ server: port: 8080 + servlet: + context-path: /api/cps spring: main: -- cgit 1.2.3-korg