2010-02-15 4 views
5

Mon application Web utilise GWT 2.0.2, GXT 2.1.1, Hibernate 3.5-CR1, Javassist 3.11.0 et Gilead 1.3.1 (dernière version de SVN).Erreur "Méthode en double" lors de l'utilisation de Hibernate + Javassist + Gilead

Mon application fonctionnait très bien avec GWT 1.7.1 + Gilead 1.2. Je veux tirer parti de certaines des fonctionnalités de GWT 2.0, et j'ai pensé que je passerais au dernier Gilead dans le processus. J'ai pointé vers le nouveau fichier gwt.xml dans Gilead 1.3. J'utilise aussi le nouveau net.sf.gilead.pojo.gwt.LightEntity au lieu de net.sf.gilead.pojo.java5.LightEntity.

J'ai quelques entités/classes Hibernate qui étendent LightEntity (c'est-à-dire, Question, Form), ainsi que quelques entités/classes supplémentaires qui étendent l'entité Question. Je ne sais pas si c'est important, mais j'utilise InheritanceType.JOINED pour la stratégie d'héritage dans l'entité Question.

Pour référence, voici la classe Question:

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

Mon application a une servlet de démarrage qui crée une usine de la session Hibernate. Dans les journaux, j'obtiens une erreur "duplicate method" sur toutes les classes qui étendent directement ou indirectement LightEntity. Je me demande si c'est un problème avec la gestion de l'héritage de 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) 

Des idées sur la façon de résoudre ce problème?

+0

donner le code de 'Question' – Bozho

+0

J'ai ajouté tout le code , Merci pour le conseil. – lupefiasco

+0

Essayez de vous débarrasser temporairement de toutes les classes qui étendent Question, mettez en question la question et supprimez tous les mappages d'héritage, et voyez si l'exception persiste. Puis donnez votre avis. – Bozho

Répondre

2

Comme illustré par ticket HIBERNATE-37, getProxyInformation() obtient défini deux fois, éventuellement avec un type de retour différent.

ticket HHH-1938 suggéré d'utiliser cglib au lieu de JavaAssist en tant qu'améliorateur de bytecode, mais je ne sais pas si cela est possible dans votre configuration.

Vous devez modifier la valeur de

hibernate.bytecode.provider=javassist 

pour

hibernate.bytecode.provider=cglib 

dans:

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

Et cela résout le problème de la méthode dupliquée

(encore une fois, ce n'est pas votre configuration, mais qui pourrait vous donner une idée où chercher)

Questions connexes