【问题标题】:Inconsistent ClassCastException for XmlBeans.Factory parse methodXmlBeans.Factory 解析方法的 ClassCastException 不一致
【发布时间】:2017-04-12 18:15:42
【问题描述】:

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

所以,我有一个使用 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 模式生成的,没有设置任何命名空间。类同名,但位于不同的包中(异常发生的解析方法位于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,但在 Heroku 和 Tomcat 8 上不起作用?

提前致谢。

【问题讨论】:

    标签: java tomcat heroku classcastexception xmlbeans


    【解决方案1】:

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

    在这种情况下,听起来您有两个同名的不同类(我说的对吗?)。即使它们是自动生成的,也只有一个会获胜。

    我认为你必须想办法给类赋予不同的名称(或包)。

    【讨论】:

    • 这些类确实有不同的包,只是名称相同,还有xsd命名空间(实际上没有)。
    【解决方案2】:

    由于this,它适用于Tomcat 7。

    在 Tomcat 8 之前,Tomcat 的 ClassLoader 按字母顺序加载资源。正因为如此,我们的应用才能正常工作。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-25
      • 2018-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-16
      相关资源
      最近更新 更多