SDO API:如何使 XSDHelper.INSTANCE 正确定义具有 <include> 的 XSD 模式?

SDO API: how to make XSDHelper.INSTANCE to define XSD schemas with <include> correctly?

我面临以下问题。 我们正在使用服务数据对象,因为我们的目标运行时是 IBM WebSphere,它应该是本机的 API。我们使用的堆栈是 Java EE,Eclipse Oxygen 作为主要 IDE,根据 SDO 2.1.0 规范、IBM WebSphere 9 和 JRE8 的 SDO 参考实现。

根据 SDO javadoc,在 XSDHelper class 下有一个 define(java.io.InputStream xsdInputStream, java.lang.String schemaLocation) 方法,它将所需的 XSD 模式加载到 WAS 运行时中。加载架构后,其类型可用于其他操作,包括 DataObject 创建.. 我定义模式的方式如下所示:

InputStream is = new BOStorage().getInputStreamXSD("/test.xsd"); 
XSDHelper.INSTANCE.define(is, null);

define() 方法从 EJB 构造函数调用。 test.xsd 位于我的 eclipse 项目的 src 文件夹下。

src
| test.xsd
| test1.xsd
|
|___ejb.package.name

现在稍微介绍一下 test.xsd 本身。它使用 <include> 标签引用相同 targetNamespace 的另一个 XSD:

test.xsd 片段:

...
<xsd:schema
    targetNamespace="http://ejb/package/name"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:bons0="http://ejb/package/name">
    <xsd:include schemaLocation="test1.xsd"></xsd:include>
    <xsd:include schemaLocation="test2.xsd"></xsd:include>
    <xsd:complexType name="TestSDO">
...
<xsd:element minOccurs="0" name="RefObject"
                type="bons0:RefObject">
            </xsd:element>
...

test1.xsd 包含一个名为 RefObjectcomplexType,它在 test.xsd.

中被引用

test1.xsd 片段:

...
<xsd:complexType name="RefObject">

          <xsd:simpleContent>
            <xsd:extension base="xsd:string">
                <xsd:attribute name="type"/>
            </xsd:extension>
        </xsd:simpleContent>

  </xsd:complexType>
...

作为 2.1.0 版的官方 SDO Java 规范说:

9.7 XSD Mapping Details

...

  1. All <group> references, <attributeGroup> references, <include>s, and <import>s are fully expanded to the equivalent XSD as if these declarations were not present.

...

就我而言,这意味着,在我的情况下,SDO 实施应该:

  1. 加载test.xsd;

  2. 计算出,它引用了 <include> 部分中的 test1.xsd

  3. 因为 test1.xsdtest.xsd 位于同一个 src 文件夹中,我的期望是它会隐式加载到 WebSphere 运行时环境中.

但是我在尝试创建 RefObject 类型的数据对象时遇到错误:

CWSDO0001E: Cannot create a data object of the type {http://ejb/package/name}RefObject because the type cannot be found

我可以得出的结论是,SDO API 并非设计为以这种方式工作,或者我的 XSD 或任何不合适或包含一些错误。

非常感谢任何帮助。

更新: 在使用 "global" XSD 的情况下,它的工作方式与预期的一样,其中包括内联的所有引用。我之前提到的所有内容都是 运行 来自无状态 EJB bean。

导致错误的示例代码:

        @Stateless(mappedName = "TestSDO")
        @Remote(TestSDORemote.class)
        @Local(TestSDOLocal.class)

        public class TestSDO implements TestSDORemote, TestSDOLocal{
            ...


        // default EJB constructor

     public TestSDO() {
           String textInfo = "";

            try {
                defineSDOTypes();
            } catch (Exception e) {
                LOGGER.log(Level.WARNING, "Could not define SDO types");
            }
        }
             ...
      private void defineSDOTypes() {
            HelperContext hc =   
            SDO.getHelperContextFactory().createHelperContext("ScopeManagerTestID", 
            null);
            XSDHelper xsdHelper = hc.getXSDHelper();
            try (InputStream is = new BOStorage().getInputStreamXSD("/test.xsd")) {          
                 xsdHelper.define(is, null);    
            } catch (IOException e) { 
              LOGGER.logp(Level.WARNING, CLASS_NAME, METHOD_NAME, "Unable to load the 
              schema: " + 
              "test.xsd" + ": " + e.getMessage());      
               e.printStackTrace();     
            }
             ...
      // creates the target Data Object (here comes the error)
      private void createBO(){
            DataObject dob = DataFactory.INSTANCE.create("http://ejb/package/name", 
            "RefObject");
        }
             ...

查看 Tuscany SDO repo 似乎您想执行以下操作:

    URL url = getClass().getResource("/test.xsd");
    InputStream inputStream = url.openStream();
    xsdHelper.define(inputStream, url.toString());
    inputStream.close();

也就是说,我认为您需要为第二个参数传递一个值,而不是 xsdHelper.define(is, null)schemaLocation 正如 javadoc 所建议的:

schemaLocation - the URI of the location of the schema, used for processing relative imports and includes. May be null if not used.