JSON Object as #RequestBody on Spring 4.16 - java

So i have this android application that send jsonObject for a jsonObjectRequest (I'm using volley) with POST method. The JSON file was sent but the server (this is where i'm using Spring btw) is not responding. The code pretty much like these.
Android Code:
JSONObject jsonObject = new JSONObject(data);
final JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, jsonObject, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
userToken = response.getString(TAG_TOKEN);
// blablabla
Server Code:
#RestController
#RequestMapping("/auth/")
public class AuthController {
String userEmail;
String userPassword;
#RequestMapping(value = "/login", method = RequestMethod.POST)
public LoginResponse loginResponse(#RequestBody Auth auth){
userEmail = auth.getEmail();
userPassword = auth.getPassword();
// blablabla
Auth Object:
public class Auth {
private String email;
private String password;
// blablabla
It seems like the server didn't receive the JsonObject from the android client correctly. (The server is able to send JSON to android client perfectly in another case, though). I'm using spring-4.16, jackson-core, jackson-annotation, jackson-databind (2.2.2). Thanks in advance!

From the code you supplied first thing that I suspect can be is that JSONObject doesn't have same field's name with Auth on server.
Also it is possible that HttpMessageConverter which is used for mapping objects from request to object in controller is not doing his job correctly.
I would first try to just try to recieve parameters from body, without Auth object. If Spring maps it fine than HttpMessageConverter is the problem, if it does not than the usage of #RequestBody, which I can't be from code you supplied.

Related

Issues using Retrofit2 to call GitHub REST API to update existing file

I'm attempting to use Retrofit to call the GitHub API to update the contents of an existing file, but am getting 404s in my responses. For this question, I'm interested in updating this file. Here is the main code I wrote to try and achieve this:
GitHubUpdateFileRequest
public class GitHubUpdateFileRequest {
public String message = "Some commit message";
public String content = "Hello World!!";
public String sha = "shaRetrievedFromSuccessfulGETOperation";
public final Committer committer = new Committer();
private class Committer {
Author author = new Author();
private class Author {
final String name = "blakewilliams1";
final String email = "blake#blakewilliams.org";
}
}
}
**GitHubUpdateFileResponse **
public class GitHubUpdateFileResponse {
public GitHubUpdateFileResponse() {}
}
GitHubClient
public interface GitHubClient {
// Docs: https://docs.github.com/en/rest/reference/repos#get-repository-content
// WORKS FINE
#GET("/repos/blakewilliams1/blakewilliams1.github.io/contents/qr_config.json")
Call<GitHubFile> getConfigFile();
// https://docs.github.com/en/rest/reference/repos#create-or-update-file-contents
// DOES NOT WORK
#PUT("/repos/blakewilliams1/blakewilliams1.github.io/contents/qr_config.json")
Call<GitHubUpdateFileResponse> updateConfigFile(#Body GitHubUpdateFileRequest request);
}
Main Logic
// Set up the Retrofit client and add an authorization interceptor
UserAuthInterceptor interceptor =
new UserAuthInterceptor("blake#blakewilliams.org", "myActualGitHubPassword");
OkHttpClient.Builder httpClient =
new OkHttpClient.Builder().addInterceptor(interceptor);
Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.client(httpClient.build()).build();
client = retrofit.create(GitHubClient.class);
// Now make the request and process the response
GitHubUpdateFileRequest request = new GitHubUpdateFileRequest();
client.updateConfigFile(request).enqueue(new Callback<GitHubUpdateFileResponse>() {
#Override
public void onResponse(Call<GitHubUpdateFileResponse> call, Response<GitHubUpdateFileResponse> response) {
int responseCode = response.code();
// More code on successful update
}
#Override
public void onFailure(Call<GitHubUpdateFileResponse> call, Throwable t) {
Log.e("MainActivity", "Unable to update file" + t.getLocalizedMessage());
}
});
What currently happens:
Currently, the success callback is triggered, but with a response code of 404 like so:
Response{protocol=http/1.1, code=404, message=Not Found, url=https://api.github.com/repos/blakewilliams1/blakewilliams1.github.io/contents/qr_config.json}
Has anyone else encountered this? I first thought it was a problem with including '/content/' in the URL but I do the same thing for reading the file contents request and it works fine (also uses same URL just a GET instead of PUT).
For anyone interested in doing this in the future, I figured out the solution.
I needed to revise the request object structure
Rather than using an authentication interceptor, I instead added an access token to the header. Here is where you can create access tokens for Github, you only need to grant it permissions to the 'repos' options for this use case to work.
This is what my updated request object looks like:
public class GitHubUpdateFileRequest {
public String message;
public String content;
public String sha;
public final Committer committer = new Committer();
public GitHubUpdateFileRequest(String unencodedContent, String message, String sha) {
this.message = message;
this.content = Base64.getEncoder().encodeToString(unencodedContent.getBytes());
this.sha = sha;
}
private static class Committer {
final String name = "yourGithubUsername";
final String email = "email#yourEmailAddressForTheUsername.com";
}
}
Then from my code, I would just say:
GitHubUpdateFileRequest updateRequest = new GitHubUpdateFileRequest("Hello World File Contents", "This is the title of the commit", shaOfExistingFile);
For using this reqest, I updated the Retrofit client implementation like so:
// https://docs.github.com/en/rest/reference/repos#create-or-update-file-contents
#Headers({"Content-Type: application/vnd.github.v3+json"})
#PUT("/repos/yourUserName/yourRepository/subfolder/path/to/specific/file/theFile.txt")
Call<GitHubUpdateFileResponse> updateConfigFile(
#Header("Authorization") String authorization, #Body GitHubUpdateFileRequest request);
And I call that interface like this:
githubClient.updateConfigFile("token yourGeneratedGithubToken", request);
And yes, you do need the prefix "token ". You could hardcode that header into the interface, but I pass it in so that I can store it in locations outside of my version control's reach for security reasons.

POST request in webclient to add a request body in JSON

I am trying to make API POST Request with WebClient in Spring Boot. But I cannot make a request with JSON body as I want and receive response as JSONObject.
JSON BODY :
{
"workspaces": [
"6eret123",
"b129078v",
"ngy66553",
"erfc1153"
]
}
Service class-
Workspaces workspace = new Workspaces(mw);
Flux<Workspaces> modifiedWorkspace = webClient.post().uri(URIDetails.MODIFIEDWORKSPACE)
.header("Authorization", bearerToken).body(Mono.just(mw), Workspaces.class).retrieve()
.bodyToFlux(Workspaces.class);
modifiedWorkspace.doOnNext(System.out::println).blockLast();
return null;
Workspaces model-
public class Workspaces {
private List<String> workspaces;
}
Main call-
Flux<ScanIDModel> modifiedWorkspaces;
final List<String> mw = new ArrayList<>();
for (Workspace w : modifiedWorkspaces) {
mw.add(w.getId());
}
modifiedWorkspaces = scanRespone(mw);
I need to send a list of JSON body mentioned as a body post request.
Please help me to do the post request
Thanks in advance
try something like this:
import org.springframework.web.reactive.function.client.WebClient;
public class Testclass{
#Autowired
private WebClient.Builder webClientBuilder;//webclient builder instance
public void testMethod(){
Class<Object> cls = Object.class;//object class of the request body
//Object obj is also the object of the request body
Object obj = webClientBuilder.build().post().uri("{{url}}")
.accept(MediaType.APPLICATION_JSON).header("Authorization", "{{authtoken}}")
.bodyValue(user).retrieve().bodyToMono(clazz).block();
}
}
hope something on it might help.

How to make a POST call using Scribe and fetch data having OAuth 1.0 Authentication in Java?

I have a requirement to make a post-call to a URL which has OAuth 1.0 authentication. I am pretty new to all these. From my research, I got to know about Scribe in Java, but I can find only Get calls using Scribe. I already have consumerKey and consumerSecret key for OAuth 1.0 authentication. Are there any suggestions on how to achieve this successfully.
With postman I am able to fetch the data successfully, but I want to achieve it using Java.
I have tried something like this
I tried this way
public String getSmartCommPDF(#RequestBody Model model) throws IOException {
OAuthService service = new ServiceBuilder().provider(ModelAPI.class).apiKey(consumerKey)
.apiSecret(consumerSecret).build();
OAuthRequest request = new OAuthRequest(Verb.POST, url);
ObjectMapper mapper = new ObjectMapper();
request.addHeader("Content-Type", "application/json;charset=UTF-8");
request.addPayload(mapper.writeValueAsString(model));
Token accessToken = new Token("", ""); // not required for context.io
service.signRequest(accessToken, request);
Response response = request.send();
System.out.println("Response = " + response.getBody());
return "Success";
}
This is my ModelAPI class
public class ModelAPI extends DefaultApi10a {
#Override
public String getRequestTokenEndpoint() {
return "https://domain/one/oauth1/api/v6/job";
}
#Override
public String getAccessTokenEndpoint() {
return "https://domain/one/oauth1/api/v6/job";
}
#Override
public String getAuthorizationUrl(Token requestToken) {
return "https://domain/one/oauth1/api/v6/job";
}
}
This part of code is not throwing any error but, the response body is empty. Where I am going wrong, any one has any idea?
Thank you.
The data was coming back in the input stream. So, I used
response.getStream();
and write it to a file and use it.

Consume Post method Rest + SpringBoot

I have been searching all morning and i think i'm missing something .
i have a Spring boot controller with a method to save a client.
this is the method :
// ajouter un client
#RequestMapping(value="/AjoutClient/{clientData}", method=RequestMethod.POST)
public String AjoutClient(#PathVariable String clientData) {
Client c = new Client();
c.setNomClient(clientData.split(";")[0]);
c.setPrenomClient(clientData.split(";")[1]);
c.setAdresseClient(clientData.split(";")[2]);
c.setTelClient(clientData.split(";")[3]);
c.setEmailClient(clientData.split(";")[4]);
c.setCinClient(clientData.split(";")[5]);
client.save(c);
return "test";
}
i want to consume this method from another application with this method :
#RequestMapping(value="/ajoutClient", method=RequestMethod.POST)
public void ajout(#RequestParam("nom") String nom,#RequestParam("prenom") String prenom,#RequestParam("adr") String adr,#RequestParam("tel") String tel,#RequestParam("mail") String mail,#RequestParam("cin") String cin) {
String ClientData=nom+";"+prenom+";"+adr+";"+tel+";"+mail+";"+cin;
RestTemplate restTemplate = new RestTemplate();
HttpEntity<String> request = new HttpEntity<>(new String(ClientData));
ResponseEntity<String> response = restTemplate
.exchange("http://localhost:9093/AjoutClient/"+ClientData, HttpMethod.POST, request, String.class);
assertThat(response.getStatusCode(), is(HttpStatus.CREATED));
}
** explication : i get the values from a form and construct a string with those values, then try to send that string to my clientController.
PS: i can't send client object, i have to send the values one by one then create the client object in the clientController.
i'm feeling pretty lost because i can see that something is wrong but i don't know what is it.
First of all I would suggest you avoid using #PathVariable for passing the data like this.
You're already sending everything in the request body, so first step is to change:
public String AjoutClient(#PathVariable String clientData) {
to
public String AjoutClient(#RequestBody String clientData) {
and
restTemplate.exchange("http://localhost:9093/AjoutClient/" + ClientData, HttpMethod.POST, request, String.class);
to just
restTemplate.exchange("http://localhost:9093/AjoutClient", HttpMethod.POST, request, String.class);
Then if you're expecting 201 status then you have to return it:
public ResponseEntity<String> AjoutClient(#RequestBody String clientData) {
...
return ResponseEntity.created(null).body("test");
}
PS: Please pay attention to what #JB Nizet mentioned, cause he has a point here. Just research that keywords (google them) or read some tutorials e.g https://www.baeldung.com/java-url-encoding-decoding or https://www.baeldung.com/rest-template and you'll easily find out more about standard practices.

web service in spring getParameter

I am creating a web service, but I am not getting the value I expect by using req.getParameter("key"). Can you please tell why I am getting values as null ?
Here, instead of getting "abcd" as value, I am getting null.
The request which I am hitting is:
http://localhost:8080/api.htm.
Post fields are:
username:abcd
#ResponseBody
#RequestMapping(value = {"api"}, method = {RequestMethod.POST})
public String apiSignUp(HttpServletRequest req) throws JSONException {
JSONObject json = new JSONObject();
Users user;
try {
String username = req.getParameter("username");

Categories

Resources