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

问题描述 投票:0回答:3

我知道这是一个非常的希望,但我已经尝试弄清楚它已经两周了,所以任何指向正确方向的想法都可能是无价的。

所以,我有一个非常旧的应用程序,它使用 XmlBeans。我的任务是从 Tomcat 7.0.67 迁移到 Tomcat 8.5.11,引入 Spring Sessions 和 Spring Security,而不是基于领域的身份验证。迁移之前,本地(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 模式生成的,没有设置任何命名空间。类共享名称,但位于不同的包中(发生异常的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,根本原因是缺少命名空间,从而导致了冲突。但由于我们的要求,我无法添加或更改 xsd 的命名空间。那么您是否知道为什么它可以在本地与 Tomcat 7、本地与 Tomcat 8 以及在带有 Tomcat 7 的 Heroku 上工作,但在带有 Tomcat 8 的 Heroku 上不起作用?

提前致谢。

java tomcat heroku classcastexception xmlbeans
3个回答
2
投票

这个问题也出现在以下错误类别的顶部,因此我在这里添加我的答案:

class org.apache.xmlbeans.impl.values.XmlComplexContentImpl cannot be cast to class <class you generated a schema from>

这是一个非常奇怪的错误,毕竟为什么会发生这种转换呢?无论如何,这是因为我正在使用 maven-shade-plugin

minimizeJar
功能,并且它正在删除某些内容(我还不知道是什么),如果我弄清楚我到底需要显式重新添加什么,我会更新这个答案,但现在我只是禁用了minimizeJar。

它似乎正在删除模式生成代码的

impl
部分。

更新:如果您想继续使用minimumJar,请将其添加到阴影插件的过滤器部分:

<filter>                                    
    <artifact>org.apache.xmlbeans:xmlbeans</artifact>
    <includes>
        <include>**</include>
    </includes>
</filter>

更新2:上面的内容似乎并不总是有效,我对这里的新问题感到非常困惑,但要点仍然是

minimizeJar
对于依赖关系非常不稳定


1
投票

由于this,它可以在 Tomcat 7 上运行。

在 Tomcat 8 之前,Tomcat 的类加载器按字母顺序加载资源。我们的应用程序之所以能运行只是因为这个。

它可以在 Tomcat 8 + MacOS 上本地运行,因为 Tomcat 8 的类加载器按照操作系统提供的顺序加载资源,在 OSX 的情况下,似乎是有序的。


0
投票

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

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

我认为你必须找到一种方法来给类赋予不同的名称(或包)。

© www.soinside.com 2019 - 2024. All rights reserved.