Cenralized handling of USER_ID header 01/61601/2
authorvempo <vitaliy.emporopulo@amdocs.com>
Tue, 21 Aug 2018 13:42:26 +0000 (16:42 +0300)
committervempo <vitaliy.emporopulo@amdocs.com>
Sun, 2 Sep 2018 08:07:48 +0000 (11:07 +0300)
Minor code style and spelling fixes.

Change-Id: I07495a08d3c02276806c9043ed7dbf81ed1a9394
Issue-ID: SDC-1670
Signed-off-by: vempo <vitaliy.emporopulo@amdocs.com>
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/ExceptionsHandler.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowController.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/WorkflowVersionController.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/config/ApplicationConfigurer.java
workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/resolvers/UserIdResolver.java [new file with mode: 0644]
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/annotations/UserId.java [new file with mode: 0644]
workflow-designer-be/src/test/java/org/onap/sdc/workflow/api/WorkflowControllerTest.java
workflow-designer-be/src/test/java/org/onap/sdc/workflow/server/resolvers/UserIdResolverTest.java [new file with mode: 0644]

index f46d19b..642c343 100644 (file)
@@ -51,7 +51,8 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep
 @RestController
 public class ExceptionsHandler extends ResponseEntityExceptionHandler {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionsHandler.class);
+    private static final Logger LOG = LoggerFactory.getLogger(ExceptionsHandler.class);
+
     private static final String LOG_MSG = "Exception was mapped to {} response";
     private static final String UNEXPECTED_ERROR_MSG = "Something bad happened. Please contact support with code %s";
     private static final RandomStringGenerator CODE_GENERATOR =
@@ -66,15 +67,15 @@ public class ExceptionsHandler extends ResponseEntityExceptionHandler {
     @Override
     public ResponseEntity<Object> handleServletRequestBindingException(ServletRequestBindingException ex,
             HttpHeaders headers, HttpStatus status, WebRequest request) {
-        //For missing header exceptions
-        LOGGER.debug(LOG_MSG, BAD_REQUEST, ex);
+        LOG.debug(LOG_MSG, BAD_REQUEST, ex);
+        // Convert Spring-generated binding exceptions into the format of an application message
         return new ResponseEntity<>(new ErrorResponse(ex.getMessage()), BAD_REQUEST);
     }
 
     @Override
     protected final ResponseEntity<Object> handleMethodArgumentNotValid(final MethodArgumentNotValidException exception,
             final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
-        LOGGER.debug(LOG_MSG, BAD_REQUEST, exception);
+        LOG.debug(LOG_MSG, BAD_REQUEST, exception);
         String errorMsg = exception.getBindingResult().getFieldErrors().stream()
                                   .map(DefaultMessageSourceResolvable::getDefaultMessage).findFirst()
                                   .orElse(exception.getMessage());
@@ -83,7 +84,7 @@ public class ExceptionsHandler extends ResponseEntityExceptionHandler {
 
     @ExceptionHandler(EntityNotFoundException.class)
     public final ResponseEntity<ErrorResponse> handleNotFoundException(Exception exception) {
-        LOGGER.debug(LOG_MSG, NOT_FOUND, exception);
+        LOG.debug(LOG_MSG, NOT_FOUND, exception);
         return new ResponseEntity<>(new ErrorResponse(exception.getMessage()), NOT_FOUND);
     }
 
@@ -92,14 +93,14 @@ public class ExceptionsHandler extends ResponseEntityExceptionHandler {
                     VersionStateModificationException.class, VersionStatusModificationException.class,
                     UniqueValueViolationException.class})
     public final ResponseEntity<ErrorResponse> handleUnprocessableEntityException(Exception exception) {
-        LOGGER.debug(LOG_MSG, UNPROCESSABLE_ENTITY, exception);
+        LOG.debug(LOG_MSG, UNPROCESSABLE_ENTITY, exception);
         return new ResponseEntity<>(new ErrorResponse(exception.getMessage()), UNPROCESSABLE_ENTITY);
     }
 
     @ExceptionHandler(Exception.class)
     public final ResponseEntity<UnexpectedErrorResponse> handleUnexpectedException(Exception exception) {
         UnexpectedErrorResponse response = UNEXPECTED_EXCEPTION_MAPPER.apply(exception);
-        LOGGER.error(response.getMessage(), exception);
+        LOG.error(response.getMessage(), exception);
         return new ResponseEntity<>(response, INTERNAL_SERVER_ERROR);
     }
 
index 8cc1df4..9010fea 100644 (file)
@@ -19,7 +19,6 @@ package org.onap.sdc.workflow.api;
 import static org.onap.sdc.workflow.api.RestParams.LIMIT;
 import static org.onap.sdc.workflow.api.RestParams.OFFSET;
 import static org.onap.sdc.workflow.api.RestParams.SORT;
-import static org.onap.sdc.workflow.api.RestParams.USER_ID_HEADER;
 import static org.onap.sdc.workflow.services.types.PagingConstants.DEFAULT_LIMIT;
 import static org.onap.sdc.workflow.services.types.PagingConstants.DEFAULT_OFFSET;
 
@@ -33,6 +32,7 @@ import org.onap.sdc.workflow.api.types.Sorting;
 import org.onap.sdc.workflow.api.types.VersionStatesFormatter;
 import org.onap.sdc.workflow.services.WorkflowManager;
 import org.onap.sdc.workflow.services.WorkflowVersionManager;
+import org.onap.sdc.workflow.services.annotations.UserId;
 import org.onap.sdc.workflow.services.types.Page;
 import org.onap.sdc.workflow.services.types.PagingRequest;
 import org.onap.sdc.workflow.services.types.RequestSpec;
@@ -49,7 +49,6 @@ import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
@@ -85,14 +84,13 @@ public class WorkflowController {
             value = "Filter by workflow name")})
     public Page<Workflow> list(@ApiIgnore String searchNameFilter,
             @ApiIgnore VersionStatesFormatter versionStateFilter, @ApiIgnore Paging paging,
-            @ApiIgnore Sorting sorting, @RequestHeader(USER_ID_HEADER) String user) {
+            @ApiIgnore Sorting sorting, @UserId String user) {
         return workflowManager.list(searchNameFilter, versionStateFilter.getVersionStates(), initRequestSpec(paging, sorting));
     }
 
     @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
     @ApiOperation("Create workflow")
-    public ResponseEntity<Workflow> create(@Validated @RequestBody Workflow workflow,
-            @RequestHeader(USER_ID_HEADER) String user) {
+    public ResponseEntity<Workflow> create(@Validated @RequestBody Workflow workflow, @UserId String user) {
         return new ResponseEntity<>(workflowManager.create(workflow), HttpStatus.CREATED);
     }
 
@@ -100,8 +98,7 @@ public class WorkflowController {
     @ApiOperation("Get workflow")
     public Workflow get(@PathVariable("workflowId") String workflowId,
             @ApiParam(value = "Expand workflow data", allowableValues = "versions")
-            @RequestParam(value = "expand", required = false) String expand,
-            @RequestHeader(USER_ID_HEADER) String user) {
+            @RequestParam(value = "expand", required = false) String expand, @UserId String user) {
         Workflow workflow = new Workflow();
         workflow.setId(workflowId);
         Workflow retrievedWorkflow = workflowManager.get(workflow);
@@ -114,7 +111,7 @@ public class WorkflowController {
     @PutMapping(path = "/{workflowId}", consumes = MediaType.APPLICATION_JSON_VALUE)
     @ApiOperation("Update workflow")
     public Workflow update(@RequestBody Workflow workflow, @PathVariable("workflowId") String workflowId,
-            @RequestHeader(USER_ID_HEADER) String user) {
+            @UserId String user) {
         workflow.setId(workflowId);
         workflowManager.update(workflow);
         return workflow;
index f869ce0..67bea00 100644 (file)
@@ -16,8 +16,6 @@
 
 package org.onap.sdc.workflow.api;
 
-import static org.onap.sdc.workflow.api.RestParams.USER_ID_HEADER;
-
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
@@ -28,6 +26,7 @@ import org.onap.sdc.workflow.api.types.VersionStatesFormatter;
 import org.onap.sdc.workflow.api.types.dto.ArtifactDeliveriesRequestDto;
 import org.onap.sdc.workflow.persistence.types.ArtifactEntity;
 import org.onap.sdc.workflow.services.WorkflowVersionManager;
+import org.onap.sdc.workflow.services.annotations.UserId;
 import org.onap.sdc.workflow.services.types.WorkflowVersion;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -43,7 +42,6 @@ import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
@@ -60,9 +58,9 @@ public class WorkflowVersionController {
 
     @Autowired
     public WorkflowVersionController(@Qualifier("workflowVersionManager") WorkflowVersionManager workflowVersionManager,
-            @Qualifier("ArtifactAssociationHandler") ArtifactAssociationService artifatcAssociationHandler) {
+            @Qualifier("ArtifactAssociationHandler") ArtifactAssociationService artifactAssociationHandler) {
         this.workflowVersionManager = workflowVersionManager;
-        this.associationHandler = artifatcAssociationHandler;
+        this.associationHandler = artifactAssociationHandler;
     }
 
     @GetMapping
@@ -70,7 +68,7 @@ public class WorkflowVersionController {
     @ApiImplicitParam(name = "state", dataType = "string", paramType = "query", allowableValues = "DRAFT,CERTIFIED",
             value = "Filter by state")
     public CollectionResponse<WorkflowVersion> list(@PathVariable("workflowId") String workflowId,
-            @ApiIgnore VersionStatesFormatter stateFilter, @RequestHeader(USER_ID_HEADER) String user) {
+            @ApiIgnore VersionStatesFormatter stateFilter, @UserId String user) {
         return new CollectionResponse<>(workflowVersionManager.list(workflowId, stateFilter.getVersionStates()));
     }
 
@@ -78,8 +76,7 @@ public class WorkflowVersionController {
     @ApiOperation("Create workflow version")
     public ResponseEntity<WorkflowVersion> create(@RequestBody @Valid WorkflowVersion version,
             @PathVariable("workflowId") String workflowId,
-            @RequestParam(value = "baseVersionId", required = false) String baseVersionId,
-            @RequestHeader(USER_ID_HEADER) String user) {
+            @RequestParam(value = "baseVersionId", required = false) String baseVersionId, @UserId String user) {
         WorkflowVersion createdVersion = workflowVersionManager.create(workflowId, baseVersionId, version);
         return new ResponseEntity<>(createdVersion, HttpStatus.CREATED);
     }
@@ -87,14 +84,14 @@ public class WorkflowVersionController {
     @GetMapping("/{versionId}")
     @ApiOperation("Get workflow version")
     public WorkflowVersion get(@PathVariable("workflowId") String workflowId,
-            @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER) String user) {
+            @PathVariable("versionId") String versionId, @UserId String user) {
         return workflowVersionManager.get(workflowId, versionId);
     }
 
     @PutMapping("/{versionId}")
     @ApiOperation("Update workflow version")
     public void update(@RequestBody @Valid WorkflowVersion version, @PathVariable("workflowId") String workflowId,
-            @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER) String user) {
+            @PathVariable("versionId") String versionId, @UserId String user) {
         version.setId(versionId);
         workflowVersionManager.update(workflowId, version);
     }
@@ -102,7 +99,7 @@ public class WorkflowVersionController {
     @GetMapping("/{versionId}/state")
     @ApiOperation("Get workflow version state")
     public VersionStateDto getState(@PathVariable("workflowId") String workflowId,
-            @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER) String user) {
+            @PathVariable("versionId") String versionId, @UserId String user) {
         return new VersionStateDto(workflowVersionManager.getState(workflowId, versionId));
     }
 
@@ -110,7 +107,7 @@ public class WorkflowVersionController {
     @ApiOperation("Update workflow version state")
     public VersionStateDto updateState(@RequestBody VersionStateDto state,
             @PathVariable("workflowId") String workflowId, @PathVariable("versionId") String versionId,
-            @RequestHeader(USER_ID_HEADER) String user) {
+            @UserId String user) {
         workflowVersionManager.updateState(workflowId, versionId, state.getName());
         return new VersionStateDto(state.getName());
     }
@@ -119,7 +116,7 @@ public class WorkflowVersionController {
     @ApiOperation("upload of artifact to VF operation workflow")
     public ResponseEntity<String> artifactDeliveries(@RequestBody ArtifactDeliveriesRequestDto deliveriesRequestDto,
             @PathVariable("workflowId") String workflowId, @PathVariable("versionId") String versionId,
-            @RequestHeader(USER_ID_HEADER) String user) {
+            @UserId String user) {
         return associationHandler
                        .execute(user, deliveriesRequestDto, workflowVersionManager.getArtifact(workflowId, versionId));
     }
@@ -127,14 +124,14 @@ public class WorkflowVersionController {
     @PutMapping("/{versionId}/artifact")
     @ApiOperation("Create/update artifact of a version")
     public void uploadArtifact(@RequestBody MultipartFile fileToUpload, @PathVariable("workflowId") String workflowId,
-            @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER) String user) {
+            @PathVariable("versionId") String versionId, @UserId String user) {
         workflowVersionManager.uploadArtifact(workflowId, versionId, fileToUpload);
     }
 
     @GetMapping("/{versionId}/artifact")
     @ApiOperation("Download workflow version artifact")
     public ResponseEntity<Resource> getArtifact(@PathVariable("workflowId") String workflowId,
-            @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER) String user) {
+            @PathVariable("versionId") String versionId, @UserId String user) {
         ArtifactEntity artifact = workflowVersionManager.getArtifact(workflowId, versionId);
 
         return ResponseEntity.ok()
@@ -146,7 +143,7 @@ public class WorkflowVersionController {
     @DeleteMapping("/{versionId}/artifact")
     @ApiOperation("Delete workflow version artifact")
     public void deleteArtifact(@PathVariable("workflowId") String workflowId,
-            @PathVariable("versionId") String versionId, @RequestHeader(USER_ID_HEADER) String user) {
+            @PathVariable("versionId") String versionId, @UserId String user) {
         workflowVersionManager.deleteArtifact(workflowId, versionId);
     }
 }
index e631a12..15df33f 100644 (file)
 
 package org.onap.sdc.workflow.server.config;
 
+import java.util.List;
+import org.onap.sdc.workflow.server.resolvers.UserIdResolver;
 import org.openecomp.sdc.logging.servlet.spring.LoggingInterceptor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
@@ -32,4 +35,9 @@ public class ApplicationConfigurer implements WebMvcConfigurer {
     public void addInterceptors(InterceptorRegistry registry) {
         registry.addInterceptor(loggingInterceptor);
     }
+
+    @Override
+    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
+        argumentResolvers.add(new UserIdResolver());
+    }
 }
diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/resolvers/UserIdResolver.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/server/resolvers/UserIdResolver.java
new file mode 100644 (file)
index 0000000..80cb07a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.onap.sdc.workflow.server.resolvers;
+
+import static org.onap.sdc.workflow.api.RestParams.USER_ID_HEADER;
+
+import java.util.Objects;
+import javax.servlet.http.HttpServletRequest;
+import org.onap.sdc.workflow.services.annotations.UserId;
+import org.springframework.core.MethodParameter;
+import org.springframework.web.bind.ServletRequestBindingException;
+import org.springframework.web.bind.support.WebDataBinderFactory;
+import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.method.support.ModelAndViewContainer;
+
+/**
+ * Resolves a user ID from an HTTP header and injects it into a parameter of type {@link String} annotated with {@link
+ * UserId}. The header is considered mandatory, therefore an error is returned to the client if no user ID was sent.
+ *
+ * @author evitaliy
+ * @since 21 Aug 2018
+ */
+public class UserIdResolver implements HandlerMethodArgumentResolver {
+
+    private static final String ERROR_MESSAGE = "Missing mandatory request header '" + USER_ID_HEADER + "'";
+
+    @Override
+    public boolean supportsParameter(MethodParameter methodParameter) {
+
+        if (!methodParameter.hasParameterAnnotation(UserId.class)) {
+            return false;
+        }
+
+        Class<?> parameterType = methodParameter.getParameterType();
+        if (!parameterType.equals(String.class)) {
+            throw new IllegalStateException("Cannot inject user ID into a parameter of type "
+                                                    + parameterType.getTypeName());
+        }
+
+        return true;
+    }
+
+    @Override
+    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
+            NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory)
+            throws ServletRequestBindingException {
+
+        HttpServletRequest httpServletRequest = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
+        String userHeader = Objects.requireNonNull(httpServletRequest).getHeader(USER_ID_HEADER);
+        if (userHeader == null) {
+            throw new ServletRequestBindingException(ERROR_MESSAGE);
+        }
+
+        return userHeader;
+    }
+}
\ No newline at end of file
diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/annotations/UserId.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/annotations/UserId.java
new file mode 100644 (file)
index 0000000..90a1a76
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.onap.sdc.workflow.services.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface UserId { }
index 258e9c5..597e27f 100644 (file)
@@ -33,6 +33,7 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.onap.sdc.workflow.RestPath;
+import org.onap.sdc.workflow.server.resolvers.UserIdResolver;
 import org.onap.sdc.workflow.services.WorkflowManager;
 import org.onap.sdc.workflow.services.types.Page;
 import org.onap.sdc.workflow.services.types.PagingRequest;
@@ -49,8 +50,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 public class WorkflowControllerTest {
 
     private static final String USER_ID = "userId";
-    private static final String MISSING_USER_HEADER_ERROR =
-            "Missing request header 'USER_ID' for method parameter of type String";
+    private static final String MISSING_USER_HEADER_ERROR = "Missing mandatory request header 'USER_ID'";
     private static final String DEFAULT_SORT_VALUE = "name:asc";
 
     private MockMvc mockMvc;
@@ -66,6 +66,7 @@ public class WorkflowControllerTest {
     public void setUp() {
         mockMvc = MockMvcBuilders.standaloneSetup(workflowController)
                                  .setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
+                                 .setCustomArgumentResolvers(new UserIdResolver())
                                  .setControllerAdvice(new ExceptionsHandler()).build();
     }
 
@@ -183,7 +184,7 @@ public class WorkflowControllerTest {
     }
 
     @Test
-    public void shouldCreateWorkflowWhenCallingPostRESTRequest() throws Exception {
+    public void shouldCreateWorkflowWhenCallingPostRestRequest() throws Exception {
         Item item = new Item();
         item.setId(new Id("abc"));
         Workflow reqWorkflow = createWorkflow(1, false);
@@ -235,9 +236,11 @@ public class WorkflowControllerTest {
         Workflow reqWorkflow = new Workflow();
         reqWorkflow.setName("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
         mockMvc.perform(post(RestPath.getWorkflowsPath()).header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON)
-                                                         .content(JsonUtil.object2Json(reqWorkflow))).andDo(print())
-               .andExpect(status().isBadRequest()).andExpect(
-                jsonPath("$.message", is("Workflow name must be at least " + MIN_LENGTH + " characters, and no more than " + MAX_LENGTH + " characters.")));
+                                .content(JsonUtil.object2Json(reqWorkflow))).andDo(print()).andExpect(
+                                        status().isBadRequest()).andExpect(jsonPath("$.message", is(
+                                                "Workflow name must be at least " + MIN_LENGTH
+                                                        + " characters, and no more than " + MAX_LENGTH
+                                                        + " characters.")));
     }
 
     @Test
@@ -245,9 +248,10 @@ public class WorkflowControllerTest {
         Workflow reqWorkflow = new Workflow();
         reqWorkflow.setName("AAA");
         mockMvc.perform(post(RestPath.getWorkflowsPath()).header(USER_ID_HEADER, USER_ID).contentType(APPLICATION_JSON)
-                                                         .content(JsonUtil.object2Json(reqWorkflow))).andDo(print())
-               .andExpect(status().isBadRequest()).andExpect(
-                jsonPath("$.message", is("Workflow name must be at least " + MIN_LENGTH + " characters, and no more than " + MAX_LENGTH + " characters.")));
+                                .content(JsonUtil.object2Json(reqWorkflow))).andDo(print()).andExpect(
+                                        status().isBadRequest()).andExpect(jsonPath("$.message",
+                is("Workflow name must be at least " + MIN_LENGTH + " characters, and no more than "
+                           + MAX_LENGTH + " characters.")));
     }
 
     private void mockManagerList3() {
diff --git a/workflow-designer-be/src/test/java/org/onap/sdc/workflow/server/resolvers/UserIdResolverTest.java b/workflow-designer-be/src/test/java/org/onap/sdc/workflow/server/resolvers/UserIdResolverTest.java
new file mode 100644 (file)
index 0000000..464af46
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.onap.sdc.workflow.server.resolvers;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.onap.sdc.workflow.api.RestParams.USER_ID_HEADER;
+
+import javax.servlet.http.HttpServletRequest;
+import org.junit.Test;
+import org.onap.sdc.workflow.services.annotations.UserId;
+import org.springframework.core.MethodParameter;
+import org.springframework.web.bind.ServletRequestBindingException;
+import org.springframework.web.context.request.NativeWebRequest;
+
+/**
+ * Tests injection of user ID from HTTP headers.
+ *
+ * @author evitaliy
+ * @since 21 Aug 2018
+ */
+public class UserIdResolverTest {
+
+    @Test
+    public void oneHeaderSelectedWhenMultipleUserIdHeadersSent() throws ServletRequestBindingException {
+
+        final String headerValue = "UserIdValueFromHeader";
+
+        HttpServletRequest servletRequestMock = mock(HttpServletRequest.class);
+        when(servletRequestMock.getHeader(USER_ID_HEADER)).thenReturn(headerValue);
+
+        NativeWebRequest webRequestMock = mock(NativeWebRequest.class);
+        when(webRequestMock.getNativeRequest(HttpServletRequest.class)).thenReturn(servletRequestMock);
+
+        Object resolved = new UserIdResolver().resolveArgument(null, null, webRequestMock, null);
+        assertEquals(headerValue, resolved);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void illegalTypeErrorThrownWhenAnnotatedParameterIsNotOfTypeString() {
+        MethodParameter methodParameterMock = mock(MethodParameter.class);
+        when(methodParameterMock.hasParameterAnnotation(UserId.class)).thenReturn(true);
+        //noinspection unchecked
+        when(methodParameterMock.getParameterType()).thenReturn((Class)String[].class);
+        new UserIdResolver().supportsParameter(methodParameterMock);
+    }
+
+    @Test(expected = ServletRequestBindingException.class)
+    public void missingHeaderErrorThrownWhenUserIdHeaderNotPopulated() throws ServletRequestBindingException {
+        NativeWebRequest webRequestMock = mock(NativeWebRequest.class);
+        when(webRequestMock.getNativeRequest(HttpServletRequest.class)).thenReturn(mock(HttpServletRequest.class));
+        new UserIdResolver().resolveArgument(null, null, webRequestMock, null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void exceptionThrownWhenRequestTypeIsNotHttpRequest() throws ServletRequestBindingException {
+        NativeWebRequest webRequestMock = mock(NativeWebRequest.class);
+        new UserIdResolver().resolveArgument(null, null, webRequestMock, null);
+    }
+
+    @Test
+    public void parameterNotSupportedWhenNotAnnotatedWithUserIdAnnotation() {
+        MethodParameter methodParameterMock = mock(MethodParameter.class);
+        assertFalse(new UserIdResolver().supportsParameter(methodParameterMock));
+    }
+
+    @Test
+    public void parameterSupportedWhenAnnotatedWithUserIdAnnotationAndOfTypeString() {
+        MethodParameter methodParameterMock = mock(MethodParameter.class);
+        when(methodParameterMock.hasParameterAnnotation(UserId.class)).thenReturn(true);
+        //noinspection unchecked
+        when(methodParameterMock.getParameterType()).thenReturn((Class) String.class);
+        assertTrue(new UserIdResolver().supportsParameter(methodParameterMock));
+    }
+}
\ No newline at end of file