I want to send a json to my REST API. i tried it with Postman and it works fine. Now i want to sent Data from my frontend. I dont know where i need to add the header and how i do it. Im using Springboot for my BackEnd and Vue for my FrontEnd.
My Controller:
#RestController
#RequestMapping("/api/auth")
public class FileController {
FileService fileService;
public FileController(FileService fileService) {
this.fileService = fileService;
}
#RequestMapping(
value = "/data",
method = RequestMethod.POST,
consumes = "application/json")
public void process(#RequestBody String payload) throws Exception{
System.out.println(payload);
try {
FileWriter writer = new FileWriter(...);
writer.write(payload);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
My main.js, which shall send the data:
const toSend ={
"name": "test",
"test1":"test2"
};
const jsonString = JSON.stringify(toSend);
const xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:8090/api/auth/data");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(jsonString);
console.log(jsonString)
You need to enable cors for this controller.
There is an annotaion for that matter.
Check out this guide
https://spring.io/guides/gs/rest-service-cors/
Are you sure that sending by xhr is best solution? why don't you use fetch?
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
Yours vue app and spring boot apps runs on different ports and browser sees it separate websites that why it blocks because of cors. Other solution that adding cors headers, can be proxy on js side.
Related
Image
I want to write a client code to consume an API. The API is expecting a text file. When I select the binary file option in the postman tool and select any text file from my local it worked. how to implement this in spring ?. I have tried MULTIPART_FORM_DATA but no luck.
If You mean file
#RestController
public class FileContentController {
#RequestMapping(value="/up", method = RequestMethod.POST)
public ResponseEntity<?> upload(#RequestParam("file") MultipartFile file)
throws IOException {
String contentType=file.getContentType());
InputStream i=file.getInputStream();
return new ResponseEntity<>(HttpStatus.OK);
}
return null;
}
also spring boot has multi part confs, you should enable it and set size and tempdir
,In Earlier version spring boot need to add:
spring.servlet.multipart.max-file-size=128KB
spring.servlet.multipart.max-request-size=128KB
spring.servlet.multipart.enabled=true
spring.servlet.multipart.location=${java.io.tmpdir}
However in your client code you should not set content-type application/json in your header post request
simple fetch should be such
const input = document.getElementById('uploadInput');
const data = new FormData();
data.append('file', input.files[0]);
var resp = await fetch('upload/', {
method: 'POST',
body: data
});
if (!resp.ok) {
throw new Error(`HTTP error! status: ${resp.status}`);
}
if (resp.ok) {
await this.images();
}
I'm trying to send a formData post request (using axios) to my backend (springboot) but I'm not sure of the proper way to do it. My plan is to pass the data through the controller to a service that will utilize it.
Axios call -
startStreamLocation() {
const location = new FormData();
location.set("accuracy", this.accuracy)
location.set("lat", this.lat)
location.set("lng", this.lng)
location.set("timeStamp", this.timeStamp)
axios.post("http://localhost:8080/api/v1/location/request-location", location,
{headers: {'Content-Type': 'application/json'}})
},
Controller -
#PostMapping(value = "request-location")
public ResponseEntity<?> requestLocation() {
connectionRequestService.addDataToStream();
return new ResponseEntity<Authenticator.Success>(HttpStatus.OK);
}
Service -
public void addDataToStream() {
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
AmazonKinesis kinesisClient = AmazonKinesisClient.builder()
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withRegion(awsRegion)
.build();
PutRecordsRequest putRecordsRequest = new PutRecordsRequest();
putRecordsRequest.setStreamName("location-stream");
List <PutRecordsRequestEntry> putRecordsRequestEntryList = new ArrayList<>();
PutRecordsRequestEntry putRecordsRequestEntry = new PutRecordsRequestEntry();
putRecordsRequestEntry.setData(ByteBuffer.wrap(( INJECT DATA HERE ).getBytes()));
putRecordsRequestEntry.setPartitionKey(String.format("partitionKey-%d"));
putRecordsRequestEntryList.add(putRecordsRequestEntry);
putRecordsRequest.setRecords(putRecordsRequestEntryList);
PutRecordsResult putRecordsResult = kinesisClient.putRecords(putRecordsRequest);
System.out.println("\nData sent successfully... \n" + putRecordsResult);
try {
Thread.sleep(1000);
}
catch (InterruptedException exception) {
throw new RuntimeException(exception);
}
}
Since you want to send form data to the server, you would need to change the Content-Type header in your Axios call to multipart/form-data. This helps the server understand the resource type being sent by the client.
On the server end, you'll want to read this form data. I can think of the following two ways to do that
Use #RequestParam to read individual form keys. For example, if my form data contains a key named Foo, I'd read it on the server end as this
#PostMapping(value = "/form-data")
public void readFormData( #RequestParam(value = "Foo") String foo )
Use #RequestBody to map the form data to a MultiValueMap which can be then read from like a normal map. Here's the code snippet for the same
#PostMapping(value = "/form-data")
public void readFormData( #RequestBody MultiValueMap<String,String> formData )
I have my endpoint in spring-boot API for uploading images. It's working fine with the postman, but if I want to send a request from my angular app I'm getting code 400 "Required request part 'file' is not present".
I think the problem is in my angular code.
My endpoint
#PostMapping(value = "/private/image/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public BasicImgurResponse uploadProfilePicture(#RequestParam(name = "file") MultipartFile file){
try {
return service.uploadProfilePicture(file);
} catch (IOException ex) {
Logger.getLogger(ImgurController.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
My angular service method
uploadAvatar(data: any){
let file = new FormData();
file.append('file',data);
return this.http.post<any>(environment.api_endpoint+'/private/image/avatar',file);
}
May be data object is empty? Make sure that data object contains a input file.
Without Angular, the command will be as below:
formData.append('file', $('input[type=file]')[0].files[0]);
I have a REST Service an external server like https://api.myrestservice.com and I have a Spring Boot Application running locally on http://localhost:8080. Now I want to make GET or POST request to the REST API address i.e https://api.myrestservice.com/users to get all users, using my locally running Spring Boot App i.e through http://localhost:8080/users. I am not getting how to redirect local app request to external server request.
I hope I got your question right. You are trying get your local app to get data from app running on your server.
You can use the below sample code in your spring boot application.
private void getUsers() {
final String uri = "https://api.myrestservice.com/users";
RestTemplate restTemplate = new RestTemplate();
Users result = restTemplate.getForObject(uri, Users.class);
System.out.println(result);
}
Then your getUsers can be invoked by getUsers Controller in your spring boot app.
I am adding the reference if you want to look at more examples -
https://howtodoinjava.com/spring-restful/spring-restful-client-resttemplate-example/
Making post Api call from your code to another server:
suppose you have a server https://searchEmployee... which returns you list of employees belonging to a particular city or belonging to a particular organization:
request body:
{
"city" : "Ranchi",
"organisation" : "Bank Of America"
}
json response: [{"name": "Vikash"},{"name":"kumar" },{}...etc]
Then to make a post api call you can use RestTemplate in java like this:
public void makeApiCall(){
final String uri = "https://searchEmployee...";
RestTemplate restTemplate = new RestTemplate();
String reqBody = "{"city": "Ranchi"}";
String result = restTemplate.postForObject(uri, reqBody, String.class);
// convert your result into json
try {
jsonResponse = new JSONObject(result);
} catch (JSONException e) {
e.printStackTrace();
}
//extract a value "name" from your json data:
try{
String value = jsonResponse.getString("name");
}catch(JSONException e) {
e.printStackTrace();
}
}
/********************************************************************/
if you have more than one request body parameters to set do it like this:
String reqBody = "{\"quantity\":100,\"name\":\"product1\",\"ifBoolean\":false}";
false is a boolean value here in your request body and 100 is an integer.
NOTE
if you are having problem in setting request body copy it directly from postman request body and paste it inside double quote.
There are many ways to do it. Like Apache HTTP Components and other. Sample
String type = "application/x-www-form-urlencoded" Or Set your desire content type;
String encodedData = URLEncoder.encode( rawData, "UTF-8" );
URL u = new URL("your remote url");
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty( "Content-Type", type );
conn.setRequestProperty( "Content-Length",
String.valueOf(encodedData.length()));
OutputStream os = conn.getOutputStream();
os.write(encodedData.getBytes());
There are a couple of thing going on here, Like URLEncoding is really mattered when came to security.
Note: Source of above code:here.
This is very Simple By using Java Clients you can Use RestTemplate or UniRest
That one running on Remote is simply Producer and the one which is in local is Consumer So you can exchange method of Resttemplate or get method of Unirest
Example Code is here.
#RequestMapping(value = "/testclient")
public String testclient()
{
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(headers);
return restTemplate.exchange("https://www.mocky.io/v2/5185415ba171ea3a00704eed", HttpMethod.GET, entity, String.class).getBody();
}
For Unirest code is like this
HttpResponse<JsonNode> jsonResponse = null;
try {
jsonResponse = Unirest.get("https://www.mocky.io/v2/5185415ba171ea3a00704eed")
.header("accept", "application/json").queryString("apiKey", "123").asJson();
} catch (UnirestException e) { // TODO Auto-generated catch block
e.printStackTrace();
}
return jsonResponse.getBody().toString();
I have an error and I am getting confuse, I have created a simple Java EE 7 project using Jersey.
I am returning this class in my Rest Rervice:
#XmlRootElement
public class LocationDTOx {
private Long id;
private String tittle;
private String description;
private Long parent;
//Getter and setters...
And in my service class i Have:
#Path("/location")
public class LocationService {
#GET
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("/findlocation")
public LocationDTOx findLocation() {
System.out.println("findlocation");
try {
LocationDTOx x = new LocationDTOx();
x.setDescription("Description");
x.setId(0l);
x.setParent(null);
x.setTittle("Tittle ...");
return x;
} catch (Exception ex) {
Logger.getLogger(LocationService.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}
I am 100% sure that my rest it is working , if I put this in my browser:
http://localhost:8080/BIReportL-war/rest/location/findlocation
I get this Json String:
{"description":"Description","id":0,"tittle":"Tittle ..."}
The deal is in my angular code, the code where I am calling the rest service from angular it is getting executed but it is just giving me the error part:
app.controller('questionsController', function ($scope, $http) {
//var url = "http://localhost:8080/BIReportL-war/rest/location/findlocation";
//var url = "http://www.w3schools.com/angular/customers.php";
var url = "http://127.0.0.1:8080/BIReportL-war/json.json";
$http.get(url)
.success(
function (data, status, headers, config) {
alert("success");
})
.error(function(data, status, headers) {
alert('Repos status ' + status + ' --- headers : ' + headers);
})
.finally(
function() {
});
});
I have with comments another local URL to a dummy json file that I can access it by that browser, and also I get the same result an error, the weird thing is that I tried with this rest public json file:
http://www.w3schools.com/angular/customers.php
And I get the success !! I don't know why, what I am doing or what I have wrong, I mean when I try with my local rest service, I see that it is getting called in the logs, that is a fact, but the angular client is getting into an error.
Thanks in advance for your help !
I am using:
*Glassfish V4
*Angular
Well, was about the CORS Issue I just put my rest as below, so here is the SOLUTION:
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("/findlocation")
public Response findLocation() {
System.out.println("findlocation");
try {
LocationDTOx x = new LocationDTOx();
x.setDescription("Description");
x.setId(0l);
x.setParent(null);
x.setTittle("Tittle ...");
return Response.ok()
.entity(x)
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
.build();
} catch (Exception ex) {
Logger.getLogger(LocationService.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
If AngularJS is accessing your local REST API, the fact that you're running it in a browser on a different port, it counts as a different origin, per the rules of CORS (separate port means separate origin).
Two pages have the same origin if the protocol, port (if one is
specified), and host are the same for both pages.
For your Access-Control-Allow-Origin response header, either set it to all via *, or specify the alternate ports explicitly. This has to do with the fact that your browser (and AngularJS) are attempting to play by the rules, which you can find on MDN's page on same origin policy.
These "rules" don't apply when you load the resource directly in your browser, as the origin (page your browser is loading from) is the same port, as you're loading just the resource, at that origin (plus port).
[Edit]
The CORS standards included adherence to certain response headers, such as Access-Control-Allow-Origin and Access-Control-Allow-Methods.
References:
MDN's page on access control
HTML5Rocks.com tutorial on CORS
[/Edit]
Your Jersey service is using GET (#GET) while your Angular client is using POST ($http.post(url)).
Change the Angular code to $http.get and you're good to go.
Your example of http://www.w3schools.com/angular/customers.php is working because it responds to both POST and GET, however for your scenario GET is clearly the correct HTTP verb.
Did you try to use relative url? var url = "/BIReportL-war/json.json";
Can you post here the entire error?
I agree with #pankajparkar it might be a CORS problem.
(Sorry for posting this 'answer', I don't have enough points for comments)