Data can be read from various generic Java classes, mainly Adaptation
and ValueContext
. The getter methods for these classes return objects that are typed according to the mapping rules described in the section Mapping of data types.
Data updates must be performed in a well-managed context:
In the context of a procedure execution, by calling the methods setValue...
of the interface ValueContextForUpdate
, or
During the user input validation, by calling the method setNewValue
of the class ValueContextForInputValidation
.
According to the mapping that is described in the Mapping of data types section, some accessed Java objects are mutable objects. These are instances of List
, Date
or any JavaBean. Consequently, these objects can be locally modified by their own methods. However, such modifications will remain local to the returned object unless one of the above setters is invoked and the current transaction is successfully committed.
The highest isolation level in ANSI/ISO SQL is SERIALIZABLE
. Three execution methods guarantee the SERIALIZABLE
isolation level within the scope of a dataspace:
If the client code is run inside a Procedure
container. This is the case for every update, for exports to XML, CSV or archive, and for data services.
If the client code accesses a dataspace that has been explicitly locked. See LockSpec
.
If the client code accesses data in a snapshot.
For custom read-only transactions that run on a dataspace, it is recommended to use ReadOnlyProcedure
.
If the client code is run outside the contexts that enable SERIALIZABLE
, its isolation level depends on the persistence mode:
In semantic mode, the default isolation level is READ UNCOMMITTED
.
In relational mode, the default isolation level is the database default isolation level.
In a Java application, a record is represented by an instance of the Adaptation
class. This object is initially linked to the corresponding persisted record. However, unless the client code is executed in a context that enables the SERIALIZABLE isolation level, the object can become "disconnected" from the persisted record. If this occurs and concurrent updates have been performed, they will not be reflected in the Adaptation
object.
Therefore, it is important for the client code to either be in a SERIALIZABLE
context, or to regularly look up or refresh the Adaptation
object.
This section describes how XML Schema type definitions and element declarations are mapped to Java types.
Each XML Schema simple type corresponds to a Java class, the mapping is documented in the table XML Schema built-in simple types.
If the attribute maxOccurs
is greater than 1, the element is an aggregated list and the corresponding instance in Java is an instance of java.util.List
.
Elements of the list are instances of the Java class that is determined from the mapping of the simple type (see previous section).
By default (no attribute osd:class
), a terminal node of a complex type is instantiated using an internal class. This class provides a generic JavaBean implementation. However, if a custom client Java code has to access these values, it is recommended to use a custom JavaBean. To do so, use the osd:class
declaration described in the next section.
It is also possible to transparently instantiate, read and modify the mapped Java object, with or without the attribute osd:class
, by invoking the methods SchemaNode.createNewOccurrence
, SchemaNode.executeRead
and SchemaNode.executeWrite
.
It is possible to map an XML Schema complex type to a custom Java class. This is done by adding the attribute osd:class
to the complex node definition. Unless the element has xs:maxOccurs > 1
, you must also specify the attribute osd:access
for the node to be considered a terminal node. If the element has xs:maxOccurs > 1
, it is automatically considered to be terminal.
The custom Java class must conform to the JavaBean protocol. This means that each child of the complex type must correspond to a JavaBean property of the class. Additionally, each JavaBean property must be a read-write property, and its implementation must ensure that the value set by the setter method is returned, as-is, by the getter method. Contextual computations are not allowed in these methods.
In this example, the Java class com.carRental.Customer
must define the methods getFirstName()
and setFirstName(String)
.
A JavaBean can have a custom user interface within TIBCO EBX®, by using a
.UIBeanEditor
<xs:element name="customer" osd:access="RW"> <xs:complexType name="subscriber" osd:class="com.carRental.Customer"> <xs:sequence> <xs:element name="firstName" type="xs:string"/> ... </xs:sequence> </xs:complexType> </xs:element>
If the attribute maxOccurs
is greater than 1, then the corresponding instance in Java is:
An instance of java.util.List
for an aggregated list, where every element in the list is an instance of the Java class determined by the mapping of simple types, or
An instance of AdaptationTable
, if the property osd:table
is specified.
Java bindings allow generating Java types that reflect the structure of the data model. The Java code generation can be done in the user interface. See Generating Java bindings.
Ensuring the link between XML Schema structure and Java code provides a number of benefits:
Development assistance: Auto-completion when typing an access path to parameters, if supported by your IDE.
Access code verification: All accesses to parameters are verified at code compilation.
Impact verification: Each modification of the data model impacts the code compilation state.
Cross-referencing: By using the reference tools of your IDE, it is easy to verify where a parameter is used.
Consequently, it is strongly recommended to use Java bindings.
The specification of the Java types to be generated from the data model is included in the main schema.
Each binding element defines a generation target. It must be located at, in XPath notation, xs:schema/xs:annotation/xs:appinfo/ebxbnd:binding
, where the prefix ebxbnd
is a reference to the namespace identified by the URI urn:ebx-schemas:binding_1.0
. Several binding elements can be defined if you have different generation targets.
The attribute targetDirectory
of the element ebxbnd:binding
defines the root directory used for Java type generation. Generally, it is the directory containing the project source code, src
. A relative path is interpreted based on the current runtime directory of the VM, as opposed to the XML schema.
See bindings XML Schema.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ebxbnd="urn:ebx-schemas:binding_1.0"> <xs:annotation> <xs:appinfo> <!-- The bindings define how this schema will be represented in Java. Several <binding> elements may be defined, one for each target. --> <ebxbnd:binding targetDirectory="../_ebx-demos/src-creditOnLineStruts-1.0/"> <javaPathConstants typeName="com.creditonline.RulesPaths"> <nodes root="/rules" prefix="" /> </javaPathConstants> <javaPathConstants typeName="com.creditonline.StylesheetConstants"> <nodes root="/stylesheet" prefix="" /> </javaPathConstants> </ebxbnd:binding> </xs:appinfo> </xs:annotation> ... </xs:schema>
Java constants can be defined for XML schema paths. To do so, generate one or more interfaces from a schema node, including the root node /
. The example generates two Java path constant interfaces, one from the node /rules
and the other from the node /stylesheet
in the schema. Interface names are described by the element javaPathConstants
with the attribute typeName
. The associated node is described by the element nodes
with the attribute root
.