Contexts

From GCube System
Jump to: navigation, search

Within service implementations, some functionality needs to be accessed by different components and for different purposes.

The most obvious case of shared functionality is that required to expose the configuration of the service, or the configuration of its RI, or the configuration of the gHN on which the RI is deployed. Information related to scope and security is also dynamically acquired and simultaneously needed by different components. And moving beyond information access, there are utilities and behaviours, both general-purpose and service-specific, which may be called upon from multiple and functionally unrelated components.

The gCF approach to shared functionality is to centralise it in distinguished components, called contexts, which are directly accessible from any other implementation component. gCF contexts are singleton classes, in that they are designed to be instantiated only once and to expose the single instance to all their clients in a thread-safe manner.

Overview

There are different type of contexts in gCF, each of which centralises functionality that is conceptually associated with key entities of service implementations:

  • the service and its RI;
  • the gHN on which the RI is deployed;
  • the port-types of the service;
  • the port-types of target services.

Some contexts are fully defined within gCF. Others are only partially implemented and need to be specialised within service implementations. Collectively, the context form a inheritance hierarchy contained in the package org.gcube.common.core.contexts:

Contexts.jpg

As shown in the diagram, the entire framework has dependencies on the contexts packages, in line with the definition of contexts as repositories of shared functionality. The high-level roles of package components is summarised below:

  • GCUBEContext: the base implementation of all contexts.
  • GCUBEServiceContext: a concrete specialisation of GCUBEContext for gCube Services and their RIs.
  • GCUBEPortTypeContext: a concrete specialisation of GCUBEContext for the port-types of gCube Services.
  • GCUBEStatefulPortTypeContext: a concrete specialisation of GCUBEPortTypeContext for the stateful port-types of gCube Services.
  • GCUBERemotePortTypeContext: a concrete specialisation of GCUBEContext for port-typea of target services.
  • GHNContext: a concrete specialisation of GCUBEContext for running gCube Hosting Nodes.
  • GHNClientContext: a concrete specialisation of GHNContext for gCube Hosting Node that are not runnning.

Before discussing each context class in detail, we refine the service model to introduce key context classes from the perspective of the service developer:

Model&contexts.jpg

The figure shows that the GHNContext, the GHNClientContext, and GCUBERemotePortTypeContext are fully implemented by the framework and live outside the boundary of specific service implementations. In contrast, service and port-type contexts fall in the scope of service implementations as specialisations of gCF context classes.

Common Facilities

All gCF contexts offer basic facilities for configuration management and local file management.

The primary form of configuration supported by gCF contexts is name-based lookup of arbitrary objects. As discussed above, the underlying configuration mechanism relies on a dedicated and read-only implementation of the JNDI interface. In particular, gCF contexts act as wrappers of standard JNDI contexts to offer a simplified lookup interface. The underlying JNDI implementation remains opaque to both clients and implementers of context classes. Developers are only exposed to the configuration files used to populate the JNDI implementation wrapped by the contexts. The direct subclasses of GCUBEContext are responsible for establishing conventions on the naming and location of such files, for the definition and documentation of pre-defined configuration properties, and for loading all the configuration properties from the files. As most service developers specialise in turn these subclasses, they need only to author the configuration files.

The basic operation for configuration management is the following:

  • getProperty(name,mandatory?): resolves a configuration property from its name.
An optional flag indicates whether the configuration of the property is mandatory or else is optional (default). The flag is used for error and log management purposes.
String bar = (String) someContext.getProperty("foo");   //lookup optional environment
Foo foo = (Foo) someContext.getProperty("foo",true);    //lookup mandatory resource

As to file management, the gCF contexts offers facilities to access:

  • files stored in the local file system, for reading or writing purposes.
File locations are abstracted over to avoid gHN-specific dependencies and all contexts offer basic backup facilities: transparently to their clients, they create copies of files that are about to be modified and used backup copies whenever the original files are corrupted.
  • files packaged with the context as classpath resources, for read-only purposes.

In both cases, the gCF contexts are agnostic to the content of the files. This may be service-specific configuration that lives outside the standard JNDI framework, or any form of state that is deemed suitable for file storage.

The basic operations for file management are the following:

  • getResource(path): returns a classpath resource from its path.
A relative path is resolved with respect to the context implementation, while an absolute path is resolved directly against the classpath.
InputStream foo = someContext.getResource("resources/foo.properties");            //relative path
InputStream bar = someContext.getResource("/org/acme/resources/bar.properties");  //absolute path
  • getFile(path,mode): returns a File for read or write access.
A write mode induces backups and a read mode (default) relies on backups to recover from failures. In write mode, directories that are specified in the path but do not exist are automatically created, while paths that identify directories are disallowed. Paths are normally to some context-specific root.
File foo = someContext.getFile("foo.txt");              //read mode
File bar = someContext.getFile("bar");                  //read mode on directory
File baz = someContext.getFile("tests/baz.xml",true);   //write mode, may create directory 'tests'

The gHN Context

GHNContext specialises GCUBEContext as the context of the local gHN. The gHN context:

  • exposes the configuration of the gHN and its hosting environment.
This functionality allows service developers to inspect at runtime the environment in which their code is deployed.
  • manages the lifetime of the gHN, from its initialisation to its shutdown and failure.
This functionality supports the internal operation of the gHN and remains transparent to most service developers.
  • mediates between RIs of deployed services.
This functionality supports mutual discovery of RIs and, while it is generically available to all service developers, it is key for the correct operation of the gHN and distinguished Local Services.

Clients obtain the gCF context by invoking the getContext() method of the GHNContext class:

 GHNContext context = GHNContext.getContext();

Note: The facilities for file management that the gHN context inherits from GCUBEContext are meant for internal use and service developers are not encouraged to use them. Service developers can access the file system using the facilities offered by service contexts or port-type contexts.

Note: Some functionality offered by the gHN context is sensitive, and as such it is intended only for internal consumption. An attempt to invoke this functionality from code defined outside authorised namespaces may result in an IllegalAccessException at runtime.

Configuration Management

The gHN exposes the following forms of configuration:

  • descriptive information contained in the gHN profile.
The profile of the gHN is governed by the schema in $GLOBUS_LOCATION/share/schema/gcube/common/core/profiles/node.xsd. The information can be accessed via the GCUBEHostingNode resource returned by the method getGHN().
Iterator<Package> iterator = GHNContext.getContext().getGHN().getDeployedPackages().iterator();
String version = GHNContext.getContext().getGHN().getNodeDescription().getOS().getVersion();
  • configuration related to the implementation of core gCF interfaces.
This includes implementations of discovery, publishing, and remote notification interfaces, among others.

The implementations are obtained by invoking the following method:

  • getImplementation(interfaceclass): returns the local implementation of the interface represented by the given Class object.
ISCLient client = GHNContext.getContext().getImplementation(ISClient.class);
  • statistics and other information related to the hosting environment.
This includes methods such as getFreeSpace), getUptime(), getMemoryUsage(), getCPUInfo(), getLoadStatistics(), and many others (consult the GHNContext documentation for details).
String url = GHNContext.getContext().getBaseURL();
Integer port = GHNContext.getContext().getFreePort();
Map<String,Double> stats = GHNContext.getContext().getLoadStatistics();
This configuration relates to the local operation of the gHN and its relationship with the infrastructure. Some of the configuration elements have dedicated accessors, for convenience or post-processing requirements. Other properties are accessible only with the facilities that the gHN context inherits from GCUBEContext.
GCUBEScope[] scopes = GHNContext.getContext().getStartScopes();
GHNContext.Type type = GHNContext.getContext().getType();
GHNContext.Mode mode = GHNContext.getContext().getMode();
String country = (String) GHNContext.getContext().getProperty("country");

Lifetime Management

For lifetime management purposes, the gHN context models the gHN as the following finite state machine:

GHNStates.jpg

Some of the states of the gHN are operational, in that the gHN can dispatch client calls to RIs of the deployed services, deploy new services, and undeploy currently deployed services. Other states are instead non-operational but characterise the transition of the gHN towards or from operational states. The gHN states can be described as follows:

  • DEPLOYED: this is the state of a gHN that is locally installed but not necessarily running within the current process (or not running at all).
This is a start and non-operational state in which the gHN context determines whether the gHN is running in the current process. If the gHN is not running, this state is also terminal and the gHN context can only be used for configuration management purposes. This mode of operation of the context is called client mode.
Note: In client mode, the gHN context returned by GHNContext.getContext() is an instance of GHNClientContext.
  • STARTED: this is the state of a running gHN that is in the process of initialisation.
This is a non-operational state in which the gHN context initialises the gHN. This involves:
  • loading its configuration.
  • deriving a GCUBEHostingNode resource that models the gHN, either from scratch or from past serialisations of its profile.
  • scheduling periodic updates to the state of the gHN which depends on the local hosting environment.
  • opening local interfaces for management and monitoring (if appropriately configured).
  • READY: this is the state of a gHN in which not all the RIs of the deployed services are operative.
This is an operational state in which some of the deployed RIs may still be in the process of initialisation or may have failed. The gHN enters this state after having triggered the initialisation of all the RIs. It may then transition back to it from after certification, if one of the RIs fails.
  • CERTIFIED: this is the state of a gHN in which all the deployed RIs are operative.
This is an operational state that marks the absence of problems on the gHN.
  • UPDATED: this is the state of a gHN that has changed some its properties.
This is a temporary state in which the gHN context:
  • notifies all interested clients of the change.
  • serialises an up-to-date version of the gHN profile.
Note: One distinguished consumer of update events is the GHNManager, the Local Service that is responsible for publishing the updated profile of the gHN in the infrastructure.
Upon successful completion of these activities, the gHN context reverts the gHN to its previous state. The gHN transitions to this state in the following cases:
  • when it transitions to one of its public states: CERTIFIED, DOWN, and FAILED.
  • in response to key lifetime event, such as the addition and removal of scopes.
  • after the periodic regeneration of the gHN profile.
  • DOWN: this is the state of a gHN that is about to terminate execution without having experienced a failure.
This is a non-operational state in which the gHN is about to terminate the current process, often to restart immediately after the deployment of new services.
  • FAILED: this is the state of a gHN that is about to terminate execution because it has experienced a failure.
This is a non-operational state in which the gHN is about to terminate the current process.
Note: Only privileged clients and the gHN itself can trigger state transitions (cf. setStatus()). All clients however can inspect the current state of the gHN, either asynchronously, via notification of state transitions as shown above, or synchronously, using the getStatus() method:
if (GHNContext.getContext().getStatus()==Status.CERTIFIED) {...}

Event Management

The gHN context acts in the role of a producer and consumer of events.

As a consumer, it subscribes with all the RIs that register their presence with it during their own their own initialisation (registerService()).

Note Any client of the gHN context can then access the service context of some or all the RIs that have registered (cf. getServiceContext()). Any service, in particular, can rely on this functionality to interact with other, co-deployed services without having static dependencies on them.
GCUBEServiceContext ctxt = GHNContext.getContext().getServiceContext("...service class...","...service name...");
Note One distinguished gCF component, the GCUBEHandler, relies on getServiceContext() to block calls made to RIs that are no longer or not yet operative, but also to propagate the scope of the call to their service contexts.

As a producer, the gHN context can notify clients of the occurrence of two different classes of events.

The first class of events relates to the lifetime of the gHN. In particular the gHN defines:

  • a number of GHNTopics, including RIREGISTRATION, READY, UPDATED,SHUTDOWN.
  • a generic GHNLifetTimeEvent that carries en empty payload, and a GHNRIRegistrationEvent specialisation of GHNLifetTimeEvent which carries the service context of the registered RI as its payload.
  • a pre-defined consumer implementation, GHNConsumer, that prospective consumers can derive by implementing the event-specific callback of interest.
  • methods to subscribe for and unsubscribe from the occurrence of events of interest (subscribeGHNEvents(GHNConsumer,GHNLifetimeEvent*), unsubscribeGHNEvents(GHNConsumer,GHNLifetimeEvent*)).
class MyConsumer extends GHNConsumer {

  /**{@inheritDoc} */
  synchronized protected void onRIRegistration(GHNRIRegistrationEvent event) {
     
     GCUBEServiceContext ctxt = event.getPayload(); 
     ...

  }

 /**{@inheritDoc} */	
  synchronized protected void onGHNReady(GHNLifeTimeEvent event) {...}

}

...

GHNContext.getContext().subscribeGHNEvents(new MyConsumer(), GHNTopic.RIREGISTRATION, GHNTopic.READY);
GHNContext.getContext().subscribeGHNEvents(new MyConsumer()); ///subscribe to all events

The second class of events related to the renewal of credentials that RIs might need to operate in a secure infrastructure. In particular, the gHN context acts as a mediator between the RIs and the RI of distinguished Local Service, the Delegation service, which is responsible for arranging the periodic renewal of credentials with remote Security Services (cf. security management). The process subsumes the following steps:

  • RIs subscribe with the gHN context to request credentials (subscribeForCredential()).
  • the RI of the Delegation also subscribes with the gHN context to be notified of credential renewal request (subscribeForCredentialRequest()).
  • When credentials are delivered by the infrastructure, the RI of the Delegation service asks the gHN to pass them on to the RI which originally requested them ((delegateCredentials())).

The mediation of the gHN context is based on dedicated topics (CREDENTIAL_REQUEST,CREDENTIAL_DELEGATION) and events (CredentialRequestEvent,CredentialDelegationEvent). The gHN context pre-defined consumer implementations that prospective consumers can derive by implementing the event-specific callback of interests (CredentialConsumer,CredentialRequestConsumer). In some special cases service developers may wish to extend CredentialConsumer, but normally they won't need to as - as discussed below - the context of their services will do it on their behalf.

Service Contexts

GCUBEServiceContext specialises GCUBEContext as the context of a service and its RI. The specialisation remains abstract, and developers must specialise it further for their services. By doing so, developers obtains a component that:

  • exposes the configuration of the service and its RI.
This functionality allows service developers to inspect the properties of the service and its RI at runtime.
  • manages the lifetime of the RI, from its initialisation and staging to its updates and failure.
This functionality supports the correct operation of the RI within the infrastructure and can be extended by service developers.
This functionality supports the loosely-coupled propagation of scope and credentials across components of the service implementation.

To specialise GCUBEServiceContext, developers must derive it and implement the following method:

Developers are also responsible for the implementation of the service context as a singleton class. The recommended approach can be exemplified as follows:

public class MyServiceContext extends GCUBEServiceContext {

   private static MyServiceContext singleton = new MyServiceContext();
   
   private MyServiceContext(){}

   public static MyServiceContext getContext() {return singleton;}

   /** {@inheritDoc} */
   protected String getJNDIName() {...}

}

Configuration and File Management

The service context exposes the following types of configuration:

  • descriptive information contained in the service profile.
The profile of the service is governed by the schema in $GLOBUS_LOCATION/share/schema/gcube/common/core/profiles/service.xsd. For convenience, the service context exposes some profile information with dedicated accessors. The rest is available via the GCUBEService resource returned by the getService() method.
String id = MyServiceContext.getContext().getID();
String name = MyServiceContext.getContext().getName(); 
List<Dependencies> dependencies = MyServiceContext.getContext().getService().getDependencies();
  • descriptive information contained in the RI profile.
This information is available via the GCUBERunningInstance resource returned by the getInstance() method.
Map<String,GCUBEScope> scopes = MyServiceContext.getContext().getInstance().getScopes();
List<Endpoints> epList = MyServiceContext.getContext().getInstance().getAccessPoint().getRunningInstanceInterfaces().getEndpoint();
Calendar time = MyServiceContext.getContext().getInstance().getDeploymentData().getActivationTime();
String data = MyServiceContext.getContext().getInstance().getSpecificData();
GCUBEScope[] scopes = MyServiceContext.getContext().getStartScopes(); //pre-defined binding
Foo foo = MyServiceContext.getContext().getFoo();                     //accessor specific to user-defined binding 
Bar bar - (Bar) MyServiceContext.getContext().getProperty("bar");     //general access to user-defined binding 

As to file management, the service context offers the following methods:

  • getFile(): overrides the method in GCUBEContext so as to target the configuration directory of the service.
The contents of this directory may outlive the current process but not the static or dynamic redeployment of the service. The developer should rely on this method only to store and access any kind of information that may be needed by the service in the scope of the current process.
  • getPersistentFile(): retains the same usage model of getFile() but targets a directory under the storage root of the gHN dedicated to longer-lived service-specific storage.
The contents of this directory outlive the current process and the redeployment of the service in the same or a different gHN.

Lifetime Management

For lifetime management purposes, the service context models the RIs as the following finite state machine:

RIStates.jpg

The state of the RI can can be described as follows:

  • DEPLOYED: this is the state of a RI that is activated but has not yet completed its initialisation.
This is a start and non-operational state in which the service context initialises the RI. This involves:
  • loading the JNDI configuration of the service.
  • deriving a GCUBEService resource from the profile of service.
  • deriving a GCUBERunningInstance resource, either from scratch of from past serialisations of the RI profile.
  • initialising the security manager that handles service credentials on behalf of the RI. The security manager is identified from the JNDI configuration of the service. In the lack of explicit configuration, the service context initialises a GCUBESimpleServiceSecurityManager.
  • initialising the scope manager that handles scope information on behalf of the RI.
  • initialising the persistence manager that manages the remote persistence of the state of the RI, if one is specified in the JNDI configuration of the service.
  • initialising the plugin manager of the service, if one is specified in the JNDI configuration of the service.
  • registering with the gHN context.
The successful completion of these activities triggers a transition of the RI to the INITIALISED state.
  • INITIALISED: this is the state of a RI that is fully initialised but not yet ready to process client requests.
This is a non-operational state in which the service context stages the RI. Staging requires the successful completion of the following parallel activities:
  • raising a request for credentials with the gHN context, if any are needed by the RI when it operates in a secure infrastructure, and waiting for their delivery.
  • recovering any state that the RI might have previously stored in the infrastructure from the current or another gHN (in case the RI has been dynamically redeployed).
  • waiting for any RI that is a logical dependency of the service READY or FAILED, assuming that the dependent RI has been activated and does not depend in turn on this RI (i.e. identifies a cyclic dependency). We refer to this task as co-dependency synchronisation and we perform it to ensure that RIs will always find their dependencies ready to use, even when they are co-deployed on the same gHN.
In parallel, the service context registers the RI with the gHN so as to be notified in occasion of:
  • GHNTopic.SHUTDOWN events: when this event occurs, the RI transitions to the state DOWN.
  • GHNTopic.REMOVESCOPE events: when this event occurs, the RIs aligns its scopes with the scopes of the gHN and removes itself from the scope from which the gHN has been removed (if it was in it in the first place).
The successful completion of these activities triggers a transition of the RI to the READY state.
  • READIED: this is the state of a RI that is fully operative within the infrastructure.
This is the operational state in which the RI can service incoming requests.
Note: A RI which is not this state will not receive calls. A distinguished gCF component, the GGCUBEHandler will intercept all calls and refuse to forward them (see also the lifetime of the gHN context for further information.
  • UPDATED: this is the state of a RI that has changed its profile.
This is a temporary state in which the service context:
  • notifies all interested clients of the change.
  • publishes an updated RI profile in the infrastructure;
Upon completion of these activities, the service context reverts the RI to its previous state. The RI transitions to this state in the following cases:
  • when it transitions to one of its public states: READIED, FAILED, and DOWN.
  • in response to key lifetime events, such as addition and removal of scopes.
  • STATECHANGED: this is the state of a RI that has changed its persistent state.
This is a temporary state in which the service context notifies all interested clients of the change before returning to its previous state. The RI may transition to this state from the INITIALISED and READY states and does so when the method notifyStateChange() is explicitly invoked by clients.
Note: the persistence manager of the RI is the primary consumer of state change events. Upon notification, the manager will attempt to store the updated state of the RI.
Note: persistence delegates of stateful port-types are distinguished producers of state change events. They invoke notifyStateChange() in correspondence with the serialisation of stateful resources.
Note: any client may invoke notifyStateChange() to notify of a change in the persistent state of the RI. A common case is when the client has successfully stored a file 'obtained' by invoking the method getPersistentFile().
  • DOWN: this is the state of a RI managed by a gHN that has experienced failure or is about shutdown.
This is a non-operational state in which the RI cannot satisfy client requests. Upon transitioning to this state, the service context notifies all interested clients.
  • FAILED: this is the state of a RI that has experienced a failure.
This is a non-operational state in which the RI cannot satisfy client requests. Upon transitioning to this state, the service context notifies all interested clients.

Event Management

All the state transitions of a RI subsume a callback on the service context that the developer can implement in its specialisation of GCUBEServiceContext. The available callbacks are: onInitalisation(), onReady(), onUpdate(), onStateChange(), onShutdown(), onFailure(). Most transitions are conditional to the faultless execution of the corresponding callback.

/** {@inheritDoc} */
protected void onReady() throws Exception {
  if (...) throw new Exception();           //would fail the transition to READY
}

Other components of the service implementation - and in fact any component that has a reference to the service context - can be notified of state transitions by subscribing with the RI for the occurrence of lifetime events. In particular, the service context defines:

  • a number of RILifetimeTopics, including DEPLOYED,INITIALISED,READY,FAILED,UPDATED,STATECHANGE,DOWN.
  • a generic RILifetimeEvent event that carries the service context as its payload.
  • a pre-defined implementation of a Consumer that prospective consumers can derive by implementing the event-specific callback of interest.
  • methods to subscribe for and unsubscribe from the occurrence of events of interest (subscribeLifeTime(Consumer,RILifetimeTopic*),unsubscribeLifeTime(Consumer,RILifetimeTopic*)).
class MyConsumer extends Consumer {

  /**{@inheritDoc} */
  synchronized protected void onReady(GHNRIRegistrationEvent event) {
     
     GCUBEServiceContext ctxt = event.getPayload();
     ...
  }

 /**{@inheritDoc} */	
  synchronized protected void onFailure(GHNLifeTimeEvent event) {...}

}

...

MyContext.getContext().subscribeLifeTime(new MyConsumer(), RILifetimeTopic.READY, RILifetimeTopic.FAILED);
MyContext.getContext().subscribeLifeTime(new MyConsumer());  //subscribes to all lifetime topics

Scope and Security Management

The service context implements the GCUBESecurityManager interface and the GCUBEScopeManager interface, thereby serving as a thread-indexed repository of scope information and service credentials for the whole service implementation. Accordingly, developers can pass their service context into all the methods of gCF that expects either type of manager, e.g.:

ISClient client = GHNContext.getContext(ISClient.class);
GCUBERIQuery query = client.getQuery(GCUBERIQuery.class);

...prepare query...

client.execute(query,MyContext.getContext()) //service context used as a scope manager

The service context implements scope the GCUBESecurityManager and the GCUBEScopeManager interfaces by delegating to internal implementations of the interfaces. The following methods in GCUBEServiceContext expose the internal implementations to subclasses (i.e. they are protected methods):

  • getSecurityManager(): returns the internal security manager.
  • getScopeManager(): returns the internal scope manager.

For security management, the service context also complements the interface with the following convenience methods:

  • useCallerCredentials(thread?): If security is enabled, it indicates that outgoing calls in a given thread must use the credentials associated with the incoming call. It has no effect otherwise. If the thread parameter is omitted, an invocation of this method is equivalent to:
MyContext.getContext().useCredentials(MyContext.getContext().getCallerCredentials())</code> 
or, if the thread is specified:
MyContext.getContext().useCredentials(thread, MyContext.getContext().getCallerCredentials())</code>

For scope management, the service context does not add convenience methods but enforces some pre-conditions before delegating to the inner scope manager. In particular:

  • setScope(scope), setScope(thread,scope), and prepareCall(remote,class,name,scope?) reject any scope that is not compatible with those of the RI.

For similar reasons, the service context adds pre-conditions and post-conditions to the methods of the inner GCUBERunningInstance that add or remove scopes. In particular:

  • addScope(scope*) filters out any scope that is not compatible with the scope of the gHN context and the scope of the service of the RI. Furthermore, it triggers a transition of the RI to the UPDATED state if some scope has actually been added post-filitering.
  • removeScope(scope*) unpublishes the RI from all the scopes from which it has been removed and triggers a transition of the RI to the UPDATED state.

Finally, the service context can expose the scopes with which the RI was first activated on the gHN. In particular:

  • getStartScopes(): returns the scopes configured for the RI, or the start scopes of the gHN if no specific scopes were configured for the RI.
The start scopes for the RI can be configured by including the following environment in the global section of the JNDI configuration file:
<environment name="startScopes" value="/some/scope,/some/other/scope,.." type="java.lang.String"/>

where the value of the environment is a comma-separated list of well-formed and gHN-compatible scope expressions.

PortType Contexts

GCUBEPortTypeContext specialises the GCUBEContext as the context of a single port-type of the service. GCUBEStatefulPortTypeContext specialises further GCUBEPortTypeContext as the context of a stateful port-type.

GCUBEPortTypeContext and GCUBEStatefulPortTypeContext are abstract and developers must specialise them further for their port-types. By doing so, they obtain components that:

  • expose the configuration of the service which relates specifically to a port-type rather than the service as a whole.
This functionality allows service developers to inspect the properties of the port-type at runtime.
  • manage the lifetime of a port-type in the broader context of the RI lifetime.
This functionality supports the correct operation of the port-type and can be extended by service developers.

Developers that derive GCUBEPortTypeContext or GCUBEStatefulPortTypeContext must implement the following methods:

  • getNamespace(): returns the namespace of the port-type, as specified in its WSDL.
  • getServiceContext(): returns the context of the service.

Like with the service context, developers are responsible for the implementation of port-type contexts as singleton classes. The recommended approach is the same:

public class MyPortTypeContext extends GCUBEPortTypeContext {

   private static MyPortTypeContext singleton = new MyPortTypeContext();
   
   private MyPortTypeContext(){}

   public static MyPortTypeContext getContext() {return singleton;}

  /** {@inheritDoc} */
   public MyServiceContext getContext() {...}

   /** {@inheritDoc} */
   protected String getJNDIName() {...}

   /** {@inheritDoc} */
   protected String getNamespace() {...}

}

Configuration and File Management

All port-type contexts expose the following forms of configuration:

Foo foo = MyPortTypeContext.getContext().getFoo();                     //accessor specific to user-defined binding 
Bar bar - (Bar) MyPortTypeContext.getContext().getProperty("bar");     //general access to user-defined binding 
WSDDService ddescriptor = MyPortTypeContext.getContext().getDeploymentDescriptor();
ServiceSecurityDescriptor sdescriptor = MyPortTypeContext.getContext().getSecurityDescriptor();
  • the endpoint of the port-type.
EndpointReferenceType epr = MyPortTypeContext.getContext().getEPR();

In addition, stateful port-type contexts expose configuration and utility methods related to the management of the stateful resources associated with the port-type (cf. State Management):

  • getRPDName(): returns the name of the Resource Property Document (RPD) of (public) stateful resources.
  • getPublicationProfile(): returns the publication profile of (public) stateful resources.
  • getResourceLifeTime(): returns the lifetime of stateful resources (in seconds).

These methods reflect mandatory elements of the port-type configuration and are used mostly by gCF. More immediately relevant to developers are the following methods:

  • getWSHome(): returns the home of public stateful resources.
  • getHome(): returns the home of private stateful resources.
  • makeKey(): returns a new qualified key for stateful resources.

As to file management, all port-type contexts delegate the methods getFile() and getPersistentFile() inherited from GCUBEContext to the corresponding methods of the service context. Port-types thus share configuration directory and persistent root with their service.

Lifetime Management

The life-time of a port-type is regulated by the lifetime of the RI. In particular, all port-types:

  • register a RI Consumer with the service context (discussed here)
This allows port-types to perform basic lifetime operations in sync with the RI.
  • define callbacks for RI lifetime events that echo those defined by Consumer: onInitalisation(), onReady(), onUpdate(), onStateChange(), onShutdown(), onFailure().
This gives a convenient place for developers to add port-type specific reactions to lifetime events of the RI.