GlassFish Server Open Source Edition 3.1 - Versioning Design Spec
Deployment/Versioning 1.2 Name(s) and e-mail address of Document Author(s)/Supplier
05/11/2010 1.4 Highlevel features overview
1.4.2 Restricted features
|
![]() |
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 |
enable | disable |
get-client-stubs | show-component-status |
create-application-ref | create-application-ref |
list-sub-components | delete-application-ref |
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:
@Pattern(regexp="[\\p{L}\\p{N}_][\\p{L}\\p{N}\\-_./;#]*") public String getRef();
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.
$ asadmin deploy foo.war
$ asadmin deploy --name=foo:1 foo_1.war
$ asadmin deploy --enabled=false --name=foo:2 foo_2.war
$ asadmin deploy --name=foo:RC-1 foo_RC-1.war
$ asadmin deploy --name=foo:RC-2 /home/user/applications/foo_RC-2/
or
$ asadmin deploydir --name=foo:RC-2 /home/user/applications/foo_RC-2/
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:
$ asadmin deploy --name=foo:1 foo_1.war (1st deployment) $ asadmin redeploy --name=foo:1 foo_1.war (redeployment) $ asadmin deploy --force=true --name=foo:1 foo_1.war (redeployment)
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).
$ asadmin enable foo
$ asadmin enable foo:2
$ asadmin enable foo:RC-1
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.
$ asadmin disable foo
$ asadmin disable foo:2
$ asadmin disable foo:*
The expression "foo:*" matches all versions of "foo" application (including the untagged version) and so the enabled version.
![]() |
Warning 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). |
$ asadmin disable foo: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.
$ asadmin undeploy foo
$ asadmin undeploy foo:2
$ asadmin undeploy foo:*
![]() |
Warning 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). |
$ asadmin undeploy foo: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.
$ asadmin get-client-stubs --appname=foo:RC-1.0.0 [path]/stubs/
$ asadmin get-client-stubs --appname=foo [path]/stubs/
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.
$ asadmin deploy foo.war $ asadmin deploy --name=foo:RC-1 foo_RC-1.war $ asadmin deploy --enabled=false --name=foo:RC-2 foo_RC-2.war $ asadmin list-applications foo <web> foo:RC-1 <web> foo:RC-2 <web>
$ asadmin list-applications --verbose=true foo <web> (disabed) foo:RC-1 <web> (enabled) foo:RC-2 <web> (disabled)
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.
$ asadmin show-component-status foo Status of foo is enabled.
$ asadmin show-component-status foo:RC-1 Status of foo:RC-1 is enabled.
$ asadmin show-component-status foo:* Status of foo is disabled. Status of foo:ALPHA-1 is disabled. Status of foo:RC-1 is enabled.
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.
$ asadmin list-sub-components --appname fooEAR fooWAR default <Servlet> jsp <Servlet>
$ asadmin list-sub-components --appname fooEAR:RC-1 fooWAR default <Servlet> jsp <Servlet>
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.
$ asadmin list-application-refs foo foo:ALPHA:1.0.0 foo:RC-1.0.0 bar bar:BETA-1.0.0 bar:PRELUDE-1.0.0 helloworld
$ asadmin list-application-refs --verbose=true foo (disabled) foo:ALPHA:1.0.0 (disabled) foo:RC-1.0.0 (enabled) bar (disabled) bar:BETA-1.0.0 (disabled) bar:PRELUDE-1.0.0 (enabled) helloworld (enabled)
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.
$ asadmin create-application-ref --target NewServer foo [WARNING] version expression are available only with --enabled=false
$ asadmin create-application-ref --target NewServer foo:RC.1 [WARNING] version expression are available only with --enabled=false
$ asadmin create-application-ref --enabled=false --target NewServer foo:RC*
Interesting usecase
$ asadmin create-application-ref --enabled=false --target NewServer foo:*
$ asadmin list-application-ref foo foo:ALPHA-1.0.0 foo:RC-1.0.0
$ asadmin deploy --name=foo:SNAPSHOT-1.0 $ asadmin deploy --name=foo:SNAPSHOT-1.1
$ asadmin create-application-ref --enabled=false --target NewServer foo:* [WARNING] version "foo" already referenced on target NewServer [WARNING] version "foo:ALPHA-1.0.0" already referenced on target NewServer [WARNING] version "foo:RC-1.0.0" already referenced on target 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.
$ asadmin delete-application-ref --target NewServer foo
$ asadmin delete-application-ref --target NewServer foo:RC.1
$ asadmin delete-application-ref --target NewServer foo:RC*
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:
javax.enterprise.deploy.spi.DeploymentManager.distribute(Target[], InputStream, InputStream)
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.
v3 documentation:
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.
$ asadmin deploy --name=foo:1 --type=osgi foo_1.jar [WARNING] OSGI bundles can't use GlassFish's versioning, any version information embeded as part of the name option will be ignored.
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:
$ asadmin deploy --name=foo:1 /home/user/applications/foo/ $ asadmin deploy --name=foo:2 --force=true /home/user/applications/foo/
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:
$ asadmin deploy --name=foo:1 /home/user/applications/foo/ $ asadmin deploy --name=foo:2 /home/user/applications/foo/ org.glassfish.api.admin.CommandException: remote failure: Error during deployment: The directory "/home/user/applications/foo/" is already assigned.
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.
$ asadmin deploy foo.war $ asadmin enable foo $ asadmin undeploy foo
$ asadmin deploy --name=foo:1 foo_1.war $ asadmin deploy foo.war
$ asadmin deploy foo.war $ asadmin deploy --name=foo:1 foo_1.war
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:
$ asadmin deploy foo.war
After some code updates, he compiles again the application and wants to re-deploy it this way:
$ asadmin deploy --force=true foo.war
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:
$ asadmin deploy --name=foo:BETA-1.0 foo_beta-1-0.war
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):
$ asadmin deploy --name=foo:BETA-1.1 --enabled=false foo_beta-1-1.war
The 'BETA-1.1' additional feature is needed now, and the user has to switch for this version:
$ asadmin enable foo:BETA-1.1
The user has now reached another version and he deploys it:
$ asadmin deploy --name=foo:RC-1.0 foo_rc-1-0.war
Before doing anything else the user wants to refresh his memory about the deployed versions:
$ asadmin list-applications --verbose=true foo <web> (disabled) foo:BETA-1.0 <web> (disabled) foo:BETA-1.1 <web> (disabled) foo:RC-1.0 <web> (enabled)
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:
$ asadmin undeploy foo:BETA*
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:
$ asadmin enable foo
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:
$ asadmin undeploy foo:* $ asadmin deploy magicFOO.war
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:
$ asadmin deploy --name=foo:* foo.war org.glassfish.api.admin.CommandException: remote failure: '*' wildcard not allowed in version identifier
or
$ asadmin enable foo:* org.glassfish.api.admin.CommandException: remote failure: '*' wildcard not allowed in version identifier
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:
$ asadmin deploy --name=foo:1 foo_1.war $ asadmin deploy --enabled=false --name=foo:3 foo_3.war $ asadmin enable foo:2 org.glassfish.api.admin.CommandException: remote failure: Version foo:2 not registered
Same case for undeploy command, it's not possible to undeploy a non-existing version:
$ asadmin deploy foo.war $ asadmin undeploy foo:1 org.glassfish.api.admin.CommandException: remote failure: Version foo:1 not registered
If an application is deployed, the user must supply the 'force' argument to specify that he wants to re-deploy the application:
$ asadmin deploy --name=foo:1 foo_1.war $ asadmin deploy --name=foo:1 foo_2.war org.glassfish.api.admin.CommandException: remote failure: Error during deployment: Application with name foo:1 is already registered.
Version expression shouldn't be used if the --enabled option is not specified or is set to true.
$ asadmin create-application-ref --target NewServer foo:* org.glassfish.api.admin.CommandException: remote failure: Error during deployment: version expressions are allowed only with --enabled=false
or
$ asadmin create-application-ref --enabled=true --target NewServer foo:* org.glassfish.api.admin.CommandException: remote failure: Error during deployment: version expressions are allowed only with --enabled=false
*Demo Instructions
*[Demo Bits|V3.1Deployment^appVersioning_MS1-Demo3.tar.gz]