2015-06-05 20 views
7

Ho un problema semplice. Ho un programma che funziona in Java JDK7 ma non funziona in JDK8 a causa di alcune modifiche all'introspezione.Java JDK 8 IndexedPropertyDescriptor è cambiato da JDK 7 con la lista oggetto

Ecco un programma di test di riprodurre il problema:

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

    } 
} 

Ecco i JDK 7 log:

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 

Qui ci sono i registri per 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 devo usare il JDK8 molto presto ma questo è un cambio di blocco perché la mia app non funziona più. Ho questo problema con tutte le classi che estendono l'interfaccia Collection (Elenco, Mappa, ...)

Il codice viene utilizzato dalla libreria commons-beanutils-1.8.0 da Apache Commons.

Sto cercando una soluzione, una soluzione, per fare la mia domanda funzionano allo stesso modo di prima, quando si utilizza il JDK7, c'è qualche soluzione? Non posso usare array al posto di Lista (perché Array non è cambiata)

Ecco i link alla documentazione ufficiale:

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: Ho trovato la mia soluzione, il mio problema era relativo ai montanti 1.3. Ho dovuto rinominare il mio indicizzato getter/setter nel mio ActionForm: http://www.coderanch.com/t/55172/Struts/Indexed-Properties

+0

vedo alcuna differenza nei tuoi esempi. Qual è esattamente il problema? –

+1

In JDK 7 il metodo getPropertyDescritor di BeanInfo restituisce 'IndexedPropertyDescriptor' per la classe MyIndexedListClass e in JDK 8 restituisce un 'PropertyDescriptor'. –

risposta

5

Beh, la specifica dice chiaramente che un IndexedPropertyDescriptor possono avere metodi di accesso basati serie supplementare, nient'altro. Questo non è cambiato. Quello che hai qui sono in conflitto con i metodi di proprietà che definiscono una semplice proprietà tipizzata List<String> e una proprietà indicizzata String con lo stesso nome. I metodi basati su List non sono mai stati associati alla proprietà indicizzata.

Quindi ciò che è cambiato è quale delle proprietà in conflitto lo rende nello BeanInfo e che verrà eliminato. Questo comportamento potrebbe dipendere dall'ordine non specificato di uno HashMap o simili. Potrebbero esserci anche altri fattori. Quindi, non vederlo come un problema Java 7 contro Java 8, ma solo un comportamento dipendente dall'implementazione che può anche cambiare tra le implementazioni Java 7 alternative.

Esistono due modi per risolvere questo problema. Si può risolvere il conflitto rinominando una delle proprietà:

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

Poi, tutte le versioni di Java si comporterà lo stesso, ma ha l'effetto collaterale di ora vedendo le due proprietà diverse, come diverso nome proprietà.


L'alternativa è quello di mantenere i metodi di come è, ma elidere esplicitamente i metodi basati List dal riconoscimento descrittore di proprietà.In altre parole, rendere esplicito il comportamento, che è successo in un'implementazione e sembra essere quello desiderato.

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