adding "is" prefix to a Boolean json request field - java

I'm using JAX-RS and Dropwizard to develop an API (I'm pretty new to both)
I want to have a json field called isInNetwork for example. But the strange thing for me is after defining the model and resource, I see inNetwork as the defined json field. (the is prefix is removed)
to be more specific when I define the model as:
#JsonProperty
private Boolean isInNetwork;
and when I run the server I see "inNetwork": false
wanted to know if that's something by default (that I'm not aware of) set by dropwizard / jax-rs for Booleans?

Don't use "is" prefix for the field at all, because of "is" prefix is used for getters for boolean fields. getIsInNetwork method name looks bad.
Better to specify JSON property name for the field
#JsonProperty("isInNetwork")
private Boolean inNetwork;
public Boolean isInNetwork() {
return inNetwork;
}
public void setInNetwork(Boolean inNetwork) {
return this.inNetwork = inNetwork;
}

Related

SpringMVC can not bind json correctly

There a json object to be sent to the server, which contains a field:
{"sName":"something"}
In my request model,I declare a var with the same name:
String sName;
But I got null when I receive in the Controller.
I change the field name to lower-case(sname) or add JsonProperty(value="sName") annotation,it work. So where is the problem?
Controller
public ResponseEntity<JSONObject> getComprehensiveInquiryCp(#Validated #RequestBody ComprehensiveInquiryRequestModel body) {
Map<String, Object> content;
JSONObject result = new JSONObject();
String sLicense = body.getSLicense();
...
}
ComprehensiveInquiryRequestModel
#Data
public class ComprehensiveInquiryRequestModel {
...
//#JsonProperty(value = "sLicense")
private String sLicense;
...
}
From top of my head: if you have accessors in that bean, then I think jackson prefers to use them if they exist. And/or Jackson prefers accessors for private fields. As you noticed you can alter that behaviour with Jakson configuration (for example via annotions).
Try:
1. to debug, remove accessor methods and make field public. If that works then change the field back to private and make sure accessor methods are named correctly.
Also single charater prefixes are not a good practise. They can be problematic and confusing. Prefixes in general are lazy and un-Clean Code(tm) practise.
It is important that your setters (and getters) are present and actually conform to the Java naming conventions. A json property named "myFirstName" usually requires a public setter "setMyFirstName(...)" for example. So "sName" needs "setSName()", I guess.
Sure sounds like the naming convnetion might be at fault here.

Jackson naming convention issue in serialization with uncommon getter method name

New to java and spring boot.
While trying to serialize the following class,
public class ActionItems {
private String APpID;
public String getAPpID() {
return APpID;
}
public void setAPpID(String aPpID) {
APpID = aPpID;
}
// other fields
}
got the json string as
{
"appID": null,
}
Whilst, cross checking the getter name with decapitilize(), it is matching with the field name.
Introspector.decapitalize("APpID") - gives "APpID"
Is jackson using a different set of rules and methods when generating the property name from the getter method?
PS: I am aware that, variable name should begin with small case. While going through the java beans naming convention spec got this question.
I am using jackson 2.9.3v.
PS: As per the link PropertyNamingStrategy, it should have produced APpID instead of appId right?
Could someone provide some input here?
Thanks.
In Jackson, you can custom PropertyNamingStrategy, and
In absence of a registered custom strategy, default Java property
naming strategy is used, which leaves field names as is, and removes
set/get/is prefix from methods (as well as lower-cases initial
sequence of capitalized characters).
Also, you can custom a property name like:
#JsonProperty("APpID") // produce {"APpID":"s"}
public String getAPpID() {
return APpID;
}

Is there a better way of obtaining an object's field getters other than java reflection api or i am misusing PropertyDescriptor's getReadMethod?

Context:
I am building an Excel document in a generic way with data i receive from a SOAP service endpoint. I receive the data as a List and i have the model (JavaBeans) for every Object i receive according to the method called.
So I set the first row of the sheet as the header from the object's fields (getDeclaredFields).
Then i go on filling up the column row by row with values from the list of objects.
The problem:
I haven't found a workable way of getting the object's field values.
I have tried using the getters with the java reflection API with something like this answer's https://stackoverflow.com/a/5503534/4807777 findGetterName , findGetter however the PropertyDescriptor's getName sometimes is a different letter case from the field name as obtained from the class's getDeclaredFields.
Let's say i overcome this by capitalizing both names, the getReadMethod stil fails - doesn't seem to find getters for the fields which use the is prefix (i.e boolean fields). I don't know if i am misusing it or it is a bug (debugging the getReadMethod appears to only work with the get prefix, even though it appears to handle the is prefix case for booleans).
Considering the fact the fields aren't accesible outside of the object's package, therefore solely through invoking getters.
Is there a better way of obtaining the object's field getters or i am missing something with the getter methods?
Update: Spring's BeanUtils seems to be better for getting the properties with it's getPropertyDescriptors is better than java Class's getDeclaredFields, when the JavaBean properties are mapped to XML elements.
This fixes the different letter cases situation. However it stil doesn't find it's readMethod when not using the get prefix.
Edited - to show an example of getReadMethod not finding the is prefixed getter, as Laszlo Lugosi requested.
A simple class:
class Test {
private String assignmentType;
private Boolean conserved;
public String getAssignmentType() {return assignmentType;}
public void setAssignmentType(String assignmentType) {this.assignmentType = assignmentType;}
public Boolean isConserved() {return conserved;}
public void setConserved(Boolean conserved) {this.conserved = conserved;}
}
Run this with the findGetter and findGetterName written in the answer linked above:
{
Test obj = new Test();
obj.setAssignmentType("someType");
obj.setConserved(true);
Field[] fields = obj.getClass().getDeclaredFields();
String fieldName;
for (int i=0;i<fields.length;i++){
fieldName = fields[i].getName();
java.lang.reflect.Method method;
Object val = null;
try {
method = obj.getClass().getMethod(findGetterName(obj.getClass(),fieldName));
val = method.invoke(obj);
}
catch (Exception e){
e.printStackTrace();
}
}
}
Edited 2
While i could simply write a getReadMethod following the convention Laszlo Lugosi highlighted i do prefer finding an API for handling accessors.
As you know only the object field name, and JavaBean has convention, you can figure out the getters easily. The rules are getUpperfieldname() and isUpperfieldname if field is boolean. And you can find out the return type as well from the object field.

Is a boolean property name prefixed by "is" still a valid Java Bean?

I just noticed something I didn't know.
private boolean isCertified;
public boolean isCertified() {
return isCertified;
}
public void setCertified(boolean certified) {
isCertified = certified;
}
The following getters and setters have been generated by Intellij. By the way, Lombok generate the same kind of getters and setters.
I would have expected something like:
private boolean isCertified;
public boolean isIsCertified() {
return isCertified;
}
public void setIsCertified(boolean certified) {
isCertified = certified;
}
That's why I usually don't prefix my boolean attributes with ìs, despites the fact I think the property name becomes more readable.
I normally write something like:
private boolean certified;
public boolean isCertified() {
return certified;
}
public void setCertified(boolean certified) {
certified = certified;
}
So I wonder:
Having a property named isXXX and a getter being isXXX instead of isIsXXX: is it a valid Java Bean definition?
Are there any other hidden Java Bean corner cases like that, that I may want to know to improve the code readability?
Thanks
AFAIK, the naming pattern of fields is not part of the JavaBeans specification.
The JavaBeans Specification specifies (among others) the "properties" concept.
The properties of a class are identified by the methods (named after a certain pattern) of a class.
The fields are irrelevant. In fact, there doesn't even have to be a field for a property.
That said, it's still a good practice to name the fields after the property names. The chance is greater that tools which need to access the fields as well (e.g. refactoring support in IDEs) will handle the fields correctly.
Having a property named isXXX and a getter being isXXX instead of isIsXXX: is it a valid Java Bean definition?
No, a getter for a property isXXX requires isIsXXX() (for boolean) or getIsXXX().
But again it's the other way around.
If you have a method:
boolean isXyz()
then you have a readable property xyz.
If you have a method
boolean isIsXyz()
then you have a readable property isXyz.
For more information have a look at the Introspector class, the tutorial or the JavaBeans Specification:
http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html
http://www.oracle.com/technetwork/java/javase/tech/index-jsp-138795.html
private boolean certified;
public boolean isCertified() {
return certified;
}
public void setCertified(boolean certified) {
this.certified = certified;
}
It's ok.
More info about variables names you can look on oracle.docs
It doesn't really matter what your private fields are called; that's why your setters and getters are there.
Since properties of Java Beans are usually just defined by their getter and setter methods (and the actual, most probably private, member variable is ignored for that purpose), yes, that is perfectly fine. Although I would still call the boolean member just certified, but that's a matter of style/taste.
When you generate setters/getters for boolean variable from IDE (Eclipse in many case), this is the standard way in which the setters and getters are created. It is a perfect valid Java bean definition. Infact when you use frameworks like JSF where values are passed using setters/getters, defining boolean variable and using the generated setter/getter becomes sort of mandatory.

Can converted #PathVariables reference each other?

I've got a Spring #RequestMapping with a couple of #PathVariables, and the first one is necessary to narrow down to the second one - you can see in the example below that I need to get the Department in order to get the Module. Using plain String #PathVariables I can do it like this:
#RequestMapping("/admin/{dept}/{mod}/")
public String showModule(#PathVariable String dept, #PathVariable String mod) {
Department department = dao.findDepartment(dept);
Module module = department.findModule(mod);
return "view";
}
But I'm keen to use Spring's Converter API to be able to specify the Department directly as the #PathVariable. So this works after I've registered a custom Converter class:
#RequestMapping("/admin/{dept}/")
public String showDept(#PathVariable Department dept) {
return "view";
}
But the Converter API doesn't give access outside of the single argument being converted, so it's not possible to implement the Converter for Module. Is there another API I can use? I'm eyeing up HandlerMethodArgumentResolver - has anyone solved a problem like this, or are you sticking to String #PathVariables?
I'm using Spring 3.1.
I haven't done it like this but one way I thought of was to make a separate converter for the both of them:
#RequestMapping("/admin/{deptAndModule}/")
public String showDept(#PathVariable DepartmentAndModule deptAndModule) {
return "view";
}
And have the converter able to take an input of the form "deptid-modid" e.g. "ch-c104". It wouldn't be possible to separate them with a slash as the request wouldn't match the RequestMapping pattern of /admin/*/.
In my case, the requirements have changed slightly so that module codes are fully unique and don't need to be scoped to department. So I don't need to do this any more. If I did, I would probably eschew the automatic Module conversion and do it manually in the method.

Categories