![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Table of Contents 1.3 How to build and run the labs using Eclipse 6 2.1 How to create a UML class diagram for an openMDX based application? 9 3.1 Package Objects and Package Creation 13 3.8 JMI Mapping – References 19 4 Getting started with a JMI client 20 4.1 How to retrieve a package? 20 4.2 How to create instance-level objects? 21 4.3 How to retrieve the openMDX XRI for a given instance? 21 4.4 How to set/retrieve attribute values? 22 4.5 How to set/retrieve referenced objects? 23 4.6 How to invoke an operation? 24 4.7 How do clients interact with application plugins? 24 5 Getting started with Queries 27 5.1 How to filter the result set? 27 5.2 How to specify filter constraints? 28 5.2.1 How to choose filter operators? 28 5.2.2 How to choose the appropriate quantor for a filter constraint? 29 5.2.3 Example filter constraints 29 5.2.4 How to specify filter constraints for null values? 31 5.2.5 How to combine multiple query constraints? 31 6 Getting started with Application Plugins 33 6.2 How to create an application plugin? 34 6.2.1 How to write a plugin class? 34 6.2.2 How to configure a plugin? 34 6.2.3 How to add business logic? 37 6.2.3.1 Signature of implementation class 37 6.2.3.2 Sample implementation 38 7.1 How to pass a context object? 40 7.2 How to access the context object? 41 8 Getting started with a Reflective JMI client 42 8.1 How to create an instance? 42 8.2 How to set/retrieve attribute values? 43 8.3 How to set/retrieve referenced objects? 44 8.4 How to invoke an operation? 46 9.2 How to setup the gateway? 48 9.3 How to setup a provider? 49 9.4 Deployment on JBoss Application Server 49 9.4.2 Steps to run openMDX EJBs on JBoss 49 9.4.5 How to write a JBoss client? 51 9.4.6 How to run the openMDX client? 51
List of Figures Figure 1: The lab model org:openmdx:example:lab1 8 Figure 2: JMI Mapping Overview 11 Figure 3: Mapping a model to Java files. 15 Figure 4: Mapping of a model to a JMI package. 15 Figure 5: Package-, class- and instance-level JMI objects and their dependencies. 16 Figure 6: Mapping a model to a class-level object. 17 Figure 7: Mapping of a model to an instance-level object. 18 Figure 8: Mapping of a model to reference features of an instance-level object. 19 Figure 9: openMDX client / server model. 24 Figure 10: A provider with four plugins. 33 Figure 11: Gateway and provider setup. 48
List of Listings Listing 1: Initializing the JMI package. 16 Listing 2: Setup initial root package and retrieve desired package. 20 Listing 3: Create an instance of class Person. 21 Listing 4: Retrieve the openMDX URI of a given object. 21 Listing 5: Retrieve the object for a given openMDX URI. 22 Listing 6: Set attribute values. 22 Listing 7: Get attribute values. 22 Listing 9: Add a group instance to the reference group of a Person instance. 23 Listing 11: Invoke an operation. 24 Listing 12: Create a Person instance, set some attributes and make it permanent in a UnitOfWork. 26 Listing 13: Simple address filter example. 27 Listing 14: Example constraints for non-optional single-valued attributes with filter operator IS_IN. 29 Listing 15: Example constraints for optional single-valued attributes with filter operator IS_IN. 30 Listing 16: Example constraints for multi-valued attributes with filter operator IS_IN. 30 Listing 17: Example constraints for non-optional single-valued attributes with filter operator IS_GREATER or IS_LESS_OR_EQUAL. 30 Listing 18: Example constraint for non-optional single-valued attributes with filter operator IS_BETWEEN. 30 Listing 19: Retrieve objects for which no attribute value has been set. 31 Listing 20: Retrieve objects for which an attribute value has been set. 31 Listing 21: Combining multiple filter criterias. 31 Listing 22: OR relation with filter operator IS_IN. 32 Listing 23: Specify sort order. 32 Listing 24: JMI Plugin implementation. 34 Listing 25: KERNEL/APPLICATION Example. 35 Listing 26: KERNEL/modelPackage Example. 35 Listing 27: KERNEL/packageImpl Example. 36 Listing 28: Signature of implementation class. 37 Listing 29: Signature of class PersonImpl. 38 Listing 30: Implementation of Person. 38 Listing 31: Pass the context object. 40 Listing 32: Access context object from within JMI object implementation. 41 Listing 33: Create a new instance of class Person. 42 Listing 34: Set attribute values. 43 Listing 35: Get attribute values. 44 Listing 36: Retrieve group instances of the reference group of a Person instance. 44 Listing 37: Add a group instance to the reference group of a Person instance. 45 Listing 38: Remove a group instance from the reference group of a Person instance. 45 Listing 39: Call an operation. 46 Listing 40: Contents of file server.log.properties. 50 Listing 41: Modify JBoss startup script to include the following Java system properties. 50
1 PrefaceThis tutorial gives an introduction to programming with openMDX. Based on a simple model the tutorial explains:
1.1 Who this book is forThis tutorial is intended for programmers interested in developing and deploying openMDX applications. 1.2 About the lab examplesTo understand the examples, you need a good knowledge of the Java programming language. The deployment of openMDX applications requires basic knowledge about EJB deployment. You can download the labs from www.openmdx.org. The README of the distribution explains how to install and setup the labs for Ant and Eclipse. To run the labs follow these steps:
1.3 How to build and run the labs using EclipseBefore you can set up the labs for Eclipse you must first install and build the labs with Ant as explained in the README of the openMDX/Example Lab distribution. Then you are ready to create an Eclipse project:
Create a new Java project in Eclipse with the "New Java Project" wizard; use the project settings listed below: That's all! From now on you can complete, build and run the labs in Eclipse. For all the labs you will find two Eclipse launch configurations (these are automatically detected by Eclipse). Please note that the following steps cannot be done in Eclipse:
1.4 Tips, Warnings, etc.We make use the following pictrograms:
2 The Lab modelFigure 1 shows the UML model org::openmdx::example::lab1. All lab examples are based on this model.
2.1 How to create a UML class diagram for an openMDX based application?openMDX supports the UML diagrams as shown in the table below:
As shown in the table below openMDX currently supports only MOF 1.4 compliant class diagrams. The class diagrams are used to apply MOF mappings such as JMI and XMI (more on this later). MOF 1.4 compliant class diagrams define the model elements as shown in the table below:
Because the set of model elements required by MOF 1.4 is very limited any UML modeling tool supporting the corresponding UML elements can be used to create an openMDX class diagram. At least a UML 1.4 compliant UML modeling does the job. Below is a list of modeling tools which are supported by the current version of openMDX:
3 JMI Mapping OverviewIn this first part of the tutorial we focus on the MOF-to-Java mapping (JMI) mapping. The JMI mapping the most 'natural' way of programming with openMDX. The class diagrams are mapped to Java interfaces. The interfaces are plain Java interfaces, i.e. they do not contain 'distribution' logic such as EJB or CORBA interfaces do. The JMI mapping is implemented in openMDX as a layer sitting on top of the generic object layer. The JMI layer is also called JMI accessor. The JMI accessor is an implementation of the [17] specification. The JMI accessor is layered on top of the openMDX generic accessor as shown in Figure 5. The JMI externalizer of the MOF repository supports the generation of JMI interfaces and implementations as defined by the JMI specification.
The JMI specification defines the purpose and scope of JMI: "The Java™ Metadata Interface (JMI) Specification defines a dynamic, platform-neutral infrastructure that enables the creation, storage, access, discovery, and exchange of metadata. JMI is based on the Meta Object Facility (MOF) specification from the Object Management Group (OMG), an industry-endorsed standard for metadata management. The MOF standard provides an open-ended information modeling capability, and consists of a base set of metamodeling constructs used to describe technologies and application domains, and a mapping of those constructs to CORBA IDL (Interface Definition Language) for automatically generating model-specific APIs. The MOF also defines a reflective programming capability that allows for applications to query a model at run time to determine the structure and semantics of the modeled system. JMI defines a Java mapping for the MOF. As the Java language mapping to MOF, JMI provides a common Java programming model for metadata access for the Java platform. JMI provides a natural and easy-to-use mapping from a MOF-compliant data abstraction (usually defined in UML) to the Java programming language. Using JMI, applications and tools which specify their metamodels using MOF-compliant Unified Modeling Language (UML) can have the Java interfaces to the models automatically generated. Further, metamodel and metadata interchange via XML is enabled by JMI's use of the XML Metadata Interchange (XMI) specification, an XML-based mechanism for interchanging metamodel information among applications. Java applications can create, update, delete, and retrieve information contained in a JMI compliant metadata service. The flexibility and extensibility of the MOF allows JMI to be used in a wide range of usage scenarios." As described the scope of JMI is metadata interfaces. However, application-models (Level M1) modeled in UML are mapped according to the 'UML Profile for MOF' to MOF-compliant models. Having a MOF-compliant application-level model allows to apply the MOF-to-JMI mapping. The MOF-to-JMI mapping has been extended by the following features:
The JMI APIs has a three-layered approach to manage objects:
3.1 Package Objects and Package CreationA package object is little more than a 'directory' of operations that give access to the classes described by the model. The outer most package extent (a.k.a. outer most extent) represents the “root” package. All other objects (i.e., instance objects, class proxies, associations, and (nested) package objects) are contained within some outer most extent. 3.2 Class Proxy ObjectsA class proxy object serves a number of purposes:
The interface of a class proxy object provides operations for accessing and updating the classifier scoped attribute state. The interface also provides factory operations that allows the client to create instance objects.
3.3 Instance ObjectsAn instance object holds the state corresponding to the instance-scoped attributes, and any other “hidden” state implied by the class specification. Generally speaking, many instance objects can exist within a given package object. Instance objects are always tied to a class proxy object. The class proxy provides a factory operation for creating instance objects. When an instance object is created, it is automatically added to the class proxy container. An instance is removed from the container when it is destroyed. The interface for an instance object provides:
3.4 Association ObjectsAn association object holds a collection of links (i.e. the link set) corresponding to an association defined in the metamodel. The association object is a 'static' container object (similar to a class proxy object) that is contained by a package object. Its interface provides:
NOTE: Association objects are NOT supported by the openMDX JMI mapping. All assocations between objects must be managed through references. Figure 3 shows the mapping of a UML model to Java files.
3.5 JMI Mapping – PackageEach model is mapped to a package file as shown in Figure 4. For each class a corresponding getter is created. The returned class is associated with the package and therefore knows the accessor.
A package is created an initialized as shown in Listing 1. Listing 1: Initializing the JMI package. RefPackage rootPkg = new RefRootPackage_1( The root package has to be initialized only once. Based on the provided manager, the root package creates a basic accessor which is used for all object management (get, create, modify). The root package serves as factory for retrieving model-specific packages which are retrieved by refPackage(). All objects managed by the JMI package (class-level and instance-level objects) delegate to the basic accessor of the root package. This allows a consistent unit of work policy even if multiple accessors delegate to the same manager. As shown in the figure each instance-level JMI object wraps a RefObject which is managed by the basic accessor. Generic objects retrieved from the generic accessor are marshalled (by the root package) to JMI objects, JMI objects forwarded to the generic accessor are marshalled to generic objects. Units of work and transactions are controlled by the manager.
3.6 JMI Mapping – ClassFigure 6 shows the mapping of a UML class to a JMI class-level Java class. The class-level class contains various create() operations for instance-level objects. In addition to the standard JMI mapping openMDX supports extend() operations which allow to extend an object of a superclass to an instance of its subclass. This allows to preserve object identity. However all required attributes to perform the extension must be supplied. For a detailed description of the mapping also see [17].
3.7 JMI Mapping – InstanceFigure 7 shows the mapping of a UML class to a JMI instance-level Java class. The instance-level class contains set, get, add, remove operations for all attributes depending on their model properties. For a detailed description of the mapping also see [17].
3.8 JMI Mapping – ReferencesFigure 8 shows the mapping of a UML reference to the JMI instance-level Java class. References are mapped to add, get and remove operations depending on the model properties with the referenced object class as argument. The openMDX mapping supports UML qualifiers which are an extension of the 'UML Profile for MOF'. For a detailed description of the reference mapping also see [17].
4 Getting started with a JMI clientThe Java Metadata Interface (JMI) provides a natural and easy-to-use mapping from a MOF-compliant data abstraction defined in UML to the Java programming language. Starting from the UML model the Java interfaces to the model can be automatically generated according to the JMI specification. In this chapter you will see how to write an openMDX client based on the model that has been introduced in Figure 1. Before you start with this chapter please make sure that you have generated the JMI accessors based on the lab model beforehand. At the end of this chapter you will have the opportunity to practice what you have learnt in this chapter in a lab exercise. 4.1 How to retrieve a package?In JMI packages play an important part. Each package object provides access to the class proxy objects wihtin its package scope. These class proxy objects are used to create instances (more on class proxy objects in the next section). The root package represents the outermost package extent. All other packages are directly or indirectly nested within the root package. The root package acts as starting point for all top level packages like e.g. org which itself acts as starting point for its nested packages, e.g. openmdx. By means of the refPackage operation a package can retrieve its nested packages. Listing 2 shows how the example package org:openmdx:example:lab1 is retrieved. This example package will be used in the subsequent sections of this chapter.
Listing 2: Setup initial root package and retrieve desired package. // setup initial root package based on a
given manager instance
4.2 How to create instance-level objects?According to JMI, class proxy objects are used to create instance-level objects. Every modeled class is mapped to a class proxy by the JMI mapping. E.g. for the modeled class Person the class proxy object PersonClass is generated. These class proxy objects provide factory operations which allow to create instance-level objects. In order to create an instance-level object first retrieve the package which contains the desired class proxy. The class proxy can then be used to create instance-level objects. Listing 3 illustrates how to retrieve a class proxy and how to create an instance-level object. Listing 3: Create an instance of class Person. // retrieve class proxy for class Person from
package
4.3 How to retrieve the openMDX XRI for a given instance?In openMDX (and MOF) every object (package-, class- and instance-level) has a unique identity. In openMDX this identity is an XRI which can be queried with the JMI operation refMofId. Listing 4: Retrieve the openMDX URI of a given object. // retrieve the openMDX URI of a given
object
To retrieve an object for a given openMDX XRI, you use the operation refObject on the root package (or any other package) for this purpose. Listing 5: Retrieve the object for a given openMDX URI. // retrieve the object (e.g. a Person
instance) for a given openMDX URI
4.4 How to set/retrieve attribute values?According to the JMI specification, each modeled attribute is mapped to corresponding setter/getter accessors in the Java interface. By using these accessors you have a simple, type-safe way to set or retrieve attribute values. Listing 6 shows how to set attribute values. Listing 6: Set attribute values. // set single-valued attribute values
Listing 7 shows how to retrieve the same attribute values. Listing 7: Get attribute values. // get single-valued attribute values
4.5 How to set/retrieve referenced objects?In compliance with the JMI specification, references are mapped to corresponding setter/getter accessors. The accessors allow a type-safe way
Listing 8: Retrieve group instances of the reference group of a Person instance. // retrieve all group instances Listing 9: Add a group instance to the reference group of a Person instance. // add a specified group
instance
Listing 10: Remove a group instance from the reference group of a Person instance. // remove a specified group
instance
4.6 How to invoke an operation?According to the JMI specification, a modeled operation is mapped to an operation in the Java interface. Listing 11 shows an operation invocation. Note that openMDX requires that operation parameters and return types are modeled as structure types. This restriction may be abandoned in future versions of openMDX. Listing 11: Invoke an operation. // The operation serialize() on a given
person instance, 4.7 How do clients interact with application plugins?In openMDX all application plugin code (business logic code) runs on the server. openMDX implements a service-oriented client / server model as shown in Figure 9.
Objects retrieved by the client from the server are cached on the client side. All behaviour (implementation of derived features, operations, etc.) is run on the server side. A round trip to access a feature is made if
Or in more detail: the default roundtrip is that each requested object is returned with its non-derived single valued attributes (including the identities of referenced objects). Plugins can modify this default fetch set by
In detail, units of work are handled on the client as follows:
Listing 12 gives an example. Listing 12: Create a Person instance, set some attributes and make it permanent in a UnitOfWork. // In our lab model Person instances are
referenced by containment by 4.8 Lab ExampleCongratulations! You now know everything you need to write a JMI client based on openMDX. Please remember that this is the most recommended way of writing clients. It is now time to practice. In the package org.openmdx.example.lab1.program.jmi.plugin.work you will find the Java class LabClient that you can complete. E.g. Create new objects, set attribute values, add objects to references, call operations, ... You can run your client by means of executing ant -f run.xml clientTypedWork. 5 Getting started with QueriesReferenced objects can be retrieved with the corresponding JMI-compliant get<reference name>() : Collection accessor of the instance-level object. In cases where the result set is large (number of objects in the collection) there must be a way to filter the result set. To solve this problem openMDX allows too filter collections by queries. openMDX queries allow to
Let us have a look at the following example: In the lab model introduced in Figure 2-1 a Segment instance can reference any number of Person objects. The generated JMI reference accessor operation getPerson() returns a collection containing all Person objects. The returned collection is an instance of the openMDX-specific class Container which supports object filtering.
5.1 How to filter the result set?The following steps are required to filter a result set:
The filter classes are generated by the JMI mapping. For every instance-level class a corresponding filter class is generated. These filter classes offer operations to set filter constraints. The following example shows how to specify and apply a filter for the reference address of class Person. Listing 13: Simple address filter example. // create an Address filter
object 5.2 How to specify filter constraints?A filter constraint has the following properties:
5.2.1 How to choose filter operators?Filter operators are used to specify whether an attribute value must be equal, greater, less, … to a given value. openMDX supports the filter operators listed in the table below:
5.2.2 How to choose the appropriate quantor for a filter constraint?Quantors specify whether a given value must match all attribute values or at least one attribute value. There are two quantors: forAll and thereExists. forAll has the meaning 'match all values', thereExists has the meaning 'match at least one value'.
The filter classes contain for every attribute X the operations forAllX and thereExistsX. 5.2.3 Example filter constraintsThe following code fragments gives an idea of how to specify filter constraints using different quantors and filter operators. Listing 14: Example constraints for non-optional single-valued attributes with filter operator IS_IN. // this constraint is met if the value for
the short attribute numberOfChildren equals 2 Listing 15: Example constraints for optional single-valued attributes with filter operator IS_IN. // this constraint is met if the value for
the String attribute middleName Listing 16: Example constraints for multi-valued attributes with filter operator IS_IN. // this constraint is met if there are values
for the String attribute nickName Listing 17: Example constraints for non-optional single-valued attributes with filter operator IS_GREATER or IS_LESS_OR_EQUAL. // this constraint is met if the value for
the short attribute numberOfChildren is greater than 2 Listing 18: Example constraint for non-optional single-valued attributes with filter operator IS_BETWEEN. // this constraint is met if the value for
the short attribute numberOfChildren is between 2 and 4 5.2.4 How to specify filter constraints for null values?Null values are only possible for optional single-valued attributes (i.e. attributes with multiplicity 0..1) and multi-valued attributes (i.e. attributes with multiplicity 0..n). The following examples illustrate how to retrieve objects for which no attribute value has been set. Listing 19: Retrieve objects for which no attribute value has been set. // this constraint is met if there is no
value for the optional Sometimes you are probabely not interested in the attribute value itself but you want to retrieve all objects for which an attribute value is set at all. The following examples illustrate how to retrieve objects for which an attribute value has been set regardless of its value. Listing 20: Retrieve objects for which an attribute value has been set. // this constraint is met if there is a value
for the optional 5.2.5 How to combine multiple query constraints?You can combine multiple constraints in a query.
Listing 21: Combining multiple filter criterias. PersonFilter personFilter =
labPkg.createPersonFilter();
Listing 22: OR relation with filter operator IS_IN. // this constraint is met if the value for
the String attribute lastName 5.2.6 Ordering the resultFilters can also be used to specify the sort order. For every attribute the filter class contains an operation orderByX. This operation takes a single input argument which indicates the sort order (ascending or descending). These operations allow to specify the sort order of all the instances that match the filter constraints. Listing 23: Specify sort order. PersonFilter personFilter =
labPkg.createPersonFilter(); 5.3 Lab ExampleIn the package org.openmdx.example.lab1.program.jmi.typed.filter.work you find the class LabClient which allows you to practice the use of filters. To test your code, you can run it by executing ant -f run.xml clientFilterWork. For more information on how to run your code, please refer to . The solution in package org.openmdx.example.lab1.program.jmi.typed.filter.solution might give you some hints in case you run into problems (execute ant -f run.xml clientFilterSolution to run it). 6 Getting started with Application PluginsIn the previous chapter we explained how to write an openMDX client. This client uses the Java interfaces which have been generated from the model shown in Figure 1. In this chapter you will see how to write implementation part of these interfaces. A provider represents the implementation part of an application and implements the interface specified by a model. A provider typically consists of several plugins defined by the provider configuration.
A plugin is a platform independent component composed of one or more classes implementing the behaviour of the provider. In other words a plugin implements the business logic of an application. This chapter shows how to implement a plugin using the JMI binding. The first section of this chapter explains the JMI binding architecture. The second section shows a sample implementation. While working through the case study you will find several opportunities to practice. 6.1 OverviewA JMI plugin is composed of two parts:
The plugin must extend the class org.openmdx.compatibility.base.dataprovider.transport.dispatching.Plugin_1. 6.2 How to create an application plugin?In this section you see how to implement a JMI plugin. As an example this case study shows how to implement an application plugin. The application plugin implements all behavioral and derived features of the model. In other words: it implements the application business logic. Features which are not implemented (typically persistent features) by the application plugin are delegated to the next configured plugin which is typically the persistence plugin. The application plugin can be viewed as implementing the 'application logic aspect' of the model, in our case the application logic specified by model introduced shown in Figure 1. 6.2.1 How to write a plugin class?The implementation of the plugin class is straight-forward. You have to extend org.openmdx.compatibility.base.dataprovider.transport.dispatching.Plugin_1 and implement the protected operation getObjectFactory. As long as you do not need an application context object (more on that later), the implementation of the application plugin looks as shown in Listing 24. Listing 24: JMI Plugin implementation. public class LabPlugin 6.2.2 How to configure a plugin?A plugin configuration consists of
The sample below shows the configuration for an example application plugin. Each provider and its plugins and their configuration options must be configured in the file ejb-jar.xml. The format of this file is defined by the J2EE specification. In order to create the configuration for the labs, the entries explained in the following sections must be added to the file. For more information on openMDX deployment configurations please refer to the openMDX deployment tutorial. The variable KERNEL/APPLICATION configures the application plugin class. Listing 25: KERNEL/APPLICATION Example. <env-entry> The variables KERNEL/modelPackage[x] tells the provider which UML model packages are used in this provider. Listing 26: KERNEL/modelPackage Example. <env-entry> The variables KERNEL/packageImpl[x] tells the provider in which Java packages to look for the JMI object implementations. This is in fact a mapping of model package names (seen above) to Java package names. Listing 27: KERNEL/packageImpl Example. <env-entry> <env-entry>
NOTE openMDX offers a LightweightContainer which allows to run openMDX providers in a VM with very small footprint. EARs can be run without any modification. This allows to run and debug openMDX applications easily and then deploy them to a J2EE application server. Therefore we strongly recommend that you first get the samples up and running with the LightweightContainer before deploying them on an application server. 6.2.3 How to add business logic?As already mentioned the application plugin implements the 'application or business logic aspect' of a model. You have to provide object implementations and methods for all the features which must implement business logic. A typical provider configuration consists of an application and a persistence plugin.
Let us have a look at the example class Person from the lab model. This class has one derived attribute age and two operations serialize and assignGroups. As mentioned before you do not have to care about the other features because the invocations are delegated automatically to the configured datastore plugin. 6.2.3.1 Signature of implementation classAn implementation class
This is shown in Listing 28. Listing 28: Signature of implementation class. public class <Class>Impl For example the class PersonImpl looks as shown in Listing 29. Listing 29: Signature of class PersonImpl. public class PersonImpl The openMDX JMI request dispatcher works as follows:
6.2.3.2 Sample implementationThe code below shows the implementation for the mentioned class Person. Listing 30: Implementation of Person.
public class PersonImpl
6.2.4 Lab ExampleIn the package org.openmdx.example.lab1.plugin.jmi.multipleinheritance.work you find the class LabPlugin. To complete the lab you have to provide implementations for all modeled objects that have operations or derived features. To test your code, you can run it with ant -f run.xml pluginJmiWork. The package package org.openmdx.example.lab1.plugin.jmi.solution contains the solution in case you run into problems (execute ant -f run.xml pluginJmiSolution to run it).
7 Plugin contextThere is often the requirement that JMI instance-level objects must have access to a plugin-wide, application-specific context object. Examples are configuration values or any other kind of user-defined objects. openMDX provides a way to pass user-defined context objects to JMI instance-level objects. This chapter explains how to pass user-defined context objects to JMI instance-level objects. 7.1 How to pass a context object?The constructor of the object factory allows you to supply a user-defined context object (the constructor is typically called in the method getObjectFactory() of the application plugin). The object factory will then pass this context object to every created instance. The following code fragment shows how this is done: Listing 31: Pass the context object. protected ObjectFactory_1_0
getObjectFactory() throws ServiceException Please refer to How to implement the plugin object? for more details about plugins and the getObjectFactory() operation.
7.2 How to access the context object?Each object created by the object factory holds a reference to its object factory. This allows the method RefObject_1_0.refObject() to return the context object (the implementation merely delegates to the object factory and returns the context object). This is illustrated by the following code fragment of class PersonImpl: Listing 32: Access context object from within JMI object implementation. public short getAge( 8 Getting started with a Reflective JMI clientGetting started with a Typed JMI client explained typed JMI interfaces. These interfaces are generated according to the JMI mapping specification. As you may have observed all these interfaces extend the interfaces from javax.jmi.reflect packages, namely RefObject, RefClass, RefPackage. etc. These reflective interfaces provide the same functionality as the generated typed interfaces, but in a reflective manner. Values can be get and set with the methods refGetValue(), refSetValue(), operations can be invoked with refInvoke(), etc. This chapter explains how to write an openMDX client using the Reflective JMI accessors. The examples used throughout this chapter are based on the model introduced in Figure 1. With the generic accessor, openMDX offers an alternate way of generic programming. In fact, the JMI implementation is a wrapper on top of the generic accessor as shown in JMI Mapping Overview. The main difference between JMI reflective and the generic accessor is, that JMI is type-safe whereas the generic accessor is not. The generic accessor does not have any model information. This may improve performance in some situations. The other difference is, that JMI reflective is specified by the JMI specification, whereas the interfaces of the generic accessor, namely Object_1_0 and ObjectFactory_1_0 are not. As always at the end of this chapter you will have the opportunity to practice what you have learnt in a lab exercise. 8.1 How to create an instance?As with typed programming, JMI class proxy objects are used to create instance level objects. The class proxy objects provide factory operations that allow the clients to create instance level objects. In order to create an instance, the corresponding class proxy object must be retrieved. For this purpose the package object that contains the desired class proxy object must retrieved first. Use the refClass operation provided by the package (in the lab example: lab1Pkg) to access the desired class proxy object. This class proxy object can then be used to create instance level objects with the refCreateInstance() operation. Listing 33 illustrates how to retrieve a class proxy object and how to create an instance level object. Listing 33: Create a new instance of class Person. // retrieve class proxy for class Person
from package |