Developing a gCube service is far more than writing code. Developers are expected to produce a number of files to configure the service and to describe it from a variety of perspectives and for a variety of purposes. For uniformity, we think of these non-programmatic components of the service implementation as the configuration of the service.
What does needs configuration, and what for?
- the service as a whole, so that it can be correctly managed by the infrastructure.
- This is a public form of configuration that identifies the service, its requirements, its dependencies, and its implementation components. The result is called the service profile. As services share profiling requirements with all the other types of gCube resources, the service profile is described elsewhere, in the broader context of the gCube system. Here, we observe that:
- developers are required to store the service profile in file called
- the schema that governs its definition can be found in
$GLOBUS_LOCATION/share/schema/gcube/common/core/profiles/service.xsdand used for validation purposes.
- developers are required to store the service profile in file called
- the interface of the service, so that the service can be correctly used by clients.
- This is a public form of configuration that describes the operations that can be invoked on the service and how to invoke them. We use standard WSDL for the purpose, but notice that the build process supported by gCore:
- expects separate WSDL definitions for multiple port-types.
- raises specific naming conventions, both in the WSDL definitions and for the files in which they are stored.
- We refer to the Primer for an illustration of the conventions.
- the security requirements of the service, so that the service can be safely used by clients.
- This is a public form of configuration that describes the authentication and authorisation requirements of the service. The result is the security descriptor of the service.
- the actual implementation of the service, so that the service will exhibit the required runtime behaviour.
- This is the primary form of local configuration that describes all the choices that were not or could not be made in the code. The result is the JNDI configuration of the service.
- the process used to build the service, so that the service can be packaged correctly for deployment.
- This is a local form of configuration that customises the process that yields the software artifact required for deployment. The result is the build configuration of the service. The build configuration is not part of the service implementation, and thus it is not included in the very artifact it helps to produce. While gCF makes no assumption on the build process, gCore supports a particular build approach and requires a particular configuration file for it. We illustrate these requirements in the Primer, and do not discusse them further in this Guide.
- the process used to deploy the service, so that the service can be correctly managed by the gHN.
- This is a local form of configuration that provides the information required by the gHN to activate the service and dispatch client calls to it. The result is the deployment descriptor of the service.
Profile, WSDL definitions, security decriptors, JNDI configuration, and deployment descriptor are all part of the software artifact that is deployed on a gHN. After service deployment, its configuration components are collected in a service-specific directory under
$GLOBUS_LOCATION/etc. We call this directory the configuration directory of the service.
The JNDI Configuration
In gCF, developers configure their code by avoiding to create some of the objects they need. Rather, they lookup those objects from a configuration file called
deploy-jndi-config.xml where the bindings between names and objects are defined. This allows them to bind the same name to different objects at different times, without changing the code that uses them.
We discuss later how gCF supports object lookup, but we notice here that it builds upon a local implementation of the JNDI interface for naming services, hence the name of the configuration file and our speaking of the JNDI configuration of the service.
The syntax of the JNDI configuration file is based on XML, and its definition is lifted from lower-level technologies. We can summarise it as follows:
- object bindings are grouped into named
services are occur below a
<?xml version="1.0" encoding="UTF-8"?> <jndiConfig xmlns="http://wsrf.globus.org/jndi/config"> <service name="...">...bindings...</service> <service name="...">...bindings...</service> </jndiConfig>
services identify sections of the service configuration that are dedicated to individual port-types. The only exception is a distinguished section, called the global section, which is used to collect cross port-type bindings and is thus associated with the service as a whole. The global section is mandatory. Port-type sections are also mandatory if they relate to stateful port-types.
- the name of configuration sections must be unique across all services deployed on the gHN; since we cannot tell in advance what services will be co-deployed with any given one, it must in fact be globally unique:
- For port-type sections, the name must match the name of the port-type as defined in the deployment descriptor, and thus coincide with the relative endpoint of the port-type.
- For the global section the naming convention is to rely on the namespace of the service implementation for uniqueness. In particular, the global section can be named after the main package of the service implementation, i.e. the first package that ensures uniqueness of naming to all the implementation components
<?xml version="1.0" encoding="UTF-8"?> <jndiConfig xmlns="http://wsrf.globus.org/jndi/config"> <!--global section --> <service name="/org/acme/sample">...bindings...</service> <!-- port-type section --> <service name="org/acme/sample/porttypeone">....bindings...</service> </jndiConfig>
Finally, there are two types of bindings:
- environments: these are bindings of names to values of a set of pre-defined classes, such as
- An environment is an empty element named
nameattribute names the bound value and the
typeattributes gives the fully qualified name of its class.
<environment name="foo" value="bar" type="java.lang.String" />
- resources: these are bindings of names to to values of custom classes.
- A resource is a complex element named
typeattributes, and a single
resourceParamschild element. The attributes retain the semantics they have in environments, except that
typecan identify any class in principle. The
resourceParamselements contains in turn one ore more
parameterelements, where each
nameelement and a
valueelement. One of the parameters must have a name of
factory, and its value must be the qualified name of a class capable to generate a value of the resource's
typeand to initialise it with the values of the remaining parameters (as
<resource name="foo" type="org.acme.Foo"> <resourceParams> <parameter> <name>factory</name> <value>org.acme.FooFactory</value> </parameter> <parameter> <name>bar</name> <value>baz</value> </parameter> </resourceParams> </resource>
- All the pre-defined resources use the
globus.wsrf.jndi.BeanFactoryfactory class. This is a generic factory that can instantiate any class that defines setter methods that match all the other resource parameters (e.g.
setBar(String)). Developers can defined their own factories, though the
BeanFactoryis expected to satisfy most resource configuration requirements.
- gCF mandates the presence of at least one standard environment in the global section of all services. The environments binds the name
configDirto the name of service's configuration directory, though the latter is represented by a placeholder (
@config.dir@) which is automatically resolved at deployment time.
<environment name="configDir" value="@config.dir@" type="java.lang.String"/>
- gCF pre-defines many other environments and resources. We will introduce them when we discuss the role of the bound objects in the service implementation.
The Deployment Descriptor