argumentResolver cannot be resolved to a variable in Spring 5.3.20 for HandlerMethodArgumentResolverComposite - spring

I am migrating Spring standalone application from Spring 2.3.2.RELEASE to 5.3.20 and below code is breaking
Method method = methodNameToMethodObjectCache.get(methodName);
MockHttpServletResponse response = new MockHttpServletResponse();
ServletWebRequest webRequest = new ServletWebRequest(request, response);
DefaultDataBinderFactory binderFactory = new DefaultDataBinderFactory(requestMappingHandlerAdapter.getWebBindingInitializer());
HandlerMethodArgumentResolverComposite argumentResolver = requestMappingHandlerAdapter.getArgumentResolvers();
LocalVariableTableParameterNameDiscoverer nameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
HandlerMethod handlerMethod = new HandlerMethod(controllerClass, method);
InvocableHandlerMethod requestMethod = new InvocableHandlerMethod(handlerMethod);
requestMethod.setDataBinderFactory(binderFactory);
requestMethod.setHandlerMethodArgumentResolvers(argumentResolver);
requestMethod.setDataBinderFactory(binderFactory);
requestMethod.setParameterNameDiscoverer(nameDiscoverer);
I change code like below :
Here I am getting HandlerMethodArgumentResolver class, what I need is HandlerMethodArgumentResolverComposite, how can I do that?
List<HandlerMethodArgumentResolver> argumentResolvers = requestMappingHandlerAdapter.getArgumentResolvers();

Just create the HandlerMethodArgumentResolverComposite instance and set its resolvers:
HandlerMethodArgumentResolverComposite argumentResolver = new HandlerMethodArgumentResolverComposite();
argumentResolver.addResolvers(requestMappingHandlerAdapter.getArgumentResolvers());

Related

413 request entity too large issue in HTTP Get method call

Please don't mistake it as already asked question. The main difference here is, this issue is coming in Get method call. All the solutions discussed here or other places talks about either POST method or multipart form data.
Configuration I have provided is as below:
String url = env.getProperty(ApplicationConstants.PMCC_MANAGER_REGION_QUERY_URL);
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url).queryParam("inTIS_PMA_NUMBER","ALL");
URI uri = builder.build().toUri();
RestTemplate restTemplate = getRestTemplateBuilder().build();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
private RestTemplateBuilder getRestTemplateBuilder() {
Integer connectionTimeOut = 2000;
Integer readTimeOut = 3000;
RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder();
restTemplateBuilder.setConnectTimeout(connectionTimeOut);
restTemplateBuilder.setReadTimeout(readTimeOut);
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setBufferRequestBody(false);
restTemplateBuilder.requestFactory(factory);
return restTemplateBuilder;
}
This code is part of Spring Boot application and deployed in WebLogic server.

Spring WebFlux WebSocket path variable

How can I get path variable in websocket handler with spring webflux?
I've tried this:
#Bean
public HandlerMapping webSocketMapping() {
Map<String, WebSocketHandler> map = new HashMap<>();
map.put("/path/{id}", session -> session.send(Mono.just(session.textMessage("123"))));
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setUrlMap(map);
mapping.setOrder(-1);
return mapping;
}
But session doesn't have any information about url parameters.
Is it possible?
It requires some casting but it is possible.
private URI getConnectionUri(WebSocketSession session) {
ReactorNettyWebSocketSession nettySession = (ReactorNettyWebSocketSession) session;
return nettySession.getHandshakeInfo().getUri();
}
Once you have the URI use the Spring UriTemplate to get path variables.
// This can go in a static final
UriTemplate template = new UriTemplate("/todos/{todoId}");
Map<String, String> parameters = template.match(uri.getPath());
String todoId = parameters.get("todoId");

send multipart response in spring boot

I am working on apis which is developed in spring boot. Now I have one API in which I have to send response which contains one binary file and and xml.
Both will be seperated by multipart boundary.
So is there any way to do this?
In spring boot try following the way to send a response in multipart.
#RequestMapping(method = { RequestMethod.GET },value = "/multipartdata",produces=MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<MultiValueMap<String, Object>> gerMultipartData()
throws Exception {
MultiValueMap<String, Object> formData = new LinkedMultiValueMap<String, Object>();
formData.add("first_name", "ganesh");
formData.add("last_name", "patil");
formData.add("file-data_1", new FileSystemResource("C:\Users\ganesh\img\logo.png"));
formData.add("file-data_2", new FileSystemResource("C:\Users\ganeshg\Desktop\download.jpg"));
formData.add("file-data_3", new FileSystemResource("C:\Users\ganeshg\Desktop\odstext.txt"));
formData.add("file-data_4", new FileSystemResource("D:\Agent\152845.docx"));
formData.add("file-data_5", new FileSystemResource("D:\testxls.xlsx"));
return new ResponseEntity<MultiValueMap<String, Object>>(formData, HttpStatus.OK);
}

Spring REST template - 401 Unauthorized error

I am using Spring Rest Template inside a Spring Boot Application.
I always get 401 Unauthorized error even though I am passing the credentials.
I am able to access this service by Chrome REST Web Service Client.
Is there a simplified way to access the REST template in SpringBoot.
Below is the code snippet done so far which results in 401 error
private DetailsBean invokeDetailsRestService(UserParam userParam){
ResponseEntity<DetailsBean> responseEntity = null;
String url = "https://dev.com/app/identifyuser/";
RestClientConfig restClientConfig =new RestClientConfig("user123","pass123");
responseEntity= restClientConfig.postForEntity(url, userParam, DetailsBean.class);
log.debug("User Details : {} ", responseEntity.getBody());
return responseEntity.getBody();
}
public ClientHttpRequestFactory getRequestFactory(String userName,String password){
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials( new AuthScope(null, -1), new UsernamePasswordCredentials(userName,password) );
HttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
return new HttpComponentsClientHttpRequestFactory(httpClient);
}
RestClientConfig class
public RestClientConfig(String username, String password) {
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(null, -1),
new UsernamePasswordCredentials(username, password));
HttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
}
Error:
WARN c7af55b5-1cac-4db6-a202-202416c27ba4
12612 --- [apr-8082-exec-8] o.a.http.impl.auth.HttpAuthenticator
: NEGOTIATE authentication error:
No valid credentials provided (Mechanism level:
No valid credentials provided (Mechanism level:
Failed to find any Kerberos tgt))
The authorization issue was fixed with the below code..
Credentials should be passed to a Spring REST Template with the below code:
String userAndPass = "Test:Test123";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
headers.add("Authorization", "Basic " + Base64Utility.encode(userAndPass.getBytes()));
I faced similar issue when i'm trying to make call to webservice, this solved my issue:
restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("userName", "password"));
restTemplate.postForObject('','',''');
Pass the credentials like this, it should solve the issue.
I used spring boot 2.2.4.RELEASE version. then I work below way.
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(username, password));
RequestDto requestDto = new RequestDto();
// set parameter
ResponseDto response = restTemplate.postForObject(URL, requestDto, ResponseDto.class);
Or
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth(username, password);
RequestDto requestDto = new RequestDto();
// set parameter
HttpEntity<RequestDto> request = new HttpEntity<>(requestDto, headers);
ResponseDto response = restTemplate.postForObject(URL, request, ResponseDto.class);

Spring Rest Template to send JsonArray

I am using spring rest template to send json array as request. Source code to send request is as follow:
JSONArray jsonArray = new JSONArray();
for (Iterator iterator = itemlist.iterator(); iterator.hasNext();) {
Item item = (Item)iterator.next();
JSONObject formDetailsJson = new JSONObject();
formDetailsJson.put("id", item.getItemConfId());
formDetailsJson.put("name", item.getItems().getItemName());
formDetailsJson.put("price", item.getPrice());
formDetailsJson.put("Cost",item.getCost());
jsonArray.put(formDetailsJson);
}
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(MediaType.APPLICATION_JSON);
// Prepare header
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
// Pass the new person and header
HttpEntity<JSONArray> entity = new HttpEntity<JSONArray>(jsonArray, headers);
System.out.println("Json Object : "+entity);
// Send the request as POST
try {
ResponseEntity<String> result = restTemplate.exchange("my url", HttpMethod.POST, entity, String.class);
} catch (Exception e) {
logger.error(e);
return "Connection not avilable please try again";
}
And to accept request:
#RequestMapping(value = "/testStock", method = RequestMethod.POST,headers="Accept=application/xml, application/json")
public #ResponseBody int testStock(#RequestBody List<ItemList> jsonArray) {
logger.debug("Received request to connect ms access : "+jsonArray.size());
//int returnSizecount = stockList.getStocklst().size();
return 1;
}
The problem is that it giving me following error:
Could not write request: no suitable HttpMessageConverter found for request type [org.json.JSONArray].Any suggestion is greatly acceptable.
There are no MessageConverter for JSONArray, so I suggest do the following.
HttpEntity<JSONArray> entity = new HttpEntity<JSONArray>(jsonArray, headers);
Convert Class JSONArray to String, and add that to HttpEntity, you know use toString
java.lang.String toString()
Make a JSON text of this JSONArray.
HttpEntity entity = new HttpEntity(jsonArray.toString(), headers);
Or change to Jackson implementation Spring have support to that. XD
If you dont want to do the above, consider create your own implementation of messageConverter, that will work but is harder
update
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
headers.setContentType(MediaType.APPLICATION_JSON);
update 2 Change endpoint to.
#RequestMapping(value = "/testStock", method = RequestMethod.POST)
public #ResponseBody int testStock(#RequestBody String jsonArray) {
you need to have httpmessageconverter configured for your resttemplate, please read my post for configuring http message conveter for you webservice
http://stackoverflow.com/questions/19963127/new-to-spring-and-jackson-2-what-does-this-bean-declaration-allow-for-in-a-spri/19973636#19973636.
and for you problem to convert your http request to json you might add this entry in your restemplate configuration
<bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
The error is quite straightforward. You do not have a converter for the JSONArray. Converting the array to a String (using toString) did help you here, but there is a better way:
Just add a converter for the json.org objects:
Add this to your pom.xml
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-json-org</artifactId>
</dependency>
And then on your ObjectMapper add the JsonOrgModule:
mapper.registerModule(new JsonOrgModule());

Resources