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();
Related
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.
I'm building my first springboot microservice project and I'm trying to POST a request to a subscriber service, which requires a body in json format and has to include a name and uri for the subscription service to reach the subscriber, this is the class which implement the POST request,
public class Registration{
public static void postRegistration(){
final String registrationUrl = "localhost:9000/registry";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
JSONObject registrationDetails = new JSONObject();
headers.setContentType(MediaType.APPLICATION_JSON);
registrationDetails.put("name", "OrderGenerator");
registrationDetails.put("uri", "http://localhost:8081/generate");
HttpEntity<String> request =
new HttpEntity<String>(registrationDetails.toString(), headers);
String response = restTemplate.postForObject(registrationUrl,request,String.class);
System.out.println(response);
}
};
i have called that method in the main class as follows as i want it to execute when i start the server,
#SpringBootApplication
public class OrderGeneratorServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderGeneratorServiceApplication.class, args);
Registration.postRegistration();
}
my compiler doesnt, not show any errors but i do not receive notifications to the url i provided, However it starts to work when i send the POST request through postman. What am i doing wrong here?
If you are using Postman, it creates auto generated code for the requests you are making. Its On the right hand side right below the "SAVE" button. You need to create your own auto format method so that you can give the correct input. Here is an example from some API that I am currently consuming.
You see how I have a super long input for the third line? You should create a method that will take your input and auto format it.
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\r\n \"categoryName\": \"PostMan\",\r\n \"categoryQuestions\": [\r\n \"When is the last time you experienced nostalgia?\",\r\n \"What's the scariest dream you've ever had?\",\r\n \"What's the weirdest thought you've ever had?\",\r\n \"What's the first thing that comes to mind when you hear the word fidget?\",\r\n \"What made-up word would you incorporate into the English language if you could?\"\r\n ]\r\n}");
Request request = new Request.Builder()
.url("http://localhost:8080/api/v1/categories")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
Here is my example (I am working with JSON Data in the format like this
{
"categoryName": "PostMan",
"categoryQuestions": [
"When is the last time you experienced nostalgia?",
"What's the scariest dream you've ever had?",
"What's the weirdest thought you've ever had?",
"What's the first thing that comes to mind when you hear the word fidget?",
"What made-up word would you incorporate into the English language if you could?"
]
}
This is how I formatted that data.
public static String inputParse(String nameInput, ArrayList<String> questionInput) {
String inputBuilder = "{\r\n \"categoryName\": \"" + nameInput + "\",\r\n \"categoryQuestions\": [\r\n ";
for (int i = 0; i < questionInput.size(); i++)
{
inputBuilder += "\"" + questionInput.get(i) + "\"";
if (i != questionInput.size()-1)
{
inputBuilder += ",";
}
}
inputBuilder += "\r\n ]\r\n}";
return inputBuilder;
}
In addition, I see that you are working with Springboot. You can use org.springframework.web.client.RestTemplate (rest-template) to consume rest api. An example for using REST Template that i got from this website.
private void createEmployee() {
Employee newEmployee = new Employee("admin", "admin", "admin#gmail.com");
RestTemplate restTemplate = new RestTemplate();
Employee result = restTemplate.postForObject(CREATE_EMPLOYEE_ENDPOINT_URL, newEmployee, Employee.class);
System.out.println(result);
}
I have a problem with Spring Boot RestTemplate exchange.
I have the following code:
#RequestMapping(path = "/add")
public #ResponseBody String addFromTo () {
String apikey = "";
String baseurl = "http://demowebshop.webshop8.dk/admin/WEBAPI/v2/orders?start=2018-10-05T20%3A49%3A41.745Z&end=2018-10-15T20%3A49%3A41.745Z&api_key=" + apikey;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setBasicAuth("", apikey);
HttpEntity<String> request = new HttpEntity<String>(" ", headers);
ResponseEntity<OrderResponse> response = restTemplate.exchange(baseurl, HttpMethod.GET, request, OrderResponse.class);
return "Some text.";
}
What I want is the equivalent of:
curl -X GET --header 'Accept: application/json' --header 'Authorization: Basic {encodedapikey}' 'http://demowebshop.webshop8.dk/admin/WEBAPI/v2/orders?start=2018-10-06T06%3A43%3A40.926Z&end=2018-10-16T06%3A43%3A40.926Z&api_key={apikey}'
I've tried using Postman with the exact same URL, and adding Basic Auth with the apikey, and an 'Accept: application/json' header, and that works fine, but when I run this code, I get the error message:
There was an unexpected error (type=Internal Server Error, status=500).
400 Bad Request
EDIT:
Pastebin link to the exception thrown by the program:
https://pastebin.com/jdYJ2nv7
In your curl request you are using an apikey and encodedapikey. Whereas in your Java code you don't. Next to that you are also passing an encoded URL as the URL to use. This will result in encoding the encoded URL again. So don't do that. Instead use a URL with placeholders and supply values for them.
#RequestMapping(path = "/add")
public #ResponseBody String addFromTo () {
String apikey = "";
String baseurl = "http://demowebshop.webshop8.dk/admin/WEBAPI/v2/orders?start={start}&end={end}&api_key={apikey}";
Map<String, Object> parameters = new HashMap<>();
parameters.put("start", "2018-10-05T20:49:41.745Z");
parameters.put("end", "2018-10-16T06:43:40.926Z");
parameters.put("apikey", apikey);
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setBasicAuth("", apikey);
ResponseEntity<OrderResponse> response = restTemplate.getForEntity(baseurl, OrderResponse.class, parameters);
return "Some text.";
}
The code above uses a proper parameterized URL together with a map containing values for the placeholders. Notice that those aren't encoded, as that will be handled by Spring!. Finally you can simply use the getForEntity method to get the result instead of the exchange method.
A final suggestion, Spring Boot already configures a RestTemplate which you can (re)use. You don't need to create a RestTemplate each time you need one (it is quite a heavy object to create, and after creation it is thread safe so it is enough to have a single instance).
public YourClassCOnstructor(RestTemplateBuilder builder) {
this.restTemplate = builder.basicAuthorization("", apikey).build();
}
Ofcourse you can also put this in an #Bean method and inject the specific RestTemplate into your class.
HttpHeaders.setBasicAuth(String, String) is used for username and password only, not for basic token.
If you want to use basic token try something like headers.add("Authorization", "Basic " + apiKey) instead of headers.setBasicAuth(...)
Hi I am trying to call some Soft layer APIs and was able to make simple calls as well as calls which include passing some ids using Spring's RestTemplate in java, but not able to make a similar call in java for below rest URL.
// formatted for readability
https://getInvoices?
objectFilter={
"invoices":{
"createDate":{
"operation":"betweenDate",
"options":[
{
"name":"startDate",
"value":[
"06/01/2016"
]
},
{
"name":"endDate",
"value":[
"06/02/2016"
]
}
]
}
}
}
Can anyone help me out how to do the same in java using springs rest template or even using soft layer rest client.
If you are willing to user Jersey Client API, your code could be like:
String json = "{\"invoices\":{\"createDate\":{\"operation\":\"betweenDate\",\"options\":[{\"name\":\"startDate\",\"value\":[\"06/01/2016\"]},{\"name\":\"endDate\",\"value\":[\"06/02/2016\"]}]}}}";
Client client = ClientBuilder.newClient();
WebTarget target = client.target("https://api.softlayer.com")
.path("rest")
.path("v3")
.path("SoftLayer_Account")
.path("getInvoices")
.queryParam("objectFilter",
URLEncoder.encode(json, StandardCharsets.UTF_8.toString()));
String result = target.request(MediaType.APPLICATION_JSON_TYPE).get(String.class);
With Spring RestTemplate, you would do:
String json = "{\"invoices\":{\"createDate\":{\"operation\":\"betweenDate\",\"options\":[{\"name\":\"startDate\",\"value\":[\"06/01/2016\"]},{\"name\":\"endDate\",\"value\":[\"06/02/2016\"]}]}}}";
RestTemplate restTemplate = new RestTemplate();
URI targetUrl = UriComponentsBuilder
.fromUriString("https://api.softlayer.com")
.path("rest")
.path("v3")
.path("SoftLayer_Account")
.path("getInvoices")
.queryParam("objectFilter",
URLEncoder.encode(json, StandardCharsets.UTF_8.toString()))
.build()
.toUri();
String result = restTemplate.getForObject(targetUrl, String.class);
You can either use RestTemplate
RestTemplate restTemplate = new RestTemplate();
String resourceUrl = "http://localhost:8080/resturl";
ResponseEntity<String> response = restTemplate.getForEntity(resourceUrl+ "/1", String.class);
or you can go with httpclient
I struggled with an extrange spring behavior using RestTemplate (org.springframework.web.client.RestTemplate) without success.
I use in my hole application below code and always receive an XML response, which I parse and evaluate its result.
String apiResponse = getRestTemplate().postForObject(url, body, String.class);
But can't figure out why a server response is in JSON format after executing:
String apiResponse = getRestTemplate().getForObject(url, String.class);
I've debugged at low level RestTemplate and the content type is XML, but have no idea why the result is in JSON.
When I access from a browser the response is also in XML, but in apiResponse I got JSON.
I tried many options after reading Spring documentation
http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/web/client/RestTemplate.html
Also tried to modify explicitly the headers but still can't figure it out.
I debugged RestTemplate class and noticed that this method is always setting application/json:
public void doWithRequest(ClientHttpRequest request) throws IOException {
if (responseType != null) {
List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
for (HttpMessageConverter<?> messageConverter : getMessageConverters()) {
if (messageConverter.canRead(responseType, null)) {
List<MediaType> supportedMediaTypes = messageConverter.getSupportedMediaTypes();
for (MediaType supportedMediaType : supportedMediaTypes) {
if (supportedMediaType.getCharSet() != null) {
supportedMediaType =
new MediaType(supportedMediaType.getType(), supportedMediaType.getSubtype());
}
allSupportedMediaTypes.add(supportedMediaType);
}
}
}
if (!allSupportedMediaTypes.isEmpty()) {
MediaType.sortBySpecificity(allSupportedMediaTypes);
if (logger.isDebugEnabled()) {
logger.debug("Setting request Accept header to " + allSupportedMediaTypes);
}
request.getHeaders().setAccept(allSupportedMediaTypes);
}
}
}
Could you give an idea?
I could solve my issue with RC.'s help. I'll post the answer to help other people.
The problem was that Accept header is automatically set to APPLICATION/JSON so I had to change the way to invoke the service in order to provide the Accept header I want.
I changed this:
String response = getRestTemplate().getForObject(url, String.class);
To this in order to make the application work:
// Set XML content type explicitly to force response in XML (If not spring gets response in JSON)
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = getRestTemplate().exchange(url, HttpMethod.GET, entity, String.class);
String responseBody = response.getBody();