What is the Deployer?

The Deployer is a tool supplied with the Sentinel SDK.

It is able to deploy artifacts stored in a repository into the Rhino SLEE. The SLEE deployer is an Ivy-based tool for deploying SLEE components into a Rhino SDK or Rhino cluster.

It takes a set of modules to deploy as input, and deploys the module and its dependencies into Rhino.

It expects Ivy modules to publish SLEE components, related artifacts and dependencies according to a convention, detailed further below.

Ivy module conventions

The SLEE deployer expects Ivy modules which follow a convention.

Seven module structures

There are seven module structures supported by the SLEE deployer.

1. SLEE component jar module

The module must publish exactly one SLEE component jar artifact (e.g. my-events.jar) in the ‘slee-component’ Ivy configuration.

The SLEE component jar must contain exactly one SLEE component, with the exception of event type jars which can contain multiple event types.

It may also publish an optional ‘component-ids.xml’ artifact in the ‘slee-component’ Ivy configuration. This makes some cases more efficient.

Note It must not publish any other artifacts in the ‘slee-component’ Ivy configuration, and must publish no artifacts in the ‘deploy’ configuration.

2. SLEE service module

The module must publish exactly one ‘service.xml’ artifact in the 'slee-component' Ivy configuration.

It may also include an optional ‘oc-service.xml’ artifact in the ‘slee-component’ Ivy configuration.

It may also publish an optional 'component-ids.xml' artifact in the 'slee-component' Ivy configuration.

Note It must not publish any other artifacts in the ‘slee-component’ Ivy configuration, and must publish no artifacts in the ‘deploy’ configuration.

3. Deploy script module

This option exists for modules which need to deploy SLEE artifacts, but which don’t fit the ‘SLEE component jar module’ or ‘SLEE service module’ structures.

The module must publish one ‘component-ids.xml’ file in the ‘deploy’ Ivy configuration.

The module must publish one ‘deploy.xml’ file in the ‘deploy’ Ivy configuration. This must be an Ant file which defines a ‘deploy’ target and an ‘undeploy’ target. The Ant file must be structured in such a way that it can run when invoked inside an arbitrary directory alongside the other artifacts in the ‘deploy’ Ivy configuration. See Deployment scripts for an example.

The module must publish any other required artifacts in the ‘deploy’ configuration, e.g. ‘my-complex-application.zip’. These artifacts will be placed in the same directory as the 'deploy.xml' file prior to invoking the 'deploy' or 'undeploy' targets.

Note It must not publish any artifacts in the ‘slee-component’ Ivy configuration.

4. Group module

A group module publishes no artifacts in either the ‘slee-component’ Ivy configuration or the ‘deploy’ Ivy configuration, but has dependencies in at least one of those configurations.

5. Deployment module

A deployment module is a special case of a group module. It has dependencies on all of the modules that together constitute a complete product, and also contains configuration that was copied from the dependencies at deployment module creation time. This configuration can be used to override the default configuration from the dependencies. Deploying such a deployment module will result in a ready-to-use product installation.

Note that the distinction between a group module and a deployment module is purely based on the way it is used, as they are functionally equivalent. A deployment module is simply a top-level group module that is meant for deploying and configuring a complete product.

6. Legacy module

A legacy module publishes no artifacts in either the ‘slee-component’ Ivy configuration or the ‘deploy’ Ivy configuration, and has no dependencies in either of those configurations.

7. Deployable unit jar module

A deployable unit jar module publishes a single “du.jar” artifact in the “du” Ivy configuration.

It publishes no artifacts in the ‘slee-component’ or ‘deploy’ configurations, and declares no dependencies in either.

File format for the ‘component-ids.xml’ file

This is an XML file with a top level ‘component-ids’ element. It contains multiple component ID entries, based on the same format used in the deployment descriptor XML files associated with each component type.

An example is as follows:

    <component-ids>
        ...
        <event-definition>
            <event-type-name>org.acme.RocketLaunched</event-type-name>
            <event-type-vendor>acme.org</event-type-vendor>
            <event-type-version>1.0</event-type-version>
        </event-definition>
        ...
    </component-ids>

Deployment scripts

Deployment scripts are Ant build files with the specific name of deploy.xml and two required targets, deploy and undeploy. They allow arbitrarily complex deployment actions to be performed.

An example is as follows, from the CDR RA deployment module:

    <?xml version="1.0" encoding="UTF-8"?>

    <project name="Sentinel CDR RA deployment" default="deploy">
        <import file="${client.home}/etc/common.xml"/>

        <target name="deploy" description="Deploy CDR resource adaptor" depends="login">
            <slee-management>
                <install srcfile="${basedir}/cdr-ra.du.jar" url="file:@basename.slee-component.cdr-ra.du.jar@"/>
            </slee-management>
        </target>

        <target name="undeploy" description="Undeploy CDR resource adaptor" depends="login">
            <slee-management>
                <cascadeuninstall url="file:@basename.slee-component.cdr-ra.du.jar@"/>
            </slee-management>
        </target>

    </project>

Dependencies between module types

This section describes Ivy dependencies between different types of modules, such that the deployer can follow all suitable dependencies. The Ivy configuration in a dependency (the ‘conf=’ portion) is important to the deployer.

Tip

These are the minimum Ivy configurations so that the module can compile and be deployed.

Additional Ivy configurations than those mentioned here are almost certainly used in a project. For example, the Binder and Configurer use additional Ivy configurations.

SLEE component jar module dependencies

SLEE component jar modules are the most common type of module, and are the recommended type of module for any new development.

The most important part of the dependencies shown is the ‘conf=’ portion.

From SLEE component jar module to SLEE component jar module

    <dependencies>
        <dependency org="rocket"  name="slee-component-module-B"   rev="latest.${ivy.status}" conf="self -> api; slee-component;"/>
        <dependency org="rocket"  name="slee-component-module-C"   rev="latest.${ivy.status}" conf="self -> api; slee-component;"/>
    </dependencies>

From SLEE component jar module to deployable unit jar module

    <dependencies>
        <dependency org="rocket"  name="deployable-unit-module-A"   rev="latest.${ivy.status}" conf="self -> api; slee-component -> du;"/>
        <dependency org="rocket"  name="deployable-unit-module-B"   rev="latest.${ivy.status}" conf="self -> api; slee-component -> du;"/>
    </dependencies>

From SLEE component jar module to deploy script module

    <dependencies>
        <dependency org="rocket"  name="deploy-script-module"   rev="latest.${ivy.status}" conf="self -> api; slee-component;"/>
    </dependencies>

From SLEE component jar module to Group module

    <dependencies>
        <dependency org="rocket"  name="group-module-A"   rev="latest.${ivy.status}" conf="self -> api; slee-component;"/>
        <dependency org="rocket"  name="group-module-B"   rev="latest.${ivy.status}" conf="self -> api; slee-component;"/>
    </dependencies>

Group module dependencies

Group modules are often created to group together logically related modules.

Group modules depend on the related modules. Group modules often have no source code, and so do not need to compile anything. Therefore the “api” conf is not used.

From group module to slee-component module

    <dependencies>
        <dependency org="rocket"  name="slee-component-module-B"   rev="latest.${ivy.status}" conf="slee-component;"/>
        <dependency org="rocket"  name="slee-component-module-C"   rev="latest.${ivy.status}" conf="slee-component;"/>
    </dependencies>

From group module to deployable unit module

    <dependencies>
        <dependency org="rocket"  name="deployable-unit-module-A"   rev="latest.${ivy.status}" conf="slee-component -> du;"/>
        <dependency org="rocket"  name="deployable-unit-module-B"   rev="latest.${ivy.status}" conf="slee-component -> du;"/>
    </dependencies>

From group module to deployment script module

    <dependencies>
        <dependency org="rocket"  name="deploy-script-module"   rev="latest.${ivy.status}" conf="slee-component;"/>
    </dependencies>

Deployable unit module dependencies

Deployable unit modules are sometimes used, due to the restriction of 1 slee-component being allowed in a slee-component module.

The most important part of the dependencies shown is the "conf=" portion.

From deployable unit module to slee-component module

    <dependencies>
        <dependency org="rocket"  name="slee-component-module-B"   rev="latest.${ivy.status}" conf="self -> api; du -> slee-component;"/>
        <dependency org="rocket"  name="slee-component-module-C"   rev="latest.${ivy.status}" conf="self -> api; du -> slee-component;"/>
    </dependencies>

From deployable unit module to deployable unit module

    <dependencies>
        <dependency org="rocket"  name="deployable-unit-module-A"   rev="latest.${ivy.status}" conf="self -> api; du;"/>
        <dependency org="rocket"  name="deployable-unit-module-B"   rev="latest.${ivy.status}" conf="self -> api; du;"/>
    </dependencies>

From deployable unit module to deploy script module

    <dependencies>
        <dependency org="rocket"  name="deployscript-module"   rev="latest.${ivy.status}" conf="du -> slee-component;"/>
    </dependencies>

Using the deployer

The deployer is able to deploy a single module, or an entire dependency tree of modules.

Deploying a single module

When the deployer is invoked with the ‘deploy’ target, it attempts to deploy just that one module into the Rhino SLEE. The module is based on the current working directory.

cd module-dir
ant deploy

Any properties needed by a module can be passed in using the -Dpropertyname=propertyvalue syntax of Ant.

ant -Dsomeproperty=value deploy

Prior to deploying the module it:

  1. analyzes the publications of the module, to attempt to classify the module

  2. downloads any necessary artifacts from the module into the target/deployer-work directory, based on the module’s classification.

  3. analyses the downloaded artifacts

  4. checks whether or not the module has been deployed into the Rhino SLEE

  5. if the module has not already been deployed it attempts to deploy it

  6. prints a summary

Deploying many modules

When the deployer is invoked with the ‘deploy-with-deps’ target, it attempts to deploy all modules in the Ivy dependency tree that are not yet installed in the Rhino SLEE. The Ivy dependency tree begins from the module in the current working directory.

cd module-dir
ant deploy-with-deps

Any properties needed by any module in the dependency tree can be passed in using the -Dpropertyname=propertyvalue syntax of Ant.

ant -Dsomeproperty=value deploy-with-deps

This is achieved through the use of the Ivy dependencies between modules.

The deployer first checks the immediate dependencies of a module, and selects dependencies that have suitable Ivy configurations. For each of those immediate dependencies (let’s call each dependency a parent module), it:

  1. analyzes the publications of the parent module, to attempt to classify the module

  2. downloads any necessary artifacts from the module into the target/deployer-work directory, based on the parent module’s classification.

  3. analyses the downloaded artifacts

  4. checks whether or not the parent module has been deployed into the Rhino SLEE

  5. if the parent module has not been installed in the SLEE it applies the same process to that parent modules dependencies (if there are any)

  6. if all parent modules either do not have any dependencies, or have nothing to install, or are installed then the 'child' module is analyzed for install purposes.

In this manner the deployer is able to be invoked multiple times, only deploying modules that need deployment.

Ordering of dependencies

When invoked with the ‘deploy-with-deps’ target, the deployer traverses each module’s dependencies of each module in a predictable order. By default, the deployer will deploy all of a module’s dependencies first. The dependencies are ordered according to their organisations, names, branches and revisions. The deployer will then deploy the module itself.

This order can be controlled for a module by setting the ‘e:deployorder’ Ivy attribute in a module’s Ivy descriptor. The ‘e:deployorder’ Ivy attribute contains a comma separated list of module names. Each of the module names corresponds to one of the module’s dependencies, or to the module itself.

In the following example, module my-module declares that my-dependency-1 should be deployed first, followed by my-dependency-2, followed by itself.

<ivy-module ...>
    <info module="my-module"
          e:deployorder="my-dependency-1,my-dependency-2,my-module" ...>
          ...
    </info>
    ...
</ivy-module>

Note that specifying the value ‘a,b’ in the ‘e:deployorder’ Ivy attribute of module m does not guarantee that a will be deployed before b. For example module b could reached when traversing the graph before module m was visited. The ‘e:deployorder’ attribute only controls the order in which the deployer iterates over `m’s dependencies.

If any of the named modules do not refer to the dependencies of the module or to the module itself, the deployer will log a warning and continue rather than failing.

Temporary work directory

The deployer creates a directory named target/deployer-work for all temporary work. This directory is used for downloading artifacts needed for analysis and deployment.

The directory is deleted after a successful deploy. If the deploy fails, then the remainder is left on disk for diagnostic purposes.

Versioning checking during deployment

When a module is published, its dependencies are published along with it.

Assume that there are the following modules:

  • a group module

  • a feature module

  • a mapper module

  • a profile module

The group module depends on the feature module. The feature module depends on both the mapper and profile modules.

When all modules are built, the ‘publish-local-branch’ target is used.

The first time ‘publish-local-branch’ target is used, the following is published

Module Published revision Dependency A name and revision Dependency B name and revision

group

1.0.0-DEV0

feature revision 1.0.0-DEV0

N/A

profile

1.0.0-DEV0

N/A

N/A

mapper

1.0.0-DEV0

N/A

N/A

feature

1.0.0-DEV0

profile revision 1.0.0-DEV0

mapper revision 1.0.0-DEV0

When the deployer reads the published group module or feature module it will retrieve revision 1.0.0-DEV0, and follow the dependencies to published revision 1.0.0-DEV0 of the appropriate module.

Then, if all modules are rebuilt, again using the publish-local-branch target, the following is published (previous publications still exist too):

Module Published revision Dependency A name and revision Dependency B name and revision

group

1.0.0-DEV1

feature revision 1.0.0-DEV1

N/A

profile

1.0.0-DEV1

N/A

N/A

mapper

1.0.0-DEV1

N/A

N/A

feature

1.0.0-DEV1

profile revision 1.0.0-DEV1

mapper revision 1.0.0-DEV1

Next, if some logic is changed in the profile module, then only the profile module is built via publish-local in the profile module, the new revisions would be:

Module Published revision Dependency A name and revision Dependency B name and revision

group

1.0.0-DEV1

feature revision 1.0.0-DEV1

N/A

profile

1.0.0-DEV2

N/A

N/A

mapper

1.0.0-DEV1

N/A

N/A

feature

1.0.0-DEV1

profile revision 1.0.0-DEV1

mapper revision 1.0.0-DEV1

When the deployer reads the latest integration of the feature publication, it will see that it depends on profile revision 1.0.0-DEV1, not profile revision 1.0.0-DEV2. So it would have to deploy profile revision 1.0.0-DEV1. This would likely cause confusion, as the changes to the profile would have not taken effect!

This is almost certainly not the desired result (after publishing some changes to the profile).

To avoid this situation, by default the deployer checks that the dependent revision of a module is also the most recently published revision of that module. If those two revisions are not equal, it will not deploy anything into Rhino.

Here’s what the error message looks like:

[oc:deploy] Deployment Result:
[oc:deploy]     ---------------------------------------------------------------------
[oc:deploy]     |  Deploy result:
[oc:deploy]     ---------------------------------------------------------------------
[oc:deploy]     |  Failed Modules:
[oc:deploy]     |  rocket#my-sip-example-profile#trunk;1.0.0-DEV1-testuser
[oc:deploy]     |  |__ Module has a newer revision available in 'latest.integration': '1.0.0-DEV2-testuser'.
[oc:deploy]     ---------------------------------------------------------------------

To override this behaviour, add the -Ddeployer.latest-revision-checks.enabled=false to the ‘deploy’ or ‘deploy-with-deps’ target:

ant -Ddeployer.latest-revision-checks.enabled=false deploy-with-deps

Undeploying modules

In order to undeploy a module, the ‘undeploy’ target is used. This task uninstalls components in Rhino which were deployed from the module in the current working directory. It sorts the components by their dependencies in Rhino, in order to uninstall downstream components before upstream components. E.g. if a profile depends on a library, it will uninstall the profile first. It will fail if there are any downstream dependencies, e.g. if attempting to uninstall a library which another component depends on. It prompts the user for verification before it uninstalls any components.

cd module-dir
ant undeploy

In order to undeploy a group of modules, rooted from the current directory, the ‘undeploy-all’ task is used. This task finds all Ivy modules on disk, in the current directory and all sub-directories. It then undeploys all of those modules, after sorting the components by their dependencies inside Rhino. This is often used in conjunction to the ‘deploy-with-deps’ target.

cd module-dir
ant undeploy-all

Interaction with the binder

The undeploy and undeploy-all targets will not remove components if there are other components which depend on them. Therefore, if a Service or SBB depends on a feature, then an attempt to undeploy the feature will fail.

It is recommended to unbind (either through unbind or unbind-all) prior to undeploying.

Previous page Next page