2015-06-05 14 views
7

Ich habe ein einfaches Problem. Ich habe ein Programm, das in Java JDK7 arbeitet, aber es funktioniert nicht in JDK8 wegen einiger Introspektionsänderungen.Java JDK 8 IndexedPropertyDescriptor hat sich seit JDK 7 mit List-Objekt geändert

Hier ein Testprogramm ist es, das Problem zu reproduzieren:

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; 
     } 

    } 
} 

Hier werden die JDK 7-Protokolle sind:

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 

Hier sind die Protokolle für 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 Ich muss das JDK8 wirklich bald benutzen, aber das ist eine blockierende Änderung, weil meine App nicht mehr funktioniert. Ich habe dieses Problem mit allen Klassen, die die Collection Schnittstelle erweitern (Liste, Karte, ...)

Der Code wird von der Bibliothek commons-beanutils-1.8.0 von Apache Commons verwendet.

Ich suche nach einer Lösung, eine Workaround, um meine Anwendung auf die gleiche Weise wie zuvor zu arbeiten, wenn Sie das JDK7 verwenden, gibt es eine Lösung? Ich kann nicht Array statt Liste verwenden (da Array nicht geändert hat)

Hier sind die Links zu der offiziellen Dokumentation:

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: Ich fand meine Lösung, mein Problem war mit Streben 1.3 verwandt. Ich musste meine indizierte Getter/Setter in meiner Action umbenennen: http://www.coderanch.com/t/55172/Struts/Indexed-Properties

+0

Ich sehe keinen Unterschied in Ihren Beispielen. Was genau ist das Problem? –

+1

In JDK 7 gibt die Methode getPropertyDescritor von BeanInfo 'IndexedPropertyDescriptor' für die Klasse MyIndexedListClass zurück und gibt in JDK 8 einen 'PropertyDescriptor' zurück. –

Antwort

5

Nun, die Spezifikation sagt deutlich, dass ein IndexedPropertyDescriptor zusätzliche Array basierte Zugriffsmethoden haben, sonst nichts. Das hat sich nicht geändert. Was Sie hier haben, sind widersprüchliche Eigenschaft Methoden definieren eine einfache List<String> typisierte Eigenschaft und und eine indexierte String Eigenschaft mit dem gleichen Namen. Die auf List basierenden Methoden wurden nie mit der indizierten Eigenschaft verknüpft.

Also, was hat sich geändert, welche der widersprüchlichen Eigenschaften macht es in die BeanInfo und die fallen gelassen werden. Dieses Verhalten hängt möglicherweise von der nicht spezifizierten Reihenfolge eines HashMap oder dergleichen ab. Es könnte auch andere Faktoren geben. Betrachten Sie es daher nicht als ein Java 7 vs. Java 8 Problem, sondern nur ein implementierungsabhängiges Verhalten, das sich auch zwischen alternativen Java 7 Implementierungen ändern kann.

Es gibt zwei Möglichkeiten, dieses Problem zu lösen. Sie können durch die Umbenennung eine der Eigenschaften, den Konflikt lösen:

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; 
    } 
} 

Dann werden alle Java-Versionen gleich verhalten, aber es hat den Nebeneffekt, jetzt die beiden unterschiedlichen Eigenschaften zu sehen, wie unterschiedlich benannte Eigenschaften.


Die Alternative ist es, die Methoden zu halten, wie ist aber explizit die List basierten Methoden aus der Eigenschaftendeskriptor Anerkennung elide.Mit anderen Worten, machen Sie das Verhalten, das in einer Implementierung passierte und anscheinend Ihr Wunsch ist, explizit.

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; 
    } 
}