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

Knowledgebase


Registering a Grid service to a secondary Index service


Overview

Certain services may choose to register to a secondary Index service. This provides the capability for users in a second Grid (using a second Index service) to discover and potentially utilize the service.

Introduce generates service code that encapsulate the registration process. This article details what modifications to make to a caGrid 1.2 service, either Analytical or Data, to peform a secondary index service registration.

Create an Introduce analytical service

In this article, we will assume that the title of the service is "MultipleIndexService" and the service package is named gov.nih.nci.cagrid.multipleindex. Create a new analytical service at this time.

Extending the service to perform a secondary registration

In Introduce, add a new service property for the secondary Index Service URL. Steps to add this property are shown in the following screenshots.

Be sure to save the service after adding the property. More information on service properties can be found in the caGrid 1.2 Developer's Guide.

Details of Java files in the service

Every service has a main service context that holds the primary services operations. This service context is implemented with a "ResourceHome" class. In our service, a class named MultipleIndexServiceResourceHome in the gov.nih.nci.cagrid.multipleindex.service.globus.resource package implements the main service context.

This class implements a createSingleton() method that initializes the main service context. The contents of this method are as follows:

public Resource createSingleton() {
		logger.info("Creating a single resource.");
		try {
		    MultipleIndexServiceResourceProperties props = new MultipleIndexServiceResourceProperties();
			MultipleIndexServiceResource resource = new MultipleIndexServiceResource();
			if (resource instanceof PersistenceCallback) {
			      //try to load the resource if it was persisted
                  try{
                    ((PersistenceCallback) resource).load(null);
			      } catch (InvalidResourceKeyException ex){
			      	  //persisted singleton resource was not found so we will just create a new one
			          resource.initialize(props, MultipleIndexServiceConstants.RESOURCE_PROPERTY_SET, UUIDGEN.nextUUID());
			      }
            } else {
                    resource.initialize(props, MultipleIndexServiceConstants.RESOURCE_PROPERTY_SET, UUIDGEN.nextUUID());
            }

			return resource;
		} catch (Exception e) {
			logger.error("Exception when creating the resource",e);
			return null;
		}
	}

The key line that initializes the main service context is the following

resource.initialize(props, MultipleIndexServiceConstants.RESOURCE_PROPERTY_SET, UUIDGEN.nextUUID());

In the next section, we will take a look at this code and modify it for our purposes.

Inside the default initialize() method

Introduce provides an extensible framework that makes it easy for a service developed to customize the service. The way this is done is by leaving the primary implementation class relatively clean so that the service developer can customize the implementation. The primary service implementation class typically extends from a parent "Base" class that contains code generated by Introduce to handle the behind-the-scenes Grid communication details.

In this case, the relevant class is the gov.nih.nci.cagrid.multipleindex.service.globus.resource.MultipleIndexServiceResource that extends MultipleIndexServiceResourceBase in the same package. Let's take a look at the parent ("Base") class.

The method that initializes the primary service context is implemented here. This method contains the following code:

public void initialize(Object resourceBean,
                           QName resourceElementQName,
                           Object id) throws ResourceException {

        // Call the super initialize on the ReflectionResource
	    super.initialize(resourceBean,resourceElementQName,id);

		// this loads the metadata from XML files if this is the main service
		populateResourceProperties();

		// register the service to the index service
		refreshRegistration(true);

	}

You will probably guess that the last call in that method,

		// register the service to the index service
		refreshRegistration(true);

is the method we are interested in. You are correct!

This method is implemented in the same class. Feel free to peruse the contents as you need, but for now we just need to know where the method is.

Because we want to perform a secondary registration, we will generally want to do what this method does. So what we need to do is implement our own initialize method with a second registration.

Updating the MultipleIndexServiceResource class

To implement our own intiailize method, we will extend the "Base" implementation and add additional logic to perform our registration.

Add the following initialize method to the MultipleIndexServiceResource java file:

	public void initialize(Object resourceBean, QName resourceElementQName,
			Object id) throws ResourceException {

		// Call the super initialize on the ReflectionResource
		super.initialize(resourceBean, resourceElementQName, id);

		// this loads the metadata from XML files if this is the main service
		populateResourceProperties();

		// register the service to the index service
		try {
			this.secondaryIndexServiceURL = MultipleIndexServiceConfiguration
					.getConfiguration().getSecondaryIndexServiceURL();
			if (this.secondaryIndexServiceURL != null) {
				URI uri = new URI(this.secondaryIndexServiceURL);
				refreshSecondaryRegistration(true, uri);
			}
		} catch (Exception e) {
			// Could not perform secondary registration
			String msg = "Could not peform secondary registration due to reason: "
					+ e.getMessage();
			logger.error(msg, e);
			e.printStackTrace();
		}

	}
In caGrid 1.3, this code has been re-written with protected fields and methods to make it easier to extend. You can use the fields and methods in the parent class as needed in caGrid 1.3 instead of duplicating them in the child class.

The above code is similar to the parent's initialize method, but it has additional lines to access the value of the secondary index service URL service property and pass this URL to the updated refreshSecondaryRegistration method, described next.

We will also copy the refreshRegistration method from the "Base" (parent) class to this class, but rename it to refreshSecondaryRegistration. The key change is to add a URI parameter that is the URI of our secondary index service. Thus, the method signature is now the following:

	public void refreshSecondaryRegistration(boolean forceRefresh,
			URI secondaryIndexURI) {

Next, we will modify the refreshSecondaryRegistration method to perform a registration using our custom service registration file as the source.

The following code in the refreshSecondaryRegistration loads the registration file from the service:

			File registrationFile = new File(ContainerConfig.getBaseDirectory() + File.separator
					+ getConfiguration().getRegistrationTemplateFile());

We want to use the same file, but simply change the URL that we register to. After the registrationFile is read, the next code reads the file and creates a ServiceGroupRegistrationParameters object to hold the data from the file. We want to modify those parameters. The following code is the relevant section:

			if (params != null) {

				AggregatorContent content = (AggregatorContent) params.getContent();
				AggregatorConfig config = content.getAggregatorConfig();
				MessageElement[] elements = config.get_any();
				GetMultipleResourcePropertiesPollType pollType = null;

...

This is where all registration parameters are added to the params to be registered with the index service. Globus registers the service to a "service group EPR". The entire Index service is a service group, so we can use the URL for the index service in this value. Add the following code to update the URL:

				EndpointReferenceType serviceGroupEPR = new EndpointReferenceType(secondaryIndexURI);
				params.setServiceGroupEPR(serviceGroupEPR);

The updated code block now looks like this:

			if (params != null) {

				EndpointReferenceType serviceGroupEPR = new EndpointReferenceType(secondaryIndexURI);
				params.setServiceGroupEPR(serviceGroupEPR);

				AggregatorContent content = (AggregatorContent) params.getContent();
				AggregatorConfig config = content.getAggregatorConfig();
				MessageElement[] elements = config.get_any();
				GetMultipleResourcePropertiesPollType pollType = null;
...

Download a complete MultipleIndexService.java file

To obtain the above class, please download the complete MultipleIndexServiceResource.java file.

Testing the service

For a complete code example, please download the attached service to your computer.  The provided service is configured to use a secondary index service installed at http://localhost:8080/wsrf/services/DefaultIndexService.

After deploying the service to a container and starting the container, check for two service registrations, one to the service's primary index service and a second registration to the secondary index service.

The following command will obtain a list of services that have been registered to the localhost's index service. (Update the command to point to your service's primary index service to verify the registration there.)

$ $GLOBUS_LOCATION/bin/wsrf-query -a -z none -s http://localhost:8080/wsrf/services/DefaultIndexService | grep "<ns8:Address xmlns:ns8"| cut -d'>' -f2 | cut -d'<' -f1
http://localhost:8080/wsrf/services/cagrid/MultipleIndexService

...
Last edited by
Joe George (1498 days ago) , ...
Adaptavist Theme Builder Powered by Atlassian Confluence