The request is not being executed in rest controller test - java

I have a test method for one of the mappings where I provide all required data for the test
#Test
public void getAllMessagesNoFilterNotByTag() throws Exception {
List<MessageDTO> messageDTOS = Arrays.asList(new MessageDTO(MESSAGE1), new MessageDTO(MESSAGE2));
when(messageService.getAllMessages("", false,
PageRequest.of(0, 5, Sort.by("creationDate").descending()))).thenReturn(messageDTOS);
mockMvc.perform(get("/api/message?filter=&bytag=false&page=0"))
.andExpect(status().isOk())
.andExpect(content().json(
objectMapper.writeValueAsString(Arrays.asList(new MessageDTO(MESSAGE1), new MessageDTO(MESSAGE2)))));
verify(messageService, times(1)).getAllMessages("", false,
PageRequest.of(0, 5, Sort.by("creationDate").descending()));
}
Here is the controller itself
#GetMapping
public List<MessageDTO> getAllMessages(#RequestParam(required = false) String filter,
#RequestParam(name = "bytag", required = false) Boolean findByTag,
#PageableDefault(sort = {"creationDate"}, direction = Sort.Direction.DESC, size = 5) Pageable pageable) {
return messageService.getAllMessages(filter, findByTag, pageable);
}
But after running it I get this exception about failing to create Pageble object
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: No primary or single public constructor found for interface org.springframework.data.domain.Pageable - and no default constructor found either
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:72)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:183)
at com.training.vueblog.controllers.MessageControllerTest.getAllMessagesNoFilterNotByTag(MessageControllerTest.java:62)
Caused by: java.lang.IllegalStateException: No primary or single public constructor found for interface org.springframework.data.domain.Pageable - and no default constructor found either
at org.springframework.beans.BeanUtils.getResolvableConstructor(BeanUtils.java:250)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:216)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:85)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:144)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:170)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
... 74 more

The problem was solve by adding extra configuration for mockMvc
#BeforeEach
public void setup(){
mockMvc = MockMvcBuilders.standaloneSetup(messageController)
.setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
.build();
}

Related

Spring & HtmlUnit & WebDriver fails when method is async

I am trying to test a Spring MVC method, which looks like this:
#PostMapping("/register")
public Callable<String> register(...) {
return () -> {...}
}
However, when I test the code like this (as described in the spring docs):
WebDriver driver;
#BeforeEach
void setup(WebApplicationContext context) {
driver = MockMvcHtmlUnitDriverBuilder
.webAppContextSetup(context)
.build();
}
#Test
void someTest() {
...
submitButton.click() // sending the post request
}
then the test always fails with the following exception:
java.lang.IllegalStateException: Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding "<async-supported>true</async-supported>" to servlet and filter declarations in web.xml.
at org.springframework.util.Assert.state(Assert.java:76) ~[spring-core-5.3.25.jar:5.3.25]
at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.startAsync(StandardServletAsyncWebRequest.java:112) ~[spring-web-5.3.25.jar:5.3.25]
at org.springframework.web.context.request.async.WebAsyncManager.startAsyncProcessing(WebAsyncManager.java:483) ~[spring-web-5.3.25.jar:5.3.25]
at org.springframework.web.context.request.async.WebAsyncManager.startCallableProcessing(WebAsyncManager.java:331) ~[spring-web-5.3.25.jar:5.3.25]
at org.springframework.web.context.request.async.WebAsyncManager.startCallableProcessing(WebAsyncManager.java:267) ~[spring-web-5.3.25.jar:5.3.25]
at org.springframework.web.servlet.mvc.method.annotation.CallableMethodReturnValueHandler.handleReturnValue(CallableMethodReturnValueHandler.java:51) ~[spring-webmvc-5.3.25.jar:5.3.25]
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78) ~[spring-web-5.3.25.jar:5.3.25]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:135) ~[spring-webmvc-5.3.25.jar:5.3.25]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.25.jar:5.3.25]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.25.jar:5.3.25]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.25.jar:5.3.25]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071) ~[spring-webmvc-5.3.25.jar:5.3.25]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964) ~[spring-webmvc-5.3.25.jar:5.3.25]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.25.jar:5.3.25]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.25.jar:5.3.25]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:696) ~[tomcat-embed-core-9.0.71.jar:4.0.FR]
...
How can I configure async support with htmlUnit/webdriver/selenium?

issue with consuming restful webservice from openweather Api?

i was trying to retreive weather details from openweathermap api , some how i am not able to get it working with below errors . Any help would be highly appreciated
Controller
#Controller
public class CurrentWeatherController {
private final StubWeatherService stubWeatherService;
private final LiveWeatherService liveWeatherService;
public CurrentWeatherController(StubWeatherService stubWeatherService, LiveWeatherService liveWeatherService) {
this.stubWeatherService = stubWeatherService;
this.liveWeatherService = liveWeatherService;
}
#GetMapping("/current-weather")
public String getCurrentWeather(Model model) {
model.addAttribute("currentWeather", liveWeatherService.getCurrentWeather("Detroit","us"));
return "current-weather";
}
public StubWeatherService getStubWeatherService() {
return stubWeatherService;
}
service code
#Service
public class LiveWeatherService {
private static final String WEATHER_URL = "http://api.openweathermap.org/data/2.5/weather?q={city},{country}&APPID={key}&units=metric";
private final String apiKey="526a647fcd4f3f465c0340c19d26ef3a";
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
public LiveWeatherService(RestTemplateBuilder restTemplateBuilder, ObjectMapper objectMapper) {
this.restTemplate = restTemplateBuilder.build();
this.objectMapper = objectMapper;
}
public CurrentWeather getCurrentWeather(String city, String country) {
URI url = new UriTemplate(WEATHER_URL).expand(city, country,this.apiKey); // line 34 issue with accepting apikey
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
return convert(response);
}
private CurrentWeather convert(ResponseEntity<String> response) {
try {
JsonNode root = objectMapper.readTree(response.getBody());
return new CurrentWeather(root.path("weather").get(0).path("main").asText(),
BigDecimal.valueOf(root.path("main").path("temp").asDouble()),
BigDecimal.valueOf(root.path("main").path("feels_like").asDouble()),
BigDecimal.valueOf(root.path("wind").path("speed").asDouble()));
} catch (JsonProcessingException e) {
throw new RuntimeException("Error parsing JSON", e);
}
}
}
error
2-07 02:34:48.710 ERROR 43384 --- [nio-8080-exec-3]
o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for
servlet [dispatcherServlet] in context with path [] threw exception
[Handler dispatch failed; nested exception is java.lang.Error:
Unresolved compilation problem:
Type mismatch: cannot convert from UriTemplate to URI
] with root cause
java.lang.Error: Unresolved compilation problem:
Type mismatch: cannot convert from UriTemplate to URI
at com.meshupProjekt.service.LiveWeatherService.getCurrentWeather(LiveWeatherService.java:34)
~[classes/:na]
at com.meshupProjekt.controller.CurrentWeatherController.getCurrentWeather(CurrentWeatherController.java:36)
~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)
~[spring-web-5.3.2.jar:5.3.2]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)
~[spring-web-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1061)
~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961)
~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
~[spring-webmvc-5.3.2.jar:5.3.2]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
~[spring-webmvc-5.3.2.jar:5.3.2]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
~[spring-webmvc-5.3.2.jar:5.3.2]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.springframework.web.servlet.resource.ResourceUrlEncodingFilter.doFilter(ResourceUrlEncodingFilter.java:67)
~[spring-webmvc-5.3.2.jar:5.3.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
~[spring-
For me your code is working like this:
String WEATHER_URL = "http://api.openweathermap.org/data/2.5/weather?q={city},{country}&APPID={key}&units=metric";
String apiKey = "526a647fcd4f3f465c0340c19d26ef3a";
var x = new UriTemplate(WEATHER_URL).expand("Darmstadt", "Deutschland", apiKey);
System.out.println(x);
Instead of URI I used var so that Java selects proper type.
Your compilation error might be caused by wrong import of URI class.

How to throw custom exception in proper way when using #javax.validation.Valid?

How to throw a custom exception in the proper way when using #javax.validation.Valid?
I'm using #Valid in controller, and #AssertTrue to validate request body fields.
public ResponseEntity<Foo> createFoo(
#Valid #RequestBody Foo FooRequest ...
#AssertTrue()
public boolean isFooValid() {
if (invalid)
return false;
...
}
However, I want to throw customized Exception class in some condition.
#AssertTrue()
public boolean isFooValid() {
if (invalid)
return false;
...
// note below
if (invalidInAnotherCondition)
throw new CustomizedException(...);
}
I know this is not desirable way to utilize #Valid in controller, and #AssertTrue. Nevertheless, as I can make my own Exception class which contains customized error info, with the convenience of #Valid.
However the error happens.
javax.validation.ValidationException: HV000090: Unable to access isFooValid
at org.hibernate.validator.internal.util.ReflectionHelper.getValue(ReflectionHelper.java:245)
at org.hibernate.validator.internal.metadata.location.GetterConstraintLocation.getValue(GetterConstraintLocation.java:89)
at org.hibernate.validator.internal.engine.ValueContext.getValue(ValueContext.java:235)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:549)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:515)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:485)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:447)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:397)
at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:173)
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:117)
at org.springframework.boot.autoconfigure.validation.ValidatorAdapter.validate(ValidatorAdapter.java:70)
at org.springframework.validation.DataBinder.validate(DataBinder.java:889)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.validateIfApplicable(AbstractMessageConverterMethodArgumentResolver.java:266)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:137)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:523)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.reflect.InvocationTargetException: null
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.hibernate.validator.internal.util.ReflectionHelper.getValue(ReflectionHelper.java:242)
... 70 common frames omitted
Caused by: com.finda.services.finda.common.exception.CustomizedException: 'df282e0d-1205-4574-adaa-0af819af66c0'
at ...
... 75 common frames omitted
I think this happens because originally, #AssertTrue throws its own Exception itself and it is to be processed through the internal logic; However, customized thrown Exception is not acceptable which can be seen in Caused by: java.lang.reflect.InvocationTargetException: null and javax.validation.ValidationException: HV000090: Unable to access isFooValid
So my final question is below,
Can I bypass this error, still throwing customized Exception?
I really appreciate that you read this long posting in advance.
Consider the example below where I implemented something like what you asking for:
#RestController
#RequestMapping("/accounts")
public class SavingsAccountController {
private final BankAccountService accountService;
#Autowired
public SavingsAccountController(SavingsAccountService accountService) {
this.accountService = accountService;
}
#PutMapping("withdraw")
public ResponseEntity<AccountBalance> onMoneyWithdrawal(#RequestBody #Validated WithdrawMoney withdrawal, BindingResult errors) {
//this is the validation barrier
if (errors.hasErrors()) {
throw new ValidationException(errors);
}
double balance = accountService.withdrawMoney(withdrawal);
return ResponseEntity.ok(new AccountBalance(
withdrawal.getAccountNumber(), balance));
}
#PutMapping("save")
public ResponseEntity<AccountBalance> onMoneySaving(#RequestBody #Validated SaveMoney savings, BindingResult errors) {
//this is the validation barrier
if (errors.hasErrors()) {
throw new ValidationException(errors);
}
double balance = accountService.saveMoney(savings);
return ResponseEntity.ok(new AccountBalance(
savings.getAccountNumber(), balance));
}
}
In the code above, we're using Bean Validation to check that the user's DTO contains valid information. Any errors found in the DTO are provided through the BindingResult errors variable, from where the developer can extract all the details of what went wrong during the validation phase.
To make it easier for the developers to deal with this pattern, in the code above, I simply wrap the BindingResult into a custom ValidationException which knows how to extract the validation error details.
public class ValidationException extends RuntimeException {
private final BindingResult errors;
public ValidationException(BindingResult errors) {
this.errors = errors;
}
public List<String> getMessages() {
return getValidationMessage(this.errors);
}
#Override
public String getMessage() {
return this.getMessages().toString();
}
//demonstrate how to extract a message from the binging result
private static List<String> getValidationMessage(BindingResult bindingResult) {
return bindingResult.getAllErrors()
.stream()
.map(ValidationException::getValidationMessage)
.collect(Collectors.toList());
}
private static String getValidationMessage(ObjectError error) {
if (error instanceof FieldError) {
FieldError fieldError = (FieldError) error;
String className = fieldError.getObjectName();
String property = fieldError.getField();
Object invalidValue = fieldError.getRejectedValue();
String message = fieldError.getDefaultMessage();
return String.format("%s.%s %s, but it was %s", className, property, message, invalidValue);
}
return String.format("%s: %s", error.getObjectName(), error.getDefaultMessage());
}
}
Notice that in my controller definition I do not use Bean Validation's #Valid annotation, but the Spring counterpart #Validated, but under the hood Spring will use Bean Validation.
How to Serialize the Custom Exception?
In the code above the ValidationException will be thrown when the payload is invalid. How should the controller create a response for the client out of this?
There are multiple ways to deal with this, but perhaps the simplest solution is to define a class annotated as #ControllerAdvice. In this annotated class we will place our exception handlers for any specific exception that we want to handle and turn them into a valid response object to travel back to our clients:
#ControllerAdvice
public class ExceptionHandlers {
#ExceptionHandler
public ResponseEntity<ErrorModel> handle(ValidationException ex) {
return ResponseEntity.badRequest()
.body(new ErrorModel(ex.getMessages()));
}
//...
}
I wrote a few other examples of this and other validation techniques with Spring in case you may be interested in reading more about it.
Here is a solution I used (that might not answer this question directly but possibly help others who get to this page that came with similar intentions as I had):
My aim was foremost to respond with a custom error message to the client who sent a request with an invalid object.
In my controller I use a standard #Valid annotation from javax.validation.Valid before the parameter
In my entity class I use the standard validation constraint, e.g. #NotNull(message = "Field XYZ has to be provided") from javax.validation.constraints.NotNull
I catch the ValidationException in my ControllerAdvice class:
#ControllerAdvice
public class MyControllerAdvice extends ResponseEntityExceptionHandler {
#Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException exception,
HttpHeaders headers,
HttpStatus status,
WebRequest request) {
return new ResponseEntity<>(
new JSONObject().put("message", extractValidationMessage(exception)).toString(),
HttpStatus.BAD_REQUEST);
}
private String extractValidationMessage(MethodArgumentNotValidException exception) {
String exceptionMessage = exception.getMessage();
String[] messageParts = exceptionMessage.split(";");
String finalPart = messageParts[messageParts.length -1];
return finalPart.trim().replaceAll("default message \\[|]]","");
}
}
This will return a 400 Error code and a body of this style:
{"message":"Field XYZ has to be provided"}

DocuSign Java API envelopesApi.getDocument return NULL exception

I am testing an API which is supposed to fetch a document from an envelope. Here is the example code:
#RestController
#Controller
#RequestMapping(value = "DocuSign")
public class DocusignController extends CoreController {
#RequestMapping(value = "/FetchPDF", method = RequestMethod.GET)
#ResponseBody
public MessageItem downloadDocument(Model model) throws ApiException, IOException {
WorkArguments args = new WorkArguments();
args.setAccountId("1e8dce91-c5....");
args.setDocumentId("1");
args.setEnvelopeId("ec1f77....");
String accessToken = "eyJ0eXAiOiJNVCIsImFsZyI6I.....";
String baseUrl = "https://demo.docusign.net/restapi";
JSONObject obj = doWork(args, null, accessToken, baseUrl);
MessageItem msg = new MessageItem();
msg.setMsg("Done!");
return msg;
}
protected JSONObject doWork(WorkArguments args, ModelMap model,
String accessToken, String basePath) throws ApiException, IOException {
// Data for this method
// accessToken (argument)
// basePath (argument)
String accountId = args.getAccountId();
String envelopeId = args.getEnvelopeId();
String documentId = args.getDocumentId();
ApiClient apiClient = new ApiClient(basePath);
apiClient.addDefaultHeader("Authorization", "Bearer " + accessToken);
EnvelopesApi envelopesApi = new EnvelopesApi(apiClient);
System.out.println("--->Checking if anything is null...");
if(envelopesApi == null )
System.out.println("Enveloper API is null!");
if(apiClient == null)
System.out.println("The apiClient is null!");
// Step 1. EnvelopeDocuments::get.
// Exceptions will be caught by the calling function
byte[] results = envelopesApi.getDocument(accountId, envelopeId, documentId);
String mimetype = ".pdf";
String docName = "success";
... etc.
When I go and test it with my rest client, I keep getting the following error:
Type Exception Report
Message Request processing failed; nested exception is
com.sun.jersey.api.client.ClientHandlerException
Description The server encountered an unexpected condition that
prevented it from fulfilling the request.
Exception
org.springframework.web.util.NestedServletException: Request
processing failed; nested exception is
com.sun.jersey.api.client.ClientHandlerException
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Root Cause
com.sun.jersey.api.client.ClientHandlerException
com.docusign.esign.client.auth.OAuth.updateAccessToken(OAuth.java:111)
com.docusign.esign.client.auth.OAuth.applyToParams(OAuth.java:99)
com.docusign.esign.client.ApiClient.updateParamsForAuth(ApiClient.java:1209)
com.docusign.esign.client.ApiClient.getAPIResponse(ApiClient.java:1094)
com.docusign.esign.client.ApiClient.invokeAPI(ApiClient.java:1158)
com.docusign.esign.api.EnvelopesApi.getDocument(EnvelopesApi.java:2624)
com.docusign.esign.api.EnvelopesApi.getDocument(EnvelopesApi.java:2556)
delaware.gov.dti.ice.esignprototypev1.controller.DocusignController.doWork(DocusignController.java:82)
delaware.gov.dti.ice.esignprototypev1.controller.DocusignController.downloadDocument(DocusignController.java:52)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Root Cause
java.lang.NullPointerException
com.docusign.esign.client.auth.OAuth.updateAccessToken(OAuth.java:109)
com.docusign.esign.client.auth.OAuth.applyToParams(OAuth.java:99)
com.docusign.esign.client.ApiClient.updateParamsForAuth(ApiClient.java:1209)
com.docusign.esign.client.ApiClient.getAPIResponse(ApiClient.java:1094)
com.docusign.esign.client.ApiClient.invokeAPI(ApiClient.java:1158)
com.docusign.esign.api.EnvelopesApi.getDocument(EnvelopesApi.java:2624)
com.docusign.esign.api.EnvelopesApi.getDocument(EnvelopesApi.java:2556)
delaware.gov.dti.ice.esignprototypev1.controller.DocusignController.doWork(DocusignController.java:82)
delaware.gov.dti.ice.esignprototypev1.controller.DocusignController.downloadDocument(DocusignController.java:52)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
I am using docusign-esign-java version 3.2.0, which is cucrently the latest. I am able to fetch the doucment when using the rest client, so I know that at least my account id, access token and document id (and template id) are correct. Also I am basing my solution from the following DocuSign refrence page Downloading Envelope Documents and using the provided downloaded code just for to doubleche to see if I am missing anything.
Furthermore I checked to see if the apiClient or the envelopesApi objects are null and they are not so I am getting the problem on the
byte[] results = envelopesApi.getDocument(accountId, envelopeId, documentId);
which for some reason, seems to give a null pointer exception. Any idea as to why?
I updated existing example without Spring to test 3.2.0 version, and it seems to work fine for me and it is not throwing any exception. If it is working w/o Spring then it will work with Spring as well, so does not look like any issue in SDK.
public void listDocuments(String envelopeId) throws ApiException, IOException {
this.checkToken();
EnvelopesApi envelopeApi = new EnvelopesApi(this.apiClient);
EnvelopeDocumentsResult envelopeDocumentsResult = envelopeApi.listDocuments(this.getAccountId(), envelopeId);
List<EnvelopeDocument> envelopeDocuments = envelopeDocumentsResult.getEnvelopeDocuments();
for (EnvelopeDocument envelopeDocument : envelopeDocuments) {
System.out.println("documentId " + envelopeDocument.getDocumentId());
envelopeApi.getDocument(this.getAccountId(), envelopeId, envelopeDocument.getDocumentId());
}
}

Circular View Path error on applying #ResponseBody

I have the below Controller.
#Controller
public class AppController {
#RequestMapping("/home")
#ResponseBody
public User home() {
User u = new User();
u.setUserId(10);
u.setUserName("Rahul");
return u;
}
}
when I comment out the annotation #ResponseBody I get an error while calling /home url.Why?
The message is below
javax.servlet.ServletException: Circular view path [home]: would
dispatch back to the current handler URL [/home] again. Check your
ViewResolver setup! (Hint: This may be the result of an unspecified
view, due to default view name generation.) at
org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:209)
~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE] at
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:147)
~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE] at
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316)
~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE] at
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1370)
~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE] at
org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1116)
~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE] at
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1055)
~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE] at
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE] at
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE] at
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEASE] at
javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
~[javax.servlet-api-4.0.1.jar:4.0.1] at
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
~[spring-webmvc-5.1.4.RELEASE.jar:5.1.4.RELEAS
But when I change my controller method to the below I don't get any error :-
Why?
#RequestMapping("/home")
//#ResponseBody // commented
public ResponseEntity<User> home(){
User u = new User();
u.setUserId(10);
u.setUserName("Raj");
return ResponseEntity.ok(u);
}
#Controller will not work stand-alone without #ResponseBody or ResponseEntity
ResponseEntity is like #ResponseBody but with status and headers.
Why we need #ResponseBody ?
Because, if any of your request mapping method, like home(), contains #ResponseBody annotation it gives an indication that a method return value should be bound to the web response body and if we don’t mention #ResponseBody, then the returned Object will be considered as one of the View and ViewResolver will start looking for respective view in the application.
For further details please refer: https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-return-types

Categories

Resources