All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.pivotal.gemfirexd.internal.shared.package.html Maven / Gradle / Ivy





	
	
	


This package and its sub-packages provides functionality that is shared between top-level Derby jar files.

NOTE - at this time, this code is not yet shared, but is used solely by gemfirexd-client.jar. The code placed here was to enable internationalization of the client. It is put under the shared package because we expect a framework to be put into place soon that will allow sharing across jar files.

List of Available Shared Components

Shared code is provided through one or more shared components. This section lists each shared component, providing essential information for the consumers of these components.

When you create a shared component, you need to add a section here to describe it for your consumers.

NOTE: Introducing a new shared component requires a vote with consensus approval. Adding a new package within an existing shared component requires a vote with lazy consensus. This is to help ensure that what we are sharing makes sense and does not accidentally paint us into some kind of architectural corner. Adding new classes or methods to an existing shared package does not need to be put up for a vote but should be reviewed using the standard patch review mechanism.

Common

Description:
This shared component is for code that is (or could be) used across all Derby jar files. This is a good place for utility routines and services such as logging/tracing, internationalization, error handling, etc.

Packages:
The Common shared component contains the following packages, all under com.pivotal.gemfirexd.internal.shared

  • common.error - utility code for error and exception handling
  • common.i18n - utility code for internationlization
  • common.reference - contains classes with shared constants
  • common.info - utility code that provides runtime information

Consumers
The only jar file currently using (and thus including) the packages in this component is gemfirexd-client.jar but it is intended to be used by other jar files once we have a working shared component infrastructure in place.

Terms and Definitions

Shared Component
A shared component is a collection of one or more packages under com.pivotal.gemfirexd.internal.shared that is used by code in more than one Derby jar file (for example, between gemfirexd-client.jar and gemfirexd.jar, or between gemfirexd.jar and gemfirexd-tools.jar).

There need only be one shared component in the system (e.g. the shared package and all its subpackages), but in some cases it may be desirable or necessary to split out some of these packages into a separate shared component. For example, if there are packages that only need to be shared between the network client and the network server, there is no need to put these classes into gemfirexd.jar, and thus these should probably be pulled out as a separate shared component.

Backward Compatibility
A consumer built against version X of a shared component should work with version X' of a module where X' > X. This is called backward compatibility.

Forward Compatibility
A consumer built against version X of a shared component should work with version X' of a module where X' < X. This is called forward compatibility.

Mixed Version Environment
If it is possible for two or more versions of Derby to be available to the same classloader, this is called a mixed version environment. It is a requirement that Derby continue to function correctly even in a mixed version environment. In particular, a Derby class that consumes a shared component must continue to run without failure, regardless of the ordering of the search path of the classloader or any other factors.

Any shared code infrastructure that we implement must meet this requirement.

Issues with Compatibility

Using backward and forward compatibility can allow Derby to run fairly well in a mixed version environment. However, there are a couple of significant issues with this approach.

First of all, maintaining compatibility, particularly forward compatibility, places a huge burden of responsibility on Derby engineers, and can also create some ugly code. Basically, for forward compatibility, you are required to check to see if any new feature exists in the current runtime environment before actually using that feature. This can get pretty ugly.

Maintaining backward and forward compatibility also does not solve the issue of shadowing. Shadowing occurs when a particular application is upgraded to use the new behavior of an existing shared component, but this behavior is not available because it is shadowed by an older version of the component.

For example, say Application A and Application B are both deployed in the same application container. The jar files for A (including Derby jars) are placed in directory A and the jar files for B (including Derby jars) are placed in directory B. In this container environment, the jars for A are loaded before the jars for B.

B is running at version 10.4 of Derby and A is running at 10.3. The Derby code for B depends upon functionality provided in a new shared package that does not exist in version 10.3. B then upgrades to 10.4.1 to get a bug fix, and are quite happy. Then A upgrades to 10.4.0, which includes the new shared package. The shared package in A shadows the shared package in B, and all of a sudden B's bugfix disappears and regresses.

For these reasons, we need another approach that guarantees that the correct version of a shared class is loaded for each consumer. We need to guarantee that Application B use 10.3 shared classes, and Application C uses 10.4 shared classes.

This can be solved in one of two ways. Which approach we use has yet to be decided.

  • Derby classloader - in this approach a specialized classloader is written that loads only from the correct jar file. This approach is currently under investigation and implementation by David Van Couvering.

  • Code copying - in this approach, at build time every shared class copied and given a different package name for each jar file that uses it. For example, com.pivotal.gemfirexd.internal.shared.common.i18n.MessageUtil would be copied as com.pivotal.gemfirexd.internal.shared.engine.common.i18n.MessageUtil for use by gemfirexd.jar and as com.pivotal.gemfirexd.internal.shared.client.common.i18n.MessageUtil for use by gemfirexd-client.jar. In this way there is no chance of clashing or shadowing in a mixed version environment.

    The problem with this approach is that developers must use discipline to modify the original source file and not the generated version. For this reason, this approach will only be used if the classloader approach ends up being unfeasible.

Note that these solutions do not allow complete flexibility in terms of mixed version environments. In particular, the application programmer or runtime administrator can not run two different versions of the embedded driver within the same classloader. As a matter of fact, that exact configuration is currently not allowed. The proposed solutions only guarantee that if you do have a mixed version environment (even by accident), nothing strange or unexpected will happen. It also allows the network driver to run at a different version from the embedded driver within the same classloader.

Location and Distribution of Shared Components

All shared components should comprise of one or more packages under the package com.pivotal.gemfirexd.internal.shared (stored in the source tree under java/common/com/pivotal/gemfirexd/internal/shared).

Although it would be conceptually nice to have a separate JAR file for each shared component, it is a priority for us to keep a very simple user experience. For this reason, the classes of a shared components will be merged into the appropriate subset of the existing jar files.

User Visible Impact and Restrictions

The intent is that the shared component infrastructure and code will have minimal to no visible impact to users.




© 2015 - 2025 Weber Informatics LLC | Privacy Policy