خطأ "طريقة مكررة" عند استخدام Hibernate + Javassist + Gilead
سؤال
يستخدم تطبيق الويب الخاص بي GWT 2.0.2 و GXT 2.1.1 و Hibernate 3.5-CR1 و Javassist 3.11.0 و Gilead 1.3.1 (الأحدث من SVN).
كان تطبيقي يعمل بشكل جيد مع GWT 1.7.1 + Gilead 1.2.
أريد أن أستفيد من بعض ميزات GWT 2.0 ، وأحسب أنني سأقوم بالترقية إلى أحدث Gilead في هذه العملية. أشرت إلى ملف GWT.XML الجديد في Gilead 1.3. أنا أيضًا أستخدم net.sf.gilead.pojo.gwt.lightentity بدلاً من net.sf.gilead.pojo.java5.lightentity.
لدي بعض الكيانات/الفصول السباتية التي تمتد الضوء (أي سؤال ، شكل) ، بالإضافة إلى عدد قليل من الكيانات/الطبقات التي تمد كيان السؤال. لست متأكدًا مما إذا كان الأمر مهمًا ، لكنني أستخدم inheritancetype.ined لاستراتيجية الميراث في كيان السؤال.
للإشارة ، إليك فئة الأسئلة:
@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;
}
}
يحتوي تطبيقي على Servlet Startup الذي ينشئ مصنع جلسة السبات. في السجلات ، أحصل على خطأ "طريقة مكررة" في جميع الفئات التي تمتد بشكل مباشر أو غير مباشر. أتساءل عما إذا كانت هذه مشكلة مع تعامل جافاسست مع الميراث.
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)
أي أفكار حول كيفية حل هذه المشكلة؟
المحلول
كما يتضح من تذكرة السبات -37, ، بطريقة ما getProxyInformation()
يحصل على تحديد مرتين ، ربما مع نوع عودة مختلف.
تذكرة HHH-1938 اقترح استخدام cglib بدلاً من Javaassist كمحسن Bytecode ، لكنني لست متأكدًا مما إذا كان هذا ممكنًا في التكوين الخاص بك.
يجب عليك تغيير قيمة
hibernate.bytecode.provider=javassist
ل
hibernate.bytecode.provider=cglib
في:
<WHERE IS YOUR JBOSS>\server\default\deploy\ejb3.deployer\META-INF\ persistence.properties
وهذا يحدد مشكلة الطريقة المكررة
(مرة أخرى ، هذا ليس تكوينك ولكن هذا قد يمنحك فكرة أين تبدو)
نصائح أخرى
سيعمل versoin javassist الجديد 3.16.1-GA مع أساليب مكررة:
https://issues.jboss.org/browse/jassist-127
وكانت هناك بعض المشكلات المماثلة الأخرى التي تم إصلاحها أيضًا لمدة 3.16.0-GA
Javassist لا يسمح أساليب مكررة (المسموح بها من قبل Java5)
https://jira.jboss.org/jira/browse/jassist-24
حاول إزالة Comparable<Question>
إذا كان ذلك ممكنا.