2010-02-15 7 views
5

La mia app Web utilizza GWT 2.0.2, GXT 2.1.1, Hibernate 3.5-CR1, Javassist 3.11.0 e Gilead 1.3.1 (ultime da SVN).Errore "metodo duplicato" quando si utilizza Hibernate + Javassist + Gilead

La mia app funzionava perfettamente con GWT 1.7.1 + Gilead 1.2.

Desidero sfruttare alcune delle funzionalità di GWT 2.0 e ho pensato di eseguire l'aggiornamento all'ultima versione di Gilead. Ho fatto riferimento al nuovo file gwt.xml in Gilead 1.3. Sto anche usando il nuovo net.sf.gilead.pojo.gwt.LightEntity invece di net.sf.gilead.pojo.java5.LightEntity.

Ho alcune Hibernate entità/classi che si estendono LightEntity (cioè Domanda, Modulo), così come alcune altre entità/classi che estendono l'entità Domanda. Non sono sicuro se è importante, ma sto usando InheritanceType.JOINED per la strategia di ereditarietà nell'entità Domanda.

Per riferimento, ecco la classe Domanda:

@Entity 
@Table(name = "Questions") 
@Inheritance(strategy = InheritanceType.JOINED) 
public abstract class Question extends LightEntity implements IsSerializable, 
     IFormItem, Comparable<Question> { 

    private static final long serialVersionUID = 9180458948973980161L; 

    public static final String FIELD_NAME_PREFIX = "field_"; //$NON-NLS-1$ 

    private static final String REQUIRED_QUESTION = "<span style=\"color: red;\">*</span>"; //$NON-NLS-1$ 

    public static int MIN_WIDTH = 50; 
    public static int DEFAULT_WIDTH = 200; 
    public static int MAX_WIDTH = 600; 

    private int id; 
    private Integer questionOrder; 
    private String questionNumber; 
    protected String questionText; 
    protected boolean required; 
    private String toolTip; 
    protected Integer fieldWidth; 

    @Id 
    @GeneratedValue 
    public int getId() { 
     return this.id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public boolean isRequired() { 
     return this.required; 
    } 

    public void setRequired(boolean required) { 
     this.required = required; 
    } 

    public String getToolTip() { 
     return this.toolTip; 
    } 

    public void setToolTip(String toolTip) { 
     this.toolTip = toolTip; 
    } 

    @Column(length = 5000) 
    @Lob 
    public String getQuestionText() { 
     return this.questionText; 
    } 

    public void setQuestionText(String pText) { 
     this.questionText = pText; 
    } 

    public Integer getQuestionOrder() { 
     return this.questionOrder; 
    } 

    public void setQuestionOrder(Integer questionOrder) { 
     this.questionOrder = questionOrder; 
    } 

    public String getQuestionNumber() { 
     return this.questionNumber; 
    } 

    public void setQuestionNumber(String questionNumber) { 
     this.questionNumber = questionNumber; 
    } 

    public boolean hasQuestionNumber() { 
     return getQuestionNumber() != null 
       && !getQuestionNumber().trim().isEmpty(); 
    } 

    public Integer getFieldWidth() { 
     return this.fieldWidth; 
    } 

    public void setFieldWidth(Integer fieldWidth) { 
     this.fieldWidth = fieldWidth; 
    } 

    public Component render(FormPanel formPanel, int order, int questionSpacing) { 
     final Component c = generateWidget(getId()); 
     if (c instanceof Field<?>) { 
      final Field<?> field = (Field<?>) c; 
      field.setLabelSeparator(FormBuilderConstants.EMPTY_TEXT); 
      field.setValidateOnBlur(true); 
      field.setAutoValidate(true); 
      field.setName(FIELD_NAME_PREFIX.concat(String.valueOf(getId()))); 
      if (getToolTip() != null) { 
       field.setToolTip(getToolTip()); 
      } 

      final FormData formData; 
      if (field instanceof SimpleComboBox<?>) { 
       formData = new FormData(); 
      } else { 
       if (getFieldWidth() == null) { 
        field.setAutoWidth(true); 
        formData = new FormData(FormBuilderConstants.FORM_ANCHOR_SPEC); 
       } else { 
        field.setWidth(getFieldWidth().intValue()); 
        field.setAutoWidth(false); 

        formData = new FormData(getFieldWidth().intValue(), -1); 
       } 
      } 

      final String questionNumber; 
      if (this.questionNumber != null && !this.questionNumber.isEmpty()) { 
       questionNumber = this.questionNumber; 
      } else { 
       questionNumber = String.valueOf(order); 
      } 

      if (this.answerable()) { 
       String displayQuestionText = questionNumber.concat(". ") //$NON-NLS-1$ 
         .concat(getQuestionText()); 
       if (isRequired()) { 
        displayQuestionText = displayQuestionText 
          .concat(REQUIRED_QUESTION); 
       } 

       field.setFieldLabel(displayQuestionText); 
      } 

      field.setIntStyleAttribute("margin-bottom", questionSpacing); //$NON-NLS-1$ 

      formPanel.add(field, formData); 
     } else { 
      formPanel.add(c); 
     } 

     return c; 
    } 

    protected abstract Component generateWidget(final int id); 

    public abstract String questionType(); 

    public int compareTo(final Question q) { 
     return this.questionOrder.intValue() - q.questionOrder.intValue(); 
    } 

    public boolean answerable() { 
     return true; 
    } 
} 

mia app ha un servlet di avvio che crea una fabbrica sessione di Hibernate. Nei log, ottengo un errore "metodo duplicato" su tutte le classi che estendono direttamente o indirettamente LightEntity. Mi chiedo se questo è un problema con la gestione dell'ereditarietà di Javassist.

16:32:59,616 DEBUG AbstractEntityPersister:2773 - Identity insert: insert into Questions (fieldWidth, questionNumber, questionOrder, questionText, required, toolTip) values (?, ?, ?, ?, ?, ?) 
16:32:59,619 ERROR BasicLazyInitializer:165 - Javassist Enhancement failed: com.function1.formbuilder.client.model.Question 
java.lang.RuntimeException: duplicate method: getProxyInformation in com.function1.formbuilder.client.model.Question_$$_javassist_5 
    at javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:344) 
    at javassist.util.proxy.ProxyFactory.createClass2(ProxyFactory.java:314) 
    at javassist.util.proxy.ProxyFactory.createClass(ProxyFactory.java:273) 
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.getProxyFactory(JavassistLazyInitializer.java:162) 
    at org.hibernate.proxy.pojo.javassist.JavassistProxyFactory.postInstantiate(JavassistProxyFactory.java:66) 
    at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactory(PojoEntityTuplizer.java:188) 
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.<init>(AbstractEntityTuplizer.java:151) 
    at org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTuplizer.java:78) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513) 
    at org.hibernate.tuple.entity.EntityTuplizerFactory.constructTuplizer(EntityTuplizerFactory.java:107) 
    at org.hibernate.tuple.entity.EntityTuplizerFactory.constructDefaultTuplizer(EntityTuplizerFactory.java:135) 
    at org.hibernate.tuple.entity.EntityEntityModeToTuplizerMapping.<init>(EntityEntityModeToTuplizerMapping.java:80) 
    at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:323) 
    at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:456) 
    at org.hibernate.persister.entity.JoinedSubclassEntityPersister.<init>(JoinedSubclassEntityPersister.java:113) 
    at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:87) 
    at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:267) 
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1341) 
    at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867) 
    at com.function1.common.F1HibernateUtil.<clinit>(F1HibernateUtil.java:22) 
    at com.function1.formbuilder.server.StartupServlet.init(StartupServlet.java:26) 
Caused by: java.lang.RuntimeException: duplicate method: getProxyInformation in com.function1.formbuilder.client.model.Question_$$_javassist_0 
    at javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:344) 
    at javassist.util.proxy.ProxyFactory.createClass2(ProxyFactory.java:314) 
    at javassist.util.proxy.ProxyFactory.createClass(ProxyFactory.java:273) 
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.getProxyFactory(JavassistLazyInitializer.java:162) 
    ... 42 more 
Caused by: javassist.bytecode.DuplicateMemberException: duplicate method: getProxyInformation in com.function1.formbuilder.client.model.Question_$$_javassist_0 
    at javassist.bytecode.ClassFile.testExistingMethod(ClassFile.java:593) 
    at javassist.bytecode.ClassFile.addMethod(ClassFile.java:577) 
    at javassist.util.proxy.ProxyFactory.override(ProxyFactory.java:658) 
    at javassist.util.proxy.ProxyFactory.overrideMethods(ProxyFactory.java:632) 
    at javassist.util.proxy.ProxyFactory.make(ProxyFactory.java:552) 
    at javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:335) 

Qualche idea su come risolvere questo problema?

+0

dare l'intero codice del 'Question' – Bozho

+0

ho aggiunto tutto il codice , grazie per il consiglio. – lupefiasco

+0

Provare a eliminare temporaneamente tutte le classi che estendono la domanda, rendere concreta la domanda e rimuovere tutti i mapping di ereditarietà e verificare se l'eccezione persiste. Quindi dare un feedback. – Bozho

risposta

2

Come illustrato da ticket HIBERNATE-37, in qualche modo getProxyInformation() viene definito due volte, possibilmente con un tipo di ritorno diverso.

ticket HHH-1938 suggerito utilizzando cglib invece di JavaAssist come un potenziatore di bytecode, ma non sono sicuro se ciò è possibile nella configurazione.

È necessario modificare il valore di

hibernate.bytecode.provider=javassist 

per

hibernate.bytecode.provider=cglib 

in:

<WHERE IS YOUR JBOSS>\server\default\deploy\ejb3.deployer\META-INF\ persistence.properties 

E questo risolve il problema del metodo duplicato

(ancora una volta, questa non è la configurazione ma che potrebbe darvi un idea di dove cercare)