Get form data from a different route in Spring PostMapping - java

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

Related

How to pass data between two endpoints in MVC Spring Controlller

I am quiet new in MVC and Spring and I want to learn best practices and solution so I decided to ask what is the best practice or how you would solve my problem.
I got controller with scope session (To store data in global variable not overrided when another user send request). I got global variable as I mentioned and two endpoints. First endpoint POST - here I send form and call another REST service to fetch data - call depends on data from form. Second endpoint GET - here i send which page to return. This endpoint is used for pagination.
Where is the problem? I have to store data in global variable because when I fetch data in POST endpoint I do not have access to it in GET endpoint. I do not like this solution. Do you have any ideas how to solve it better?
#Controller
#SessionScope
public class someController {
Global variable
#PostMapping(value = "/endpoint")
public String endpoint1(Form form){
//here I fetch data from another REST service depends on form data and save it to global variable
}
#GetMapping(value = "/anotherenpoint")
public String endpoint1(int page){
//here I get data from global variable and return to view as Page object
}
Your #Controller shouldn't be session scoped, instead make your variable session scoped. (you can also annotate it with #Autowired, so your controller automatically has the right variable for the current user)

Spring boot - WeatherApp - API

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.

How to sign JSON message used by Spring Rest controller?

I have a Spring REST application that accepts JSON messages, written like
#RequestMapping(value = "/myhook", method = RequestMethod.POST,
produces = JSON, consumes = JSON)
public #ResponseBody MyResponse doIt
(#Valid #RequestBody(required = true) MyContractRequest request) {
MyResponse response;
...
return response;
}
This works really well with almost no code to support, but now I have a requirement to sign both response and request.
I started from simply computing the shared signature of all message fields at Java level and assigning it to the dedicated signature field. However this requires to have and maintain code for computing the signatures:
public void update(java.security.Signature sign) throws Exception {
sign.update(name);
sign.update(value);
sign.update(etc);
}
Some people around me expressed opinion that the need to write and maintain this signing code may not be the best design, and it may be better to sign the whole message as a single JSON string. I could fetch the request as a string manually, and then process JSON manually, but I really would like to preserve the Spring controller concepts.
Also, I cannot longer have the signature field in the message itself because the value of this field obviously also changes the signature of the JSON string.
Is there any way to compute the signature of the whole JSON message body on the message departure and arrival, and where to place the signature so it could be passed together with the message? One of the idea is to use the custom HTTP header for the signature. Anyway, how to compute it first?
You can use a servlet filter with Spring MVC and modified your content whatever you want in request and response as well
Example :
http://www.mkyong.com/spring-mvc/how-to-register-a-servlet-filter-in-spring-mvc/
or you can use Spring 3 MVC Interceptor
http://viralpatel.net/blogs/spring-mvc-interceptor-example/

Any simple way to test a #RequestBody method?

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/

Spring MVC(Spring 2.5) Question about Post-Redirect-Get

I have a Spring Annonted Controller that is used to capture the information from a form and get a list of search results from the database.
Here is the definition of the method
#RequestMapping(method = RequestMethod.POST, params = {SUBMIT_BTN })
public ModelAndView processForm(#ModelAttribute(COMMAND_NAME){
// 1. Load search results using search parameters from form (Contained in a collection of some sort)
// 2. Create the ModelAndView
// 3. Redirect with RequestView or redirect: to generate a GET.
}
I think I need to redirect with redirect: since i have a list of items in a collection store in the session. Cannot add that as a url request param.
Basically I'm trying to prevent problems whith the back button where it says that the page is expired. I want to implement the PRG pattern in strings.
I'm having a hard time wrapping my head around converting the POST into a GET. Can I just redirect or do I need two methods? Thanks for any help you can provide.
The standard pattern is to have a controller method to handle the GET,and which shows the form (or whatever) to the user, and one to handle the POST, which is the form submission. The POST method sends a redirect after it has finished processing the submission, which comes back in to the GET method.
#RequestMapping(value="/myapp", method=GET)
public String showForm(#ModelAttribute(COMMAND_NAME){
return "form.jsp";
}
#RequestMapping(value="/myapp", method=POST)
public String processForm(#ModelAttribute(COMMAND_NAME){
// do stuff to process for submission
return "redirect:/myapp";
}
Returning a view name with the "redirect:" prefix forces Spring to send an HTTP direct rather than an internal request forward.
This is the same pattern that Spring 2.0 implemented with SimpleFormController, but the new way is far more transparent.

Categories