Spring Multiple RequestParams vs RequestBody, which is Preferred? - spring

I am new to Spring Rest. While Doing POST, we have 2 options either #RequestBody or #RequestParams.
My query is not what they are. I am pretty well know what they are.
Normally we use #RequestParams for form-urlencoded and #RequestBody for JSON/XML.
I have a scenario as below:
class EmployeeDTO {
long id;
String name;
String age;
String address;
String salary;
//Getters and Setters
}
For POST, I can directly use as void doSomething(#RequestBody EmployeeDTO){ }
and also I can do same thing but using 5 RequestParams
void doSomething(#RequestParam(id) long id, #RequestParam(name) String name, #RequestParam(age) String age, #RequestParam(address) String address, #RequestParam(salary) String salary){ }
I have seen some good sites like Stripe, they following only #RequestParam in their REST Api.
I actually got to understand that we use RequestBody for Complex Input and#RequestParam for simple parameters.
So, my actual query is: In above class, had only 5 parameters, I am thinking its okay going with #RequestParam, But what if there are like 7 or 10 input params, then should I chose RequestBody or (7 or 10) REquestParam?
EDIT:
class Orders {
String id;
Employee employee;
}

It is not really a choice based on "number of data I have to push on server".
Historically and in general the use of the query string is, as the name implies, to query data. And so request param would be the preferred choice when you want to "pull" data HTTP GET
Here if the goal is to "push" data on the server (for instance "to create an employee") you should prefer sending this data in request body.
Moreover the query string is part of the URL, and it can be read by everyone sitting between the clients and the API, so we shouldn’t put sensitive data like passwords into the query string.
you can mimic the format of query string in your body by using the mime type application/x-www-form-urlencoded. Here request body uses the same format as the query string.
parameter=value&parameter2=another

Related

Consuming API and store results to database

I need to consume this API: https://api.punkapi.com/v2/beers and after consuming, I have to store it in the database, but only with next fields: internal id, name, description and mean value of the temperature. Any ideas or advice?
The simplest approach would be to have your Model only containing those attributes so that Spring only deserialize them from JSON to object. Something like the following:
public class YourModel {
private long id;
private String name;
private String description;
}
Then in your Service you would have:
ResponseEntity<YourModel> response = restTemplate.getForEntity(url, YourModel.class);
You can then either save YourModel directly to the database (first you need to add some #Annotations if you want to rely on JPA) or you may build another more suited model to your use case.

How can I map the fields return in JSON with my entity provided the key in JSON has different name than fields in my entity

I am trying to Map a JSON response to a Java POJO which has a different field name from different API.
I need an efficient way to do this reducing boilerplate codes.
I have tried mapping the JSON property field in Java POJO.
However, the problem is I am fetching data from different sources.
Let's say I have below user class
Class User{
String name;
String contact;
}
The JSON I may receive from different sources can be
{"name": "ABC" , "contact": "123456"}
or
{"userName": "XYZ" , "mobileNo":"4354665"}
There may be more variations as we go on integrating more API's
Is there a way I can archive this?
above is just a simple example
there could be more complex JSON object I may need to read.
like List of User etc.
You can use the #JsonAlias() to give the variable more than one JSON key binding.
#JsonAlias is introduced in Jackson 2.9 release. #JsonAlias defines one or more alternative names for a property to be accepted during deserialization i.e. setting JSON data to Java object. But at the time of serialization i.e. while getting JSON from Java object, only actual logical property name is used and not alias. #JsonAlias is defined as follows.
#Entity
Class User{
#JsonProperty()
#JsonAlias({"name", "userName"})
String name;
#JsonProperty()
#JsonAlias({"contact", "mobileNo"})
String contact;
}
You could use the #JsonSetter annotation like :
public class User{
public String contact;
public String name;
#JsonSetter("name")
public void setName(String name) {
this.name = name;
}
#JsonSetter("userName")
public void setName(String name) {
this.name = name;
}
}
Instead of directly mapping to an entity class , you should have a DTO object or model in between to map the json response. Then, you can convert that into any entity you may choose.If you are fetching the data from different sources , it means you are calling different endpoints, why don't you create different DTO 's for that.In that way even if one of the endpoints introduce a change , it won't affect the rest of the endpoint calls.
Vice-versa you could have different DTO objects being returned from the two endpoints instead of returning the same Entity class as well, that way you can have control over which attributes should be there in the response.
To reduce the boiler plate code, you could use library such as MAP STRUCT to enable conversion between entity and DTO objects easily
Read here about the advantages of using a DTO .

obscuring url strings in spring mvc

How do I obscure the values of fields used in url strings in a spring mvc web app?
For example, if I want to send the record with recordID=1 into the view, I give the user a hyperlink with the following url:
https://myapp.com/urlpattern?recordID=1
As you can see, this not only exposes the recordID=1, it also tempts a malicious user to start typing other numbers to mine other records such as recordID=5 or recordID=9.
Does the spring framework or spring security have a built-in way of encrypting url strings? Or do I need to change the id values in the underlying database using hibernate?
The controller code for the above url pattern is:
#RequestMapping(value = "/urlpattern", method = RequestMethod.GET)
public String processUrlPattern(#RequestParam("recordID") String recordId,
HttpServletRequest request, BindingResult result, Map<String, Object> model) {
Long recId = Long.valueOf(recordId).longValue();
RecordObject sel_record = this.appService.findRecordById(recId);
model.put("sel_record", sel_record);
return "foldername/jspname";
}
Note that all entities in the app inherit from the same BaseEntity whose id-generating code is as follows:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#DiscriminatorFormula("(CASE WHEN dtype IS NULL THEN 'BaseEntity' ELSE dtype END)")
#org.hibernate.annotations.DiscriminatorOptions(force=true)
public abstract class BaseEntity {
#Transient
private String dtype = this.getClass().getSimpleName();
#Id
#GeneratedValue(strategy=GenerationType.TABLE, generator="TBL_GEN")
#TableGenerator(
name="TBL_GEN",
table="GENERATOR_TABLE",
pkColumnName = "mykey",
valueColumnName = "hi",
pkColumnValue="id",
allocationSize=20
)
protected Integer id;
//other stuff
}
NOTE: All the users are authenticated/authorized using Spring security. However, the data is very sensitive, and it is important that no one be able to manipulate url strings.
Use HDIV, it does this out of the box:
http://hdiv.org/hdiv-documentation-single/doc.html
"A6 (Sensitive data exposure) : HDIV offers a confidentially property to all data generated at sever side. That is to say, HDIV replace original parameter values generated at server side by relative values (0,1,2,4, etc.) that avoid exposing critical data to the client side."

How to customized Json response using WCF service

I am trying to return some JSON from a WCF service. This service simply returns some content from my database. I can get the data. However, I am concerned about the format of my JSON. Currently, the JSON that gets returned is formatted like this:
{"d":"[{\"Age\":35,\"FirstName\":\"Peyton\",\"LastName\":\"Manning\"},{\"Age\":31,\"FirstName\":\"Drew\",\"LastName\":\"Brees\"},{\"Age\":29,\"FirstName\":\"Tony\",\"LastName\":\"Romo\"}]"}
In reality, I would like my JSON to be formatted as cleanly as possible. I believe (I may be incorrect), that the same collection of results, represented in clean JSON, should look like so:
Sucess([{"Age":35,"FirstName":"Peyton","LastName":"Manning"},{"Age":31,"FirstName":"Drew","LastName":"Brees"},{"Age":29,"FirstName":"Tony","LastName":"Romo"}])
can anyone please suggest me how could i achive this or let me correct if I am doing something wrong.
It normally depends on what and how you are returning data from JSON. If you are returning String then it might contain / in your string.
But if you are sending custom data, then it will be clean JSON. For example:
[DataContract(Namespace = "")]
public class MyData
{
private int age;
private String firstName;
private String LastName;
[DataMember]
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
//Apply same for other members
}
And suppose this is your operation contract.
MyData getData();
Hope, this will work.

Generated json not including certain fields of POJO class

I have a complex Employee POJO class which has Name, id, salary, dept and Address(vector type) fields.I have generated the json using the jersey restful web service. But the output json does not include the certain pojo fields like address which has datatype as vector. All the fields in POJO class has getter and setters.
Any specific reason that why certain fields are not part of generated JSON ?
//Used below code to generate the JSON
#Path("/employeedDetails")
#GET
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public EmployeedBean getDetails(#QueryParam("Id") String Id,
#Context HttpServletRequest servletRequest) {
Employee e1 = new Employee();
// Sets all Name, id, salary, dept and Address
return e1;
}
You are missing code. Can you post what you are returning? If you are returning an array (such as a Java List object), you'll want to wrap that inside another POJO class. I was having the same issue (see RESTful POJO -> JSON mapping not picking up new fields) and this was what was causing it, since the returned JSON was starting with brackets [] instead of {} and therefore JavaScript wasn't parsing it properly. Returning a single object instead of a List fixed the issue.

Resources