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.
Related
I'm using Retrofit 1.9.0. I have the following interface:
import retrofit.http.PUT;
public interface ShovelsApi {
#PUT("/api/parameters/shovel/{vhost}/{name}")
RetrievedShovel putShovel(#Path("vhost") final String vhost, #Path("name") final String name, #Body final Component<Shovel> shovel);
}
However, when this fails, all I get back is a null RetrievedShovel :
final Shovel shovel = new Shovel();
shovel.setSrcDeleteAfter(1);
shovel.setAckMode("on-confirm");
shovel.setSrcQueue("srcq");
shovel.setSrcUri("amqp://");
shovel.setDestQueue("destq");
shovel.setDestUri("amqp://");
final RetrievedShovel retrievedShovel = shovelsApi.getApi().putShovel(
"/", "myshovel", new Component<>("shovel", "myshovel", shovel));
System.out.println(retrievedShovel); // null
How do I get back the HTTP response, to inspect the status code and message etc?
Thanks!
How do I get the header and body of the current request from an application which called my Springboot application? I need to extract this information. Unfortunately this does not work. I tried to get the current request with this code sample (https://stackoverflow.com/a/26323545/5762515):
public static HttpServletRequest getCurrentHttpRequest(){
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes instanceof ServletRequestAttributes) {
HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
return request;
}
throw new IllegalArgumentException("Request must not be null!");
}
And then I tried to get the body
ContentCachingRequestWrapper requestWrapper = (ContentCachingRequestWrapper) currentRequest;
String requestBody = new String(requestWrapper.getContentAsByteArray());
Can someone tell me what im doing wrong?
Thanks in advance
#RestController
public class SampleController {
#PostMapping("/RestEndpoint")
public ResponseEntity<?> sampleEndpoint(#RequestHeader Map<String, String> headers,#RequestBody Map<String,String> body) {
//Do something with header / body
return null;
}
}
If the application's are communicating through a rest endpoint I believe this would be the simplest solution. In spring you can add RequestHeader and RequestBody annotations to method arguments to have them setup to be used.
Of course you can map RequestBody directly to some POJO instead of using a map but just as an example.
Let me know if this is what you were looking for !
#TryHard, You're using spring boot then following way is more preferable for you,
#RestController
public class SampleController {
#RequestMapping("/get-header-data")
public ResponseEntity<?> sampleEndpoint(HttpServletRequest request) {
// request object comes with various in-built methods use as per your requirement.
request.getHeader("<key>");
}
}
you can get header with your code but need apply some changes.
private String getRequest() throws Exception {
RequestAttributes attribs = RequestContextHolder.getRequestAttributes();
if (attribs != null) {
HttpServletRequest request = ((ServletRequestAttributes) attribs).getRequest();
return request ;
}
throw new IllegalArgumentException("Request must not be null!");
}
after you can extract header info from request. For example if you want get Accept-Encoding
String headerEncoding = getRequest().getHeader("Accept-Encoding");
obliviusly you don't use this approce if not necessary.
If you want exract the body NOT use this solution
I have a method in class which does a HTTP GET call to get the response object and utilize this object further. The pesudo code is below:
public class ABC{
public method abc1(){
HttpUrl url = HttpUrl.parse("url").newBuilder()
.addPathSegment("path1")
.build();
Request request = new Request.Builder().url(url).build();
try (Response response = client.newCall(request).execute()) {
ResponseBody responseBody = response.body();
String body = responseBody.string();
//other logic
}catch (IOException e) {}
}
}
Now I am writing a unit test to test with different values in the response object (json object). This is as below:
public class ABCTest{
#Mock
private OkHttpClient mockHttpClient;
#Mock
private Call mockCall;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
#Test
public void abc1Test(){
ResponseObjectInJson responseObjectInJson = new ResponseObjectInJson(); //this is a object from my POJO class that i create in order to be received as a response
JSONObject jsonObject = new
JSONObject(responseObjectInJson);
ResponseBody body =
ResponseBody.create(MediaType.parse("application/json"),new
Gson().toJson(jsonObject));
Response.Builder builder = new Response.Builder();
builder.code(200);
Response response = builder.body(body).build();
when(mockCall.execute()).thenReturn(response);
when(mockHttpClient.newCall(any(Request.class))).thenReturn(mockCall);
//call the abc1() method here to see the response and behaviour
}
}
The problem is, when i debug, it throws InvocationTargetException when building the response builder.body(body).build();
And shows java.lang.IllegalStateException: request == null. I understand that i need to set request in the Response.Builder because when i evaluate the expression builder.body(body) in debugger, in the result it shows headers and body, but request is null.
i.e., builder.request(//a request here)
My question is:
1. In response why the request is needed?
2. How to set this? because i am unable to mock since its final.
Thanks in advance
I want to trigger a method to create a ArrayList and return this list to a callback-URL. This method can take a while until the data has been generated so it should be an asynchronous running method.
So I got a few questions:
What's a callback-URL? I assume it's the URL the method is returning the value to?
How to returna value to a callback-URL?
How to access the value after it has been returned?
#Async
#GetMapping("/createcustomer/{start}/{end}"){
public ArrayList<Customer> createCustomer(#PathVariable int start,
#PathVariable int end) {
//code to generate random data
return arrayList;
}
In order to call your handler method you can use javascript code on your front-end side. Here is an example how you can do it with axios library:
axios.get('createcustomer/something/something')
.then(function (response) {
console.log(response);
// response.data will contain your json with returned list content
})
.catch(function (error) {
console.log(error);
});
You will also need to modify your hanlder method like this:
#ReponseBody
#GetMapping("createcustomer/{start}/{end}"){
public ArrayList<Customer> createCustomer(#PathVariable int start,
#PathVariable int end) {
//code to generate random data
return arrayList;
}
The #ResponseBody annotation will cause the ArrayList to be returned as json in the body of the response. Alternatively, you can change #Controller class annotation to #RestController. It will make all your handler methods in this class to return back to the client.
This way, the request will be totally asynchronous and you can access it in your front-end code as soon as it's available.
Edit:
If you want to send this list somewhere else using callback-url, you can use RestTemplate to send post request with list as body. You can use something similiar to this code inside your handler method:
String callback-URL = "http://my.server.com/customerListEndpoint";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<?> entity = new HttpEntity<>(headers);
restTemplate.exchange(callback-URL,HttpMethod.POST,entity,ArrayList.class);
You need an endpoint that can be mapped with post requests to callback-URL. Something like:
#PostMapping("/customerListEndpoint"){
public void createCustomer(#RequestBody ArrayList<Customer> arrayList) {
// do what you want with arrayList here
}
Also, be sure to configure the RestTemplate bean in some class anottated with #Configuration:
#Bean
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setOutputStreaming(false);
RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(requestFactory));
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
return restTemplate;
}
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.