This wiki has undergone a migration to Confluence found Here
<meta name="googlebot" content="noindex">

Difference between revisions of "Technology"

From HL7Wiki
Jump to navigation Jump to search
 
(4 intermediate revisions by the same user not shown)
Line 27: Line 27:
 
</pre>
 
</pre>
  
IDL was chosen because there is a definitive, standard mapping defined between IDL and most programming languages.  There are two problems, however.  The first is that, while IDL is supposedly technology neutral, the language mappings carry some CORBA related artifacts.  The ConceptID declaration above compiles to:
+
IDL was chosen because there is a definitive, standard mapping defined between IDL and most programming languages.  There are two problems, however.   
 +
 
 +
=== Binding Problem 1: Java mapping issues ===
 +
The first is that, while IDL is supposedly technology neutral, the language mappings carry some CORBA related artifacts.  The ConceptID declaration above compiles to:
 
<pre>
 
<pre>
 
public final class ConceptId implements org.omg.CORBA.portable.IDLEntity
 
public final class ConceptId implements org.omg.CORBA.portable.IDLEntity
Line 46: Line 49:
 
} // class ConceptId
 
} // class ConceptId
 
</pre>
 
</pre>
While the IDLEntity abstract
+
org.omg.CORBA.portable.IDLEntity is not a serious issue, as it defines an interface with no properties or methods and is present in most JRE's. You will note, however, that this mapping is not an interface specification, but rather a concrete class.  This turns out to be a serious issue for many implementations, including SOAP, which expect bean-style interfaces.
You will note that this standardized mapping is not an interface specification, but rather a concrete class.  This  
+
The compliler also creates the CORBA specific files:
It also creates the files:
 
 
*ConceptIdHelper.java
 
*ConceptIdHelper.java
 
*ConceptIdHolder.Java
 
*ConceptIdHolder.Java
Both of which contain a lot of CORBA specific information.
+
Both of which can be ignored or discarded.
 
----
 
----
The UnexpectedError exception declaration causes a lot of problems.  It generates the Java:
+
The exception declaration has more problems of problems.  It generates the Java:
 
<pre>
 
<pre>
 
public final class UnexpectedError extends org.omg.CORBA.UserException
 
public final class UnexpectedError extends org.omg.CORBA.UserException
Line 80: Line 82:
 
</pre>
 
</pre>
  
Which contains references to a CORBA specific UserException as well as UnexpectedErrorHelper references. Both of these are CORBA specific.
+
Not only is this not an interface, it contains references to a CORBA specific UserException which is NOT benign as well as referencing UnexpectedErrorHelper which contains many CORBA specific references.
 +
----
 +
The actual isConceptValid operation can be generated in a variety of different ways, the Portable Object Adaptor (POA) approach being the most neutral. The IDL compiler generates RunTime.java:
 +
<pre>
 +
public interface Runtime extends RuntimeOperations, org.omg.CORBA.portable.IDLEntity
 +
{
 +
} // interface Runtime
 +
</pre>
 +
as well as RunTimeOperations.java
 +
<pre>
 +
public interface RuntimeOperations
 +
{
 +
  ...
 +
  boolean isConceptIdValid (org.hl7.CTSVAPI.ConceptId concept_id,
 +
                            boolean activeConceptsOnly)
 +
              throws org.hl7.CTSVAPI.UnknownCodeSystem,
 +
                    org.hl7.CTSVAPI.UnexpectedError;
 +
  ...
 +
};
 +
</pre>
 +
As well as:
 +
*RunTimeHelper.java
 +
*RunTimeHolder.java
 +
*RunTimePOA.java
 +
*RunTimePOATie.java
 +
Both of which can be ignored or discarded.
 +
----
 +
To turn the Java IDL into a truly neutral API, we have to do the following:
 +
# Rename xxxOperations.java to xxx.java
 +
# Delete xxxHelper.java, xxxHolder.java, xxxPOA.java, xxxPOATie.java
 +
# Remove the UserException extension from the exceptions
 +
# Remove the xxxHelper.id() calls from the exceptions
 +
# Edit the documentation so that it looks half-way decent in JavaDoc
 +
 
 +
Note that none of these changes create bean style interfaces.
 +
 
 +
=== Binding Problem 2: No definitive XML/SOAP mapping  ===
 +
The second problem with the CTS IDL binding is that there isn't (or at least wasn't at the point in time the specification was published) a definitive IDL to SOAP mapping.  This meant that we had to define our own.  It turned out that the solution to the second problem contained an inherent solution to the first problem as well.
 +
 
 +
We chose to the non-standard, but widely available Apache axis WSDL compiler to convert edited Java output from the IDL compiler into WSDL:
 +
<pre>
 +
      ...
 +
  <element name="isConceptIdValid">
 +
    <complexType>
 +
    <sequence>
 +
      <element name="in0" type="impl:ConceptId"/>
 +
      <element name="in1" type="xsd:boolean"/>
 +
    </sequence>
 +
    </complexType>
 +
  </element>
 +
      ...
 +
  <wsdl:message name="isConceptIdValidRequest">
 +
    <wsdl:part element="impl:isConceptIdValid" name="parameters"/>
 +
  </wsdl:message>
 +
      ....
 +
  <wsdl:operation name="isConceptIdValid">
 +
      <wsdl:input message="impl:isConceptIdValidRequest" name="isConceptIdValidRequest"/>
 +
      <wsdl:output message="impl:isConceptIdValidResponse" name="isConceptIdValidResponse"/>
 +
      <wsdl:fault message="impl:UnexpectedError" name="UnexpectedError"/>
 +
      <wsdl:fault message="impl:UnknownCodeSystem" name="UnknownCodeSystem"/>
 +
  </wsdl:operation>
 +
</pre>
 +
The code above only shows part of the WSDL binding, but it is enough to show two of the issues we wrestle with:
 +
# Argument naming - in order to have meaningful argument names, it is necessary to have actual implementation code available.  An inherent problem in Java interface definitions is that that only the argument type is pereserved - thus the "in0", "in1", etc. above
 +
# Lack of documentation - the documentation ends up getting stripped in the process.
 +
 
 +
One of the benefits of going through the WSDL transformation, however, is that we can reverse the process and, in the end, produce something that is at least bean compliant.
 +
 
 +
 
 +
(To be Continued)

Latest revision as of 18:52, 31 March 2005

Binding and function definition issues

Current CTS approach

The current CTS specification defines the information model using UML and defines the API using the OMG Interface Definition Language (IDL). A sample IDL declaration follows:

     typedef string  OID;
     typedef OID     CodeSystemId;
     typedef string  ConceptCode;
     exception UnexpectedError {
          string possible_cause;
     };
     exception UnknownCodeSystem {
          CodeSystemId codeSystem_id;
     };

     struct ConceptId {
          CodeSystemId codeSystem_id;
          ConceptCode  concept_code;
     };

     boolean isConceptIdValid(
          in ConceptId concept_id,
          in boolean   activeConceptsOnly
     )
     raises (UnknownCodeSystem,
             UnexpectedError);

IDL was chosen because there is a definitive, standard mapping defined between IDL and most programming languages. There are two problems, however.

Binding Problem 1: Java mapping issues

The first is that, while IDL is supposedly technology neutral, the language mappings carry some CORBA related artifacts. The ConceptID declaration above compiles to:

public final class ConceptId implements org.omg.CORBA.portable.IDLEntity
{
  public String codeSystem_id = null;
  public String concept_code = null;

  public ConceptId ()
  {
  } // ctor

  public ConceptId (String _codeSystem_id, String _concept_code)
  {
    codeSystem_id = _codeSystem_id;
    concept_code = _concept_code;
  } // ctor

} // class ConceptId

org.omg.CORBA.portable.IDLEntity is not a serious issue, as it defines an interface with no properties or methods and is present in most JRE's. You will note, however, that this mapping is not an interface specification, but rather a concrete class. This turns out to be a serious issue for many implementations, including SOAP, which expect bean-style interfaces. The compliler also creates the CORBA specific files:

  • ConceptIdHelper.java
  • ConceptIdHolder.Java

Both of which can be ignored or discarded.


The exception declaration has more problems of problems. It generates the Java:

public final class UnexpectedError extends org.omg.CORBA.UserException
{
  public String possible_cause = null;

  public UnexpectedError ()
  {
    super(UnexpectedErrorHelper.id());
  } // ctor

  public UnexpectedError (String _possible_cause)
  {
    super(UnexpectedErrorHelper.id());
    possible_cause = _possible_cause;
  } // ctor


  public UnexpectedError (String $reason, String _possible_cause)
  {
    super(UnexpectedErrorHelper.id() + "  " + $reason);
    possible_cause = _possible_cause;
  } // ctor

} // class UnexpectedError

Not only is this not an interface, it contains references to a CORBA specific UserException which is NOT benign as well as referencing UnexpectedErrorHelper which contains many CORBA specific references.


The actual isConceptValid operation can be generated in a variety of different ways, the Portable Object Adaptor (POA) approach being the most neutral. The IDL compiler generates RunTime.java:

public interface Runtime extends RuntimeOperations, org.omg.CORBA.portable.IDLEntity 
{
} // interface Runtime

as well as RunTimeOperations.java

public interface RuntimeOperations
{
   ...
   boolean isConceptIdValid (org.hl7.CTSVAPI.ConceptId concept_id,
                             boolean activeConceptsOnly) 
              throws org.hl7.CTSVAPI.UnknownCodeSystem, 
                     org.hl7.CTSVAPI.UnexpectedError;
   ...
};

As well as:

  • RunTimeHelper.java
  • RunTimeHolder.java
  • RunTimePOA.java
  • RunTimePOATie.java

Both of which can be ignored or discarded.


To turn the Java IDL into a truly neutral API, we have to do the following:

  1. Rename xxxOperations.java to xxx.java
  2. Delete xxxHelper.java, xxxHolder.java, xxxPOA.java, xxxPOATie.java
  3. Remove the UserException extension from the exceptions
  4. Remove the xxxHelper.id() calls from the exceptions
  5. Edit the documentation so that it looks half-way decent in JavaDoc

Note that none of these changes create bean style interfaces.

Binding Problem 2: No definitive XML/SOAP mapping

The second problem with the CTS IDL binding is that there isn't (or at least wasn't at the point in time the specification was published) a definitive IDL to SOAP mapping. This meant that we had to define our own. It turned out that the solution to the second problem contained an inherent solution to the first problem as well.

We chose to the non-standard, but widely available Apache axis WSDL compiler to convert edited Java output from the IDL compiler into WSDL:

       ...
   <element name="isConceptIdValid">
    <complexType>
     <sequence>
      <element name="in0" type="impl:ConceptId"/>
      <element name="in1" type="xsd:boolean"/>
     </sequence>
    </complexType>
   </element>
      ...
   <wsdl:message name="isConceptIdValidRequest">
     <wsdl:part element="impl:isConceptIdValid" name="parameters"/>
   </wsdl:message>
      ....
   <wsdl:operation name="isConceptIdValid">
      <wsdl:input message="impl:isConceptIdValidRequest" name="isConceptIdValidRequest"/>
      <wsdl:output message="impl:isConceptIdValidResponse" name="isConceptIdValidResponse"/>
      <wsdl:fault message="impl:UnexpectedError" name="UnexpectedError"/>
      <wsdl:fault message="impl:UnknownCodeSystem" name="UnknownCodeSystem"/>
   </wsdl:operation>

The code above only shows part of the WSDL binding, but it is enough to show two of the issues we wrestle with:

  1. Argument naming - in order to have meaningful argument names, it is necessary to have actual implementation code available. An inherent problem in Java interface definitions is that that only the argument type is pereserved - thus the "in0", "in1", etc. above
  2. Lack of documentation - the documentation ends up getting stripped in the process.

One of the benefits of going through the WSDL transformation, however, is that we can reverse the process and, in the end, produce something that is at least bean compliant.


(To be Continued)