- GlassFish Server Open Source Edition 3.1 - Versioning Design Spec
- 1. Introduction
- 1.1 Project/Component Working Name
- 1.2 Name(s) and e-mail address of Document Author(s)/Supplier
- 1.3 Date of This Document
- 1.4 Highlevel features overview
- 1.5 Basic versioning interest
- 2. Functionality
- 2.1 Syntax definitions
- 2.2 Use context
- 3. Unversioned vs. versioned apps and backward compatibility
- 4. Implementation
- 4.1 Domain.xml
- 4.2 Deployment Related Admin Classes
- 4.3 Deployment Object Library
- 4.4 ApplicationRef
- 5. Basic commands
- 5.1 Version deployment
- 5.2 Version redeployment
- 5.3 Version switch
- 5.4 Version deactivation
- 5.5 Version(s) undeployment
- 5.6 Version client-stubs
- 5.7 Version list
- 5.8 Version application-ref
- 6. JSR-88
- 7. OSGi and GlassFish versioning
- 8. In-place directory deployment
- 9. Versioned / unversioned
- 10. Samples scenarios
- 11. Rejected scenarios
- 11.1 Bad use of commands
- 11.2 Bad scenarios
- 12. Some Open Issues
- 13. Demos
- 14. Dev Tests
- 15. Email Alias
- Romain Grécourt - SERLI (firstname.lastname@example.org)
- Hervé Souchaud - SERLI (email@example.com)
- Mathieu ANCELIN - SERLI (firstname.lastname@example.org)
- Pierre-Henri DEZANNEAU - SERLI (email@example.com)
- Application Versioning allows multiple versions of the same application to exist in a GlassFish domain. It provides the developer and the administrator extensions to the relevant existing tools and commands to deploy, view, and manage multiple versions of applications.
- At most one version of an application may be enabled on any target. To the extent possible, implement the changes to the exposed interfaces so that the same changes could be used as-is or with minimal revision to support runtime versioning.
- Explicit versioning: the user will experience the v2 behavior for all application operations he or she invokes without specifying a version.
- Unlimited number of versions of an application: the user may create, aside from limitations in disk space for storing the application and its configuration information.
- Any published interface that supports the application operations that are affected by application versioning (e.g., deploy, undeploy, enable, disable, create/delete-app-ref, get- client-stubs) will support application versioning. This includes the CLI, the GUI, ant tasks, and the callable DeploymentFacility.
- Using more than one in-place directory deployed applications deployed from the same directory is ambiguous. In order to introduce a new behavior of --force option for in-place deployments, GlassFish will reject deployments of already used directories and display warnings about the --force option use. This behavior is consistent with the regular cases as using --force=true will undeploy the currently deployed application before the new deployment. For instance it will be possible to redeploy in-place directory deployed applications by using --force=true.
- Because OSGi already has its own versioning system, GlassFish will ignore the version information provided with the name option but will let the deployment go through. In the case where users are using the GlassFish versioning with an OSGI bundle, some warnings will be printed out to inform them that the version information they provides will be ignored.
- Automatic versioning, in which users specify no version information but GlassFish automatically supplies successive automatically-generated version identifiers in response to successive deployments of an application.
- Runtime versioning, in which multiple versions of an application can be enabled on a single target. This would require added runtime support in the containers and in naming which is not needed for application versioning alone.
The versioning system described in this document is a basic feature. Eventually we want to provide runtime versioning where more than one version of the application are enabled at the same time in the runtime, so there will be no loss of service for users when they are upgrading or rolling back the versions. This basic application versioning is one step toward that direction.
Users can be interested in this feature in terms of administration. As all the versions of an application are stored in the GlassFish repository, it will help minimize downtime during upgrade or rollback. Indeed upgrade and rollback operations can be done by "hand", for instance deploying a new copy of running application consists:
- downing the current application
- undeploying the current application
- copying up the new artifact
- expanding that artifact on GlassFish
- deploying the new application
- starting the new application
In a clustered environment theses operations can also be done by "hand" but this result in a lot of hoop jumping and coordination. With versioned applications, GlassFish can do these steps for the user, and, ideally let he or she switch over (and back) very quickly with little management.
There are two kinds of syntax defined to handle versioning within GlassFish server:
A version identifier satisfies the following regular expression :
This expression allows the use of maven/OSGi version values (major.minor.micro-QUALIFIER or QUALIFIER-major.minor.micro) as identifiers.
A version expression is either a version identifier or a wildcard expression that contains one or more « * » characters as the wildcard. GF applies the associated operation to all versions of the application which match the expression.
Version identifier and expression are used as suffixes to application names, introduced by a colon « : » ; for example « myApp:Beta » or « inventory:RC* ».
This approach preserves existing APIs (e.g. JSR-77, JSR-88, AMX) while allowing them to take advantage of the versioning feature. Places where an application name appears in the v2 APIs will accept a name with version expression in v3.
|Be careful with wildcard character|
There are possible issues with the use of the wildcard character * in commands with some shells. Many Unix shells provide globbing on filenames at the command line and in shell scripts. The shell expands the "glob pattern" (foo:* for example) and supplied the list of all the matches to the execution of the command.
When encoutering this issue, please surround the version expression by quotes like :
$ asadmin undeploy "foo:*"
The untagged version is a version having an empty string as identifier and that follows the same rules as all others version. This concept was introduced to maintain backward compatibility with GlassFish v2 users.
The GlassFish versioning system embeds the version information as part of application names. An application becomes a versioned application if the version information is provided at deployment time. Users can follow either Maven or OSGI versioning schema but there is no relationship among versions of the same application (no later/previous versions).
For all deployment mechanisms using a name option, the use of --name is mandatory to pass in the version information. For the others mechanisms (e.g. "JSR88" or "Autodeploy") a new version element will be introduced in the GlassFish deployment descriptor (glassfish-*.xml).
In v2 GlassFish enforces some restrictions among different applications, such as requiring each application to have a unique context root and to use distinct JNDI names (same jndi names among versions of a same application). These restrictions remain among different applications in v3 but do not apply to different versions of the same application. GlassFish v3 permits different versions of the same application to use the same context root and the same JNDI names. This causes no runtime conflict because at most one of the versions can be enabled at a time.
Database tables created or deleted as part of deployment and undeployment are global resources and so cannot be qualified by an application version, so users have to be very carefull when using global resources among versions of the same application.
GlassFish supports version rollback through the enable command. If the user deploys a new version he or she can rollback simply by enabling a different version. Because enable automatically disables any enabled version of the application, enable accomplishes rollback.
An identifier is bound to an unique version while an expression matches a set of versions. Consequently there are two different command groups using either an identifier or an expression as argument
|Identifier aware operations||Expression aware operations|
|deploy / deploydir / redeploy||undeploy|
The sessions are preserved during the redeployment of a version as GlassFish treats it like a distinct application. On the other side, preserving sessions among different versions of the same application is more complex as the key used for session variables has to be the same between the versions being switched.
Resources are created with reference to the resource-adapter's (application's) name.
Since we embed version within the application's name, the older version's resources will not refer to newer version of the application. Administrator/Developer need to explicitly create resources for the newer version of the application.
Moreover GlassFish will ignore any duplicate exported global resources and let deployment go through.
Although the same operations apply to versions and unversioned applications, the effects can be slightly different. We want users to have a consistent experience in v3 when they use a sequence of operations they have used from v2. We also want users to be able to deploy an unversioned application and later use versioned application whenever they want.
GlassFish provides explicit versioning through the use of the name option: the user has to provide explicitly an application name following the versioning syntax described above. For the commands where the name option is optional such as deploy, the use of the --name attribute is mandatory if the user wants to use versioned applications. Therefore the complete versioned name won't be deduced from the archive name to avoid some ambiguity.
This approach gives users the same experience they had with v2.
This proposal requires no new changes in the layout. The version information is embedded in the module name.
As we are using the versioning syntax as part of the application name, all the impacted classes (identifier aware operations and expression aware operations) will evolve so they operates on the correct version of the application.
The DOL will evolve so that the getAppName() method for application and getModuleName() method for module descriptor returns only the untagged name of the versioned application excluding the version identifier. The getRegistrationName() for application will return the versioned name as we use it to register the application.
Theses modifications will provide the possibility to have unique JNDI names for versioned EJBs and unique context roots for versioned WAR where it's not known (not provided in the web file descriptor or at deployment time through asadmin option --contextroot).
The colon character has to be allowed for ref attribute in ApplicationRef so we can use it as part of application names. The restriction in GlassFish v3.0 was:
The deployment process is performed by the deploy command which is an identifier aware operation. The syntaxes presented above are used as name option, therefore there is no relationship between the archive name and the versioning system at all.
The deploydir command is currently deprecated but has to be presented because it extends the deploy command in order to provide some backward compatibilty for v2 users.
Moreover deploying an enabled version will automatically disable the currently enabled one if there is one depending of the value of the --enabled attribute. The default behaviour of a new version deployment is to disable the currently enabled version as the default value of the --enabled attribute is true.
- A user wants to deploy the application "foo" (untagged version)
- A user wants to deploy an enabled version:
- A user wants to deploy a new disabled version:
- A user wants to deploy a version named "RC-1":
- A user wants to deploy a version named "RC-2" from a directory:
The redeployment process is accomplished by the redeploy command which simply invokes the deploy command correctly. The use and the behavior of this command is similar to deploy command:
The last two commands are equivalent. The force option is needed for redeployment when using deploy command so the user does not accidentally overwrite the version.
The user can perform switch operation by using the enable command which is an identifier aware operation because only one application can be enabled at runtime. The enable process disables the currently enabled version before enabling the one specified by the user.
The primary argument of this command is the application name, it's used to specify the version to enable (the targeted version must be already deployed).
- A user wants to activate the untagged version:
- A user wants to activate a version with a simple identifier:
- A user wants to activate a version with a more complex identifier:
The disable command is an expression aware operation which allows the user to disable any version.
Although only one version of an application can be enabled at runtime, this command accepts version expressions to be more flexible for users. Only one application can be disabled by the command process even if the targeted expression matches more than one version.
If the currently enabled version doesn't matched by the expression, the command will result in a no-operation. This is to be consistent with the current non versioned commands (disabling an already disabled application will do nothing because what the user wants to achieve is achieved).
If a user disables the currently enabled version, then GlassFish will not enable automatically another version.
- A user wants to disable the untagged version:
- A user wants to disable a version with a simple identifier:
- A user wants to disable the currently enabled version, but he doesn't know the version identifier:
The expression "foo:*" matches all versions of "foo" application (including the untagged version) and so the enabled version.
foo* is not a valid version expression. The wildcard character is only allowed in the version part of the command value (ie. after the colon character).
- A user wants to disable the currently enabled version if its identifier begins with "RC":
The undeployment process is performed by the undeploy command which is an expression aware operation because several versions can be undeployed at the same time unlike the disable command that process over one version at most whatever expression supplied.
Indeed the undeployment process deletes matched version bits in repository which might also result in undeploying the currently enabled version if the expression matches it.
If a user undeploys the currently enabled version, then GlassFish will not enable automatically another version.
- A user wants to undeploy the untagged version:
- A user wants to undeploy a version with a simple identifier:
- A user wants to undeploy all versions (including the untagged) of "foo" application:
foo* is not a valid version expression. The wildcard character is only allowed in the version part of the command value (ie. after the colon character).
- A user wants to undeploy all the version(s) of an application where the identifier begins with "RC":
The client-stubs generation process is performed by the get-client-stubs command which is an identifier aware operation because the generated files can only match one version.
The targeted version is specified as identifier.
- A user wants to retrieve the stubs of an application with a specific version:
- A user wants to retrieve the stubs of an application with the untagged version:
The list-applications and list-components commands allow users to display the versions of each deployed application, no identifier will be shown for untagged applications. The interest of this command in the context of versioning is that in addition to list all versions, it allows users to quickly find which version of an application is currently enabled.
This command has two modes of use, a default and a verbose mode.
The default mode will display the versions in a compact way, using the version identifier format used in the commands. This mode allows v2 users to keep using GlassFish as they are used to.
The verbose mode will be activated with the --verbose option, it will add the enabled state of each version in addition with the information of the default mode.
- A user wants to list versions after some deployments:
- After some time, the user might not remember which version is enabled, he can then get the version list again, but this time with the enabled state information:
The show-component-status command allow users to display the enabled state of a given application. This command is an expression aware operation as the v2 users can still use it as they used to (by refering to the untagged version) and as it provide users the possibility to look at the enable states of a version set.
- A user wants to show the status of an application:
- A user wants to show the status of a specific version:
- A user wants to show the status of the version set:
The list-sub-components command is an identifier aware operations because it use a module name as argument and an application name as option. The restriction to version identifier exist primarily in order to not make users confuse.
- A user list the subcomponents of the untagged version of an application "fooEAR" within a module "fooWAR":
- A user list the subcomponents of a specific version of the "fooEAR" application within a Web module "fooWAR":
The list-application-refs command is very similar to the list-applications command but it process over application references. As the list-applications command we will provide two modes of use: a default and a verbose mode.
- A user who had v2 experience has created some references to applications and want to list them:
- Then he process the same command in verbose mode to display the enable states of the references:
The create-application-ref command is an identifier aware operation or an expression aware operation depending on the value of --enabled option. It accepts version expression to provide user facilities. As the default value of --enabled option is true, processing this command over a set of versions will try to enable all of them on the provided target. This user facility is only consistent with --enabled=false.
So this command accepts version identifier by default because the default value of --enabled is true ; it also accepts version expression only if the --enabled option is false and warnings will be printed out if some references are already created in the target.
GlassFish will reject the command with a meaningful error message when --enabled=true is used with a version expression. GlassFish will also display a message when --enabled=true is used with a version identifier to warn users that they can use version expressions.
- A user creates a reference to the untagged version of Web module "foo" on the unclustered server instance NewServer:
- A user creates a reference to a specific version of Web module "foo" on the unclustered server instance NewServer:
- A user creates references to a set of versions of Web module "foo" on the unclustered server instance NewServer:
- A user creates references to a previously deployed version set of the Web module "foo" on the unclustered server instance NewServer, then deploy 2 new versions on the DAS and finally updates the references on the instance NewServer:
The delete-application-ref command is an expression aware operations to allow users to delete references over a version set or a targeted version.
- A user deletes a reference to the untagged version of Web module "foo" on the unclustered server instance NewServer:
- A user deletes a reference to a specific version of Web module "foo" on the unclustered server instance NewServer:
- A user deletes references to a set of versions of Web module "foo" on the unclustered server instance NewServer:
It is possible to use versions with a JSR88 client application. For the commands where the application name is optional such as deploy, the use of a specific name is mandatory if the user wants to use versioned applications.
Although there are two common ways to deploy with JSR88 depending on the API used, only one allow users to fill a specific name:
The application name is taken from the display-name entry in the Java EE standard deployment descriptor. If it's not present GlassFish will use a temporary name for deployment like : jsr88-2866258839334960706.tmp, in this case the version information is not provided explicitly so GlassFish will not deploy the application as a version.
As OSGi have its own versioning system, GlassFish will let the deployment go through but will display a warning if a version information is provided as part of the name option.
A directory shouldn't be deployed twice with a different version identifier. The versioning for in-place directory must be managed by users: if they wants to use two version of a same application with a unique directory, they has to provide the --force=true option:
The fact that users provide the --force option indicates an unusual behavior, as a directory is already assigned to a version. If the --force option is not provided, the deploy command will fail:
Users not using versioning as in GlassFish v2 are implicitly processing on the untagged version. Actually when people refer to an application foo, GlassFish performs the task over a version with an empty string as identifier.
The user can start to use versions and go back to the untagged one when he wants, he can also operate on the untagged version as he would with all others basic commands.
- A user wants to use v2 unversioned commands:
- A user starts using versions and then go back to use the untagged version:
- A user starts using GlassFish without versioning and then use the versioning:
This part attends to present the life-cycle of an application from a user perspective through command sequences.
A user is developing a simple Java EE application named foo and uses GlassFish to deploy it. He deploys his application the first time as follows:
After some code updates, he compiles again the application and wants to re-deploy it this way:
At this point the user thinks he has reached the milestones he fixed, but he wants to go further in the development of its application by proposing new features. Consequently he plans new milestones and decides to version his application.
Once the development of the next targeted version finished, the user deploys it like:
Then the user has decided to plan a new "BETA" version containing a special feature not needed at this moment but potentially required later. Therefore once the version developed, he deploys it but doesn't enable it (he will switch later):
The 'BETA-1.1' additional feature is needed now, and the user has to switch for this version:
The user has now reached another version and he deploys it:
Before doing anything else the user wants to refresh his memory about the deployed versions:
At this moment the current enabled version is "RC-1.0", and the user assumes that the "BETA" versions are no longer useful. Therefore he can undeploy all the "BETA" versions this way:
A moment later, a major bug is found in version RC-1.0. He knows that the application before versioning does not include the bug, so he decides to return to the untagged version:
A famous company released an open source Java EE application named "magicFOO" performing exactly the "foo" process in a more powerful way. Therefore the user decides to drop his application and use the new one instead:
The scenarios presented below show what the user cannot do in accordance with the definitions. ;:The error message "Version untaggedName:versionIdentifier not registered" is used as somehow the previous releases chose to use word "registered". Moreover there is no real difference between "registered" and "deployed".
The identifier aware operations can't process if the expected argument is a version expression:
This part deals with the forbidden sequences causing a GlassFish error. The rejected commands cause no change in which version (if any) of an application is enabled.
It is not possible to enable a version not previously deployed:
Same case for undeploy command, it's not possible to undeploy a non-existing version:
If an application is deployed, the user must supply the 'force' argument to specify that he wants to re-deploy the application:
Version expression shouldn't be used if the --enabled option is not specified or is set to true.
- There are possible conflicts between application name and repository name with the "-".
For instance if a user has deployed a version "foo:BETA-1.0", it will be stored in a directory named "foo-BETA-1.0" of the application repository ; then if the name "foo-BETA-1.0" is used either as application name or archive name during a deployment, this will raise an issue.
A solution could be using a specific characters combinaison to minimize the possible conflicts.
- Are there aspects other than context root and JNDI names that should either be permitted to be the same in different versions of the same app, required to be the same, or required to be different?
- Please contact us at firstname.lastname@example.org