Skip to content
This repository has been archived by the owner on Jul 12, 2024. It is now read-only.

Profile

Thomas Diesler edited this page May 26, 2014 · 33 revisions

Working with Profiles

A Profile is an identifiable set of configuration and resource items that can be applied to a Container.

A Profile has the following properties.

Clients can obtain instances of profiles from the ProfileManager.

Managing Profile

The ProfileManager is the central entry point for working with profiles. It contains operations to

  • Add, update, remove profiles
  • Find profiles by given identifiers

Profile instances returned by the ProfileManager are shallow immutable objects. They represent the state of physical profile at a moment in time.

There is the notion of LinkedProfile which gives access to the complete hierarchy of a given Profile (including its parent profiles).

Effective Profile

From the ProfileManager you can obtain the effective profile for a given profile. This would be the flat profile representation of a given profile and the transitive tree of its parents. Child items override parent items based on identity.

ProfileManager manager = ProfileManagerLocator.getProfileManager();
Profile effectiveFoo = manager.getEffectiveProfile(version, "foo");

Creating a Profile

To create a profile, a client would use a ProfileBuilder and pass the so built Profile to the ProfileManager like this

// Building the profile
Profile profile = ProfileBuilder.Factory.create("foo")
   .addConfigurationItem("some.pid", Collections.singletonMap("foo", "bar"))
   .getProfile();

// Adding the profile to a version
ProfileManager manager = ProfileManagerLocator.getProfileManager();
profile = manager.addProfile(version, profile);

Every builder (not just for Profiles) supports the use of OptionsProvider. An OptionsProvider can take its information from an arbitrary source and invoke methods on a builder. This decouples data format from the Fabric8 builders.

Here is an example that builds a profile from JMX composite data.

Profile profile = ProfileBuilder.Factory.create()
   .addOptions(new CompositeDataOptionsProvider(cdata));
   profileBuilder.getProfile();

class CompositeDataOptionsProvider implements OptionsProvider<ProfileBuilder> {

    public ProfileBuilder addBuilderOptions(ProfileBuilder builder) {
        Profile profile = ProfileOpenType.getProfile(cdata);
        builder.identity(profile.getIdentity());
        builder.addAttributes(profile.getAttributes());
        ...
        return builder;
    }
}

Updating a Profile

Profile update uses a copy => modify => publish approach.

  1. Obtain a deep copy of the Profile you want to update
  2. Use the ProfileBuilder to modify that Profile (possibly including its parents)
  3. Publish the updated Profile through the ProfileManager.
Profile updateProfile = ProfileBuilder.Factory.createFrom(version, identity)
        .addConfigurationItem("some.pid", Collections.singletonMap("xxx", "zzz"))
        .getProfile();

Profile profile = prfManager.updateProfile(updateProfile, profileListener);

Updating a Profile hierarchy may be a lengthy operation, especially when that profile needs to be provisioned to many containers - therefore, this is conceptually an asynchronous operation.

Throughout the API it possible to pass along an event listener when an asynchronous operation is invoked. In the example above, we pass along a ProfileEventListener that will receive ProfileEvent#UPDATED when done.

Removing a Profile

// Removing the profile to a version
ProfileManager manager = ProfileManagerLocator.getProfileManager();
manager.removeProfile(version, profile.getIdentity());

A profile that is associated with an active container cannot be removed.

Profile Items

A Profile has an association with a ProfileVersion, an identity and attributes. This alone would make a Profile not very useful - the meat is in the ProfileItems

Supported are three types of ProfileItems

A ProfileItem is identified by a name that must be unique in the context of the encompassing Profile.

ConfigurationItem

A ConfigurationItem associates a persistent configuration identity (PID) with a configuration map. A Profile may contain multiple configuration items. When the Profile is provisioned to a container, the content of the configuration items is published to ConfigurationAdmin

// Building a profile that contains a ConfigurationItem
Profile profile = ProfileBuilder.Factory.create("foo")
   .addConfigurationItem("some.pid", Collections.singletonMap("foo", "bar"))
   .getProfile();

ResourceItem

A ResourceItem associates a Resource with a given Profile. A Resource has a ResourceIdentity and a set of Capabilities/Requirements. To be useful in the context of a Profile, the Resource would have at least one ContentCapability. ResourceItems support multiple content capabilities that can be associated with specific RuntimeTypes. Using include/exclude attributes on the ContentCapability, it is possible to limit the set of Runtimes that the artefact applies to.

When the Profile is provisioned to a container, the content of the ResourceItems are deployed to the target container in the same order as they are defined. A client using this method must be aware of the runtime state of the target container and make sure that the resources deployed like this have their dependencies correctly defined and that they are satisfied by in the target Runtime. A more intelligent way of provisioning is to use RequirementItems (see below).

There are various ways to build a Resources though a Gravia ResourceBuilder. Here are examples that build a Resources from a given InputStream or MavenCoordinates. Readily built Resources can then be added to the ProfileBuilder.

ContainerManager manager = ContainerManagerLocator.getContainerManager();
Provisioner provisioner = manager.getProvisioner(CURRENT_CONTAINER_IDENTITY);

// Build a ResourceItem from 
ResourceIdentity identityA = ResourceIdentity.fromString(RESOURCE_A);
ResourceBuilder builderA = provisioner.getContentResourceBuilder(identityA, getDeployment(RESOURCE_A));
Resource resourceA = builderA.getResource();

ResourceIdentity identityB = ResourceIdentity.fromString("resitem.camel.core");
MavenCoordinates mavenid = MavenCoordinates.parse("org.apache.camel:camel-core:jar:2.11.0");
ResourceBuilder builderB = provisioner.getMavenResourceBuilder(identityB, mavenid);
Resource resourceB = builderB.getResource();

// Build a profile
Profile profile = ProfileBuilder.Factory.create("foo")
        .profileVersion(DEFAULT_PROFILE_VERSION)
        .addResourceItem(resourceA)
        .addResourceItem(resourceB)
        .getProfile();

Reference ResourceItem

It is also possible to add free format resource items that are part of the profile but do not get deployed to the container. Instead, they can be referenced by URL and consumed by a target subsystem.

// Build the reference Resource
ResourceIdentity identity = ResourceIdentity.fromString(RESOURCE_A);
ResourceBuilder builder = provisioner.getContentResourceBuilder(identity, xmlInput);
Resource resource = builder.getResource();

// Build a profile
Profile profile = ProfileBuilder.Factory.create("foo")
        .addReferenceResourceItem(resource)
        .getProfile();

RequirementItem

A RequirementItem associates an abstract ResourceIdentity Requirement with a Profile. Typically this would name an abstract feature in the Gravia Repository.

When the Profile is provisioned to a container, the Provisioner first gathers the complete set of requirements from the RequirementItems. It then does a no impact analysis of whether these requirements can be satisfied by installing the missing delta of Resources that provide the wanted Capabilities. This process is described in more detail here

You can build a Requirement though a Gravia RequirementBuilder.

ResourceIdentity featureId = ResourceIdentity.fromString("camel.core.feature:0.0.0");
Requirement requirement = new IdentityRequirementBuilder(featureId).getRequirement();

Profile profile = ProfileBuilder.Factory.create("foo")
        .profileVersion(DEFAULT_PROFILE_VERSION)
        .addRequirementItem(requirement)
        .getProfile();

URL access to Profile content

The system supports direct URL access to Profile content in the Profile registry.

profile://[profileVersion]/[profileName]/[itemName]?version=[version]&cntindex=[contentIndex]

Both, the version and cntindex parameters are optional. If they are missing the URLStreamHandler will use the higest version and the first content respectively.

Clients can also use the container:// URL scheme to address content in effective profile of the current container. Because the container already knows the associated ProfileVersion and list of Profiles, there is no need to give that information in the URL. Such URLs are therefore portable across ProfileVersions and Profiles

container://[itemName]?version=[version]&cntindex=[contentIndex]