Im trying to make weather apps with spring boot MVC. I wanted to use api from: openweather.com.
In the controller I have a method to pass the parameter. I have two html pages. One with form and submit, the other to display the string of the form.
How to bind an API with my parameter from a form and how to retrieve JSON information.
#GetMapping("/show")
public String show(#RequestParam ("city") String city, ModelMap modelMap){
modelMap.addAttribute("city", city);
return "article/show";
}
You should have a get listener in your back-end code that will get the weather from openweather. It should look something like this:
#RequestMapping("/weather")
public String show(#RequestParam ("city") String city)
//Method body
//In the method body you should make a request to the openweather server with an api key which you can get by registering in the website. You can achieve this with Unirest library (it's the easiest way)
HttpResponse<JsonNode> response = Unirest.get("http://api.openweathermap.org/data/2.5/weather")/
.queryString("APPID","YOUR_APP_ID")
.queryString("city",city)
.header("content-type","application/json")
.asJson();
This method will return a JSON with all the data you need, which you can parse with RestTemplate.
You can use RestTemplate to retrieve JSON from weather API.
You have an example on link below:
http://www.baeldung.com/rest-template
After you receive the JSON object then you can add it to the model and send it to JSP or some other templating engine.
Related
I have an API controller:
#RestController
#RequestMapping("api")
public class ListingRestController {
#PostMapping("/listings/edit/{id}")
public void editListing(ListingForm newListing, #PathVariable Integer id, Model model) {
ListingDto newListingDto = new ListingDto(newListing.getId(), newListing.getUserId(), newListing.getTitle());
model.addAttribute("submitURL", String.format("edit/%s", id));
listingService.deleteListingById(id);
listingService.addListing(newListingDto);
}
}
It takes a POST request from api/listings/edit/{id}. Also it should get the data from form inputs ListingForm newListing.
The problem is, the form is defined in a route listings/edit/{id}, so the controller method cannot get data. Any idea how I can get form data from route listings/edit/{id} in my API controller?
You must define GET api beside Api Post to get data. First, client call API GET to get data from server and place data to the form. After finish editing data, call API POST to post data to server.
You can write #RequestBody annotation to ListeningForm parameter
I am using a FeignClient and a GetMapping to interact with an external system.
My GetMapping is defined as:
#GetMapping(value = "/path/to/endpoint?fields=[\"nm\",\"label\"]")
public String hitEndpoint() {}
Debug shows that the endpoint is being called with:
https://url/path/to/endpoint?fields=[%22nm%22&fields=%22label%22]
Which is failing because the endpoint expects valid json for the fields parameter:
https://url/path/to/endpoint?fields=[%22nm%22,%22label%22]
How do I convince GetMapping to make the request correctly?
Thanks for any help.
Although I think its better to pass JSON as body of a POST method to your controller. But if you insist on doing this I can propose to you 2 solutions:
First Solution
Encode your JSON array into Percent-encoding so you can send it via URL.
For example, your array will be like this:
["nm","label"] -> %5B%22nm%22%2C%22label%22%5D
I used this online tool to encode it.
Second Solution
Encode your array into Base64 and GET it via URL to your controller.
Decode the given Base64 string in the controller and parse it as a JSON array.
There is no need to define your Array parameter in the URL, using spring you can define your API as below and with the power of #RequestParam annotation you can define that you expect to receive an array as a parameter in the URL
#RequestMapping(value = "/path-to-endpoint", method = RequestMethod.GET)
public ResponseEntity<YourResponseDTO> yourMethodName(
#RequestParam("ids") List<Long> arrayParam) {
// Return successful response
return new ResponseEntity<>(service.yourServiceMethod(requestDTO), HttpStatus.OK);
}
Then you can call your GET endpoint using below URL:
/path-to-endpoint?ids=1,2,3,4
I have a Spring Boot online shop application and my shopping cart component is accessible from several different views.
I make my views in Thymeleaf and those - and + are <a th:href="#{'/products/addToCart/'+${product.id}}">. Now inside my products controller I do some backend work and return a redirect:home but that kind of kills the whole point of putting these - and + there. I'd like it to return the same view from which the request was sent. Can that be done somehow? I don't like the idea of making seperate controllers for every view.
You could use the referer (yes the official header has a typo) request header to know where you navigated from:
public String addProduct(#RequestHeader(value = HttpHeaders.REFERER, required = false) final String referrer) {
// update cart
// redirect to the referred
return "redirect:" + referrer;
}
However, that is probably quite brittle. I'm not sure the referrer URL will always be there.
For something like this, I would probably use JavaScript to do an AJAX request to a dedicated endpoint that returns JSON. You can add #ResponseBody on a method in your controller so the response is not seen as a redirect or a page view, but a JSON string for example.
#ResponseBody
public CartInfo updateCart(...) {
// do update to cart here
// return a CartInfo object. It will be serialized with Jackson to a JSON string
}
In your HTML page, you will need to add some JavaScript to handle the AJAX call using plain JS or your framework of choice.
I'm using the proxy integration with my Java lambda function. The input for the lambda handler is a JSON object that represents an incoming request. It has a body, headers, query params and so on. But it doesn't include the source URL that is parsed by the API Gateway for the body, query params and etc. Is there a way to get it?
The thing is API Gateway doesn't support arrays in query parameters. Example: /endpoint?numbers=1&numbers=2. Seems, the only way to pass an array is to pass it as a JSON array string /endpoint?numbers=[1,2] but it is not always suitable. So I want to parse the URL by myself.
Unfortunately, API Gateway doesn't provide you with the full URL for you to parse yourself.
If you have the option of using the POST method to /endpoint, you might consider sending a request body instead of query string parameters.
The 'path' field inside the 'requestContext' field contains the path of API gateway resource. See docs for more details.
you can inject the UriInfo object. It holds all the information you need.
#Context
UriInfo uri;
If I have a #Controller method whose parameter is a #RequestBody param, I usually have to write some jQuery script or something similar to perform an AJAX request with JSON object in order to call that method. If I tried calling that method via a web browser directly, it returns with a Error 415 Unsupported Media Type.
Is there any alternative to just quickly call such method using browser without having to write some jQuery code? Like perhaps a way to write the JSON object in the URL/address bar?
code:
#RequestMapping("testCall")
#ResponseBody
public List<TestObject> getTestCall (#RequestBody TestParams testParams) {
return stuff;
}
public class TestParams {
private Integer testNumber;
//getter/setter for testNumber
}
I thought maybe I could just do:
http://localhost/testCall?testNumber=1
maybe Spring would auto populate a new TestParams instance with that property set to 1 but that didnt work...
maybe I need to do something extra for that?
The whole point of a #RequestBody annotated parameters is for the Spring MVC stack to use the HTTP request body to produce an argument that will be bound to the parameter. As such, you need to provide a request body. Sending a request body is very atypical for a GET request. As such, browsers don't typically support it, at least not when simply entering an address in the address bar and submitting the request.
You'll need to use a different HTTP client, like jQuery. I typically have a small Java project in Eclipse that's setup with an Apache HTTP components client which can send HTTP requests to whatever server. It takes a few seconds/minutes to setup the correct request body and run.
I have spent the last year building a REST API, and by far the best way to exercise that API manually is using the Chrome Extension, Postman. I cannot recommend this tool enough.
https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en
To test your simple example you'll need to invoke a POST (I assume that as you have a request body, but your controller method doesn't define a HTTP Verb) using POSTMAN to your Url (like the following example):
POST /contextRoot/testCall
{
"testNumber": 1
}
If you want to test your API automatically (which I recommend), you can use the excellent Spring Mvc Test project. This allows your to call your API via a rest-like DSL and assert that the response is in the shape you want. More details can be found here:
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/testing.html#spring-mvc-test-framework
you can add request params to the getTestCall method:
#RequestParam(value = "testNumber", required = false, defaultValue = "") String testNumber
There is a chrome app called Advanced REST client. You can pass the data in form of json to your controller using this chrome app. For eg. json data is
id:1,
name:"xyz"
whereas the controller can have #RequestBody Person form.
The Person class would be a POJO having id and name as instance variables. The Spring would automatically map the json data to the form.
I think this is the easiest and simplest way of checking your spring controller.
Check the extension Advanced REST client here
From what I know You can send JSON object to the webbrowser and it will be displayed without further need of AJAX.
useful tutorial:
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/