JavaBeans and introspection - messed up with boolean and indexed properties?

My former colleague started a discussion about half an hour ago about JavaBeans and why they didnโ€™t quite work the way he wants in JSF. In the particular case, we are talking about Boolean properties.

1 . For a boolean property named isUrl Eclipse generates this

 private boolean isUrl; public boolean isUrl() {..} public boolean setUrl(boolean url) {..} 

But this does not work in JSF. He launched it by adding public boolean getIsUrl() The implementation may be a mistake, so let someone be right using the introspection API:

 BeanInfo info = Introspector.getBeanInfo(ClassTest.class); for (PropertyDescriptor pd : info.getPropertyDescriptors()) { System.out.println(pd.getName() + ": " + pd.getReadMethod() + " : " + pd.getWriteMethod()); } 

In the above code, this prints both methods - that is, Eclipse is right, JSF is wrong. But that sounds suspicious to me, as the spec says nothing about the double "is".

But as I looked through the specification, I saw something that I had never used - the so-called indexed properties. You can have private String[] bar and then public String getBar(int idx) . So:

2 . I tried this with the Introspector and it did not find a reading method for the bar. The result from the above code: bar: null : null . So I thought - now the inspector does not follow the specification. Perhaps in the previous case this did not follow, and, ultimately, JSF is right. In fact, indexed properties can make sure that there are two reading methods for a given property. And this is not possible with the introspection API PropertyDescriptor class.

What this forces us to do is that we may have a broken API that does not meet the specification. This leads to other implementations of the specification (JSF uses the usual one). This leads to further misunderstanding and confusion.

Sidenit for something that bothered me - in the JavaBeans specification, they call naming conventions for methods of "design patterns." That sounds wrong to me.

So now for the questions:

  • - JavaBeans clear specification
  • is an introspection API.
  • is the new specification of JavaBeans, at least to clarify the behavior of Booleans (which is subjective to the extent)

Update it seems that using JSF bean.isUrl more likely than bean.url . Which makes perfect sense not to work with the isUrl() accessory.

PS JDK 1.6.0_20, JSF 1.2, MyFaces

+7
source share
2 answers

As @Peter Lawrey already mentioned, the field name is not related to JavaBeans. It does not even exist, or you can call it a stupid name, for example, the prefix m_ .

You did not provide suitable read or write methods for the bar property as a whole, so they will not be displayed. You cannot synthesize Method for an existing class at runtime. I believe that indexed properties were later versions, although @since does not exist, therefore they are not used by the java.beans interfaces.

I do not have the JSF specification (and it will be outside the jcp.org lawyer wall), so I donโ€™t know what it says. It may indicate something different from the JavaBeans specification [probably], or you can use the implementation with errors [I think also probably].

โ€œDesign Patternโ€ is just a phrase. Like in the template that is found in our design. This is not a design pattern like in GoF.

+2
source

Java Bean Properties are defined by methods, not fields. For this reason, the PropertyDescriptor class has getReadMethod() and getWriteMethod() , but not getField() methods.

Personally, I think your colleague is using bad practice.

a) is is a verb. Fields should not be named after verbs.
b) while this is not required, it is good practice to call a field like a property that allows you to write code as follows:

 PropertyDescriptor pd; // let assume this is set Method referenceMethod = pd.getReadMethod() == null // at least one of these is not null ? pd.getWriteMethod() : pd.getReadMethod(); Field underLyingField = referenceMethod .getDeclaringClass() .getDeclaredField(pd.getName()); 

Although this code is not standardized, it complies with the rules and can be very convenient. If you do not follow such conventions, you have no way to associate a field with a property (which is intentional, I know).

eg. I use the code as above to check if there are annotations in the field


About indexed properties:

Index syntax can be used for array or list (or map) properties, but only if they are defined as standard Bean properties.

So, if you have a property like this:

 private String[] bar; public String[] getBar(){ return bar; } public void setBar(String[] bar){ this.bar = bar; } 

or like this:

 private List<String> bar; public List<String> getBar(){ return bar; } public void setBar(List<String> bar){ this.bar = bar; } 

you can access the first element with the expression ${bar[0]}

And with this map property:

 private Map<String, String> bar; public Map<String, String> getBar(){ return bar; } public void setBar(Map<String, String> bar){ this.bar = bar; } 

You can access the value converted to "baz" , like this ${bar['baz']} .

This functionality is built on top of the standard beans functionality, so it requires regular getters / setters.

+4
source

All Articles