2010-02-15 10 views
5

Mi aplicación web está utilizando GWT 2.0.2, GXT 2.1.1, Hibernate 3.5-CR1, Javassist 3.11.0 y Gilead 1.3.1 (lo último de SVN).Error de "método duplicado" al utilizar Hibernate + Javassist + Gilead

Mi aplicación funcionaba perfectamente con GWT 1.7.1 + Gilead 1.2.

Quiero aprovechar algunas de las características de GWT 2.0, y pensé que me gustaría actualizar a la última Gilead en el proceso. Señalé el nuevo archivo gwt.xml en Gilead 1.3. También estoy usando el nuevo net.sf.gilead.pojo.gwt.LightEntity en lugar de net.sf.gilead.pojo.java5.LightEntity.

Tengo algunas entidades/clases de Hibernate que extienden LightEntity (es decir, pregunta, formulario), así como algunas entidades/clases más que extienden la entidad de la pregunta. No estoy seguro si es importante, pero estoy usando InheritanceType.JOINED para la estrategia de herencia en la entidad Question.

Como referencia, aquí está la clase Pregunta:

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

Mi aplicación tiene un servlet de inicio que crea una fábrica de sesión de Hibernate. En los registros, aparece un error de "método duplicado" en todas las clases que extienden directa o indirectamente LightEntity. Me pregunto si este es un problema con el manejo de herencia 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) 

¿Alguna idea sobre cómo resolver este problema?

+0

dar todo el código de 'Question' – Bozho

+0

he añadido el código entero , gracias por el consejo. – lupefiasco

+0

Intente deshacerse temporalmente de todas las clases que extienden la pregunta, haga que la pregunta sea concreta y elimine todas las asignaciones de herencia, y vea si la excepción persiste. Luego da tu opinión. – Bozho

Respuesta

2

Como se ilustra en ticket HIBERNATE-37, de alguna manera getProxyInformation() se define dos veces, posiblemente con un tipo de devolución diferente.

ticket HHH-1938 sugirió usar cglib en lugar de JavaAssist como un mejorador de bytecode, pero no estoy seguro de si esto es posible en su configuración.

Debe cambiar el valor de

hibernate.bytecode.provider=javassist 

para

hibernate.bytecode.provider=cglib 

en:

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

Y se soluciona el problema del método duplicado

(de nuevo, esto no es su configuración, pero que podría dar una idea de dónde buscar)

Cuestiones relacionadas