XmlBeans.Factory解析方法的ClassCastException不一致

时间:2017-04-12 18:15:42

标签: java tomcat heroku classcastexception xmlbeans

我知道这是一个非常远景,但我已经试图解决它已经两周了,所以任何指向正确方向的想法都可能是无价的。

所以,我有一个非常古老的应用程序,它使用XmlBeans。我的任务是从Tomcat 7.0.67迁移到Tomcat 8.5.11,引入Spring Sessions和Spring Security而不是基于Realm的身份验证。在迁移之前,一切都在本地(MacOS,Oracle JDK 8)和Heroku(Ubuntu,OpenJDK 8)上运行良好,但是在迁移之后一切都在我的本地环境中运行,但是在Heroku上,有时,当应用程序尝试解析时字符串到适当的XmlBean,发生此ClassCastException:

java.lang.ClassCastException: foo.bar.2.impl.PreferencesDocumentImpl cannot be cast to foo.bar.1.PreferencesDocument
    at foo.bar.1.PreferencesDocument$Factory.parse(Unknown Source)

我有两个由XmlBeans类自动生成的类,它们是从两个没有任何名称空间集的xsd-schemas生成的。类共享名称,但位于不同的包中(发生异常的parse方法位于Factory内部类中,其他方法省略):

/*
 * An XML document type.
 * Localname: Preferences
 * Namespace: 
 * Java type: foo.bar.1.PreferencesDocument
 *
 * Automatically generated - do not modify.
 */
package foo.bar.1;

public interface PreferencesDocument extends org.apache.xmlbeans.XmlObject {
    public static final org.apache.xmlbeans.SchemaType type = (org.apache.xmlbeans.SchemaType)
        org.apache.xmlbeans.XmlBeans.typeSystemForClassLoader(PreferencesDocument.class.getClassLoader(), "schemaorg_apache_xmlbeans.system.s2D5798E4F4AFDA8394735C8512CDCBC7").resolveHandle("preferencesa8bfdoctype");

    public static final class Factory {
        public static foo.bar.1.PreferencesDocument parse(java.lang.String xmlAsString) throws org.apache.xmlbeans.XmlException {
          return (foo.bar.PreferencesDocument) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( xmlAsString, type, null ); 
        }   
    }
}

/*
 * An XML document type.
 * Localname: Preferences
 * Namespace: 
 * Java type: foo.bar.1.PreferencesDocument
 *
 * Automatically generated - do not modify.
 */
package foo.bar.1.impl;

public class PreferencesDocumentImpl extends org.apache.xmlbeans.impl.values.XmlComplexContentImpl implements foo.bar.1.PreferencesDocument {
    public PreferencesDocumentImpl(org.apache.xmlbeans.SchemaType sType) {
        super(sType);
    }

    private static final javax.xml.namespace.QName PREFERENCES$0 = new javax.xml.namespace.QName("", "Preferences");
}

/*
 * An XML document type.
 * Localname: Preferences
 * Namespace: 
 * Java type: foo.bar.2.PreferencesDocument
 *
 * Automatically generated - do not modify.
 */
package foo.bar.2;  

public interface PreferencesDocument extends org.apache.xmlbeans.XmlObject {
    public static final org.apache.xmlbeans.SchemaType type = (org.apache.xmlbeans.SchemaType)
        org.apache.xmlbeans.XmlBeans.typeSystemForClassLoader(PreferencesDocument.class.getClassLoader(), "schemaorg_apache_xmlbeans.system.sC8953008EC716AA258D3951B84AB1CB7").resolveHandle("preferencesa8bfdoctype");

    public static final class Factory {
        public static foo.bar.2.PreferencesDocument parse(java.lang.String xmlAsString) throws org.apache.xmlbeans.XmlException {
          return (foo.bar.2.PreferencesDocument) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( xmlAsString, type, null ); }

    }
}

/*
 * An XML document type.
 * Localname: Preferences
 * Namespace: 
 * Java type: foo.bar.2.PreferencesDocument
 *
 * Automatically generated - do not modify.
 */
package foo.bar.2.impl;

public class PreferencesDocumentImpl extends org.apache.xmlbeans.impl.values.XmlComplexContentImpl implements foo.bar.2.PreferencesDocument {

    public PreferencesDocumentImpl(org.apache.xmlbeans.SchemaType sType) {
        super(sType);
    }

    private static final javax.xml.namespace.QName PREFERENCES$0 = 
        new javax.xml.namespace.QName("", "Preferences");
    }
}

有时,当重新启动部署到Heroku的应用程序时,问题就会消失,但是在重新启动之后它又会重新出现。

根据this,根本原因是缺少导致冲突的命名空间。但由于我们的要求,我无法添加或更改xsds的命名空间。那么你有什么想法它为什么它在本地使用Tomcat 7,在本地使用Tomcat 8和在Heroku上使用Tomcat 7,但是在Tomoku 8上不适用于Heroku?

提前致谢。

2 个答案:

答案 0 :(得分:0)

我怀疑问题的不可预测性(即有时它在重启后会发生或不发生)是由于JVM类加载器的非确定性。如果您有两个不同版本的同一个类,它们将以非确定性顺序加载。

在这种情况下,听起来你有两个具有相同名称的不同类(我是否正确?)。即使它们是自动生成的,也只有一个会赢。

我认为你必须找到一种方法来为这些类提供不同的名称(或包)。

答案 1 :(得分:0)

由于this,它适用于Tomcat 7。

在Tomcat 8之前,Tomcat的ClassLoader按字母顺序加载资源。我们的应用程序只是因为这个而工作。

它在Tomcat 8 + MacOS上本地工作,因为Tomcat 8的类加载器按OS提供的顺序加载资源,在OSX的情况下,似乎是订购的。