1

I'm facing a following problem. We're using Service Data Objects since our target runtime is IBM WebSphere which supposes to be native for this API. The stack that we're using is Java EE, Eclipse Oxygen as the main IDE, SDO reference implementation according to SDO 2.1.0 specification, IBM WebSphere 9 and JRE8.

According to SDO javadoc there are a define(java.io.InputStream xsdInputStream, java.lang.String schemaLocation) method under XSDHelper class which loads a desired XSD schema into the WAS runtime. Once the schema is being loaded its type becomes available for other operations, including DataObject creation.. The way I define schemas looks like the following:

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

The define() method invokes from the EJB constructor. test.xsd is located under the src folder of my eclipse project.

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

Now a little bit about the test.xsd itself. It references to another XSDs of the same targetNamespace using <include> tag:

test.xsd snippet:

...
<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 contains a complexType named RefObject, which is referenced in test.xsd.

test1.xsd snippet:

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

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

  </xsd:complexType>
...

As official SDO Java spec for the version 2.1.0 says:

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.

...

For my vision that means, that in my case, SDO implementation should:

  1. Load test.xsd;

  2. Figures out, that it references to the test1.xsd in its <include> section;

  3. As the test1.xsd located at the same src folder, as the test.xsd is, my expectations is that it would be implicitly loaded in WebSphere runtime environment.

But I'm experiencing an error while trying to create a DataObject of RefObject type:

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

The conclusions I can make is that SDO API isn't designed to work that way or my XSD's or any aren't suitable or contain some mistakes.

Any help would be highly appreciated.

UPDATE: It works just as expected in case of using the "global" XSD, which includes all references inline. Everything I've mentioned before is running from stateless EJB bean.

A sample code leading to the error:

        @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");
        }
             ...
Alex Sergeenko
  • 642
  • 5
  • 22
  • The namespace URI `http://http://ejb/package/name` in the error message looks odd; maybe an instance of [this Tuscany bug](https://issues.apache.org/jira/browse/TUSCANY-2080)? – imhotap Jun 09 '18 at 09:37
  • Btw. SDO/SCA is IMHO a fantastic API, but has been long superseded by JEE APIs (JAXB/JAX-WS etc.) as Java implementation for a component within SCA (the Apache Tuscany SCA/SDO reference implementation on which WebSphere's is based [has been retired](http://tuscany.apache.org/)) – imhotap Jun 09 '18 at 09:48
  • @imhotap , i'm sorry, it was my fault since I've slightly edited the error message. The actual URI from the log seems to be correct. As for me SDO is a nice API, but the specs sometimes are not transparent and as you've mentioned, it has been retired and not widely used. – Alex Sergeenko Jun 09 '18 at 09:50
  • Since you already have been warned this is an older API... it might help you to realize that WebSphere's SDO type registry is set up analogous to the classloader hierarchy, allowing applications to define types in their own scopes, in isolation from other applications. It could be the case that you are defining the type in one scope, but accessing it from another. Maybe include the Java code leading up to the error when you "create a DataObject.." Also, is this an SCA application or not? – Scott Kurz Jun 11 '18 at 14:20
  • I realized my last update suggests another question: "does it work if you copy the included defs inline into the including XSD?" (If it's a scoping issue you'd think you'd hit the same problem either way). – Scott Kurz Jun 11 '18 at 15:01
  • @Scott Kurz it works perfectly if i merging all referenced XSD together. Please see updated question. Thanks. – Alex Sergeenko Jun 13 '18 at 06:31

1 Answers1

1

Looking at the Tuscany SDO repo it seems you want to do something like:

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

That is, instead of doing xsdHelper.define(is, null), I think you need to pass in a value for the second parm: schemaLocation as the javadoc suggests:

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

Scott Kurz
  • 4,985
  • 1
  • 18
  • 40