WSAG4J Client

Set up a client

WSAG4J is shipped with server and client distributions that can be downloaded from WSAG4J client distribution In order to set up a wsag4j client, all files that are located in the classes folder of the client distribution must also be presented in the classpath of the application that uses the wsag4j Client API. These files are used to configure the clients default behavior.

  • wsag4j-client.properties - configures the client implementation and client security
  • wsrf-client.config - configures the client security handler
  • wsag4j-client-keystore.jks - client keystore used by the example client
  • axis2-client/client.axis2.xml - default Axis2 configuration

WSAG4J Server URL

On a server side, a WSAG4J factory action called "WSAG4J-SAMPLE" is configured in the wsag4j engine configuration file (see factory actions). This server factory action specifies a template creation strategy (SampleGetTemplateAction), a negotiation strategy (SampleNegotiateAction), and an agreement creation strategy (SampleCreateAgreementAction).

The client contacts the WSAG4J server to retrieve templates and to create an agreement after negotiation. It is important to clarify the address of the WSAG4J server in question in advance, however, here for this example we assume that WSAG4J server is running under the url: (http://127.0.0.1:8080/wsag4j-agreement-factory-$wsag4j-version).

Loading Agreement Factory Clients & Templates

Since WSAG4J uses WS-Security to digitally sign messages exchanged between client and server, a client must provide a set of security credentials. The easiest way to provide these credentials is to provide a valid LoginContext as shown below:

KeystoreProperties properties = new KeystoreProperties();
properties.setKeyStoreAlias("wsag4j-user");
properties.setPrivateKeyPassword("user@wsag4j");

properties.setKeyStoreType("JKS");
properties.setKeystoreFilename("/wsag4j-client-keystore.jks");
properties.setKeystorePassword("user@wsag4j");

properties.setTruststoreType("JKS");
properties.setTruststoreFilename("/wsag4j-client-keystore.jks");
properties.setTruststorePassword("user@wsag4j");

LoginContext loginContext = new KeystoreLoginContext(properties);
loginContext.login();

This LoginContext is passed to the AgreementFactoryLocator that allows retrieval of available agreement factory clients from the deployed wsag4j server identified by its url as shown below. The client factory array (factories) stores objects of AgreementFactoryClient's type.

EndpointReferenceType wsag4j_server_epr = EndpointReferenceType.Factory.newInstance();
wsag4j_server_epr.addNewAddress().setStringValue("http://127.0.0.1:8080/wsag4j-agreement-factory-${wsag4j-version}");

AgreementFactoryRegistryClient registry = AgreementFactoryRegistryLocator.getFactoryRegistry(wsag4j_server_epr, getLoginContext());
AgreementFactoryClient[] factories = registry.listAgreementFactories();   

It is possible to get a particular agreement factory specified by an ID. The agreement factory IDs can be specified in the wasg4j-engine.config file. In current snippet an agreement factory with ID "SAMPLE-INSTANCE-1" is retrieved:

AgreementFactoryClient factory = null;
for (int i = 0; i < factories.length; i++) {
    if ("SAMPLE-INSTANCE-1".equals(factories[i].getResourceId())) {
        factory = factories[i];
        break;
    }
}

After the agreement factory client is created, this client can be used to retrieve valid agreement templates from the factory. The next example shows how an agreement factory client retrieves all templates from the agreement factory:

AgreementTemplateType[] templates = factory.getTemplates();

Retrieving templates by ID is also possible, for example, the sample template with template name "SAMPLE-TEMPLATE" and id "1" from the "SAMPLE-INSTANCE-1" agreement factory:

AgreementTemplateType template = factory.getTemplate("SAMPLE-TEMPLATE", "1");

After an agreement template was retrieved from the factory, a client can use this template to create a valid agreement offer. The agreement offer is a request to create a new service level agreement under the conditions stated in the offer. An agreement offer can be created by the following code:

AgreementOffer offer = new AgreementOfferType(template);

Negotiating Agreement

Following code snippets are taken from the Sample Negotiator Client that implement the example described in negotiation scenario. In this example, a service provider offers compute resources to customers that are available in a specific time frame. The compute resource service consists of a job submission service. The compute resource provider offers available compute resources via an agreement template. This sample template includes the description of the service as well as a set of options the customer can choose from. The service description contains the available compute resources and the time-frame the resources should be available.

At first step, agreement templates are loaded from a negotiation instance that is created from the SAMPLE-INSTANCE-1 agreement factory as follows:

NegotiationClient negotiation = factory.initiateNegotiation(negotiation_context);

To start the negotiation process, we have to retrieve the agreement templates for which negotiation is supported, and select the one we are interested to negotiate SLA, for instance the one with the template name "SAMPLE-TEMPLATE".

AgreementTemplateType[] negotiableTemplates = negotiation.getNegotiableTemplates();
AgreementTemplateType template = null;

for (int i = 0; i < negotiableTemplates.length; i++) {
    AgreementTemplateType agreementTemplate = negotiableTemplates[i];

    if(agreementTemplate.getName().equals("SAMPLE-TEMPLATE")) {
        template = agreementTemplate;
    }
}

The "SAMPLE-TEMPLATE" template exposes the current availability of computing resources by a resource provider. This template includes the service description term 'RESOURCE_SDT' with a JSDL document describing the available compute resources. And the service description term 'TIME_CONSTRAINT_SDT' which define the time frame during which the resources are available.

SampleAgreementTemplate sampleTemplate = new SampleAgreementTemplate(template);

ResourcesType jobResources_1 = sampleTemplate.getResourceDefinition();
RangeValueType totalCountRange_1 = RangeValueType.Factory.newInstance();
totalCountRange_1.addNewExact().setDoubleValue(5); 
jobResources_1.setTotalResourceCount(totalCountRange_1);

TimeConstraintType timeConstraint_1 = sampleTemplate.getTimeConstraint();
Calendar startTime_1 = (Calendar) timeConstraint_1.getStartTime().clone();
Calendar endTime_1 = (Calendar) timeConstraint_1.getEndTime().clone();
timeConstraint_1.setStartTime(startTime_1);
timeConstraint_1.setEndTime(endTime_1);
timeConstraint_1.setDuration(15);

The SampleAgreementTemplate is a pattern class to retrieve RESOURCE_SDT and TIME_CONSTRAINT_SDT service description terms from the template to fulfill the application execution requirements. As shown above, we negotiate 5 resources (*TotalResourceCount*) and specify the start time (*StartTime*) as 5 minute ahead of the current time and end time (*EndTime*) after 60 minutes (based on the start time) and the effective duration (*Duration*) of the advance reservation is 15 minutes.

Now we create negotiation offer from a negotiable template for the reservation of required resources to fulfill the application execution requirements.

SampleNegotiationOffer negotiationOffer_1 = negotiationTemplate.getNegotiationOffer();

The SampleNegotiationOffer is also a pattern that applies on RESOURCE_SDT and TIME_CONSTRAINT_SDT service description terms. Refer to Sample Negotiator Client on creating negotiation offer context, negotiation constraint and updating respective service description terms in the negotiation offer.

Invoking negotiate method from Negotiation instance and in return counter offers are received.

NegotiationOfferType[] negotiationOfferTypes_1 = {negotiationOffer_1.getXMLObject()};
NegotiationOfferType[] counterOffers_1 = negotiation.negotiate(negotiationOfferTypes_1);

First we check whether the negotiation (counter) offer is rejected.

NegotiationOfferType counterOffer_1 = counterOffers_1[0];
if(counterOffer_1.getNegotiationOfferContext().getState().isSetRejected()) {
        ... do something ...
}

Two counter offers are received with different resource availability. Another negotiation iteration can be performed if both counter offers are not sufficient to fulfill our requirements. However, we select counter offer 1 that is satisfying the required criteria. Refer to Sample Negotiator Client for all negotiation iterations.

NegotiationOfferType selectedCounterOffer = counterOffers_1[0];

AgreementOffer offer = new AgreementOfferType(selectedCounterOffer);

An agreement offer can be created from the initial negotiation template without performing negotiation iterations as follows:

SampleAgreementOffer agreementOffer = sampleTemplate.getAgreementOffer();
AgreementOffer offer = new AgreementOfferType(agreementOffer.getXMLObject());

Finally negotiation process can be terminated. It wouldn't be possible to create an agreement from the negotiated offer once the negotiation instance has been terminated. Therefore, negotiation instance should only be terminated when an agreement has already been created.

negotiation.terminate();

Creating Agreement

Now create the agreement instance based on the (negotiated) agreement offer:

AgreementClient agreement = factory.createAgreement(offer);

During the creation of an agreement the factory might throw an exception. This indicates that an error occurred during the creation process. An application should catch that exception as indicated by the following code:

AgreementClient agreement = null;
try {
    agreement = factory.createAgreement(offer);
} catch (AgreementFactoryException e) {
    ...
}

After agreement creation, current states of service description term(s) can be queried as shown below:.

ServiceTermStateType[] states = agreement.getServiceTermStates();

On the server-side, the SampleSDTMonitor updates the service term state "RESOURCE_SDT" with JSDL document that contain the name of the reserved host on which application is going to execute. On the client side, this JSDL document can be extracted from the service term state as follows:

ServiceTermStateType resourceServiceTerm  = agreement.getServiceTermState("RESOURCE_SDT");
XmlObject[] jobDefinition = resourceServiceTerm.selectChildren(JobDefinitionDocument.type.getDocumentElementName());
JobDefinitionType jobDef = (JobDefinitionType) jobDefinition[0];
ResourcesType resources = jobDef.getJobDescription().getResources();
String reservedHostName = resources.getCandidateHosts().getHostNameArray(0);  

To access the Guarantee Term States, the getGuaranteeTermStates() method can be used.

GuaranteeTermStateType[] guaranteeTermStates = agreement.getGuaranteeTermStates();

To get the status of an agreement:

AgreementStateType state = agreement.getState();

Depending on the site policy of a SLA provider, active agreements can be terminated. In general, wsag4j does not deal with the policies or the circumstances under which agreements may be terminated. This topic is subject of concrete implementations. To terminate an agreement use the following code:

agreement.terminate(TerminateInputType.Factory.newInstance());