Consuming the SOAP API – Sample Java Application

Edit Requirements

The sample code in this document requires Java and JAX-WS RI.

Creating the Port

We create a JAX-WS port object form the client with the following extensions:

  • MTOMFeature
  • StreamingAttachmentFeature

Streaming attachments directs JAX-WS RI to handle attachments as streams (as opposed to byte arrays) and MTOM enables XOP binary attachments. We also specify the chunk size for http entity streaming.

private static EntityAPIService getPort() throws MalformedURLException {

 EntityAPIService_Service service = new EntityAPIService_Service(new URL(WSDL_LOCATION), new QName("http://datasolutions.pervasive.com/api/service", "EntityAPIService"));

final StreamingAttachmentFeature streamingAttachmentFeature = new StreamingAttachmentFeature(null, false, 4000000L);

final MTOMFeature mTOMFeature = new MTOMFeature();

EntityAPIService servicePort = service.getEntityAPIPort(streamingAttachmentFeature, mTOMFeature);

Map context = ((BindingProvider) port).getRequestContext();

context.put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192);

return servicePort;

}

Logging In

The login method returns a LoginResult. We determine success or failure from the isSuccess field. Notes about the success or failure are available in the message field. The sessionId field is used throughout the rest of the API.

private static String login(String username, String password) throws Exception {

    LoginResult loginResult = port.login(username, password);

    if (!loginResult.isSuccess()) {

        throw new Exception("login failed: " + loginResult.getMessage());

}

return loginResult.getSessionId();

}

Manually Setting the Session Expiration

Find the Active Credential Object

Get a list of all Credentials available to the user, and iterate over them until one with type="pervasiveSession" is found, having a sessionId matching our current sessionId.

//get a list of credentials available to the session User

List listCredentials = port.listCredentials(0, Integer.MAX_VALUE, sessionId);

Credential currentCredential = null;

//Iterate over entire list

Iterator it1 = listCredentials.iterator();

while (currentCredential == null && it1.hasNext()) {

                Credential credential = it1.next();

                //Pervasive username/password credentials will have 
                a type of "pervasiveSession"

                if (credential.getType().equals("pervasiveSession")) {

                                //iterate through parameters -- the session id will be stored in

                                //a credential parameter

                                Iterator it2 = credential.getParameters().getParameter().iterator();

                                while (currentCredential == null && it2.hasNext()) {

                                                CredentialParameter cp = it2.next();

                                                //If the parameter key is sessionId and the value matches our

                                                //actual session Id then we've found our credential

                                                if ("sessionId".equals(cp.getKey()) && sessionId.equals
                                                (cp.getValue())) {

                                                                currentCredential = credential;

                                                 }

                            }

            }


}

if (currentCredential == null) {

                throw new Exception("Failed to retrieve current credential");

}

Setting the Credential Expiration

Once we have the Credential object, we need only create an XMLGregorianCalendar corresponding to the desired end date.

//Create a gregorian calendar with the current date and time

GregorianCalendar calendar = new GregorianCalendar();

//Add the offset that corresponds to when the session should expire

calendar.add(durationUnits, duration);

//Create a new XMLGregorianCalendar based on our GregorianCalendar

XMLGregorianCalendar expiration = datatypeFactory.newXMLGregorianCalendar(calendar);

//set that as the expiration date

currentCredential.setExpiration(expiration);

//persist the changes

port.editCredential(currentCredential, sessionId);

Getting User Data

If we need access to the current User object, we need to enumerate the list of all users associated with this session. The sole user returned will be the current user.

List users = port.listUsers(0, Integer.MAX_VALUE, sessionId);

User user = users.get(0);

Creating an Application

Creating a datacloud application needs at minimum three components:

  1.  A Destination describing where to run the job.
  2.  A Product describing what should be run.
  3.  A Provisioning corresponding to an instance of the product containing customer-specific data

Multiple products can use the same destination, and multiple provisionings can be created for each product.

Creating a Destination

Virtually all of the fields in a Destination object are required. Here we set some defaults, persist and return the destination.

private static Destination createDestination(String sessionId) throws CloudAPIException, InvalidSessionException {

    Destination destination = new Destination();

    destination.setSecurityGroup("default");

    destination.setAmiId("ami-00729269");

    destination.setQueueLowerThreshold(0);

    destination.setQueueUpperThreshold(1);

    destination.setInstanceType("m1.small");

    destination.setKeyName("cloud-key");

    destination.setMaxInstances(2);

    destination.setAvailabilityzone("us-east-1a");

    destination.setSqsQueuePrefix("myTestQueuePrefix");

    destination.setUserDataTemplateName("userdata.sh");

    destination.setMinInstances(0);

    destination = port.createDestination(destination, sessionId);

    return destination;

}

Creating a Product

Create the product entity:

//create a product

 Product product = new Product();

//Unlike other entites, the ID must be set by the user for product

product.setId(UUID.randomUUID().toString());

product.setDestination(destination.getId());

product.setActive(Boolean.TRUE);

product.setConcurrent(Boolean.FALSE);

product.setName("My Test Product");

product.setDescription("A product for testing the API.");

product.setUserProduct(Boolean.TRUE);

final Parameters parameters = new Product.Parameters();

ProductParameter productParameter = new ProductParameter();

productParameter.setKey("foo");

productParameter.setValue("bar");

parameters.getParameter().add(productParameter);

productParameter = new ProductParameter();

productParameter.setKey("key2");

productParameter.setValue("value2");

parameters.getParameter().add(productParameter);

product.setParameters(parameters);

//TODO set process

product.setProcess("test.1.0.djar");

product = port.createProduct(product, sessionId);

 

Upload the Process File

//open the local file

File file = new File("C:\\ec2\\test.1.0.djar");

//create a javax.activation.DataHandler to wrap it

DataHandler dataHandler = new DataHandler(new FileDataSource(file));

//upload the file to datacloud. Note the integrationSpec folder specified

//processes are expected to be relative to the integrationSpec folder

port.putProductFile(product.getId(), "integrationSpec/test.1.0.djar", dataHandler, sessionId);

 

Creating a Provisioning

private static Provisioning createProvisioning(Product product, String sessionId) throws InvalidSessionException, CloudAPIException {
    //create a provisioning for the product

    Provisioning provisioning = new Provisioning();

    //Set the product field to the corresponding product id

    provisioning.setProduct(product.getId());

    //Set the expiration

    GregorianCalendar calendar = new GregorianCalendar();

    calendar.add(Calendar.YEAR, 1);

    XMLGregorianCalendar expirationDate = datatypeFactory.newXMLGregorianCalendar(calendar);

    provisioning.setExpirationDate(expirationDate);


    provisioning.setParameters(new Provisioning.Parameters());

    ProvisioningParameter provisioningParameter = new ProvisioningParameter();

    provisioningParameter.setKey("foo");

    provisioningParameter.setValue("baz"); //overrides foo=bar in product

    provisioning.getParameters().getParameter().add(provisioningParameter);

    provisioning = port.createProvisioning(provisioning, sessionId);

    return provisioning;

}

Running an application

Creating an execution

To run the product we must first instantiate an Execution object, optionally specifying runtime parameters to be passed to the process. Then we must call the startExecution function to being the processing.

private static Execution execute(Provisioning provisioning, String sessionId) throws InvalidSessionException, CloudAPIException {

    //create an execution for the provisioning

    Execution execution = new Execution();

    //optionally set any job-specific parameters

    execution.setParameters(new Execution.Parameters());

    ExecutionParameter executionParameter = new ExecutionParameter();

    executionParameter.setKey("recordId");

    executionParameter.setValue("abc123xyz");

    execution.getParameters().getParameter().add(executionParameter);

    //presist the execution

    execution = port.createExecution(execution, provisioning.getId(), sessionId);

    //start the process execution

    port.startExecution(execution.getId(), sessionId);

    return execution;

}

 

Waiting for completion

To track the status of the execution, poll with findExecution.

  • If the startTime is null, it has not yet started
  • If the finishTime is null, but the start time is not null, it is executing
  • If the finishTime is not null, the job completed (successfully or unsuccessfully)

while (execution.getFinishTime() == null) {

    execution = port.findExecution(execution.getId(), sessionId);

    if (execution.getStartTime() != null) {

        System.out.println("Execution has started");

    } else {

        System.out.println("Execution has not yet started");

    }

    Thread.sleep(10 * 1000);

    }

System.out.println("Execution is finished");

 

 

Getting the log file

Currently, logs are stored in the log folder under the provisioning folder, with the execution id as the file name. Once the execution is complete, we can download the file for review.

File logFile = new File("C:\\logs\\mylog.txt");

DataHandler logFileHandler = port.getProvisioningFile(provisioning.getId(), "log/" + execution.getId
(), sessionId);

OutputStream fos = new FileOutputStream(logFile);

logFileHandler.writeTo(fos);

fos.flush();

fos.close();

Logging out

port.logout(sessionId);