Java JDK 8 IndexedPropertyDescriptor Changed Since JDK 7 With List Object

I have a simple problem. I have a program running in Java JDK7, but it does not work in JDK8 due to some changes to introspection.

Here is a test program to reproduce the problem:

import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) throws IntrospectionException { BeanInfo info = Introspector.getBeanInfo(MyListClass.class); PropertyDescriptor[] descriptors = info.getPropertyDescriptors(); for (int i = 0; i < descriptors.length; i++) { System.out.println(descriptors[i].getClass().getName() + ":" + descriptors[i].getName()); } System.out.println("\n"); BeanInfo info2 = Introspector.getBeanInfo(MyIndexedListClass.class); PropertyDescriptor[] descriptors2 = info2.getPropertyDescriptors(); for (int i = 0; i < descriptors2.length; i++) { System.out.println(descriptors2[i].getClass().getName() + ":" + descriptors2[i].getName()); } System.out.println("\n"); BeanInfo info3 = Introspector.getBeanInfo(MyArrayClass.class); PropertyDescriptor[] descriptors3 = info3.getPropertyDescriptors(); for (int i = 0; i < descriptors3.length; i++) { System.out.println(descriptors3[i].getClass().getName() + ":" + descriptors3[i].getName()); } System.out.println("\n"); BeanInfo info4 = Introspector.getBeanInfo(MyIndexedArrayClass.class); PropertyDescriptor[] descriptors4 = info4.getPropertyDescriptors(); for (int i = 0; i < descriptors4.length; i++) { System.out.println(descriptors4[i].getClass().getName() + ":" + descriptors4[i].getName()); } } public class MyListClass { private List<String> myListClass = new ArrayList<String>(); public List<String> getMyListClass() { return myListClass; } public void setMyListClass(List<String> myListClass) { this.myListClass = myListClass; } } public class MyIndexedListClass { private List<String> myIndexedListClass = new ArrayList<String>(); public String getMyIndexedListClass(int index) { return myIndexedListClass.get(index); } public void setMyIndexedListClass(int index, String element) { this.myIndexedListClass.set(index, element); } public List<String> getMyIndexedListClass() { return myIndexedListClass; } public void setMyIndexedListClass(List<String> myIndexedListClass) { this.myIndexedListClass = myIndexedListClass; } } public class MyArrayClass { private String[] myArrayClass = new String[20]; public String[] getMyArrayClass() { return myArrayClass; } public void setMyArrayClass(String[] myArrayClass) { this.myArrayClass = myArrayClass; } } public class MyIndexedArrayClass { private String[] myIndexedArrayClass = new String[20]; public String getMyIndexedArrayClass(int index) { return myIndexedArrayClass[index]; } public void setMyIndexedArrayClass(int index, String myValue) { this.myIndexedArrayClass[index] = myValue; } public String[] getMyIndexedArrayClass() { return myIndexedArrayClass; } public void setMyIndexedArrayClass(String[] myIndexedArrayClass) { this.myIndexedArrayClass = myIndexedArrayClass; } } } 

Here are the JDK 7 logs:

 java.beans.PropertyDescriptor:class java.beans.PropertyDescriptor:myListClass java.beans.PropertyDescriptor:class java.beans.IndexedPropertyDescriptor:myIndexedListClass java.beans.PropertyDescriptor:class java.beans.PropertyDescriptor:myArrayClass java.beans.PropertyDescriptor:class java.beans.IndexedPropertyDescriptor:myIndexedArrayClass 

Here are the logs for JDK8:

 java.beans.PropertyDescriptor:class java.beans.PropertyDescriptor:myListClass java.beans.PropertyDescriptor:class java.beans.PropertyDescriptor:myIndexedListClass -> Here is the change java.beans.PropertyDescriptor:class java.beans.PropertyDescriptor:myArrayClass java.beans.PropertyDescriptor:class java.beans.IndexedPropertyDescriptor:myIndexedArrayClass 

I have to use JDK8 very soon, but this is a lock because my application is no longer working. I have this problem with all classes extending the Collection interface (List, Map, ...)

The code is used by the commons-beanutils-1.8.0 library from Apache Commons.

I'm looking for a solution, a workaround, so that my application works the same as before when using JDK7, is there any solution? I can't use Array instead of List (because Array hasn't changed)

Here are the links to the official documentation:

JDK7: http://docs.oracle.com/javase/7/docs/api/java/beans/IndexedPropertyDescriptor.html

JDK8: http://docs.oracle.com/javase/8/docs/api/java/beans/IndexedPropertyDescriptor.html


EDIT: I found my solution, my problem was with struts 1.3. I had to rename my indexed getter / setter to my ActionForm: http://www.coderanch.com/t/55172/Struts/Indexed-Properties

+7
java java-7 java-8 introspection
source share
1 answer

Well, the spec clearly states that IndexedPropertyDescriptor can have additional array-based access methods, nothing more. This has not changed. Here you have conflicting property methods defining a simple List<String> property and a property with a String index of the same name. List based methods have never been associated with an indexed property.

So, what has changed, which of the conflicting properties turns it into BeanInfo and which will be deleted. This behavior may depend on the unspecified order of a HashMap or the like. There may be other factors. Thus, do not see it as a problem with Java 7 and Java 8, but simply implementation-dependent behavior that can also change between alternative Java 7 implementations.

There are two ways to solve this problem. You can resolve the conflict by renaming one of the properties:

 public class MyIndexedListClass { private List<String> myIndexedListClass = new ArrayList<String>(); public String getMyIndexedListClass(int index) { return myIndexedListClass.get(index); } public void setMyIndexedListClass(int index, String element) { this.myIndexedListClass.set(index, element); } public List<String> getMyIndexedListClassAsList() { return myIndexedListClass; } public void setMyIndexedListClassAsList(List<String> myIndexedListClass) { this.myIndexedListClass = myIndexedListClass; } } 

Then all versions of Java will behave the same, but now it has a side effect, treating two different properties as properties with different names.


An alternative is to save the methods as they are, but explicitly excluding List based methods from the recognition of the property descriptor. In other words, do the behavior that happened in one implementation and seems to be your desired, explicit.

 public class MyIndexedListClass { private List<String> myIndexedListClass = new ArrayList<String>(); public String getMyIndexedListClass(int index) { return myIndexedListClass.get(index); } public void setMyIndexedListClass(int index, String element) { this.myIndexedListClass.set(index, element); } public List<String> getMyIndexedListClass() { return myIndexedListClass; } public void setMyIndexedListClass(List<String> myIndexedListClass) { this.myIndexedListClass = myIndexedListClass; } } static // in your example all classes are inner classes public class MyIndexedListClassBeanInfo extends SimpleBeanInfo { private PropertyDescriptor[] properties; public MyIndexedListClassBeanInfo() throws IntrospectionException { PropertyDescriptor[] p=Introspector.getBeanInfo(MyIndexedListClass.class, Introspector.IGNORE_IMMEDIATE_BEANINFO).getPropertyDescriptors(); ArrayList<PropertyDescriptor> list=new ArrayList<>(p.length+1); for(PropertyDescriptor d: p) if(!d.getName().equals("myIndexedListClass")) list.add(d); list.add(new IndexedPropertyDescriptor("myIndexedListClass", MyIndexedListClass.class, null, null, "getMyIndexedListClass", "setMyIndexedListClass")); properties=list.toArray(new PropertyDescriptor[list.size()]); } @Override public PropertyDescriptor[] getPropertyDescriptors() { return properties; } } 
+6
source share

All Articles