WebSphere EJB CMP Support


In Chapter 5, we used the "top-down" mapping support for CMP fields, in which a database schema is automatically generated based on the definition of an EJB. This is the easiest way to implement EJB persistence during new development, but it also contains a number of inherent restrictions. The most obvious of these is when you are not creating a new database in reality, but need to map your newly created bean to an existing database. However, there are a number of additional mapping options, which are not available using the top-down approach, and we will review them here.

The WebSphere Studio mapping editor provides the ability to define the specific mapping between individual CMP fields and the database columns. The mapping editor is used to map an entire JAR at once. Nodes in the editor represent the beans and CMP fields that need to be mapped, as there are some scenarios such as container-managed relationships (CMRs) and EJB inheritance that require a complete view of all beans in the JAR. You cannot create mappings that span JARs; if you wish to share mapping information for different beans (in cases such as EJB inheritance), you must have all those beans in the same JAR file.

click to expand

In this view, the underlying model files are seen in the left, in the Navigator view. The mapping editor displays the JAR and the entity beans on the top left-hand side of the editor view, and the database tables and columns on the top right-hand side. Those beans and fields that are mapped have a triangle by their name, and appear in the overview view (bottom-half of the editor) and in the Outline view (bottom-left of the screen). Suppose we wished to change the default mapping of the Inventory bean's INVENTORYID field, from a VARCHAR(250) column to an INTEGER, perhaps because we are now going to reuse an existing database, then the following steps should be followed.

The first action is to remove the existing mapping for the field; do this by opening the context menu from the INVENTORYID node in the Overview view, and selecting Remove Mapping. Next, we need to update the definition of the INVENTORY table. Select the table in the top-right view, and from the context menu select Open Table Editor. The table editor allows you to make arbitrary changes to the schema – to change the column type, we select the Columns tab at the bottom of the editor, select the column desired, and then make the change using Column type as shown. Now simply save and close the table editor:

click to expand

Back in the Mapping editor, you can define the new map by selecting both the inventoryID CMP field and INVENTORYID column nodes, in the top-left and top-right editor views. Bring up the context menu, and select Create Mapping; you will see the results added immediately to the Overview view.

This series of actions highlights several features, most obviously how easy it is to change a mapping using the WebSphere Studio Mapping editor. However, you will also note that the new mapping of a String to an Integer requires a type conversion. This code is generated automatically when the bean is deployed. The implementation details of how a particular CMP field is persisted, are not defined by the specification, and previous versions of WebSphere Studio and VisualAge for Java required a Converter object to be defined to implement this form of type mapping. WebSphere Version 5.0 can exploit the changes in the EJB 2.0 specification, with the result that entity beans with CMP 2.0 style persistence no longer require converters – the correct type-conversion code is now generated in place. Converters are still supported, but are now only required for semantic, or data-value conversion – type conversion is handled automatically.

The ability to change the persistent mapping of a field also highlights the benefits of using CMP entity beans. We have just changed how a bean maps to a column, without having to change any user code, queries, or implementation. You simply have to re-deploy the bean, and the correct code will be generated for you.

EJB Inheritance

EJB inheritance is an IBM extension that is a form of advanced persistence. Inheritance is a fundamental part of object-oriented code, with benefits ranging from simple code reuse, to advanced polymorphic behavior. The behavior of Java objects that use inheritance is a well defined part of the language, but Java objects exist only in memory and do not provide any native form of persistence. Enterprise beans are implemented as Java objects, and as such, the runtime behavior is well defined as well. You can treat an instance of a child class as though it is an instance of the parent class, and you can invoke and override methods defined at various points in the hierarchy. The complex issue is how the type and state of CMP entity beans can be persisted and reloaded again. We will use a simple example to highlight the options:

  • Vehicle – root enterprise bean whose CMP fields include id and dateAcquired

  • Automobile – inherits from Vehicle and adds CMP field numberOfAirBags

  • RaceCar – inherits from Automobile and adds CMP field topSpeed

  • Bus – inherits from Vehicle and adds CMP field maximumPassengers

  • Truck – inherits from Vehicle and adds CMP fields maximumLoad and numberOfWheels

There are two modes of persistence for EJB inheritance available:

  • Single table
    In single-table mapping, each bean type is mapped to the same table. In the Mapping editor, you need to establish a discriminator column for the root bean type, and a distinct value for that column for each bean type. The top-down mapping wizard will also prompt you for these details, on the last page of the wizard. The type of each row is then determined by the value of the discriminator column in that row. This property is set in the Properties view in the EJB Mapping editor, and can be any value you choose, as long as each type is distinct. The benefit of single table mapping is that the data can be queried and reloaded quite efficiently without the need for complex multi-table joins. The cost of this style is that the table definition can grow quite wide, with only a subset of the columns used for each bean type.

    The resulting table for the above example, using single-table mapping, would look like this:

    Table: VEHICLE

    ID

    DISCRIM

    DATE

    AIRBAGS

    SPEED

    MAXPASS

    MAXLOAD

    WHEELS

    12

    Vehicle

    2002/06/13

    15

    Bus

    1966/05/22

    35

    27

    RaceCar

    1993/07/05

    1

    218

    28

    RaceCar

    1994/11/05

    1

    235

    42

    Truck

    1981/08/01

    4400

    18

    52

    Automobile

    1991/05/14

    0

    55

    Bus

    1999/12/01

    28

  • Root/Leaf
    In root/leaf mapping, each type is mapped to a distinct table, but fields defined in the root type(s) are not duplicated. As the name implies, there is a root table, and the table for each derived type only contains the key, and the additional fields defined by that type. Note that queries defined on the root type can result in large joins, due to the need to select all possible fields for all possible types – as a result, queries should generally be defined as low in the hierarchy as possible. The benefit of root/leaf mapping is that each table is smaller, and only contains relevant information. The cost of this style is that the queries needed to load a bean consist of large joins, which can be expensive to run.

  • The resulting tables for the above example, using root/leaf table mapping, would look like this:

    Table: VEHICLE

    ID

    DISCRIM

    DATE

    12

    Vehicle

    2002/06/13

    15

    Bus

    1966/05/22

    27

    RaceCar

    1993/07/05

    28

    RaceCar

    1994/11/05

    42

    Truck

    1981/08/01

    52

    Automobile

    1991/05/14

    55

    Bus

    1999/12/01

    click to expand

In both mapping models, a series of additional WHERE clauses of database joins are required to implement the persistence pattern you select, but with CMP these mechanics are hidden from you. Your responsibility is to ensure that the schema defined is the one you want, and the bean's mapping to that schema is logically correct. The WebSphere persistence manager and the generated code will then do all the hard work, providing the behavior you want in a way that performs at run time.

You need to define the details of EJB inheritance in two different locations. The basic structure of the inheritance, defining which beans inherit from other beans, is set as part of the EJB deployment descriptor extension. This information can be best changed using the deployment descriptor editor in Studio. The second piece of information is the type of mapping model to use, and the associated data such as a discriminator column and the discriminator values. This data is saved in the mapping document, and changed in the Studio Mapping editor. You can select various beans in the editor, and update the values as properties.

The details of the mappings described above are saved in metadata files that are included with the deployment descriptor in the JAR. As a result, the mapping variants described above are all possible, but the code to implement them does not need to be generated within Studio. The EJBDeploy command that can be invoked on the command line, or during the application installation process, has access to the metadata files and will reflect this data during the code and query generation. There are multiple files used to represent the persistence of a single JAR, as described below. As with the mapping editor, the files all represent a complete JAR. The XMI files are all based on an OMG-compliant specification, so you can use a number of tools to browse through them or compare different versions for changes. The files contain a number of links that need to be self-consistent, so it is recommended that you do not manually edit the files; use the Studio editors instead.

The links to the various mapping elements require the use of ID tags within each file, including the deployment descriptor itself. The EJB deployment descriptor DTD does allow for the use of IDs, but the deployment descriptor is not otherwise modified during the mapping of CMP fields. The metadata files saved in the JAR file are:

File name

Description

META-INF/ejb-jar.xml

Spec deployment descriptor

META-INF/ibm-ejb-jar-ext.xmi

IBM deployment descriptor extensions

META-INF/ibm-ejb-jar-bnd.xmi

IBM deployment descriptor bindings

META-INF/map.mapxmi

Mapping information for CMP beans

META-INF/schema/*

Schema information for CMP beans

Mapping CMP Beans with 2.x Persistence

The above text applies to all CMP beans, but there is additional mapping and support, and a resulting change to the number and structure of the metadata files, when CMP 2.0 persistence is used. Note that an EJB JAR file may be a 2.0 level JAR (meaning, the deployment descriptor uses the 2.0 DTD), but the entity beans within the JAR may use either 1.x or 2.x persistence. It is even possible to mix 1.x and 2.x persistence beans in the same JAR, although that practice is not recommended. There are several differences between the two persistence styles, but the most visible one is the change in the way persistent fields are represented. The 1.x persistence uses public fields in the bean, while 2.x persistence beans have abstract getter and setter methods.

Another important change that comes with WebSphere's support of CMP 2.x beans is the ability to map a single JAR to multiple databases. The whole premise of the CMP design is to separate the implementation of the bean from the mapping to the underlying database, but that mapping has to occur at some point, and from then on the bean implementation is typically bound to a particular schema. With CMP 2.x beans however, you can create multiple mappings to different databases, or even different styles of mappings to the same database – perhaps one mapping for a test database, and another for a production database. When multiple mappings are defined, the metadata files saved in the JAR are modified as follows:

File Name

Description

META-INF/ejb-jar.xml

Spec deployment descriptor

META-INF/ibm-ejb-jar-ext.xmi

IBM deployment descriptor extensions

META-INF/ibm-ejb-jar-bnd.xmi

IBM deployment descriptor bindings

META-INF/backends/id1/map.mapxmi

Mapping information for CMP beans

META-INF/backends/id1/table*.xmi

Schema information for CMP beans

META-INF/backends/id2/map.mapxmi

Mapping infovrmation for CMP beans

META-INF/backends/id2/table*.xmi

Schema information for CMP beans

This approach uses a unique backend ID to store all mapping related metadata that is associated with each backend. Any number of backends can be defined, with as many similarities or differences between them as necessary. The mapping and table editors within Studio understand this structure. The available backends are displayed, and once one is selected, the editors behave as before. The code necessary to execute all included backends is generated when the EJB is deployed, meaning that the current or "active" backend can be changed in the assembly tool without requiring any additional code regeneration. The current backend can also be set at creation time, in the deployment descriptor editor in Studio.

SQLJ Support

An additional mapping option that is available for CMP 2.x beans is the style of database access. The standard approach is to use dynamic access via JDBC, but some advanced databases (such as DB2 Version 8.1) offer substantial performance improvements by using static access via SQLJ. SQLJ is a standard for static SQL usage, but can offer substantial performance benefits over dynamic SQL (such as JDBC). For example, SQLJ provides a SELECT INTO statement that will populate Java variables directly from the results of a SQL statement, avoiding the use of underlying database cursors. The generated code for single-valued EJB finder methods (such as findByPrimaryKey()) will exploit this style, resulting in improved performance. Additional details about SQLJ can be found at http://www.sqlj.org.

The use of SQLJ requires three stages; the SQLJ-specific code needs to be generated, next it needs to be translated into Java, and finally the Java code needs to be profiled against a specific database. The first two of these stages are implemented by the EJB deploy tool. For this, a property can be set in the Properties view of the Mapping editor, indicating that the mapping is to be implemented via SQLJ. This will then be persisted as part of the metadata, and when the code is generated, it will use the static SQL approach. The translation of the SQL into Java code will also occur under the control of the EJB deployment tool, using a translator provided by the database vendor. Finally, the generated code needs to be profiled against a specific database instance. This profiling step allows the database to optimize the interaction and subsequent performance.

Profiling uses a tool provided by the database vendor, and must be run on a machine with live access to the target database. The deployment tool will generate an Ant script that can be run on this machine, to invoke the profiling step. In summary, if you are targeting a database with good SQLJ support, then the tradeoff is simple; in exchange for a slightly more complex build and deployment step requiring live access to the target database, you can substantially improve the performance of your database access (depending on your access patterns).

The entire mapping variations described above, work in conjunction with the access intents described earlier. Each method on the bean may have multiple implementations generated, and the specific implementation used is selected by the WebSphere persistence manager at run time. This is how the dynamic nature of the access intents can be supported, and the use of any or all of the advanced mappings described, does not impede the function of the access intents. Pulling all the options together, it is therefore possible to define a single JAR that contains multiple beans related via EJB inheritance. The persistence of the beans could be spread across multiple tables and loaded via a join at run time, or all beans could be persisted into a single table. The access to the database in either scenario could be via JDBC, or via static SQLJ. Finally, each of these combinations can be used with or without optimistic concurrency, pessimistic locking, read-ahead relationship support, and all the other access intents.




Professional IBM WebSphere 5. 0 Applicationa Server
Professional IBM WebSphere 5. 0 Applicationa Server
ISBN: N/A
EAN: N/A
Year: 2001
Pages: 135

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net