I need to initialize my builder class members with some Dummy values while calling .param()
#Builder
public class MyQuery {
private String param1;
private String param1;
private String param1;
private String param1;
...
private String param100;
}
When I call the builder class like below, I want them to be initialized with some dummy value(or empty string) and the rest should be null. If I use the LOMBOK builder, it has to be initialized with some value as .param1("some string"). Is there any library which can help me here.
MyQuery query = MyQuery.builder()
.param1()
.param2()
.param3()
.build();
whichever parameter I call, should have some dummy value(non-null, could be empty as well).
After going through the lombok builder doc, I realized that I could do something as follows. Lombok will not generate the resources if a resource with the same name already exists. This approach will still reduce some of the boiler plate codes.
import lombok.Builder;
#Builder
public class MyQuery {
private static final String SOME_STRING = "This is needed";
private String paramWithNoSpecialCase // This is any other parameter, lombok will generate the builder for this.
private String param1;
private String param2;
private String param3;
public static class MyQueryBuilder {
public MyQuery.MyQueryBuilder param1() {
this.param1 = SOME_STRING;
return this;
}
public MyQuery.MyQueryBuilder param2() {
this.param1 = SOME_STRING;
return this;
}
public MyQuery.MyQueryBuilder param3() {
this.param1 = SOME_STRING;
return this;
}
}
}
I have multiple endpoints in my RestControllers that follow some similar signature:
#GetMapping
public SomeItem get(#RequestParam String sortBy,
#RequestParam String sortField,
#RequestParam int pageNumber,
#RequestParam int pageSize) {
QueryOptions queryOptions = QueryOptions.of(sortyBy, sortField, pageNumber, pageSize);
// ...
}
I was wondering if there is a way of removing this code duplication from all the different methods and move the QueryOptions construction somewhere before the RestController method, so that I could use a method like the following:
#GetMapping
public SomeItem get(QueryOptions queryOptions) {
// ...
}
How can I do this? Maybe adding a filter in the filterchain?
It turns out that this is supported out of the box:
#Getter
#Setter
public class QueryOptions {
private String pageNumber;
private String pageSize;
private String orderBy;
private String sortField;
}
And then you can accept this Class in the Controller method:
#GetMapping
public SomeItem get(QueryOptions queryOptions) {
// ...
}
How can I simply redirect a url if a specific query parameter is missing?
#RestController
public class PersonController {
//only in case the "sort" query parameter is missing
#GetMapping("/persons")
public String unsorted() {
return "redirect:/persons?sort=name";
}
//only in case the "sort" query parameter exists
#GetMapping("/persons")
public String sorted() {
//...
}
}
Use #RequestParam to extract query parameters
Add parameter for #RequestParam: value, defaultValue, required
with java >= 8:
#RestController
public class PersonController {
#GetMapping("/persons")
public String personList(#RequestParam(value = "sort", defaultValue = "name") Optional<String> sort) {
//handling process here
}
}
with java < 8:
#RestController
public class PersonController {
#GetMapping("/persons")
public String personList(#RequestParam(value = "sort", defaultValue = "name", required=false) String sort) {
//handling process here
}
}
You could use #GetMapping.params
#GetMapping(value = "/persons", params = "sort")
public String sorted() {
You can use the params element. One mapping will supports params="sort" for when the sort parameter is present and the other params="!sort" for when it is missing.
However, you may want to consider using a default value instead of performing a redirect. What benefit does the redirect provide? It will require the server respond and then and have the client make a second HTTP request.
Using params
#RestController
public class PersonController {
//only in case the "sort" query parameter is missing
#GetMapping(value = "/persons", params = "!sort")
public String unsorted() {
return "redirect:/persons?sort=name";
}
//only in case the "sort" query parameter exists
#GetMapping(value = "/persons", params = "sort")
public String sorted() {
//...
}
}
Using default value
#RestController
public class PersonController {
//only in case the "sort" query parameter exists
#GetMapping("/persons")
public String sorted(
#RequestParam(name = "sort", defaultValue = "name") String sort)
{
//...
}
}
You can set a default value:
#RestController
public class PersonController {
//only in case the "sort" query parameter is missing
#GetMapping("/persons")
public String unsorted(#RequestParam(value = "sort", defaultValue = "name") String name) {
// do logic
}
}
You can also set the default value for the missing value and continue forward
#RequestParam(value = "sort", defaultValue = "name") String name
Is it possible to rename the parameters used inside a GET webservice in spring? Like search.limitResults in the following example:
localhost:8080/firstname=test&search.limitResults=10
You get the idea. Can this be achieved?
#RestController
public class MyServlet {
#RequestMapping(value = "/", method = RequestMethod.GET)
private String test(RestParams p) {
}
}
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class RestParams {
private String firstname;
private String lastname;
//is that possible to nest?
#XmlElement(name = "search")
private MyComplexSearch search;
public MyComplexSearch getSearch() {return search;}
public void setSearch(MyComplexSearch) {this.search = search;}
#XmlRootElement(name = "search")
#XmlAccessorType(XmlAccessType.FIELD)
public class MyComplexSearch {
private int limitResults;
//some more
}
}
The request will not work with the code above. Instead one would have to use myComplexSearch as the objects name.
localhost:8080/firstname=test&myComplexSearch.limitResults=10
How can I redefine the name of the input property, without having to rename the java class itself?
Nested classes have to be static.
public static class MyComplexSearch
I'm not clear how jackson deals with capitalization in mapping fields. If anyone could help I'd appreciate it.
{"user":{"username":"user#host.com","password":"pwd","sendercompid":"COMPID","service":{"host":"address","port":6666,"service":"S1","serviceAsString":"s1"}},"MDReqID":"ghost30022","NoRelatedSym":1,"Symbol":["GOOG"],"MarketDepth":"0","NoMDEntryTypes":3,"MDEntryType":["0","1","2"],"SubscriptionRequestType":"1","AggregatedBook":"N"}:
Above is my json, below is my exception...
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "MDReqID" (class com.myco.qa.fixrest.MarketDataRequest), not marked as ignorable (10 known properties: , "mdreqID", "marketDepth", "user", "subscriptionRequestType", "aggregatedBook", "mdentryType", "symbol", "mdupdateType", "noRelatedSym", "noMDEntryTypes"])
Above is my exception, below is my class...
public class MarketDataRequest {
private User user;
private String MDReqID;
private char SubscriptionRequestType;
private int MarketDepth;
private int MDUpdateType;
private char AggregatedBook;
private int NoMDEntryTypes;
private ArrayList<Character> MDEntryType;
private int NoRelatedSym;
private ArrayList<String> Symbol;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getMDReqID() {
return MDReqID;
}
public void setMDReqID(String MDReqID) {
this.MDReqID = MDReqID;
}
public char getSubscriptionRequestType() {
return SubscriptionRequestType;
}
public void setSubscriptionRequestType(char subscriptionRequestType) {
SubscriptionRequestType = subscriptionRequestType;
}
... et cetera
Since your setter method is named setMDReqID(…) Jackson assumes the variable is named mDReqID because of the Java naming conventions (variables should start with lower case letters).
If you really want a capital letter use the #JsonProperty annotation on the setter (or - for serialization - on the getter) like this:
#JsonProperty("MDReqID")
public void setMDReqID(String MDReqID) {
this.MDReqID = MDReqID;
}
You can also do
#JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
on the class to capitalise all property names in the JSON message
Add #JsonProperty on the setter that matches the property name in your received JSON string:
#JsonProperty("MDReqID")
public void setMDReqID(String MDReqID) {
this.MDReqID = MDReqID;
}
Additionally add #JsonProperty annotation to the getter as well for your output to appear in the conventional format:
#JsonProperty("mDReqID")
public String getMDReqID() {
return MDReqID;
}
Now you can name your variable whatever you like:
private String mdReqID;
I solve this problem by:
#Getter
#Setter
static class UserInfo {
//#JsonProperty("UUID")
private String UUID = "11";
private String UserName = "22";
private String userName = "33";
private String user_Name = "44";
private String user_name = "55";
private String User_name = "66";
private boolean HasDeleted=true;
private boolean hasDeleted=true;
private boolean has_Deleted=true;
private boolean has_deleted=true;
private boolean HAS_DELETED=true;
}
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
String s = objectMapper.writeValueAsString(new UserInfo());
System.out.println(s);
UserInfo userInfo = objectMapper.readValue(s, UserInfo.class);
System.out.println(objectMapper.writeValueAsString(userInfo));
}
output:
{"UUID":"11","UserName":"22","userName":"33","user_Name":"44","user_name":"55","User_name":"66","HasDeleted":true,"hasDeleted":true,"has_Deleted":true,"has_deleted":true,"HAS_DELETED":true}
I face the same problem , after have try UpperCamelCaseStrategy but still this error occurred , the strategy made my field pContent to ObjectMapper property Pcontent, as not want to add #JsonProperty for every field, simply use gson instead at last
Use JsonNaming Annotation to get all Class Field Names in Proper Case
Use lombok.Data Annotation to automatically make it work without adding getters and setters in your class
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import lombok.Data;
#JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class)
#Data