Access Keys:
Skip to content (Access Key - 0)

Introduce

Introduce 1.4 Developers Guide

Contents

Preamble


Before you decide to build grid services you should at least be familiar with basic grid service architecture and also that of stateful grid services if you plan to create asynchronous services and/or stateful services. To read more about grid service architecture and grid middleware to refresh your memory or get basic understanding, please read some of the following basic information:
Overview Papers on Grid Computing
Globus Best Practices

Overview


Introduce Overall Service Creation Process
The Introduce toolkit is designed to support the three main steps of service development:

  1. Creation of Basic Service Structure - The service developer describes at the highest level some basic attributes about the service such as service name and service's WSDL namespace. Once the user has set these basic service configuration properties, Introduce will create the basic service implementation to which the developer can then add application-specific methods and security options through the service modification step.
  2. Service Modification - The modification step allows the developer to add, remove, and modify service methods, properties, resources, service contexts, and service-/method-level security. In this step, the developer can create a strongly typed service interface using well-defined, published schemas, which are registered in a system like the Global Model Exchange (GME), as the type definitions of the input and output parameters of the service methods. Once the operations are added to the service, the developer will then be able to add the logic which implements the methods.
  3. Deployment - The developer can deploy the service which has been created with Introduce to a Grid service container (e.g., a Globus, Tomcat, or JBoss service container). A service developer can access the functions required to execute these three steps through the Graphical Development Environment (GDE) of Introduce. The runtime support behind the GDE functionality is provided by the Introduce engine, which consists of the Creation Engine, Synchronization Engine, and Service Deployer components. The toolkit provides an extension framework that allows Introduce to be customized and extended for custom service types and discovery of custom data types. In the following sections, we describe the software prerequisites, the Introduce Graphical Development Environment, the Introduce Engine, and the Introduce Extension Framework in greater detail.

Software Prerequisites

Changes from Introduce 1.3


  • Fixed circular schema bug in filesystem data type discovery tool.
  • Fixed bug in updater that was looking in the wrong place for introduce.extension.properties and template when trying to set the patch version.
  • Added new build-deploy.xml to fix problems with un-deployments.
  • New heuristic for schema imports:
    • If Introduce imports the schema it will only set namespace excludes or type maps for that schema.
    • If it is desired to do this for the schemas which that schema imports, then those schemas must be added and handled appropriately and individually. This is different from prior versions.
    • Prior versions of Introduce would simply exclude any namespace that was imported from a schema for which stub generation was set to false. However this is not always the desired behavior.
  • Added button to enable user to control whether or not stubs will be generated for imported schema.
  • Added to Introduce model so that services and methods can have extension data added to them.
  • Added an Introduce log viewer component to the GUI.
  • Added new extension type called INTRODUCE_GDE which enables adding grape components to the UI through extensions.
  • Added another subscribe method to base clients that takes in a NotificationCallback so that clients do have to overload the deliver method if they want to implement a notification callback on their own or use another.
  • Complete re-factor of authorization within Introduce. Introduce now has an Authorization Extension that enables authorization plugins to the Introduce-Generated PDP. This is much cleaner and removes the hard-coded GridGrouper and CSM support and now opens the doors to other authorization plugins to be generated rapidly.
  • Added ability for Introduce-generated clients to have a setAnonymousPreferred. This will enable control of whether the client will attempt to connect anonymously or not. The default is set to true and can now be changed programmatically.
  • Added to Introduce service extension so that service extension providers can plug a deployment validator into the service that will be executed before the service is deployed. This will enable service extension providers to validate that the service is properly configured prior to deployment.

Known Issues

  • Introduce generated services fail to build if $ANT_HOME or $GLOBUS_LOCATION contains spaces in the path

Introduce Graphical Development Environment


Introduce Graphical Development Environment (GDE)
The Introduce Graphical Development Environment (GDE) can be used to create, modify, and deploy a grid service. It is designed to be very simple to use, enable using community accepted data types, and provide easy configuration of service metadata, operations, resources, and security. It also allows customized plugins to be added for such things as discovering data types from grid repositories and for creating custom service style design templates.
The Introduce GDE contains several screens and options for the service developer to 1) create a new service, 2) modify an existing service, 3) discover and use published data types in order to create strongly typed service methods, and 4) deploy the service.

Launching Introduce


Introduce Environment Variables

You may want to configure Introduce to pass Java command-line arguments to Introduce and to other processes that Introduce creates during execution. An example scenario is the need to modify the heap or stack size used for these processes. Introduce utilizes the ANT_OPTS environment variable to hold your custom settings. Just set the contents of ANT_OPTS to include system properties that you would like passed to the VM. For example:

ANT_OPTS=-Xms256m -Xmx1024m

Set ANT_OPTS in your environment before launching Introduce.

Introduce Configuration Properties

Some low-level features of Introduce can be configured by modifying the introduce.properties file found in the conf directory of the Introduce project. Specifically this might be useful for maintaining multiple configurations of Introduce on the same machine with one installation, or for changing the timeout allowed for the Axis WSDL2Java process to complete. The timeout for WSDL 2 Java can be changed by editing the line in the properties file which reads introduce.wsdl2java.timeout.ms=90000 to a different value. Note this is the time in milliseconds which Introduce will wait for WSDL 2 Java to complete processing. Increasing this timeout may be useful when schemas with a large number of types and elements is used, or when imported schemas and wsdls must be resolved over a slow internet connection.

Launching from the Command Line

Introduce can be launched from the command line via ant. You will simply need to open a terminal and change directory to the cagrid installation directory execute:

 ant introduce 

Service Creation

Introduce GDE Service Creation Component
The service creation component, shown above, enables the developer to create a new grid service. Using the creation interface, the service developer can provide this information about the service:

  • Select a directory for your service - Select or enter the directory in which the grid service will be generated. If you enter the name of a directory that already exists, a caution icon will appear, as shown in the above image, to warn you that the directory's entire contents will be replaced.
  • Enter a name for the service - Enter the name to use for generating the service. The service name must be a valid java identifier and begin with an uppercase letter.
  • Enter a Java package for the generated code - Enter the base package name to use for generating the grid service source code.
  • Enter a namespace for the generated WSDL - Enter the namespace to use for the service's WSDL.

The developer also has the ability to add service extensions. A service extension is an Introduce plugin that is designed to add customizations to the service. For example, service extensions might add pre-defined operations, resources/resource properties, or security settings. They enable the development of custom service types with predefined methods, which must be implemented. They also enable Introduce to run the custom code implemented in the plugin, which makes modifications to the underlying service being created. This capability allows the specialization of Introduce to support domain-specific common scenarios, further abstracting the individual service developer from responsibilities related to the deployment of grid technologies in a production environment. Once the information and extensions (if any have been selected) have been entered, the user will select the create button. Once the create button is selected, the Introduce creation engine will begin generating the service. After the service is generated, it will be compiled and the Modification component will be displayed. For a list of available caGrid Service extension and their documentation, please look here.

Service Modification

Service modification can be performed on any new or previously modified Introduce-generated service. The service developer can perform a series of operations in order to begin to customize the grid service or modify the existing grid service. The overall flow in the modification of a grid service is to first use the namespaces tab to be sure that all the data types that are desired to be used in the grid service have been selected and added to the service. Next the service can choose to either add/remove or modify operations, metadata in the form of resource properties, service properties, security setting, and service contexts.

The following sections will describe in detail how each of the components of the modification viewer can be used to modify the grid service to achieve desired functionality. By selecting the "Modify Service" button on the main menu, a prompt will appear to enable choosing the service to be modified. Once the desired directory containing the service to be modified is selected, the modification viewer component will be launched. The modification viewer contains 6 main areas where modifications can occur on the main service:

Data Types

Introduce GDE Service Modification Component

The first task in the modification of a grid service is to discover the data types that are desired to be used as the input and output types of methods of the service and the data types for describing the resource properties of the service. Adding a data type to the service is equivalent to copying schemas into the schema location of the service and importing the schemas into the WSDL file so that the types can be referenced by the service. This is done via the "Types" tab of the Graphical Service Modification Environment. This tab shows the current types the service is using and provides access to the data type discovery components (such as the Mobius GME) for selecting and configuring additional types.

The "Import Data Types" frame enables several types of ways to locate data types and bring them into the service. Currently, there are two main discovery mechanisms (Globus, and File System) that come with Introduce, however, this is extensible via the Discovery Extension described in the Extensions section. For a link of available Data Type Discovery Extensions and their documentation, please look here.

Once a set of data types from a namespace is brought into the service, users have the ability to describe how these data types will be mapped into their respective Java classes. This can be done automatically by Introduce via Axis. By default, Axis will create new JavaBeans for each data type and also provide a serializer and deserializer for those objects. If, for example, a set of objects already exists for this particular data type, then users can decide to provide their own classes and serialization/deserialization factories.

Importing Data Types

Using the Introduce GDE, developers can obtain the data types they want to use for operation input parameters and return types from any data type discovery plugin. Utilizing common and standard data types, which are defined outside of any application-specific service, enables the creation of strongly typed grid service interfaces. This increases service-to-service interoperability. Once a data type is chosen through the GDE, the data type definition is retrieved, written into the schema/<service_name> location of the service, and imported for use in the service WSDL description so that JavaBeans can be generated and the data types can be programmatically used.
The Introduce toolkit comes with a set of pre-installed discovery plugins, such as the basic file system browser, which can be used to locate and import schemas.

When importing a data type, there are several options of where to acquire the data type definitions. Introduce comes with the following built-in data type definition tools. However, this is a pluggable area of Introduce.

Once a data type is imported using an import tool, the data type can be customized for the generation of JavaBeans. If you select data type on the left you will see in the lower left panel that the namespace and package name have been listing. This is called the namespace to package map. This determines the package name of the JavaBeans that are created for the data type. Feel free to alter the package name if the Introduce-suggested package name does not work well.

  • File System Data Type Importing
    The File System tab of the Import Data Types Panel enables developers to load in schemata that contain the data types for which they wish to use the service from the local filesystem. The developer can browse to choose the schema they wish to import and the click the add button. Once the add button is clicked, the schema and any locally included or imported schemata will be copied to the services schema location in the schema/<service name> directory.
  • Globus Data Types Importing
    The Globus Data Types extension enables the developer to import schema from the Globus toolkit into their service. Such schemas might include the various WS-* specification base types. There is a drop-down menu containing a list of the available schemata from the current installation of the Globus Tooolkit. Once a namespace has been selected and the add button has been selected then the schema will be added to the service's available data types list.
Schemata Must Specify a Target Namespace
Introduce requires each schema that it uses to specify a targetNamespace attribute. If a schema does not have a targetNamespace attribute, then introduce will produce an error message.
Re-Importing a Modified Data Type

Introduce will enable re-importing of a data type if the developer wants to re-import a particular schema which may have been modified or extended. In order to do this you must make sure the "Namespace Type Replacement Policy" configuration setting in the Introduce "Configuration-->Preferences" menu is set to "warn". Once this is done, you can browse back to the data model and import it again. Re-importing the data type is a simple way to clear out any custom package names, class names, or serialization configuration you might have done on the schema. It also allows the developer a chance to make changes to the schema and reload it into Introduce with those changes.

Using Custom or Pre-Existing JavaBeans

Once a namespace and corresponding data types have been imported into the service, each data type can be further customized. For a particular data type, the developer can choose to use a Custom JavaBean that already exists instead of having Introduce create the JavaBeans for the service. This can be accomplished by selecting the Configure Types tab in the Types tab and then the + button beside the Customize Bean label. This will drop down the customization panel for that particular data type. In this panel, to support using a custom bean for the selected data type definition, the developer must fill out the three fields: the classname of the bean to be used (Note: make sure the package name above matches the package name being entered for the custom beans classname), the deserializer factory class, and the serializer factory class. For more information on using custom serialization or what it means to be a custom bean, please refer to the Globus 4.0 documentation on type mapping.

Services

The services tab of the GDE is the main tab for editing the service and the service contexts associated with this service. It contains a tree which shows all the services, or service contexts, that are part of the service, their methods, and their resource properties. This tree is the main view of the services which will be deployed as part of a deployment of the Introduce service. The developer has the ability to add new service contexts, add/remove/modify operations on a particular service, and add/remove/modify resource properties of a particular service. A service context is just another service that is being built with this service. The services are deployed together as a bundle and share the same source tree and libraries. This makes it easy to compose services that utilize each other. An example of this would be to create services which create resources in a factory pattern, and then hand pointers to those resources off to services which manipulate them.

Introduce GDE Services View

Modify the Service

Once in the tree view of the Services tab, you can right-click on any service and select the Edit button. This will pop up a window, like the image below, that will enable the user to configure the service context. From this pop-up window, the resource framework options can be added or removed, service level security can be configured, and a description of the service can be added.

Resource Framework Options

The resource framework options for a service will add or remove a particular type of functionality to the service resource. The supported resource framework options for this release of Introduce are as follows:

  • Custom - Enables the user to provide thier own implantation of the resource class.
  • Singleton - The service will only have one instance of the resource.
  • Lifetime - The resources created by this service will support the WS-Lifetime specification and therefore the service will implement the setTerminationTime and destory operations as part of its WSDL. These operations allow clients to specify when the resource should be destroyed, and to preempt that process to discard an unneeded resource, respectively.
  • Persistent - The resources created by this service will automatically persist themselves, including resource properties and registered notification consumers, to the file system so that if the container is restarted or inadvertently dies, they will come back to life once the container is up and running again.
  • Secure - The resources will implement SecureResource and therefore have the getServiceSecurityProvider so that they can provide a security descriptor for each particular instance of the resource. Management of the service security provider is provided by Introduce using the Security tab of the modification interface.
  • Notification - The resources created by this service will automatically support the WS-Notification specification, and therefore the service will implement the subscribe operation in its WSDL. The client will have operations to make subscriptions and utilize notifications. Notifications allow the server to "call back" to the client when changes occur on a resource property.
  • Resource Property Access - The resources will implement the getResourcePropterty, getResourceProperties and QueryResourceProperty operations and these methods will be exposed through the service's WSDL.
Introduce GDE Modify Service View
Security

Introduce enables the graphical security configuration on the service and its operations. Security is broken up into two main categories: Authentication (are you who you say you are?) and Authorization (are you authorized to perform the action you are requesting?). When new operations are created they automatically inherit the security settings from the service in which they exist. This is true for authorization and authentication. If you want to specifically alter an operation's settings you can do that by modifying the operation security specifically.

Authentication
Introduce exposes the functionality of Globus GSI through a set of panels that enable the user to customize security for the entire service or specific methods on a service context. The user can choose any of the GSI configuration scenarios that help strengthen Authentication such as Transport Level Security with Integrity and Secure Communication with Privacy. For detailed information about what the configuration options for Secure Conversation or Secure Credentials are, please refer to documentation for the GSI framework.

Secure Communication

Authorization
Introduce also enables the configuration of a particular service, operation, or resource, for authorization. Authorization Extensions can be installed into Introduce to enable graphical configuration of service or method level authorization. Graphical panels will enable the user to describe an authorization policy which must be met in order to allow access to the particular service or operation. Grid service authorization options are discussed in their own article.
Configure Authorization

Other
Introduce services have security metadata which is available as a resource property on the service. This metadata is retrieved automatically by Introduce-generated clients so that the clients know what is required to communicate with the service for a particular operation. The metadata describes to the client if they need credentials, if they can connect anonymously, etc. In the Introduce Service or Operation service security panels users will see an option for "Client should connect anonymously". This tells the client that even though the service is secure it is OK to connect anonymously by default.

This feature can be overridden on the client by calling the setAnonymousPrefered(boolean) operation in the Introduce-generated client code. This can force the client to use anonymous or authenticated communication based on this value. The default value in an Introduce-generated client is true, meaning the client will connect anonymously if the service metadata says it is acceptable.

Other Security Configurations

Operations

The developer can add, remove, or modify operations on the service. To add an operation, click on the Services tab as described in the earlier section, and then select the service in the tree to which you wish to add the operation. Once you have selected the service, you can then select the Add Method button from the panel on the right. For modifying or removing an operation just select the operation from the Services tree on the left and select the Modify or Remove button from the panel on the right.

Creating or Modifying a Method

Introduce GDE Method Modification Component

Each operation needs to have a unique name. All new methods will be a default name called "newMethod". This should be changed to the desired operation name and also a description, if desired, can be added to this operation. For each operation, the developer needs to set the input parameters, return type, and any fault types that can be thrown from each service method. The tabs within the Modify Method panel will allow you to set the Input, Output, Faults, and Security settings of the operation.

  • Input
    To set the input parameters of the operation, first select the Input tab of the Method Modification panel. This will display a table of the input parameters for this method. The input data types can be selected from the types tree on the left. This tree represents the available data types that can be used by this service. To add a data type to the input parameters, select the data type from the tree on the left by clicking it. Then either double-click the item to add it to the input parameters table or use the Add button. If any input parameter is to be used as an array, the array checkbox must be checked in the table on the right once the data type has been added to the table. Also, once an input parameter is added, the name of the parameter is defaulted. This name can be edited by the developer by selecting the cell in the name column and editing the text.
  • Output
    To set the return type of the operation first select the Output tab of the Method Modification panel. This will display the return type or this method. The output data types can be selected from the types tree on the left. This tree represents the available data types which can be used by this service. To set the return type simply select the data type from the tree on the left by double-clicking it. If you would like to reset the operation back to have no return type (i.e., the default), you can click the "Clear Output Type" button. If any output type to be used is an array, the array checkbox must be checked in the table on the right once the data type has been added to the table.
  • Faults There are three ways to add faults: 1.) choose a type from the types tree on the left which extends WSRF BaseFaultType and click the Add From Type button, 2.) select from a fault that already exists in the service that is being used somewhere else and reuse it from the Used Faults drop-down menu and then click the Add Used Fault button, or 3.) create a new fault which will tell Introduce to create you a new fault type that extends the BaseFaultType by typing in the fault name in the Fault Type Name text box and then click the Add New Fault button. Adding faults enables you to throw failure information back to the client for which they can plan. This enables your operations to be more user-friendly with respect to known errors that you service operation might run into.
Using a Pre-Existing Operation Implementation

The implementation of a described operation may already exist in another class which is provided by a jar file. You can tell Introduce not to stub this methods server side implementation but instead call a provided method implementation directly in the class provided. In order to use this functionality, the Provided checkbox must be selected and the class name attribute must be filled out in the Provider Information tab. The class name attribute will point to the fully qualified class name of the class which implements this WSDL-described operation. The jar file that contains the provided class which implements this operation must also be copied into the lib directory of the service. This will ensure that the operation will be located at the time the operation is called on the service. For more information on this particular topic refer to the Globus Documentation on Operation Providers.

Importing Operations

Operations can also be imported from other services. Importing an operation enables the service to implement the exact same operation signature as described in the other service. This enables the service to have an operation that has the exact same WSDL signature of the operation that is being imported. This enables either client to invoke this operation on either service. Importing can be done from two places: (1) an Introduce-generated service, or (2) a WSDL file. For case 1, importing from an Introduce service, the developer would browse and select the Introduce-generated service which contains the operation to be imported. Once the Introduce service is selected, a list of services that contain this method will be available from which to select. Select the service from which you want to import the operation. The methods signature will be imported and the developer will be prompted to make sure to copy over the WSDL and XSD files needed to import the method into the schema/<service name> directory of the service. For case 2, if a method is described in another WSDL but the developer wants to implement this exact method from this WSDL, the developer must have the WSDL and corresponding XSD's in the schema/<service name> directory of the service. Then the developer will be able to browse those WSDL files and select the port type from which they wish to import the operation. The importing of a method across services will assure not only that each service has completely protocol-compatible methods but also that each service's method can be invoked by the same base client. This enables the notion of basic inheritance in grid services and is discussed further in the Introduce technical guide.

Resource Properties

Service state information and metadata in the form of resource properties can be added, removed and configured via the Metadata tab of the Introduce Service Modification interface. The metadata elements which are added to the service can be populated by a file statically or managed dynamically within the service. Also, these metadata entities can be registered with an index service so that users can use the metadata to locate the service. Once the "Metadata" tab is clicked, the left panel will contain a list of available data types that can be used for metadata and the right will contain the list of currently chosen data types. Double-clicking on a data type in the left panel will add it to the main service's metadata list. Any of the service's metadata can be initially populated from a file if desired. If this is chosen then once the service is started up in the container, the file will be used to populate the particular metadata object in the service. If the resource property is not populated from a file, it can be set programmaticaly by the service at runtime. Each resource property in the service can also be selected to be published to an index service. This will enable some or all of the metadata to be used in to locate the service via an index service.

Every resource property is required to have a unique QName (namespace and name). The same "type" can be used, but a different Element should be used if you want multiple instances of them. For example, you can define a "JobStatus" complex type, and create a FooJobStatus element of that type, and a BarJobStatus element of that type, and expose each as a resource property. These can both be deserialized into the same Class, but their name needs to be different; a resource property needs to have a unique name, if it doesn't it would be the same thing.

Service Contexts

A power user feature which can be enabled at modification time is the addition or removal of service contexts. A service context is a sub-service or complimentary service which is used with the main service or some other service context. The service context is comprised of the service, resource, operations, and resource properties. So, in a sense, service context is exactly the same thing as the main service, except that it is not a singleton-based resource and instances can be more dynamically created and/or destroyed. Contexts can be added via the "Service Contexts" tab of the GDE Service Modification interface. Service contexts define additional operations needed to support the desired service functionality. This is enabled by using WSRF capabilities of the Globus Toolkit. As an example, if an operation on the main service enables the user to query a database, that operation might create a resource in another context and return the handle of that context to the user as opposed to the full query result set. This secondary context can then enable the user to iterate through the query results. This is accomplished by operations or resource properties to this secondary service context which will be responsible for iteratively providing results to the user. It should be noted that multiple instances of these contexts can be created and executed concurrently (e.g., one for each query that comes in). This style of grid service is supported by the WSRF specifications. Though the details of the WSRF-implementation of these concepts are abstracted away from developers, its worth noting how they are realized, and this is described in detail in other sections. Introduce makes it easier for service developers to create such complex services, via the GDE, without having to fully understand the underlying service implementations. Anything that can be done to the main service, except service properties that are globally accessible can be added to a service context. For example, resource properties can be added and used to maintain state or for publishing metadata to an index service. Also, operations can be added to the service context and can also be implemented in the service itself or in the service's resource if they are acting on the state of the instance of the resource.
A Statefull Grid service is comprised of several key components which make it able to maintain state and enable a client to invoke the service several time under the same context. A stateful grid service is composed of the service, a resource home, and the resource type. This service organization can be used in many different scenarios. For, example, when an operation on the service is invoked, the service can be implemented to handle that operation, or if the operation is addressing a particular resource instance in the service, the service can look up the resource and call whatever might be necessary to call on the particular addressed resource.

Service Properties

Introduce GDE Service Properties View

Service properties are key value pairs which can be set at deployment time and are available to the server side implementation of the service at run time. This enables passing in configuration variables to the server side of the service at deployment. These key value-pair properties can be declared in "Service Properties" tab of the GDE Service Modification interface. Once the "Service Properties" tab is clicked, the main panel will show a table of the service properties. The bottom panel has an entry that can be used to create a new service property. The properties will be confirmed and/or can be changed from their default values at service deployment time. The variables can then be accessed inside the user's implementation of the operations through the service's ServiceConfiguration class. For example, you can add a property called foo under the service properties tab, and then save the service. If you then look at the source code for the <service package>.service.ServiceConfiguration.java class you will see that it now has available methods for string getFoo() and void setFoo(string foo). These operations are now available to your service and can be used to pass properties into your service at deployment time as well as other users for configuring and sharing properties in your service. The <service package>.service.ServiceConfiguration.java contains a static method for obtaining an instance of itself called getConfiguration(). Any call to that operation from anywhere in the service will return the handle to the "ServiceConfiguration" instance and hence provide access to the service properties.

Service Extensions

Introduce GDE Extensions View

Services can select extensions to add to their Introduce service. These extensions can provide special functionality to the service that might be useful. For example, the caGrid Transfer extension enables service developers to utilize the caGrid Transfer API in their service and client which can enable them to utilize xml-based movement of data between service and client, and vice-versa. For more information on available extensions that can be added to Introduce or its services please look at the Extensions page.

Setting Service Metadata

You can set your service metadata by using the Modify Service option in introduce.

  1. Click on the Modify Service button and choose your service
  2. Select the Service tab
  3. Select Service Metadata under Resource Properties
  4. Click on the Edit Resource Property button

You can fill in your Service Metadata in the Resource Property Editor

  1. Research Center
    1. Type the name of your institution in the Display Name field
    2. Type the name of your institution in the Short Name field
  2. Point of Contact (The person responsible for maintaining the deployed service)
    1. Click on the Hosting Center tab
    2. Click on the Point of Contact tab
    3. Type the contact first name in the First Name field
    4. Type the contact last name in the Last Name field
    5. (Optional) Type the contact phone number in the Phone Number field
    6. Type the contact email address in the Email field
    7. Type the group name / Department in the Affiliation field
    8. In the Role drop down box, select Maintainer
    9. Press the Add button
  3. Address
    1. Click on the Address tab
    2. Type the name of your institution in the Street 1 field - This is important for mapping your service on the caGrid Portal
    3. (Optional) Type the name of your institution in the Street 2 field
    4. Type the city name of your institution in the Locality (city) field
    5. Type the state abbreviation of your institution in the State field - Example: OH for Ohio
    6. Type your ZIP code of your institution in the Zip Code field
    7. Type the abbreviation of your country in the Country field - Example: US for USA
  4. Service Description
    1. Click on the Service Information tab
    2. Enter the description of the service in the Description field
    3. Enter your service version number in the Version field
      The version field under the Service Information tab is NOT for the caGrid version number, it's the version number of your service.
  5. Point of Contact (The person responsible for developing the deployed service)
    1. Click on the Service Information tab
    2. Type the contact first name in the First Name field
    3. Type the contact last name in the Last Name field
    4. (Optional) Type the contact phone number in the Phone Number field
    5. Type the contact email address in the Email field
    6. Type the group name / Department in the Affiliation field
    7. In the Role drop down box, select Developer
    8. Press the Add button

Deployment

Introduce GDE Service Deployment Component

The deployment option of the GDE allows the service developer to deploy the implemented grid service, which has been created with Introduce, to a Grid service container. The toolkit currently supports deploying a service to either a Globus, Tomcat, or JBoss Grid service container; however, support for other deployment options can easily be added to the GDE. The General Deployment tab shows basic information about the service you are going to deploy and provides the ability to choose the container to which it will deploy. Introduce will detect the avialable containers on the host machine by checking for the existence of environmental variables (GLOBUS_LOCATION (Globus), CATALINA_HOME (Tomcat), JBOSS_HOME (JBoss)). The Advanced Deployment tab enables configuration of many standard deployment options:
Property Name
Value(s)
Description
perform.index.service.registration
true or false
Whether or not the service should register with the Index Service
index.service.url
URL
The URL of the Index Service to register with.
index.service.index.refresh_milliseconds
Integer
How often to reregister with the index service (this should be a relatively large amount of time and is simply usefull for makeing sure the index service does not loose your registration).
index.service.registration.refresh_seconds
Integer
This number specifies the period of the interval, in seconds, between attempts of the Index Service to retrieve metadata from the Grid service
The Service Properties deployment tab allows the service deployer to populate service configuration properties, which the service will have access to at runtime.

Undeployment

Introduce GDE Service Undeployment Component

Services generated with Introduce 1.2 and higher support undeployment. The service, when deployed, creates a log file that contains information about what was copied into the container. This log file is an XML document named "introduceDeployment.xml", and it is deployed to the container under the etc directory for your service (i.e. webapps/wsrf/WEB-INF/etc/cagrid_HelloWorld). Utilizing this information, the undeployment task of the service is able to determine what was copied to the container that is not shared by any other service and will remove it. This feature enables the container from getting to prevent corruption by leftover jars and schema from deployments.

Software Updates

Introduce is capable of downloading and installing new extensions, upgrades to older extensions, and newer versions of itself. In the GDE there is a Help menu. In this menu there is a Check for Updates button. This button will take the user to a wizard, which will walk through looking for any software updates or new packages that the user may want to download and install. The user can also put in a different software update site URL to point to a custom site containing Introduce extensions.

Open Introduce Software Update

Introduce Software Update

Introduce Preferences

Introduce Preferences

This configuration can be reached by selecting Window -> Preferences in Introduce and clicking down the tree on the left-hand side to Preferences -> Introduce -> Portal Configuration. The Namespace replacement policy is one of ERROR, IGNORE, or REPLACE.

  • ERROR: if a namespace exists in the service that matches the namespace of the types being added, show the user an error.
  • IGNORE: if a namespace exists in the service that matches the namespace of the types being added, ignore the attempted update (i.e., don't do anything).
  • REPLACE: if a namespace exists in the service that matches the namespace of the types being added, replace existing types with new types as indicated in the schema. Note: This action discards existing serialization options.

Other preferences can be set under the Global Extension Properties tree node which control the default services used by Introduce for things like model discovery and security services.

Service Development


Service Upgrading

Introduce has the ability to help upgrade a service to a newer version of Introduce. If the developer attempts to open a service generated with an older version of Introduce (1.0 and newer), Introduce will prompt the user to proceed with the migration process. The migration process is fully automated and when it is complete, it will report out to the developer what might be left for them to adjust based on their potentially custom changes or if there were any errors during the process.

When using Introduce to open a service for modification, it will check the service to see which version of Introduce and its extensions were used to create/modify the service. If those versions are different from those installed in the Introduce being used, it will prompt the user and notify them that the service needs upgrading. When prompted, the user will have to decide to either:

  1. Upgrade: upgrade the service to the version that Introduce can properly work with it.
  2. Open: attempt to have Introduce work without upgrading, which is potentially dangerous and not recommended.
  3. Close: do nothing to the service and do not proceed with the modification process.

If the user chooses to upgrade the service the upgrade process will begin. Once finished, a report indicating the major changes and potential issues will be displayed to the user for review. Once the user is confident any issues in the upgrade report have been addressed, they can select the "Proceed" option and the Modification Viewer will be opened, displaying the newly upgraded service. If the report warns about potential modifications possibly needed in order to finish the Upgrade process, then the user can select the "Edit" button. This will enable them to halt the upgrade process to make changes. In doing so, the service can be opened up for modification at a later time and Introduce should be able to work with the service. If the user is not confident in the changes and doesn't want to upgrade, they can select the "Roll Back" option to restore the service to its previous state.

Debugging My Service

[caGrid debugging article]

Debugging the Introduce Service Development Process

[Introduce debugging article]

Using the Client

Introduce generates a client API for the service which is exactly as described within the graphical editing environment (see Auto-boxing/Unboxing of Service Operations). This client API can be used in order to leverage this type of service from another application or service. The API contains four constructors which can use used, each of which is different depending on 1.) having a handle or just an address and 2.) the need for security to be used.

 /**
  * Takes in the url of the service to connect to as a string
  */
 HelloWorldClient(String url)

 /**
  * Takes in the url of the service to connect to as a string and
  * a proxy to be used to represent the credentials or the caller
  */
 HelloWorldClient(String url, GlobusCredential proxy)

 /**
  * Takes in the epr which refers to the service or resource
  */
 HelloWorldClient(EndpointReferenceType epr)

 /**
  * Takes in the epr which refers to the service or resource and
  * a proxy to be used to represent the credentials or the caller
  */
 HelloWorldClient(EndpointReferenceType epr, GlobusCredential proxy)

Once a client handle is constructed, each of the operations which were created in the service are available as operations to this newly constructed client instance. Below is an example snippet of code which creates a new client handle to a service called "HelloWorld" and calls the "echo" operation.

try {
 HelloWorldClient client = new HelloWorldClient("http://localhost:8080/wsrf/services/HelloWorld");
 client.echo("Testing)";
} catch (Exception e) {
 System.out.println("Problem creating handle to or calling service" + e.getMessage(), e);
}

Advanced Client Usage

Secure Client Usage

Introduce generated client code can utilize a certificate to communicate with its service securely. This certificate can come from many places; it may be a user certificate or a host certificate or some other certificate received from a delegation service for example. The client by default will attempt to use the credential in the default location in the users home directory. So for example, if you logged in using Dorian the credential would be written to the file system in the default location and your client would automatically use that credential when required by the service. If you want the client to use a different certificate you must pass that certificate into the constructor of the client or by calling the setProxy operation on the client. When the client makes a call to the service it will check the security metadata which tells the client how to configure itself so that it can properly communicate with the service. Even though a service's method is set to require secure communication, this does not mean the client will always use its own credentials. Introduce generated clients by default will connect anonymously to methods that allow both anonymous and non-anonymous access. If you want your client to use its credentials to invoke a method, even though that method can be invoked anonymously, you can set the client to prefer not connecting anonymously. This will force the client to use its own credentials to communicate with the service as opposed to connecting anonymously. In order to do this you must call the setAnonymousPrefered operation on the client you are using:

client.setAnonymousPrefered(false);

The client will then connect with credentials always until you set this back to true letting the client know it is ok to connect anonymously to methods that allow anonymous users. The reason for having this capability is because there may be methods that change the way they work based on who they are talking to. If they are talking to an anonymous user they may not return all the data and if the user has authenticated using their credentials than maybe they get back more privileged information.

You can also change the proxy (the credentials) that your client is using by calling the setProxy operation and passing in the new credentials you now want to use.

client.setProxy(newCredentials);

Printing Detailed Faults

Ordinarily, simply calling printStackTrace() on a RemoteException that may have been thrown by a grid service won't provide much detail, and won't print the attached server-side exception that caused the fault. The example below shows how a client can print a more detailed stack trace from an exception that is received from the service.

     try {
       ...
     } catch (Exception e) {
 gov.nih.nci.cagrid.common.FaultUtil.printFault(e);
     }
Using Subscription and Notification

If the Introduce service you are using supports the Notification resource framework option then the client will be enabled to subscribe to that service and listen for particular changes to resource properties. An example below shows how to perform the subscription:

     IntroduceTestNotificationServiceClient client = new IntroduceTestNotificationServiceClient("http://localhost:8080/wsrf/services/IntroduceTestNotificationServiceClient");
     client.subscribe(new QName("http://testing.org","TestResourceProperty");

The above code presents an example of a client that is subscribing to a service to listen for changes to the TestResourceProperty resource property of the service. If the value of this resource property gets changed in the resource, a notification will be sent out to all registered subscribers. Now we need to implement some code so that we receive these notifications. The introduce client generated for this service will automatically be able to listen for these changes. For us to be able to perform our own actions when we receive a notification, we must overload the deliver operation in the client:

    public void deliver(List topicPath, EndpointReferenceType producer, Object message) {
        org.oasis.wsrf.properties.ResourcePropertyValueChangeNotificationType changeMessage = ((org.globus.wsrf.core.notification.ResourcePropertyValueChangeNotificationElementType) message)
            .getResourcePropertyValueChangeNotification();

        if (changeMessage != null) {
            recievedNotificationCount++;
            try {
                System.out.println("GOT NOTIFICATION: " + changeMessage.getNewValue().get_any()[0].getAsString());
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

Another way to subscribe is to implement a NotificationCallback class and pass an instance into the subscribe method as shown below:

     IntroduceTestNotificationServiceClient client = new IntroduceTestNotificationServiceClient("http://localhost:8080/wsrf/services/IntroduceTestNotificationServiceClient");
     NotificationCallback callback = new MyNotificationCallback();
     client.subscribe(new QName("http://testing.org","TestResourceProperty",callback);

This will enable the client to send notification back to the provided callback as opposed to all messages coming back to this client class and expecting the local implementation of the deliver method. This is useful for a more centralized message handling approach for when notifications are returned from many different clients.

Loading a Proxy from a File

If you want to use a specific proxy file, other than the locations that Globus will automatically look, the ProxyUtil class can be used to load the proxy and create a GlobusCredential.

        GlobusCredential creds = null;
        try {
           creds = gov.nih.nci.cagrid.common.security.ProxyUtil.loadProxy("user.proxy");
           System.out.println("Using proxy with id= " + creds.getIdentity() + " and lifetime "
                            + creds.getTimeLeft());
        } catch (Exception e1) {
           System.out.println("No proxy file loaded so running with no credentials");
        }

Implementing the Service


When an operation is added in the Introduce GDE and the save button is clicked, Introduce will add the new stubbed method into the <service package>.service.<service name>Impl.java class. The developer is then responsible for implementing the method prior to deployment. For example, the snippet below would be generated in the <service package>.service.<service name>Impl.java if the developer added an add operation to the service with Introduce that took in two integers and returned an integer.

  public int add(java.math.BigInteger a,java.math.BigInteger b) throws RemoteException {
    //TODO: Implement this autogenerated method
    throw new RemoteException("Not yet implemented");
  }

The developer would then have to edit this method to implement the logic the service would execute on invocation.

  public int add(java.math.BigInteger a,java.math.BigInteger b) throws RemoteException {
    return a + b;
  }

Advanced Service Development Topics

Obtaining the Callers Identity

In the service it is sometime required to get the identity of the caller. The identity is carried in the context of the message which was passed into the service. In order to get this information, the following lines will be needed:

     String userDN = gov.nih.nci.cagrid.introduce.servicetools.security.SecurityUtils.getCallerIdentity()

Accessing Service Properties

Service properties are the properties that the main service can be configured with and that all service contexts deployed with that service can access. These properties are configured at deploy time and will likely need to be accessed in the service. Below is example code for how to access these properties where the main service was named HelloWorld and the name of the service property was testing:

     HelloWorldConfiguration.getConfiguration().getTesting();

Getting a Handle to a Resource

When developing in the service context you must remember that the ServiceImpl class is just the service interface, but the service should act on the addressed resource as there may be more than one resource instance being used by the service at a time. See an example of how to get a handle to the resource that is being addressed by the current caller below (example from the counter service context as described in the section on Utilizing the factory patter):

  public void incrementCounter() throws RemoteException {
      int currentCounter;
      try {
          currentCounter = getResourceHome().getAddressedResource().getIntValue();
          currentCounter++;
          getResourceHome().getAddressedResource().setIntValue(currentCounter);
      } catch (Exception e) {
          e.printStackTrace();
      }
  }

Programmatically Accessing and/or Editing Resource Properties (Metadata)

From the resource there will be getters and setters automatically generated for the resource properties of your service. For instance, in the above example, the counter service has an "int" resource property. This enables Introduce to automatically generate getters and setters for that resource property that the service implementer can use to access and modify values in the resource properties.

Creating a Security Descriptor for a Resource

Sometimes it is necessary to set a security descriptor on an instance of a resource. This might be to protect resource instances so that only the creator of the resource can use it. In order to do this, ensure that when the context was generated in Introduce that the "secure" resource framework option was selected. This will allow the resource to have a setSecurityDescriptor() method enabled on it. When the resource is being created, as in the example below, the security descriptor should be generated and set on the resource. Once set, it will be utilized on any access to the resource. Below is an example method from the counter service used in the utilizing a factory patter section. This is the method that Introduce generated to create the counter-instance for the caller. In this code there is a place documenting how to set the security descriptor on the resource.

 public example.counter.context.stubs.types.CounterContextReference createCounter() throws RemoteException {

  org.apache.axis.message.addressing.EndpointReferenceType epr = new org.apache.axis.message.addressing.EndpointReferenceType();
  example.counter.context.service.globus.resource.BaseResourceHome home = null;
  org.globus.wsrf.ResourceKey resourceKey = null;
  org.apache.axis.MessageContext ctx = org.apache.axis.MessageContext.getCurrentContext();
  String servicePath = ctx.getTargetService();
  String homeName = org.globus.wsrf.Constants.JNDI_SERVICES_BASE_NAME + servicePath + "/" + "counterContextHome";

  try {
   javax.naming.Context initialContext = new javax.naming.InitialContext();
   home = (example.counter.context.service.globus.resource.BaseResourceHome) initialContext.lookup(homeName);
   resourceKey = home.createResource();

   //  Grab the newly created resource
   example.counter.context.service.globus.resource.CounterContextResource thisResource = (example.counter.context.service.globus.resource.CounterContextResource)home.find(resourceKey);

   //  This is where the creator of this resource type can set whatever needs
   //  to be set on the resource so that it can function appropriately. For instance
   //  if you want the resource to only have the query string, then this is where you would
   //  give it the query string.

   // sample of setting creator only security.  This will only allow the caller that created
   // this resource to be able to use it.
   //thisResource.setSecurityDescriptor(gov.nih.nci.cagrid.introduce.servicetools.security.SecurityUtils.createCreatorOnlyResourceSecurityDescriptor());

   String transportURL = (String) ctx.getProperty(org.apache.axis.MessageContext.TRANS_URL);
   transportURL = transportURL.substring(0,transportURL.lastIndexOf('/') +1 );
   transportURL += "CounterContext";
   epr = org.globus.wsrf.utils.AddressingUtils.createEndpointReference(transportURL,resourceKey);
  } catch (Exception e) \
   throw new RemoteException("Error looking up CounterContext home:" + e.getMessage(), e);
  }

  //return the typed EPR
  example.counter.context.stubs.types.CounterContextReference ref = new example.counter.context.stubs.types.CounterContextReference();
  ref.setEndpointReference(epr);

  return ref;
  }

Setting the Termination Time on a Resource

When the lifetime resource framework option is set on a service, the resources of that service will be able to have tier lifetime managed. From the client side, a SetTerminationTime() or Destroy() grid call can be made to the service either setting the time to terminate or destroying the addressed resource. You can also call the set termination time directly on the resource inside the service. An example below, utilizing the same code as above, enables the creation of counters for users that will only be alive for 5 minutes:

 public example.counter.context.stubs.types.CounterContextReference createCounter() throws RemoteException {
  org.apache.axis.message.addressing.EndpointReferenceType epr = new org.apache.axis.message.addressing.EndpointReferenceType();
  example.counter.context.service.globus.resource.BaseResourceHome home = null;
  org.globus.wsrf.ResourceKey resourceKey = null;
  org.apache.axis.MessageContext ctx = org.apache.axis.MessageContext.getCurrentContext();
  String servicePath = ctx.getTargetService();
  String homeName = org.globus.wsrf.Constants.JNDI_SERVICES_BASE_NAME + servicePath + "/" + "counterContextHome";

  try {
   javax.naming.Context initialContext = new javax.naming.InitialContext();
   home = (example.counter.context.service.globus.resource.BaseResourceHome) initialContext.lookup(homeName);
   resourceKey = home.createResource();

   //  Grab the newly created resource
   example.counter.context.service.globus.resource.CounterContextResource thisResource = (example.counter.context.service.globus.resource.CounterContextResource)home.find(resourceKey);

   //  This is where the creator of this resource type can set whatever needs
   //  to be set on the resource so that it can function appropriately. For instance
   //  if you want the resource to only have the query string then there is where you would
   //  give it the query string.


   // sample of setting creator only security.  This will only allow the caller that created
   // this resource to be able to use it.
   //thisResource.setSecurityDescriptor(gov.nih.nci.cagrid.introduce.servicetools.security.SecurityUtils.createCreatorOnlyResourceSecurityDescriptor());

   //set the termination time of this resource
                        Calendar cal = new GregorianCalendar();
                        cal.add(Calendar.MINUTE,5);
                        thisResource.setTerminationTime(cal);

   String transportURL = (String) ctx.getProperty(org.apache.axis.MessageContext.TRANS_URL);
   transportURL = transportURL.substring(0,transportURL.lastIndexOf('/') +1 );
   transportURL += "CounterContext";
   epr = org.globus.wsrf.utils.AddressingUtils.createEndpointReference(transportURL,resourceKey);
  } catch (Exception e) {
   throw new RemoteException("Error looking up CounterContext home:" + e.getMessage(), e);
  }

  //return the typed EPR
  example.counter.context.stubs.types.CounterContextReference ref = new example.counter.context.stubs.types.CounterContextReference();
  ref.setEndpointReference(epr);

  return ref;
  }

Utilizing the Factory Pattern

Link to the entire example service source code described below

Last edited by
David Ervin (686 days ago) , ...
Adaptavist Theme Builder Powered by Atlassian Confluence