Spring Boot + React CORS issue without spring security - java

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);
}
}

Related

Spring Boot Exception Handling -> Not Return Generic Exception

I have a problem to return the ErrorDTO from Generic Exception.
When I send a request to http://localhost:8080/v1/locations with this response body shown below, I get this issue underneath GlobalExceptionHandler.
{
    "code" : "DELHI_IN_QWERTYUI", -> IT thows an error because of its length (length is 12)
    "city_name" : "New Delhi",
    "region_name" : "Delhi",
    "country_name" : "India",
    "country_code" : "IN",
    "enabled" : true
}
Here is the method defined in controller shown below?
#PostMapping
public ResponseEntity<Location> addLocation(#RequestBody #Valid Location location) {
Location addedLocation = service.add(location);
URI uri = URI.create("/v1/locations/" + addedLocation.getCode());
return ResponseEntity.created(uri).body(addedLocation);
}
How can I fix the issue?
Here is the ErrorDTO below.
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class ErrorDTO {
private LocalDateTime timestamp;
private int status;
private String path;
private HttpStatus httpStatus;
List<String> errorDetails;
}
Here is the GlobalExceptionError shown below
#ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);
// handleMissingServletRequestParameter : triggers when there are missing parameters
#Override
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
List<String> details = new ArrayList<String>();
StringBuilder builder = new StringBuilder();
builder.append(ex.getMessage() + " is not supported");
details.add(builder.toString());
HttpStatus httpStatus = HttpStatus.valueOf(status.value());
ErrorDTO error = new ErrorDTO.ErrorDTOBuilder()
.timestamp(LocalDateTime.now())
.status(status.value())
.errorDetails(details)
.path(request.getContextPath())
.httpStatus(httpStatus)
.build();
LOGGER.error("GlobalExceptionHandler | handleHttpRequestMethodNotSupported", error);
return ResponseEntity.status(status).body(error);
}
// handleMethodArgumentNotValid : triggers when #Valid fails
#Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(err -> errors.put(err.getField(), err.getDefaultMessage()));
LOGGER.error("GlobalExceptionHandler | handleMethodArgumentNotValid", errors);
return ResponseEntity.badRequest()
.body(errors);
}
// handleMissingServletRequestParameter : triggers when there are missing parameters
#Override
protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
List<String> details = new ArrayList<String>();
StringBuilder builder = new StringBuilder();
builder.append(ex.getParameterName());
details.add(builder.toString());
HttpStatus httpStatus = HttpStatus.valueOf(status.value());
ErrorDTO error = new ErrorDTO.ErrorDTOBuilder()
.timestamp(LocalDateTime.now())
.status(status.value())
.errorDetails(details)
.path(request.getContextPath())
.httpStatus(httpStatus)
.build();
LOGGER.error("GlobalExceptionHandler | handleMissingServletRequestParameter", error);
return ResponseEntity.status(status).body(error);
}
// handleHttpMessageNotReadable : triggers when the JSON is malformed
#Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
List<String> details = new ArrayList<String>();
StringBuilder builder = new StringBuilder();
builder.append(ex.getMessage());
details.add(builder.toString());
HttpStatus httpStatus = HttpStatus.valueOf(status.value());
ErrorDTO error = new ErrorDTO.ErrorDTOBuilder()
.timestamp(LocalDateTime.now())
.status(status.value())
.errorDetails(details)
.path(request.getContextPath())
.httpStatus(httpStatus)
.build();
LOGGER.error("GlobalExceptionHandler | handleHttpMessageNotReadable", error);
return ResponseEntity.status(status).body(error);
}
#ExceptionHandler(Exception.class)
public ErrorDTO handleGenericException(HttpServletRequest request, Exception ex) {
List<String> details = new ArrayList<String>();
details.add(ex.getMessage());
ErrorDTO error = new ErrorDTO.ErrorDTOBuilder()
.timestamp(LocalDateTime.now())
.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
.errorDetails(details)
.path(request.getServletPath())
.httpStatus(HttpStatus.INTERNAL_SERVER_ERROR)
.build();
LOGGER.error("GlobalExceptionHandler | handleGenericException", error);
return error;
}
}
Here is the error shown below.
{
    "timestamp": "2023-02-17T12:56:02.341+00:00",
    "status": 404,
    "error": "Not Found",
    "trace": "org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]\r\n\tat org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:273)\r\n\tat org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)\r\n\tat org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566)\r\n\tat org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743)\r\n\tat org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)\r\n\tat org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654)\r\n\tat org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407)\r\n\tat org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)\r\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)\r\n\tat org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)\r\n\tat org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703)\r\n\tat com.skyapi.weatherforecast.location.LocationService$$SpringCGLIB$$0.add(<generated>)\r\n\tat com.skyapi.weatherforecast.location.LocationApiController.addLocation(LocationApiController.java:21)\r\n\tat java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)\r\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:578)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207)\r\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)\r\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1080)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:973)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)\r\n\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:731)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)\r\n\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:223)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)\r\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)\r\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)\r\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)\r\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)\r\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)\r\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\r\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)\r\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119)\r\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\r\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)\r\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400)\r\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:859)\r\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1734)\r\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.base/java.lang.Thread.run(Thread.java:1589)\r\nCaused by: org.hibernate.exception.DataException: could not execute statement\r\n\tat org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:53)\r\n\tat org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56)\r\n\tat org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)\r\n\tat org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95)\r\n\tat org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:200)\r\n\tat org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3429)\r\n\tat org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:4058)\r\n\tat org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:103)\r\n\tat org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:612)\r\n\tat org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:483)\r\n\tat java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:729)\r\n\tat org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:480)\r\n\tat org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:329)\r\n\tat org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)\r\n\tat org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)\r\n\tat org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1425)\r\n\tat org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:477)\r\n\tat org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2234)\r\n\tat org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1930)\r\n\tat org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439)\r\n\tat org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)\r\n\tat org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)\r\n\tat org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)\r\n\tat org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562)\r\n\t... 58 more\r\nCaused by: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Data too long for column 'code' at row 1\r\n\tat com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:104)\r\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:916)\r\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1061)\r\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1009)\r\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1320)\r\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:994)\r\n\tat com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)\r\n\tat com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)\r\n\tat org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)\r\n\t... 77 more\r\n",
    "message": "could not execute statement; SQL [n/a]",
    "path": "/v1/locations"
}
Here is the console output shown
org.springframework.web.HttpMediaTypeNotAcceptableException: No acceptable representation
It return this kind of exception message rather than ErrorDTO.
Here is the repo : Link
How can I fix the issue?
After adding #Data annotation to ErrorDTO, the issue disappeared.
#Builder
#AllArgsConstructor
#NoArgsConstructor
#Data
public class ErrorDTO {
private LocalDateTime timestamp;
private int status;
private String path;
private HttpStatus httpStatus;
List<String> errorDetails;
}

Rest Template dependency not mocked in case of static mock block due to which exchange method returning null

I am trying to write junit for existing class which i can't modify but there are two method for which i need to write junit both are using restTemplate but for some reason rest template is not mocking if i mock it within a mock static context in junit .
But if i Mock globally then getRestTemplateInstance().exchange returning null. Could you please someone correct or point out problem so my test case can achieve 100% coverage
Class:
#Service
public class LocationRestTemplate {
private static final int READ_TIME_OUT = 5000;
private RestTemplate restTemplate;
#Value("${external-services.api}")
private String fallBackApiUrl;
RestTemplate getRestTemplateInstance() {
if (this.restTemplate == null) {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
this.restTemplate = new RestTemplate(clientHttpRequestFactory());
restTemplate.setRequestFactory(factory);
List<HttpMessageConverter<?>> messageConverterList = restTemplate.getMessageConverters();
// Set HTTP Message converter using a JSON implementation.
MappingJackson2HttpMessageConverter jsonMessageConverter = new MappingJackson2HttpMessageConverter();
// Add supported media type
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(new MediaType("text", "plain"));
supportedMediaTypes.add(new MediaType("application", "json"));
jsonMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
messageConverterList.add(jsonMessageConverter);
restTemplate.setMessageConverters(messageConverterList);
}
return restTemplate;
}
public ExternalSkuInfo getSkuInfoFromExternalService(String store, List<String> skuList) {
java.net.URI builtUrl = null;
try {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(fallBackApiUrl + "/bays/store/")
.pathSegment(store).path("/sku").pathSegment(String.join(",", skuList));
builtUrl = builder.build().encode().toUri();
ResponseEntity<ExternalSkuInfo> response = getRestTemplateInstance().exchange(builtUrl, HttpMethod.GET,
getRequestEntity(), ExternalSkuInfo.class);
if (response.getStatusCode() == HttpStatus.OK) {
return response.getBody();
}
} catch (RestClientException e) {
} catch (Exception exception) {
}
return null;
}
private ClientHttpRequestFactory clientHttpRequestFactory() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setReadTimeout(READ_TIME_OUT);
factory.setConnectTimeout(READ_TIME_OUT);
return factory;
}
HttpEntity<Object> getRequestEntity() {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Lists.newArrayList(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN));
return new HttpEntity<>(headers);
}
}
Test Class
public class LocationRestTemplateTest {
#InjectMocks
private LocationRestTemplate cut;
#Before
public void setUp() {
MockitoAnnotations.openMocks(this);
}
#Test
public void testGetRestTemplateInstance() {
RestTemplate restTemplate = cut.getRestTemplateInstance();
Assert.assertNotNull(restTemplate);
}
#Test(expected = Exception.class)
public void testGetSkuInfoFromExternalService() {
RestTemplate restTemplate1 = Mockito.mock(RestTemplate.class);
try (MockedStatic<UriComponentsBuilder> uriComponentsBuilderMockedStatic = Mockito
.mockStatic(UriComponentsBuilder.class)) {
List<String> sku = new ArrayList<>();
sku.add("01234");
ReflectionTestUtils.setField(cut, "fallBackApiUrl", "test");
UriComponentsBuilder uriComponentsBuilder = Mockito.mock(UriComponentsBuilder.class);
UriComponents uriComponents = Mockito.mock(UriComponents.class);
URI uri = Mockito.mock(URI.class);
RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
ResponseEntity responseEntity = Mockito.mock(ResponseEntity.class);
uriComponentsBuilderMockedStatic.when(() -> UriComponentsBuilder.fromHttpUrl("test/bays/store/"))
.thenReturn(uriComponentsBuilder);
Mockito.doReturn(uriComponentsBuilder).when(uriComponentsBuilder).pathSegment("0123");
Mockito.doReturn(uriComponentsBuilder).when(uriComponentsBuilder).path("/sku");
Mockito.doReturn(uriComponentsBuilder).when(uriComponentsBuilder).pathSegment(String.join(",", sku));
Mockito.doReturn(uriComponents).when(uriComponentsBuilder).build();
Mockito.doReturn(uriComponents).when(uriComponents).encode();
Mockito.doReturn(uri).when(uriComponents).toUri();
Mockito.doReturn(responseEntity).when(restTemplate)
.exchange(uri, HttpMethod.GET, getRequestEntity(), ExternalSkuInfo.class);
cut.getSkuInfoFromExternalService("0123", sku);
}
}
HttpEntity<Object> getRequestEntity() {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Lists.newArrayList(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN));
return new HttpEntity<>(headers);
}
}

How can add Bearer before token

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);
}
}

Custom exception not giving correct message, spring?

I have added customexception class to handle my api class.
Exception class
#SuppressWarnings({ "unchecked", "rawtypes" })
#ControllerAdvice
public class ApiExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler(Exception.class)
public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
List<String> details = new ArrayList<>();
details.add(ex.getLocalizedMessage());
ErrorMessage error = new ErrorMessage("Server Error", details);
return new ResponseEntity(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
#ExceptionHandler(RecordNotFoundException.class)
public final ResponseEntity<Object> handleConfigNotFoundException(RecordNotFoundException ex, WebRequest request) {
List<String> details = new ArrayList<>();
details.add(ex.getLocalizedMessage());
ErrorMessage error = new ErrorMessage("Record Not Found", details);
return new ResponseEntity(error, HttpStatus.NOT_FOUND);
}
#Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
List<String> details = new ArrayList<>();
for (ObjectError error : ex.getBindingResult().getAllErrors()) {
details.add(error.getDefaultMessage());
}
ErrorMessage error = new ErrorMessage("Validation Failed", details);
return new ResponseEntity(error, HttpStatus.BAD_REQUEST);
}
}
API method
#RequestMapping(value = "/config", params = { "appCode", "appVersion" }, method = RequestMethod.GET)
public ResponseEntity<ConfigResponse> getConfig(#RequestParam(value = "appCode", required = true) String appCode,
#RequestParam(value = "appVersion", required = true) String appVersion) {
List<AppConfig> result = configRepository.findByCodeAndVersion(appCode, appVersion);
if (result.isEmpty()) {
throw new RecordNotFoundException(appCode + " or " + appVersion + "does not exist");
}
AppConfig config = new AppConfig();
return new ResponseEntity<ConfigResponse>(config.convertToResponse(result), HttpStatus.OK);
}
Record Not found
#ResponseStatus(HttpStatus.NOT_FOUND)
public class RecordNotFoundException extends RuntimeException {
public RecordNotFoundException(String exception) {
super(exception);
}
}
I am checking for the record not found but it still gives me the spring exception and not my custom exception.

Return Value from async rest template spring

I am creating a async rest call using spring
#GetMapping(path = "/testingAsync")
public String value() throws ExecutionException, InterruptedException, TimeoutException {
AsyncRestTemplate restTemplate = new AsyncRestTemplate();
String baseUrl = "https://api.github.com/users/XXX";
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
String value = "";
HttpEntity entity = new HttpEntity("parameters", requestHeaders);
ListenableFuture<ResponseEntity<User>> futureEntity = restTemplate.getForEntity(baseUrl, User.class);
futureEntity.addCallback(new ListenableFutureCallback<ResponseEntity<User>>() {
#Override
public void onSuccess(ResponseEntity<User> result) {
System.out.println(result.getBody().getName());
// instead of this how can i return the value to the user ?
}
#Override
public void onFailure(Throwable ex) {
}
});
return "DONE"; // instead of done i want to return value to the user comming from the rest call
}
And is there any way i can convert ListenableFuture to use CompletableFuture that is used in java 8 ?
There are basically 2 things you can do.
Remove the ListenableFutureCallback and simply return the ListenableFuture
Create a DeferredResult and set the value of that in a ListenableFutureCallback.
Returning a ListenableFuture
#GetMapping(path = "/testingAsync")
public ListenableFuture<ResponseEntity<User>> value() throws ExecutionException, InterruptedException, TimeoutException {
AsyncRestTemplate restTemplate = new AsyncRestTemplate();
String baseUrl = "https://api.github.com/users/XXX";
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
String value = "";
HttpEntity entity = new HttpEntity("parameters", requestHeaders);
return restTemplate.getForEntity(baseUrl, User.class);
}
Spring MVC will add a ListenableFutureCallback itself to fill a DeferredResult and you will get a User eventually.
Using a DeferredResult
If you want more control on what to return you can use a DeferredResult and set the value yourself.
#GetMapping(path = "/testingAsync")
public DeferredResult<String> value() throws ExecutionException, InterruptedException, TimeoutException {
AsyncRestTemplate restTemplate = new AsyncRestTemplate();
String baseUrl = "https://api.github.com/users/XXX";
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
String value = "";
HttpEntity entity = new HttpEntity("parameters", requestHeaders);
final DeferredResult<String> result = new DeferredResult<>();
ListenableFuture<ResponseEntity<User>> futureEntity = restTemplate.getForEntity(baseUrl, User.class);
futureEntity.addCallback(new ListenableFutureCallback<ResponseEntity<User>>() {
#Override
public void onSuccess(ResponseEntity<User> result) {
System.out.println(result.getBody().getName());
result.setResult(result.getBody().getName());
}
#Override
public void onFailure(Throwable ex) {
result.setErrorResult(ex.getMessage());
}
});
return result;
}
I don't know too much about async calls in Spring but I would imagine that you could return the text that you want through the ResponseBody
It would look like this:
#GetMapping(path = "/testingAsync")
#ResponseBody
public String value() throws ExecutionException, InterruptedException, TimeoutException {
...
...
#Override
public void onSuccess(ResponseEntity<User> result) {
return result.getBody().getName();
}
...
}
Sorry if this isn't what you are asking about.

Categories

Resources