1

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

根据 SDO javadoc,define(java.io.InputStream xsdInputStream, java.lang.String schemaLocation)在类下有一个方法XSDHelper可以将所需的 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 本身。它引用了另一个相同targetNamespaceusing<include>标签的 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包含一个complexType命名RefObject的 ,在 中引用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 映射细节

...

  1. 所有<group>引用、<attributeGroup>引用、<include>s 和 <import>s 都完全扩展为等效的 XSD,就好像这些声明不存在一样。

...

对于我的愿景,这意味着在我的情况下,SDO 实施应该:

  1. 加载test.xsd;

  2. 弄清楚,它test1.xsd在其<include>部分中引用了;

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

但是我在尝试创建RefObject类型的 DataObject 时遇到错误:

CWSDO0001E: 无法创建类型为 { http://ejb/package/name }RefObject 的数据对象,因为找不到该类型

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

任何帮助将不胜感激。

更新: 在使用“全局”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");
        }
             ...
4

1 回答 1

1

查看托斯卡纳 SDO 存储库,您似乎想要执行以下操作:

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

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

schemaLocation - 架构位置的 URI,用于处理相对导入和包含。如果不使用,可能为 null。

于 2018-06-13T13:17:26.977 回答