OpenFeign not decoding response - java

#FeignClient(name = "Authorization-API", url = "https://www.reddit.com/api/v1")
public interface AuthorizationApi {
#RequestMapping(method = RequestMethod.POST, value = "/access_token")
Token getToken(#PathVariable("grant_type") String grantType,
#PathVariable String code,
#PathVariable("redirect_uri") String redirectUrl,
#RequestHeader(name = "Authorization") String authorizationHeader,
#RequestHeader("User-agent") String agent
);
}
Call:
Token token = authorizationApi.getToken(
"authorization_code",
code,
REDIRECT_URI,
getAuthorizationCredentials(),
"porymol");
System.out.println(token.access_token()); //returns null
Token record:
public record Token(String access_token, String token_type, Long expires_in, String scope, String refresh_token) {
}
When I make request from Postman I get this response:
{
"access_token": "token",
"token_type": "bearer",
"expires_in": 86400,
"refresh_token": "token",
"scope": "read"
}
Trying to get any value from Token returns null
Java 17, Spring boot 3
Any idea what's going wrong here?

First of all you have declared two path variables which dont show up the path:
#PathVariable String code and #PathVariable("redirect_uri") String redirectUrl.
Overall it looks like you are trying to request an oauth access token which requires an request of content type application/x-www-form-urlencoded.
Maybee this helps: How to POST form-url-encoded data with Spring Cloud Feign

Related

How do I to send custom HTTP error responses in String?

I am stuck with validating a String if the url is sending the path variables with invalid data.
Currently, the exception is throwing back a response. But I want to send back the response with a message.
E.g {"message": "Invalid Data"}.
I'm using #RestController API.
URL: ==> http://((domain))/getdata/"dd"
#GetMapping(value = { "/{id[]}" })
public ResponseEntity<JsonNode> getData( #PathVariable(name = "id[]") Long[] id ) {..}

Spring: Parameter conditions "loanTitle" not met for actual request parameters

Java Spring MVC. I can't open url without a parameter. I found suggestions in Internet(Spring MVC Thymeleaf Error: Parameter conditions not met for actual request parameters, http://www.baeldung.com/spring-requestmapping), but they didn't help me.
#Controller
#RequestMapping("/loans/")
public class LoanController {
#Autowired
LoanDAO loanDAO;
#GetMapping(value= "objectloan", params = {"loanTitle"})
public String index(Model theModel, HttpSession session, #RequestParam(value = "loanTitle", required = false, defaultValue = "") Optional<String> loanTitle)
{
....
}
URL works
http://localhost:8080/college/loans/objectloan?loanTitle=test
URL with error
http://localhost:8080/college/loans/objectloan
Error:
Type Status Report
Message Parameter conditions "loanTitle" not met for actual request parameters:
Description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
Since loanTitle might not present in your query url,try to remove params = {"loanTitle"} in your controller method
#GetMapping(value= "objectloan")
public String index(Model theModel, HttpSession session, #RequestParam(value = "loanTitle", required = false, defaultValue = "") Optional<String> loanTitle)
{
....
}

Getting the OAUTH2 Token

I'm trying to retrieve a OAUTH2 token from our IDM server - I've tried several flavors of rudimentary examples, but all of them return a 200 status with no code included. I can do it with no trouble via postman, using a header of:
Content-Type application/x-www-form-urlencoded
... and sending the client_id, redirect_uri and code parameters. I get something back that looks like this:
{
"access_token": "abcd...",
"token_type": "bearer",
"expires_in": 3600
}
Here's the super rudimentary code intended to do no more than see if I can grab the token (at this point):
public class Service {
public String getToken() {
String client_id = "f2e8...";
String redirect_uri = "https://mysite/";
String code = "AAAAAA...";
form = new Form();
form.param("client_id", client_id);
form.param("code", code);
form.param("redirect_uri", redirect_uri);
JerseyClientBuilder jerseyClientBuilder = new JerseyClientBuilder();
JerseyWebTarget jerseyWebTarget =
jerseyClientBuilder.build().target("https://token-source-site/");
Response response = jerseyWebTarget.request().post(Entity.form(form));
return response.toString();
}
}
But all I get back is:
InboundJaxrsResponse{context=ClientResponse{method=POST,
uri=https://token-source-site/, status=200, reason=OK}}
Any thoughts on what Postman might be doing that my code isn't?
It's not going to show to the response body when you just call toString() on the Response. You need to extract the body from it by calling Response#readEntity.
But even trying to extract it to a String, you have the problem of still having to parse the string. Best thing to do is to create a POJO for the token response
public class AccessTokenResponse {
#JsonProperty("access_token")
private String accessToken;
#JsonProperty("token_type")
private String tokenType;
#JsonProperty("expires_in")
private long expiresIn;
// getters and setters
}
Then you can do
Response response = jerseyWebTarget.request().post(Entity.form(form));
return response.readEntity(AccessTokenResponse.class);
Make the method return AccessTokenResponse, so the client has access to the other properties also.
For this to work, you will need to have the Jackson provider dependency
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>

Bug: Required request body is missing

I'm trying spring framework.
I have RestController and function:
#RequestMapping(value="/changePass", method=RequestMethod.POST)
public Message changePassword(#RequestBody String id, #RequestBody String oldPass,
#RequestBody String newPass){
int index = Integer.parseInt(id);
System.out.println(id+" "+oldPass+" "+newPass);
return userService.changePassword(index, oldPass, newPass);
}
and code angularJS
$scope.changePass = function(){//changePass
$scope.data = {
id: $scope.userId,
oldPass:$scope.currentPassword,
newPass:$scope.newPassword
}
$http.post("http://localhost:8080/user/changePass/", $scope.data).
success(function(data, status, headers, config){
if(date.state){
$scope.msg="Change password seccussful!";
} else {
$scope.msg=date.msg;
}
})
.error(function(data, status, headers, config){
$scope.msg="TOO FAIL";
});
}
and when i run it.
Error Message :
Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.csc.mfs.messages.Message com.csc.mfs.controller.UserController.changePassword(java.lang.String,java.lang.String,java.lang.String)
Help me fix it, pls...
Issue is in this code.
#RequestBody String id, #RequestBody String oldPass,
#RequestBody String newPass
You cannot have multiple #RequestBody in same method,as it can bind to a
single object only (the body can be consumed only once).
APPROACH 1:
Remedy to that issue create one object that will capture all the relevant data, and than create the objects you have in the arguments.
One way for you is to have them all embedded in a single JSON as below
{id:"123", oldPass:"abc", newPass:"xyz"}
And have your controller as single parameter as below
public Message changePassword(#RequestBody String jsonStr){
JSONObject jObject = new JSONObject(jsonStr);
.......
}
APPROACH 2:
Create a custom implementation of your own for ArgumentResolver
You can't have request body for the GET method. If you want to pass username and password as part of request body then change RequestMethod type to POST/PUT.
If you want to use GET only then you will have to pass username and password as either path variables or request/query parameters - which is not best practice.
I would recommend changing RequestMethod and pass username & password as request body.

Java Spring MVC - Send JSON request body error

I am trying to send a JSON string as a request to my application. This is my code:
#RequestMapping(
value = "/mylink/upload",
method = RequestMethod.POST,
consumes ="application/json",
produces = "application/json")
public
#ResponseBody
List<Upload> upload(
#RequestParam(value = "hdfsLocation") String hdfsLocation
) throws Exception {
return S3HdfsTransfer.uploadFromHDFS(hdfsLocation);
}
I am trying to send a request with Postman. The method I use is POST, the header contains: Accept "application/json",Content-Type "application/json", the request body is the following:
{
"hdfsLocation" : "hdfs://145.160.10.10:8020"
}
This is the response I get. If I put the parameter in the URL, it works.
{
"httpStatus": 500,
"appErrorId": 0,
"message": "Required String parameter 'hdfsLocation' is not present",
"trackingId": "8c6d45fd-2da5-47ea-a213-3d4ea5764681"
}
Any idea what I am doing wrong?
Thanks,
Serban
Looks like you have confused #RequestBody with #RequestParam. Do either of following :
Pass the request param as a request param(not as a body). Like, (encoded)
http://example.com?hdfsLocation=http%3A%2F%2Fexample.com%3FhdfsLocation%3Dhdfs%3A%2F%2F145.160.10.10%3A8020
Replace the #RequestParam with #RequestBody. If you are sending a body, don't send it along with request param. Those are two different things.
I guess you over looked :)
Shouldn't it be #RequestBody instead of #RequestParam?
Also, even after using #RequestBody, the whole of the JSON string:
{
"hdfsLocation" : "hdfs://145.160.10.10:8020"
}
will be the value of String hdfsLocation and not just the hdfs url. Hence, you'll have to JSON parse that JSON by yourself to get just the hdfs url.

Categories

Resources