Pass thru error details from remote APIs 51/351/5
authorLott, Christopher (cl778h) <cl778h@att.com>
Mon, 17 Jun 2019 15:57:23 +0000 (11:57 -0400)
committerLott, Christopher (cl778h) <cl778h@att.com>
Tue, 18 Jun 2019 13:40:26 +0000 (09:40 -0400)
Tweak RAN connection dialog behavior

Change-Id: I597aa55e9a769e83d0a538a822e339cf8816bf62
Signed-off-by: Lott, Christopher (cl778h) <cl778h@att.com>
16 files changed:
docs/release-notes.rst
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/A1MediatorConfiguration.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/A1MediatorMockConfiguration.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AnrXappConfiguration.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AnrXappMockConfiguration.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/E2ManagerConfiguration.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/E2ManagerMockConfiguration.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerConfiguration.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/XappManagerMockConfiguration.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AcXappController.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AnrXappController.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/E2ManagerController.java
webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/XappManagerController.java
webapp-backend/src/main/resources/application.properties
webapp-backend/src/main/resources/logback.xml
webapp-frontend/src/app/ran-connection/ran-connection-dialog.component.ts

index 033bdf7..458a4ec 100644 (file)
@@ -20,7 +20,7 @@
 RIC Dashboard Release Notes
 ===========================
 
-Version 1.0.4, 13 June 2019
+Version 1.0.4, 17 June 2019
 ---------------------------
 * Add AC xApp neighbor control screen
 * Add ANR xApp neighbor cell relation table
@@ -32,6 +32,7 @@ Version 1.0.4, 13 June 2019
 * Adjust CSS and HTML for main container positioning
 * Revise config property keys to use URL (not basepath)
 * Left menu overlap main content fix
+* Extend back-end controllers to return error details
 
 Version 1.0.3, 28 May 2019
 --------------------------
index 2ed6b9a..240522b 100644 (file)
@@ -49,7 +49,7 @@ public class A1MediatorConfiguration {
 
        @Autowired
        public A1MediatorConfiguration(@Value("${a1med.url}") final String url) throws MalformedURLException {
-               logger.info("Configuring A1 Mediator at URL {}", url);
+               logger.info("Configuring A1 Mediator at base URL {}", url);
                new URL(url);
                this.a1medUrl = url;
        }
@@ -61,6 +61,7 @@ public class A1MediatorConfiguration {
        }
 
        @Bean
+       // The bean (method) name must be globally unique
        public A1MediatorApi a1MediatorApi() {
                return new A1MediatorApi(apiClient());
        }
index 485597a..672e304 100644 (file)
@@ -55,6 +55,7 @@ public class A1MediatorMockConfiguration {
        }
 
        @Bean
+       // Use the same name as regular configuration
        public A1MediatorApi a1MediatorApi() {
                ApiClient apiClient = apiClient();
                A1MediatorApi mockApi = mock(A1MediatorApi.class);
index 5f2ae9b..4573ff0 100644 (file)
@@ -49,7 +49,7 @@ public class AnrXappConfiguration {
 
        @Autowired
        public AnrXappConfiguration(@Value("${anrxapp.url}") final String url) throws MalformedURLException {
-               logger.info("Configuring ANR client at URL {}", url);
+               logger.info("Configuring ANR client at base URL {}", url);
                new URL(url);
                this.anrXappUrl = url;
        }
@@ -61,11 +61,13 @@ public class AnrXappConfiguration {
        }
 
        @Bean
+       // The bean (method) name must be globally unique
        public HealthApi anrHealthApi() {
                return new HealthApi(apiClient());
        }
 
        @Bean
+       // The bean (method) name must be globally unique
        public NcrtApi anrNcrtApi() {
                return new NcrtApi(apiClient());
        }
index 4d80d4f..340036a 100644 (file)
@@ -97,6 +97,7 @@ public class AnrXappMockConfiguration {
        }
 
        @Bean
+       // Use the same name as regular configuration
        public HealthApi anrHealthApi() {
                ApiClient apiClient = apiClient();
                HealthApi mockApi = mock(HealthApi.class);
@@ -111,7 +112,8 @@ public class AnrXappMockConfiguration {
        }
 
        @Bean
-       public NcrtApi ncrtMockApi() {
+       // Use the same name as regular configuration
+       public NcrtApi anrNcrtApi() {
                ApiClient apiClient = apiClient();
                NcrtApi mockApi = mock(NcrtApi.class);
                when(mockApi.getApiClient()).thenReturn(apiClient);
index 92bef31..6e791e3 100644 (file)
@@ -49,7 +49,7 @@ public class E2ManagerConfiguration {
 
        @Autowired
        public E2ManagerConfiguration(@Value("${e2mgr.url}") final String url) throws MalformedURLException {
-               logger.info("Configuring E2 Manager at base path {}", url);
+               logger.info("Configuring E2 Manager at base URL {}", url);
                new URL(url);
                this.e2mgrUrl = url;
        }
@@ -61,12 +61,14 @@ public class E2ManagerConfiguration {
        }
 
        @Bean
-       public HealthCheckApi e2HealthCheckApi() {
+       // The bean (method) name must be globally unique
+       public HealthCheckApi e2MgrHealthCheckApi() {
                return new HealthCheckApi(apiClient());
        }
 
        @Bean
-       public NodebApi e2NodebApi() {
+       // The bean (method) name must be globally unique
+       public NodebApi e2MgrNodebApi() {
                return new NodebApi(apiClient());
        }
 
index 04bb8fc..334915c 100644 (file)
@@ -62,7 +62,8 @@ public class E2ManagerMockConfiguration {
        }
 
        @Bean
-       public HealthCheckApi e2HealthCheckApi() {
+       // Use the same name as regular configuration
+       public HealthCheckApi e2MgrHealthCheckApi() {
                ApiClient apiClient = apiClient();
                HealthCheckApi mockApi = mock(HealthCheckApi.class);
                when(mockApi.getApiClient()).thenReturn(apiClient);
@@ -75,7 +76,8 @@ public class E2ManagerMockConfiguration {
        }
 
        @Bean
-       public NodebApi e2NodebApi() {
+       // Use the same name as regular configuration
+       public NodebApi e2MgrNodebApi() {
                ApiClient apiClient = apiClient();
                NodebApi mockApi = mock(NodebApi.class);
                when(mockApi.getApiClient()).thenReturn(apiClient);
index 7ecd95c..1b699de 100644 (file)
@@ -50,7 +50,7 @@ public class XappManagerConfiguration {
 
        @Autowired
        public XappManagerConfiguration(@Value("${xappmgr.url}") final String url) throws MalformedURLException {
-               logger.info("Configuring xApp Manager at base path {}", url);
+               logger.info("Configuring xApp Manager at base URL {}", url);
                new URL(url);
                this.xappMgrUrl = url;
        }
@@ -65,7 +65,8 @@ public class XappManagerConfiguration {
         * @return A HealthApi with an ApiClient configured from properties
         */
        @Bean
-       public HealthApi xappHealthApi() {
+       // The bean (method) name must be globally unique
+       public HealthApi xappMgrHealthApi() {
                return new HealthApi(apiClient());
        }
 
@@ -73,7 +74,8 @@ public class XappManagerConfiguration {
         * @return An XappApi with an ApiClient configured from properties
         */
        @Bean
-       public XappApi xappMgrApi() {
+       // The bean (method) name must be globally unique
+       public XappApi xappMgrXappApi() {
                return new XappApi(apiClient());
        }
 }
index ed4f49c..b944c95 100644 (file)
@@ -73,7 +73,8 @@ public class XappManagerMockConfiguration {
        }
 
        @Bean
-       public HealthApi xappHealthMockApi() {
+       // Use the same name as regular configuration
+       public HealthApi xappMgrHealthApi() {
                ApiClient mockClient = mock(ApiClient.class);
                when(mockClient.getStatusCode()).thenReturn(HttpStatus.OK);
                HealthApi mockApi = mock(HealthApi.class);
@@ -88,7 +89,8 @@ public class XappManagerMockConfiguration {
        }
 
        @Bean
-       public XappApi xappMgrMockApi() {
+       // Use the same name as regular configuration
+       public XappApi xappMgrXappApi() {
                ApiClient mockClient = mock(ApiClient.class);
                when(mockClient.getStatusCode()).thenReturn(HttpStatus.OK);
 
index 3782656..279d504 100644 (file)
@@ -31,11 +31,13 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 import org.springframework.util.Assert;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.HttpStatusCodeException;
 
 import com.fasterxml.jackson.databind.JsonNode;
 
@@ -43,8 +45,10 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 
 /**
- * Provides methods to manage policies of the Admission Control xApp, which
- * initially defines just one. All requests go via the A1 Mediator.
+ * * Proxies calls from the front end to the AC xApp via the A1 Mediator API.
+ * All methods answer 502 on failure: <blockquote>HTTP server received an
+ * invalid response from a server it consulted when acting as a proxy or
+ * gateway.</blockquote>
  */
 @RestController
 @RequestMapping(value = DashboardConstants.ENDPOINT_PREFIX + "/xapp/ac", produces = MediaType.APPLICATION_JSON_VALUE)
@@ -62,6 +66,8 @@ public class AcXappController {
        public AcXappController(final A1MediatorApi a1MediatorApi) {
                Assert.notNull(a1MediatorApi, "API must not be null");
                this.a1MediatorApi = a1MediatorApi;
+               if (logger.isDebugEnabled())
+                       logger.debug("ctor: configured with client type {}", a1MediatorApi.getClass().getName());
        }
 
        @ApiOperation(value = "Gets the A1 client library MANIFEST.MF property Implementation-Version.", response = SuccessTransport.class)
@@ -87,11 +93,18 @@ public class AcXappController {
         */
        @ApiOperation(value = "Sets the admission control policy for AC xApp via the A1 Mediator")
        @RequestMapping(value = "catime", method = RequestMethod.PUT)
-       public void setAdmissionControlPolicy(@ApiParam(value = "Admission control policy") @RequestBody JsonNode acPolicy, //
+       public Object setAdmissionControlPolicy(
+                       @ApiParam(value = "Admission control policy") @RequestBody JsonNode acPolicy, //
                        HttpServletResponse response) {
                logger.debug("setAdmissionControlPolicy {}", acPolicy);
-               a1MediatorApi.a1ControllerPutHandler(AC_CONTROL_NAME, acPolicy);
-               response.setStatus(a1MediatorApi.getApiClient().getStatusCode().value());
+               try {
+                       a1MediatorApi.a1ControllerPutHandler(AC_CONTROL_NAME, acPolicy);
+                       response.setStatus(a1MediatorApi.getApiClient().getStatusCode().value());
+                       return null;
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("setAdmissionControlPolicy failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
 }
index dae8ae2..9faeff7 100644 (file)
@@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 import org.springframework.util.Assert;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -43,6 +44,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.HttpStatusCodeException;
 
 import io.swagger.annotations.ApiOperation;
 
@@ -70,11 +72,14 @@ public class AnrXappController {
        private final NcrtApi ncrtApi;
 
        @Autowired
-       public AnrXappController(final HealthApi healthApi, final NcrtApi ncrtApi) {
-               Assert.notNull(healthApi, "API must not be null");
-               Assert.notNull(ncrtApi, "API must not be null");
-               this.healthApi = healthApi;
-               this.ncrtApi = ncrtApi;
+       public AnrXappController(final HealthApi anrHealthApi, final NcrtApi anrNcrtApi) {
+               Assert.notNull(anrHealthApi, "API must not be null");
+               Assert.notNull(anrNcrtApi, "API must not be null");
+               this.healthApi = anrHealthApi;
+               this.ncrtApi = anrNcrtApi;
+               if (logger.isDebugEnabled())
+                       logger.debug("ctor: configured with client types {} and {}", anrHealthApi.getClass().getName(),
+                                       anrNcrtApi.getClass().getName());
        }
 
        @ApiOperation(value = "Gets the ANR client library MANIFEST.MF property Implementation-Version.", response = SuccessTransport.class)
@@ -85,57 +90,94 @@ public class AnrXappController {
 
        @ApiOperation(value = "Performs a liveness probe on the ANR xApp, result expressed as the response code.")
        @RequestMapping(value = "/health/alive", method = RequestMethod.GET)
-       public void getAnrXappHealthAlive(HttpServletResponse response) {
-               healthApi.getHealthAlive();
-               response.setStatus(healthApi.getApiClient().getStatusCode().value());
+       public Object getHealthAlive(HttpServletResponse response) {
+               logger.debug("getHealthAlive");
+               try {
+                       healthApi.getHealthAlive();
+                       response.setStatus(healthApi.getApiClient().getStatusCode().value());
+                       return null;
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("getHealthAlive failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
        @ApiOperation(value = "Performs a readiness probe on the ANR xApp, result expressed as the response code.")
        @RequestMapping(value = "/health/ready", method = RequestMethod.GET)
-       public void getAnrXappHealthReady(HttpServletResponse response) {
-               healthApi.getHealthReady();
-               response.setStatus(healthApi.getApiClient().getStatusCode().value());
+       public Object getHealthReady(HttpServletResponse response) {
+               logger.debug("getHealthReady");
+               try {
+                       healthApi.getHealthReady();
+                       response.setStatus(healthApi.getApiClient().getStatusCode().value());
+                       return null;
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("getHealthAlive failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
        @ApiOperation(value = "Returns list of gNodeB IDs based on NCRT in ANR", response = GgNodeBTable.class)
        @RequestMapping(value = "/gnodebs", method = RequestMethod.GET)
-       public GgNodeBTable getGnodebs() {
-               return ncrtApi.getgNodeB();
+       public Object getGnodebs() {
+               logger.debug("getGnodebs");
+               try {
+                       return ncrtApi.getgNodeB();
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("getGnodebs failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
        @ApiOperation(value = "Returns neighbor cell relation table for all gNodeBs or based on query parameters", response = NeighborCellRelationTable.class)
        @RequestMapping(value = "/ncrt", method = RequestMethod.GET)
-       public NeighborCellRelationTable getNcrt( //
+       public Object getNcrt( //
                        @RequestParam(name = QP_NODEB, required = false) String ggnbId, //
                        @RequestParam(name = QP_SERVING, required = false) String servingCellNrcgi, //
                        @RequestParam(name = QP_NEIGHBOR, required = false) String neighborCellNrpci) {
                logger.debug("getNcrt: ggnbid {}, servingCellNrpci {}, neighborCellNrcgi {}", ggnbId, servingCellNrcgi,
                                neighborCellNrpci);
-               return ncrtApi.getNcrt(ggnbId, servingCellNrcgi, neighborCellNrpci);
+               try {
+                       return ncrtApi.getNcrt(ggnbId, servingCellNrcgi, neighborCellNrpci);
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("getNcrt failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
        // /ncrt/servingcells/{servCellNrcgi}/neighborcells/{neighCellNrpci} :
        @ApiOperation(value = "Modify neighbor cell relation based on Serving Cell NRCGI and Neighbor Cell NRPCI")
        @RequestMapping(value = "/ncrt/" + PP_SERVING + "/{" + PP_SERVING + "}/" + PP_NEIGHBOR + "/{" + PP_NEIGHBOR
                        + "}", method = RequestMethod.PUT)
-       public void modifyNcrt(@PathVariable(PP_SERVING) String servingCellNrcgi, //
+       public Object modifyNcrt(@PathVariable(PP_SERVING) String servingCellNrcgi, //
                        @PathVariable(PP_NEIGHBOR) String neighborCellNrpci, //
                        @RequestBody NeighborCellRelationMod ncrMod, HttpServletResponse response) {
                logger.debug("modifyNcrt: servingCellNrcgi {}, neighborCellNrpci {}, ncrMod {}", servingCellNrcgi,
                                neighborCellNrpci, ncrMod);
-               ncrtApi.modifyNcrt(servingCellNrcgi, neighborCellNrpci, ncrMod);
-               response.setStatus(healthApi.getApiClient().getStatusCode().value());
+               try {
+                       ncrtApi.modifyNcrt(servingCellNrcgi, neighborCellNrpci, ncrMod);
+                       response.setStatus(healthApi.getApiClient().getStatusCode().value());
+                       return null;
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("modifyNcrt failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
        @ApiOperation(value = "Delete neighbor cell relation based on Serving Cell NRCGI and Neighbor Cell NRPCI")
        @RequestMapping(value = "/ncrt/" + PP_SERVING + "/{" + PP_SERVING + "}/" + PP_NEIGHBOR + "/{" + PP_NEIGHBOR
                        + "}", method = RequestMethod.DELETE)
-       public void deleteNcrt(@PathVariable(PP_SERVING) String servingCellNrcgi, //
+       public Object deleteNcrt(@PathVariable(PP_SERVING) String servingCellNrcgi, //
                        @PathVariable(PP_NEIGHBOR) String neighborCellNrpci, //
                        HttpServletResponse response) {
                logger.debug("deleteNcrt: servingCellNrcgi {}, neighborCellNrpci {}", servingCellNrcgi, neighborCellNrpci);
-               ncrtApi.deleteNcrt(servingCellNrcgi, neighborCellNrpci);
-               response.setStatus(healthApi.getApiClient().getStatusCode().value());
+               try {
+                       ncrtApi.deleteNcrt(servingCellNrcgi, neighborCellNrpci);
+                       response.setStatus(healthApi.getApiClient().getStatusCode().value());
+                       return null;
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("modifyNcrt failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
 }
index f4888fc..ba98aed 100644 (file)
@@ -33,28 +33,30 @@ import org.oransc.ric.portal.dashboard.DashboardApplication;
 import org.oransc.ric.portal.dashboard.DashboardConstants;
 import org.oransc.ric.portal.dashboard.model.E2SetupRequestType;
 import org.oransc.ric.portal.dashboard.model.E2SetupResponse;
-import org.oransc.ric.portal.dashboard.model.IDashboardResponse;
 import org.oransc.ric.portal.dashboard.model.SuccessTransport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 import org.springframework.util.Assert;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.HttpStatusCodeException;
 
 import io.swagger.annotations.ApiOperation;
 
 /**
- * Provides methods to contact the E2 Manager.
+ * Proxies calls from the front end to the E2 Manager API. All methods answer
+ * 502 on failure: <blockquote>HTTP server received an invalid response from a
+ * server it consulted when acting as a proxy or gateway.</blockquote>
  * 
- * As of this writing the E2 interface only supports setup connection and check
- * health actions, and query by RAN name. But it does not support get-all, oo
- * this class mocks up some of that functionality.
+ * As of this writing the E2 interface does not support get-all, so this class
+ * mocks up some of that functionality.
  */
 @Configuration
 @RestController
@@ -101,11 +103,19 @@ public class E2ManagerController {
 
        @ApiOperation(value = "Gets the health from the E2 manager, expressed as the response code.")
        @RequestMapping(value = "/health", method = RequestMethod.GET)
-       public void getE2ManagerHealth(HttpServletResponse response) {
-               e2HealthCheckApi.healthGet();
-               response.setStatus(e2HealthCheckApi.getApiClient().getStatusCode().value());
+       public Object healthGet(HttpServletResponse response) {
+               logger.debug("healthGet");
+               try {
+                       e2HealthCheckApi.healthGet();
+                       response.setStatus(e2HealthCheckApi.getApiClient().getStatusCode().value());
+                       return null;
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("healthGet failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
+       // TODO replace with actual functionality
        @ApiOperation(value = "Gets the unique requests submitted to the E2 manager.", response = E2SetupResponse.class, responseContainer = "List")
        @RequestMapping(value = "/setup", method = RequestMethod.GET)
        public Iterable<E2SetupResponse> getRequests() {
@@ -115,12 +125,17 @@ public class E2ManagerController {
 
        @ApiOperation(value = "Get RAN by name.", response = GetNodebResponse.class)
        @RequestMapping(value = "/nodeb/{" + PP_RANNAME + "}", method = RequestMethod.GET)
-       public GetNodebResponse getNb(@PathVariable(PP_RANNAME) String ranName) {
+       public Object getNb(@PathVariable(PP_RANNAME) String ranName) {
                logger.debug("getNb {}", ranName);
-               return e2NodebApi.getNb(ranName);
+               try {
+                       return e2NodebApi.getNb(ranName);
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("getNb failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
-       // TODO replace with actual delete all RAN connections functionality
+       // TODO replace with actual functionality
        @ApiOperation(value = "Disconnect all RAN Connections.")
        @RequestMapping(value = "/disconnectAllRAN", method = RequestMethod.DELETE)
        public void disconnectAllRANConnections() {
@@ -130,44 +145,48 @@ public class E2ManagerController {
 
        @ApiOperation(value = "Sets up an EN-DC RAN connection via the E2 manager.", response = E2SetupResponse.class)
        @RequestMapping(value = "/endcSetup", method = RequestMethod.POST)
-       public E2SetupResponse endcSetup(@RequestBody SetupRequest setupRequest, HttpServletResponse response) {
+       public Object endcSetup(@RequestBody SetupRequest setupRequest) {
                logger.debug("endcSetup {}", setupRequest);
-               int responseCode = -1;
                try {
                        assertNotEmpty(setupRequest.getRanIp());
                        assertNotEmpty(setupRequest.getRanName());
                        assertNotNull(setupRequest.getRanPort());
-                       e2NodebApi.endcSetup(setupRequest);
-                       responseCode = e2NodebApi.getApiClient().getStatusCode().value();
                } catch (Exception ex) {
-                       logger.warn("endcSetup failed", ex);
-                       response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
-                       responseCode = HttpServletResponse.SC_BAD_REQUEST;
+                       return new E2SetupResponse(E2SetupRequestType.ENDC, setupRequest, HttpServletResponse.SC_BAD_REQUEST);
+               }
+               try {
+                       e2NodebApi.endcSetup(setupRequest);
+                       E2SetupResponse r = new E2SetupResponse(E2SetupRequestType.ENDC, setupRequest,
+                                       e2NodebApi.getApiClient().getStatusCode().value());
+                       responses.add(r);
+                       return r;
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("endcSetup failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
                }
-               E2SetupResponse r = new E2SetupResponse(E2SetupRequestType.ENDC, setupRequest, responseCode);
-               responses.add(r);
-               return r;
        }
 
        @ApiOperation(value = "Sets up an X2 RAN connection via the E2 manager.", response = E2SetupResponse.class)
        @RequestMapping(value = "/x2Setup", method = RequestMethod.POST)
-       public IDashboardResponse x2Setup(@RequestBody SetupRequest setupRequest, HttpServletResponse response) {
+       public Object x2Setup(@RequestBody SetupRequest setupRequest) {
                logger.debug("x2Setup {}", setupRequest);
-               int responseCode = -1;
                try {
                        assertNotEmpty(setupRequest.getRanIp());
                        assertNotEmpty(setupRequest.getRanName());
                        assertNotNull(setupRequest.getRanPort());
-                       e2NodebApi.x2Setup(setupRequest);
-                       responseCode = e2NodebApi.getApiClient().getStatusCode().value();
                } catch (Exception ex) {
-                       logger.warn("x2Setup failed", ex);
-                       response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
-                       responseCode = HttpServletResponse.SC_BAD_REQUEST;
+                       return new E2SetupResponse(E2SetupRequestType.ENDC, setupRequest, HttpServletResponse.SC_BAD_REQUEST);
+               }
+               try {
+                       e2NodebApi.x2Setup(setupRequest);
+                       E2SetupResponse r = new E2SetupResponse(E2SetupRequestType.X2, setupRequest,
+                                       e2NodebApi.getApiClient().getStatusCode().value());
+                       responses.add(r);
+                       return r;
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("x2Setup failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
                }
-               E2SetupResponse r = new E2SetupResponse(E2SetupRequestType.X2, setupRequest, responseCode);
-               responses.add(r);
-               return r;
        }
 
 }
index efb296d..e5249b1 100644 (file)
@@ -25,7 +25,6 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.oransc.ric.portal.dashboard.DashboardApplication;
 import org.oransc.ric.portal.dashboard.DashboardConstants;
-import org.oransc.ric.portal.dashboard.model.ErrorTransport;
 import org.oransc.ric.portal.dashboard.model.SuccessTransport;
 import org.oransc.ric.xappmgr.client.api.HealthApi;
 import org.oransc.ric.xappmgr.client.api.XappApi;
@@ -37,19 +36,21 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 import org.springframework.util.Assert;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.HttpStatusCodeException;
 
 import io.swagger.annotations.ApiOperation;
 
 /**
- * Mimics the xApp Manager API. These controller methods just proxy calls from
- * the front-end thru to the real back-end.
- *
+ * Proxies calls from the front end to the xApp Manager API. All methods answer
+ * 502 on failure: <blockquote>HTTP server received an invalid response from a
+ * server it consulted when acting as a proxy or gateway.</blockquote>
  */
 @Configuration
 @RestController
@@ -66,11 +67,11 @@ public class XappManagerController {
        public XappManagerController(final HealthApi healthApi, final XappApi xappApi) {
                Assert.notNull(healthApi, "health API must not be null");
                Assert.notNull(xappApi, "xapp API must not be null");
+               this.healthApi = healthApi;
+               this.xappApi = xappApi;
                if (logger.isDebugEnabled())
                        logger.debug("ctor: configured with client types {} and {}", healthApi.getClass().getName(),
                                        xappApi.getClass().getName());
-               this.healthApi = healthApi;
-               this.xappApi = xappApi;
        }
 
        @ApiOperation(value = "Gets the XApp manager client library MANIFEST.MF property Implementation-Version.", response = SuccessTransport.class)
@@ -81,57 +82,79 @@ public class XappManagerController {
 
        @ApiOperation(value = "Calls the xApp Manager liveness health check.")
        @RequestMapping(value = "/health/alive", method = RequestMethod.GET)
-       public void getHealth(HttpServletResponse response) {
-               logger.debug("getHealth");
-               healthApi.getHealthAlive();
-               response.setStatus(healthApi.getApiClient().getStatusCode().value());
+       public Object getHealth(HttpServletResponse response) {
+               logger.debug("getHealthAlive");
+               try {
+                       healthApi.getHealthAlive();
+                       response.setStatus(healthApi.getApiClient().getStatusCode().value());
+                       return null;
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("getHealthAlive failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
        @ApiOperation(value = "Calls the xApp Manager readiness health check.")
        @RequestMapping(value = "/health/ready", method = RequestMethod.GET)
-       public void getHealthReady(HttpServletResponse response) {
+       public Object getHealthReady(HttpServletResponse response) {
                logger.debug("getHealthReady");
-               healthApi.getHealthReady();
-               response.setStatus(healthApi.getApiClient().getStatusCode().value());
+               try {
+                       healthApi.getHealthReady();
+                       response.setStatus(healthApi.getApiClient().getStatusCode().value());
+                       return null;
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("getHealthReady failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
        @ApiOperation(value = "Calls the xApp Manager to get the list of xApps.", response = AllXapps.class)
        @RequestMapping(value = "/xapps", method = RequestMethod.GET)
-       public AllXapps getAllXapps() {
-               if (logger.isDebugEnabled())
-                       logger.debug("getAllXapps via {}", xappApi.getApiClient().getBasePath());
-               return xappApi.getAllXapps();
+       public Object getAllXapps() {
+               logger.debug("getAllXapps");
+               try {
+                       return xappApi.getAllXapps();
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("getAllXapps failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
        @ApiOperation(value = "Calls the xApp Manager to get the named xApp.", response = Xapp.class)
        @RequestMapping(value = "/xapps/{xAppName}", method = RequestMethod.GET)
-       public Xapp getXapp(@PathVariable("xAppName") String xAppName) {
+       public Object getXapp(@PathVariable("xAppName") String xAppName) {
                logger.debug("getXapp {}", xAppName);
-               return xappApi.getXappByName(xAppName);
+               try {
+                       return xappApi.getXappByName(xAppName);
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("getXapp failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
+               }
        }
 
        @ApiOperation(value = "Calls the xApp Manager to deploy the specified Xapp.", response = Xapp.class)
        @RequestMapping(value = "/xapps", method = RequestMethod.POST)
-       public Object deployXapp(@RequestBody XAppInfo xAppInfo, HttpServletResponse response) {
+       public Object deployXapp(@RequestBody XAppInfo xAppInfo) {
                logger.debug("deployXapp {}", xAppInfo);
                try {
                        return xappApi.deployXapp(xAppInfo);
-               } catch (Exception ex) {
-                       logger.error("deployXapp failed", ex);
-                       response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
-                       return new ErrorTransport(500, "deployXapp failed", ex);
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("deployXapp failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
                }
        }
 
        @ApiOperation(value = "Calls the xApp Manager to undeploy the named Xapp.")
        @RequestMapping(value = "/xapps/{xAppName}", method = RequestMethod.DELETE)
-       public void undeployXapp(@PathVariable("xAppName") String xAppName, HttpServletResponse response) {
+       public Object undeployXapp(@PathVariable("xAppName") String xAppName, HttpServletResponse response) {
                logger.debug("undeployXapp {}", xAppName);
                try {
                        xappApi.undeployXapp(xAppName);
-               } catch (Exception ex) {
-                       logger.error("deployXapp failed", ex);
-                       response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+                       response.setStatus(healthApi.getApiClient().getStatusCode().value());
+                       return null;
+               } catch (HttpStatusCodeException ex) {
+                       logger.warn("undeployXapp failed: {}", ex.toString());
+                       return ResponseEntity.status(HttpServletResponse.SC_BAD_GATEWAY).body(ex.getResponseBodyAsString());
                }
        }
 
index 6015f51..fa2d578 100644 (file)
 server.port = 8080
 
 # A1 Mediator
-a1med.url = http://A1-URL
+a1med.url = http://jar-app-props-default-A1-URL
 
 # ANR xApp
-anrxapp.url = http://ANR-URL
+anrxapp.url = http://jar-app-props-default-ANR-URL
 
 # E2 Manager
-e2mgr.url = http://E2-URL
+e2mgr.url = http://jar-app-props-default-E2-URL
 
 # Xapp Manager
-xappmgr.url = http://MGR-URL
+xappmgr.url = http://jar-app-props-default-Xapp-Mgr-URL
index 0d2348f..26c9ffb 100644 (file)
@@ -65,4 +65,7 @@
        <!-- Code under test should be chatty --> >
        <logger name="org.oransc.ric.portal.dashboard" level="DEBUG" />
 
+       <!-- Report URLs to the log -->
+       <logger name="org.springframework.web.client.RestTemplate" level="DEBUG" />
+
 </configuration>
index 52db4ba..3867ef9 100644 (file)
@@ -21,6 +21,7 @@ import { Component, OnInit, Inject } from '@angular/core';
 import { FormGroup, FormControl, Validators } from '@angular/forms';
 import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
 import { E2ManagerService } from '../services/e2-mgr/e2-mgr.service';
+import { NotificationService } from './../services/ui/notification.service';
 import { ErrorDialogService } from '../services/ui/error-dialog.service';
 import { E2SetupRequest } from '../interfaces/e2-mgr.types';
 import { HttpErrorResponse } from '@angular/common/http';
@@ -37,7 +38,9 @@ export class RANConnectionDialogComponent implements OnInit {
 
     constructor(
         private dialogRef: MatDialogRef<RANConnectionDialogComponent>,
-        private service: E2ManagerService, private errorService: ErrorDialogService,
+        private service: E2ManagerService,
+        private errorService: ErrorDialogService,
+        private notifService: NotificationService,
         @Inject(MAT_DIALOG_DATA) public data: E2SetupRequest) {
     }
 
@@ -60,7 +63,6 @@ export class RANConnectionDialogComponent implements OnInit {
     }
 
     public setupConnection = (ranFormValue) => {
-
         if (this.ranDialogForm.valid) {
             this.executeSetupConnection(ranFormValue);
         }
@@ -75,21 +77,28 @@ export class RANConnectionDialogComponent implements OnInit {
             ranPort: ranFormValue.ranPort
         };
         if (ranFormValue.ranType === 'endc') {
-            this.service.endcSetup(setupRequest).subscribe((val: any[]) => {},
+            this.service.endcSetup(setupRequest).subscribe(
+                (response: any) => {
+                    this.notifService.success('Endc connect succeeded!');
+                    this.dialogRef.close();
+                },
                 (error => {
                     httpErrRes = error;
                     this.errorService.displayError(aboutError + httpErrRes.message);
                 })
             );
         } else {
-            this.service.x2Setup(setupRequest).subscribe((val: any[]) => {},
+            this.service.x2Setup(setupRequest).subscribe(
+                (response: any) => {
+                    this.notifService.success('X2 connect succeeded!');
+                    this.dialogRef.close();
+                },
                 (error => {
                     httpErrRes = error;
                     this.errorService.displayError(aboutError + httpErrRes.message);
                 })
             );
         }
-        this.dialogRef.close();
     }
 
     public hasError(controlName: string, errorName: string) {