PostMan
My BaseController code
#SuppressWarnings("unused")
#Autowired
private UserService userService;
public User handleTokenAccess(String encodeString) throws Exception {
byte[] decodedBytes = Base64.getMimeDecoder().decode(encodeString);
String decodedMime = new String(decodedBytes);
ObjectMapper mapper = new ObjectMapper();
try {
UserClient map = mapper.readValue(decodedMime, UserClient.class);
User user = userService.findOne(map.getUserId());
if (user != null)
return user;
else
throw new Exception();
} catch (Exception e) {
throw new Exception("Sai token , vui lòng chim cút");
}
}
My CategoriesController code
#RestController
#RequestMapping("/api/categories")
public class CategoriesController extends BaseController {
#Autowired
private CategoriesService categoriesService;
#Autowired
UserService userService;
#RequestMapping(value = "/create-category", method = RequestMethod.POST, produces = {
MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<BaseResponse> create(#Valid #RequestBody CRUDCategories wrapper,
#RequestHeader(value = "Authorization") String token) throws Exception {
BaseResponse response = new BaseResponse();
User userToken = this.handleTokenAccess(token);
Categories category = categoriesService.spUCreateCategory(userToken.getId(), wrapper.get_name(),
wrapper.getDescpiption(), wrapper.get_sort());
response.setData(new CategoriesResponse(category));
return new ResponseEntity<BaseResponse>(response, HttpStatus.OK);
}
}
Related
I'm using Spring Boot 2.2.2.RELEASE as a REST service and React for front-end.
Just a simple GET method implemented, But getting CORS issue when communicating to the server via REACT.
https://spring.io/guides/gs/rest-service-cors/ -> followed this link, but no luck.
my Spring Boot Controller:
#RestController
public class FeedController {
#Autowired
private IFeedService IFeedService;
#CrossOrigin(origins = "http://localhost:3000")
#GetMapping(path="/v1/getdashboard")
public ResponseEntity<String> feedDashBoardController(){
String result = null;
HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
try {
List<FeedData> dashBoardFeedInfo = IFeedService.getDashBoardFeedService();
// Create ObjectMapper
ObjectMapper mapper = new ObjectMapper();
JsonNode dataNode = mapper.valueToTree(dashBoardFeedInfo);
result = FeedResponseData.generateFeedResponse(dataNode);
httpStatus = HttpStatus.OK;
}catch(TBServiceException e) {
result = AppExceptions.handleException("Something Went Wrong");
httpStatus = HttpStatus.BAD_REQUEST;
}
return new ResponseEntity<String>(result,httpStatus);
}
}
my Spring Boot Application:
#SpringBootApplication
public class TechnicalBlogApplication {
public static void main(String[] args) {
SpringApplication.run(TechnicalBlogApplication.class, args);
System.out.println("Application Main - Update -1");
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/v1/getdashboard").allowedOrigins("http://localhost:3000");
}
};
}
}
my Spring application properties:
spring.profiles.active=dev
server.port=6001
server.servlet.context-path=/technical-blog
my React Code Snippet:
async componentDidMount() {
const dashboardData= await fetch("http://localhost:6001/technical-blog/v1/getdashboard");
console.log("dash ",dashboardData)
}
I have also tried setting the headers, below is the re-modified controller. i got multi CORS definition error.
#RestController
public class FeedController {
#Autowired
private IFeedService IFeedService;
#CrossOrigin(origins = "http://localhost:3000")
#GetMapping(path="/v1/getdashboard")
public ResponseEntity<String> feedDashBoardController(){
String result = null;
HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
try {
List<FeedData> dashBoardFeedInfo = IFeedService.getDashBoardFeedService();
// Create ObjectMapper
ObjectMapper mapper = new ObjectMapper();
JsonNode dataNode = mapper.valueToTree(dashBoardFeedInfo);
result = FeedResponseData.generateFeedResponse(dataNode);
httpStatus = HttpStatus.OK;
}catch(TBServiceException e) {
result = AppExceptions.handleException("Something Went Wrong");
httpStatus = HttpStatus.BAD_REQUEST;
}
return new ResponseEntity<String>(result,setHeaders(),httpStatus);
}
}
private HttpHeaders setHeaders() {
List<HttpMethod> allowedMethods = new ArrayList<>();
allowedMethods.add(HttpMethod.GET);
allowedMethods.add(HttpMethod.POST);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
//httpHeaders.setAccessControlAllowOrigin("*");
httpHeaders.setAccessControlAllowCredentials(true);
httpHeaders.setAccessControlAllowMethods(allowedMethods);
httpHeaders.setAccessControlMaxAge(3600);
return httpHeaders;
}
i think you should put #CrossOrigin(origins = "http://localhost:3000") on the controller it self because the first thing that request goes to is the controller not the function
so it will be like that
#RestController
#CrossOrigin(origins = "http://localhost:3000")
public class FeedController {
#Autowired
private IFeedService IFeedService;
#GetMapping(path="/v1/getdashboard")
public ResponseEntity<String> feedDashBoardController(){
String result = null;
HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
try {
List<FeedData> dashBoardFeedInfo = IFeedService.getDashBoardFeedService();
// Create ObjectMapper
ObjectMapper mapper = new ObjectMapper();
JsonNode dataNode = mapper.valueToTree(dashBoardFeedInfo);
result = FeedResponseData.generateFeedResponse(dataNode);
httpStatus = HttpStatus.OK;
}catch(TBServiceException e) {
result = AppExceptions.handleException("Something Went Wrong");
httpStatus = HttpStatus.BAD_REQUEST;
}
return new ResponseEntity<String>(result,setHeaders(),httpStatus);
}
}
I'm trying to override default error messages in BindingResult. I implemented Controller advice like this
#ControllerAdvice
public final class DefaultControllerAdvice {
private static final String ERROR_MESSAGE_FORMATTER = " - ";
#ExceptionHandler(BindException.class)
#ResponseStatus(value = HttpStatus.BAD_REQUEST)
public List<String> handleValidationException(final BindException exception) {
return exception.getBindingResult()
.getAllErrors()
.stream()
.filter(error -> error instanceof FieldError)
.map(objectError -> (FieldError) objectError)
.map(errorMessageFormatter)
.collect(Collectors.toList());
}
private final Function<FieldError, String> errorMessageFormatter =
error -> error.getField() + ERROR_MESSAGE_FORMATTER + error.getDefaultMessage();
}
and my controller
#PostMapping(value = "/register")
private String postRegistration( #ModelAttribute #Valid final UserCreateFormDto user, final BindingResult result,
final RedirectAttributes redirectAttributes, final WebRequest webRequest) {
try {
if (result.hasErrors()) {
redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.user", result);
redirectAttributes.addFlashAttribute("user", user);
throw new BindException(result);
}
if (userService.checkEmailExist(user.getEmail())) {
throw new UserNotExistsException("User with email: "+ user.getEmail()+" already exists.");
}
final User registered = userService.createNewUserAccount(user);
final String appUrl = webRequest.getContextPath();
eventPublisher.publishEvent(
new RegistrationCompleteEvent(registered, webRequest.getLocale(), appUrl));
return "redirect:/login?success";
} catch (UserNotExistsException error) {
return "redirect:/register?exists";
} catch (BindException error) {
return "redirect:/register";
}
}
and test case
#Test
public void shouldNotCreateUserWhenUsernameIsEmpty() throws Exception {
//given
final UserCreateFormDto userCreateFormDto = createUserCreateForm();
final User user = createUser();
given(userService.checkEmailExist(userCreateFormDto.getEmail())).willReturn(false);
given(userService.createNewUserAccount(any(UserCreateFormDto.class))).willReturn(user);
//when
final MvcResult response = mockMvc
.perform(post("/register").with(csrf())
.contentType(MediaType.MULTIPART_FORM_DATA)
.param("username","")
.param("email",userCreateFormDto.getEmail())
.param("password", Arrays.toString(userCreateFormDto.getPassword()))
.param("matchingPassword", Arrays.toString(userCreateFormDto.getMatchingPassword())))
.andReturn();
//then
assertThat(response.getFlashMap().isEmpty()).isFalse();
assertThat(response.getResponse().getStatus()).isEqualTo(HttpStatus.FOUND.value());
assertThat(response.getResponse().getRedirectedUrl()).isEqualTo("/register");
verify(userService, times(1)).checkEmailExist(userCreateFormDto.getEmail());
verify(userService, times(0)).createNewUserAccount(any(UserCreateFormDto.class));
my question is how to get the bindingResult default error message?
I would like to test what an error message is getting while validate input fields.
I am trying to create a Mock of my controller to update data inside user. From the code I am trying to update only the email, password, and age. Is this how we should do the mock? Because I'm still really new with this Mockito and Junit
Controller Mock
#Test
public void testUpdateUserController() throws Exception{
String username = "User";
String email = "user#email.com";
String password = "password123";
int age = 90;
Mockito.when(userService.updateUser(username,email,password,age)).then(invocationOnMock -> {
User user = new User();
user.setUsername("User");
user.setEmail("user#user.com");
user.setPassword("123456");
user.setAge(12);
user.setAddress("11111");
user.setIsActive(true);
return Optional.of(user);
});
mockMvc.perform(MockMvcRequestBuilders.put(BASE_URL + "/users/{username}",username)
.contentType(MediaType.APPLICATION_JSON_UTF8)).andExpect(MockMvcResultMatchers.status().isOk());
Mockito.verify(userService, Mockito.times(1)).updateUser(userCaptor.capture(),emailCaptor.capture(),passwordCaptor.capture(),ageCaptor.capture());
Assert.assertEquals("User", userCaptor.getValue());
Assert.assertEquals("user#email.com", emailCaptor.getValue());
Assert.assertEquals("password123", passwordCaptor.getValue());
Assert.assertEquals("90", ageCaptor.getValue());
Assert.assertEquals("11111", addressCaptor.getValue());
}
UserServiceImpl
#Override
public boolean updateUser(String username, String email, String password, Integer age) {
Optional<User> userList = userRepository.findByUsernameAndIsActiveTrue(username);
if (userList.isPresent()) {
User user = userList.get();
user.setEmail(email);
user.setPassword(password);
user.setAge(age);
userRepository.save(user);
return true;
} else {
return false;
}
}
Here is one of my code samples for MVC Mocks
#RunWith(PowerMockRunner.class)
public class TrainingControllerTest {
#Mock
private TrainingService trainingService;
#Mock
private FileStorageService fileStorageService;
#InjectMocks
private TrainingController controller = new TrainingController();
private MockMvc mockMvc;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(controller)
.setControllerAdvice(new ExceptionController())
.build();
}
#Test
public void testCreateHappyPath() throws Exception {
Training training = new Training();
Optional<Training> result = Optional.of(training);
TrainingExt ext = result
.map(TrainingExt::of)
.get();
when(trainingService.createTraining(any(Training.class))).thenReturn(result);
ObjectMapper mapper = new ObjectMapper();
String trainingPayloadJSON = mapper.writerFor(Training.class).writeValueAsString(training);
String trainingExtJSON = mapper.writerFor(TrainingExt.class).writeValueAsString(ext);
mockMvc.perform(MockMvcRequestBuilders.post(TestConstants.POST_TRAINING_URI)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(trainingPayloadJSON)
)
.andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(content().json(trainingExtJSON));
}
#Test
public void testPutHappyPath() throws Exception {
Training training = new Training();
Optional<Training> result = Optional.of(training);
TrainingExt ext = result
.map(TrainingExt::of)
.get();
when(trainingService.update(any(Training.class))).thenReturn(result);
ObjectMapper mapper = new ObjectMapper();
String trainingPayloadJSON = mapper.writerFor(Training.class).writeValueAsString(training);
String trainingExtJSON = mapper.writerFor(TrainingExt.class).writeValueAsString(ext);
mockMvc.perform(MockMvcRequestBuilders.put(TestConstants.GET_PUT_DELETE_TRAINING_URI, TestConstants.ID)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(trainingPayloadJSON)
)
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(content().json(trainingExtJSON));
}
#Test
public void testAddAttendeesHappyPath() throws Exception {
Attendees attendees = new Attendees();
Optional<Training> result = Optional.of(new Training());
TrainingExt ext = result
.map(TrainingExt::of)
.get();
when(trainingService.registerTrainingAttendees(any(Attendees.class))).thenReturn(result);
ObjectMapper mapper = new ObjectMapper();
String attendeesPayloadJSON = mapper.writerFor(Attendees.class).writeValueAsString(attendees);
String trainingExtJSON = mapper.writerFor(TrainingExt.class).writeValueAsString(ext);
mockMvc.perform(MockMvcRequestBuilders.post(TestConstants.ADD_ATTENDEES_URI)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(attendeesPayloadJSON)
)
.andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(content().json(trainingExtJSON));
}
}
Getting following exception while hitting a Rest endpoint. How do I typecast from String to ProtectPanReplyType class?
Error:
Error - Request: http://localhost:9090/hosted-payments-webapp-1.0.0/pan/protect
raised java.lang.ClassCastException: com.gsicommerce.api.checkout.ProtectPanReplyType cannot be cast to java.lang.String
ProtectPanServiceImpl.java
#Service
public class ProtectPanServiceImpl implements ProtectPanService {
#Override
public ResponseEntity<?> sendProtectPanRequest(ProtectPan protectPan) {
String pan = protectPan.getPaymentAccountNumber();
String tenderClass = protectPan.getTenderClass();
String protectPanRequest = XMLHelper.createProtectPanRequest(pan, tenderClass);
System.out.println("protectPanRequest = " + protectPanRequest);
ResponseEntity<String> response = null;
try {
response = ApiClientUtils.callClientByEndpointandMessage(protectPanRequest, DEV_PUBLIC_API_URL,
ProtectPanReplyType.class);
System.out.println("response.getClass() = " + response.getClass());
//DOES NOT WORK
//ProtectPanReplyType protectPanReplyType = (ProtectPanReplyType)response.getBody();
//THROWS ClassCastException HERE
System.out.println(response.getBody());
} catch (JiBXException e) {
e.printStackTrace();
}
return response;
}
}
ApiClientUtils.java
public ResponseEntity<String> callClientByEndpointandMessage(String xmlRequest, String endpoint, Class<?> replyType) throws JiBXException {
HttpEntity<String> request = createRequestForUser("username", "secret",xmlRequest);
ResponseEntity<String> response = restOperations.postForEntity(endpoint, request, String.class);
ResponseEntity formattedResponse = new ResponseEntity(null, HttpStatus.BAD_REQUEST);
try {
Object jibxObject = JibxHelper.unmarshalMessage(response.getBody(), replyType);
formattedResponse = new ResponseEntity(jibxObject, HttpStatus.OK);
} catch (JiBXException e) {
FaultResponseType faultResponse = JibxHelper.unmarshalMessage(response.getBody(), FaultResponseType.class);
formattedResponse = new ResponseEntity(faultResponse, HttpStatus.BAD_REQUEST);
}
return formattedResponse;
}
ProtectPan.java
public class ProtectPan {
#JsonProperty("paymentAccountNumber")
private String paymentAccountNumber;
#JsonProperty("tenderClass")
private String tenderClass;
public String getPaymentAccountNumber() {
return paymentAccountNumber;
}
public String getTenderClass() {
return tenderClass;
}
}
ProtectPanReplyType.java
public class ProtectPanReplyType {
private String token;
private List<Element> anyList = new ArrayList<Element>();
private String sessionId;
//getters and setter removed for brevity
}
Use ResponseEntity<ProtectPanReplyType> instead ResponseEntity<String>
Build and Return ProtectPanReplyType from your restOperations.postForEntity()
Was finally able to get the object after making following changes.
ApiClientUtils.java
public ResponseEntity<?> callClientByEndpointandMessage(String xmlRequest, String endpoint, Class<?> replyType) throws JiBXException {
HttpEntity<String> request = createRequestForUser("payment", "SONitc2m8y", xmlRequest);
ResponseEntity<String> response = restOperations.postForEntity(endpoint, request, String.class);
ResponseEntity<?> formattedResponse = null;
try {
Object jibxObject = JibxHelper.unmarshalMessage(response.getBody(), replyType);
formattedResponse = new ResponseEntity(jibxObject, HttpStatus.OK);
} catch (JiBXException e) {
FaultResponseType faultResponse = JibxHelper.unmarshalMessage(response.getBody(), FaultResponseType.class);
formattedResponse = new ResponseEntity(faultResponse, HttpStatus.BAD_REQUEST);
}
return formattedResponse;
}
ProtectPanServiceImpl.java
#Override
public ResponseEntity<?> sendProtectPanRequest(ProtectPan protectPan) {
String pan = protectPan.getPaymentAccountNumber();
String tenderClass = protectPan.getTenderClass();
String protectPanRequest = XMLHelper.createProtectPanRequest(pan, tenderClass);
ResponseEntity<?> response = null;
try {
response = publicApiClientUtils.callClientByEndpointandMessage(protectPanRequest, DEV_PUBLIC_API_URL, ProtectPanReplyType.class);
ProtectPanReplyType protectPanReplyType = (ProtectPanReplyType) response.getBody();
System.out.println("protectPanReplyType = " + protectPanReplyType);
} catch (JiBXException e) {
e.printStackTrace();
}
return response;
}
I have a below controller
#Controller
public class TestController{
public Future<ArrayList<String>> global_value = null;
#Autowired
private AsyncService asyncService;
#RequestMapping(value = "/asyncCall", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public String getToken(HttpServletRequest request) {
global_value = asyncService.execute();
return "OK";
}
#RequestMapping(value = "/getAsyncData", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ArrayList<String> getData() {
try {
if (global_value != null && global_value.get().size() > 0) {
return global_value.get();
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
}
When I long poll the getAsncData endpoint, how do I maintain the global_value is just for a request. global_value must be unique for the request scope.
How can I achieve this?