Convert form data to object (DTO) - java

I have this route in controller which accepts - application/x-www-form-urlencoded
#RequestMapping(value = "/browser", method = RequestMethod.POST, produces = {"application/xml"}, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
#ResponseBody
public ResponseEntity<String> processServerCallback(#RequestBody final MultiValueMap<String, String> formVars) {
System.out.println(formVars);
return null;
}
Now I need to convert formVars to my DTO object. How can I do that?

Say, formVars looks like this:
public class FormVars{
private String name;
private int age;
//constructors and getters and setters
}`
Then in your controller method, you need to replace #RequestBody MultiValueMap<String, String> with #RequestBody FormVars formVars

Related

Map multipart data to POJO on Spring WebFlux

On the frontend we have a form which send the data as multipart/form-data and we need to receive the data in the controller. Keys nameconvention is to use hyphens.
We can receive the data in the controller by using #RequestPart annotation
#PostMapping(value = "/create", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Mono<String> create(#RequestPart("first-name") String firstName,
#RequestPart("last-name") String lastName) {
// ...
}
But the form can contains more fields, and in this case it is not so convenient to receive data by using #RequestPart.
Is there a way to map multipart fields to a POJO on Spring WebFLux? Something like
class UserData {
private String firstName;
private String lastName;
// getters & setters
}
#PostMapping(value = "/create", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Mono<String> create(UserData userData) {
// ...
}

Send value from Front To Back without changing java methods signature (springboot)

I need to send a value from an Angularjs front to a springboot Java back-office.
The back is called by many other fronts and services.
Which means I can change The front but I have to make sure that any change on the back must not break it for the other callers.
So Extra headers or Other fields in the request body etc... any change that won't break the other existing calls is what I'm looking for.
An example of some methods signature:
A HTTP GET signature
#Override
#ResponseStatus(code = HttpStatus.OK)
#RequestMapping(value = "/", method = RequestMethod.GET)
public ResponseEntity<List<Something>> getSomething(
#RequestHeader(name = Constants.HEADER.SOME_CODE) final String code,
#RequestHeader(name = Constants.HEADER.COMPANY_ID) final String companyId,
#RequestHeader(name = Constants.HEADER.CLIENT_ID) final String clientId) {
A HTTP POST signature
#Override
#ResponseStatus(code = HttpStatus.OK)
#RequestMapping(value = "/{pathValue}/transactions", method = RequestMethod.POST)
public ResponseEntity<SomeResponse> requestSomething(
#RequestHeader(name = Constants.HEADER.EFS_CODE) final String vode,
#RequestHeader(name = Constants.HEADER.COMPANY_ID) final String companyId,
#RequestHeader(name = "Access-Code", required = false) final String codeAcces,
#RequestHeader(name = Constants.HEADER.CLIENT_ID) final String clientId,
#PathVariable("pathValue") final String pathValue,
#RequestBody #Valid Transact transaction) {

Spring - is it possible to give same url (path) in request mapping for two different post methods?

Is it possible to map same path (uri) in request mapping for two different post methods, only difference is request body.
Example
#RequestMapping(value = "/hello", method = RequestMethod.POST)
public String helloEmployee(#RequestBody Employee employee) {
return "Hello Employee";
}
#RequestMapping(value = "/hello", method = RequestMethod.POST)
public String helloStudent(#RequestBody Student student) {
return "Hello Student";
}
No, you can't give same url in request mapping of post method having different request body type but same media type. Below won't work:
#PostMapping(path = "/hello", consumes = MediaType.APPLICATION_JSON_VALUE)
public String hello(#RequestBody Pojo1 val) {
return "Hello";
}
#PostMapping(path = "/hello", consumes = MediaType.APPLICATION_JSON_VALUE)
public String hello(#RequestBody Pojo2 val) {
return "Hello";
}
If you have different media type, then it will. Below will work:
#PostMapping(path = "/hello", consumes = MediaType.APPLICATION_JSON_VALUE)
public String hello(#RequestBody Pojo val) {
return "Hello";
}
#PostMapping(path = "/hello", consumes = MediaType.TEXT_PLAIN_VALUE)
public String hello(#RequestBody String val) {
return "Hello";
}
Your RequestMapping should differ on at least one of the conditions; path,method,params,headers,consumes,produces
I needed the same url post mapping but it was giving me an error so I added different params and it worked for me
//url1 post mapping
#PostMapping(value = "/applicant/{step}", params = "validatedata")
//url2 post mapping
#PostMapping(value = "/applicant/{step}", params = "data")
if any of the below is different(as mentioned by the above answers)then you can have the same URL post mapping
path,method,params,headers,consumes,produces
In my case params was diffrent
Yes you can do that but you need to specify unique parameters signature in RequestMapping annotation:
public class MyController {
#RequestMapping(method = RequestMethod.POST, params = {"!name", "!name2"})
public String action(HttpServletRequest request, HttpServletResponse response){
// body
}
#RequestMapping(method = RequestMethod.POST, params = "name")
public String action(HttpServletRequest request, HttpServletResponse response,
#RequestParam(value = "name", required = true) String name) {
// body
}
}
`

Spring MVC how #RequestBody works

I thought that #RequestBody tries to map request params to the object after the annotation by the property names.
But if I got:
#RequestMapping(value = "/form", method = RequestMethod.GET)
public #ResponseBody Person formGet(#RequestBody Person p,ModelMap model) {
return p;
}
The request:
http://localhost:8080/proj/home/form?id=2&name=asd
Return 415
When I change #RequestBody Person p with #RequestParam Map<String, String> params it's OK:
#RequestMapping(value = "/form", method = RequestMethod.GET)
public #ResponseBody Person formGet(#RequestParam Map<String, String> params) {
return new Person();
}
Person class:
public class Person{
private long id;
private String name;
public Person() {
}
public Person(long id, String name) {
super();
this.id = id;
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Spring vresion 3.2.3.RELEASE
Where did I go wrong?
No, it's a job for #ModelAttribute, not #RequestBody.
#ModelAttribute populates fields of the target object with values of the corresponding request parameters, performing conversions if necessary. It can be used for requests generated by HTML forms, links with parameters, etc.
#RequestBody converts requests to object using one of preconfigured HttpMessageConverters. It can be used for requests containing JSON, XML, etc. However, there is no HttpMessageConverter that replicates behavior of #ModelAttribute.
The conversion of input to a bean needs:
Use POST or PUT request for instance with JSON body.
It is also good to specify expected content tipe by "consumes" in Request mapping:
#RequestMapping(value = "/form", method = RequestMethod.POST, consumes = "application/json" )
Add an instance of converter that implements HttpMessageConverter to the servlet context (servlet.xml for instance)
<bean id="jsonConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
Add jackson core and mapper jars to classpath (or to pom.xml)
then you can try it using curl
curl -X POST http://localhost:8080/proj/home/form -d '{"name":"asd", "id": 2}' -H 'Content-type:application/json'
Sorry for missing details but I hope that it helps

Spring REST-ful uri with optional querystring

The normal uri which triggers the default controller to get all cars is just "/cars"
I want to be able to search for cars aswell with an uri, for example: "/cars?model=xyz" which would return a list of matching cars. All the request parameters should be optional.
The problem is that even with the querystring the default controller triggers anyway and I always get "all cars: ..."
Is there a way to do this with Spring without a separate search uri (like "/cars/search?..")?
code:
#Controller
#RequestMapping("/cars")
public class CarController {
#Autowired
private CarDao carDao;
#RequestMapping(method = RequestMethod.GET, value = "?")
public final #ResponseBody String find(
#RequestParam(value = "reg", required = false) String reg,
#RequestParam(value = "model", required = false) String model
)
{
Car searchForCar = new Car();
searchForCar.setModel(model);
searchForCar.setReg(reg);
return "found: " + carDao.findCar(searchForCar).toString();
}
#RequestMapping(method = RequestMethod.GET)
public final #ResponseBody String getAll() {
return "all cars: " + carDao.getAllCars().toString();
}
}
You can use
#RequestMapping(method = RequestMethod.GET, params = {/* string array of params required */})
public final #ResponseBody String find(#RequestParam(value = "reg") String reg, #RequestParam(value = "model") String model)
// logic
}
ie, the #RequestMapping annotation has a property called params. If all of the parameters that you specify are contained in your request (and all other RequestMapping requirements match), then that method will be called.
Try a variation of this:
#Controller
#RequestMapping("/cars")
public clas CarController
{
#RequestMapping(method = RequestMethod.get)
public final #ResponseBody String carsHandler(
final WebRequest webRequest)
{
String parameter = webRequest.getParameter("blammy");
if (parameter == null)
{
return getAll();
}
else
{
return findCar(webRequest);
}
}
}

Categories

Resources