Backport API (CALS API via NXCALS)
We have implemented an indirection layer that enables using NXCALS via the old CALS API. We refer to the project as backport-api.
Deprecated API
Please note that some methods, public APIs or classes do not conform easily to the new system. We have marked a number of methods with @Deprecated to signal this situation.
While me might not remove these methods, you use them at your own risk. You might run into a series of issues, be it very low performance, unpredictable results or even inability to run at all.
Please avoid deprecated methods if possible and treat very seriously every warning about using a deprecated method in your project. Notify us if you consider a deprecated method to be absolutely essential to your workflow.
Dependencies
In order to start working with the backport-api first you have to import the required jars:
dependencies {
(...)
compile group: 'cern.nxcals', name: 'nxcals-backport-api', version: nxcalsVersion
compile group: 'cern.nxcals', name: 'nxcals-hadoop-pro-config', version: nxcalsVersion
(...)
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- !!! IMPORTANT: for CBNG configuration remove build.gradle files !!! -->
<products>
(...)
<dependencies>
(...)
<dep product="nxcals-backport-api" />
<dep product="nxcals-hadoop-pro-config" />
(...)
</dependencies>
</product>
</products>
Packages
We have renamed the java packages for all the public CALS classes:
- cern.accsoft.cals.extr.client.service. -> cern.nxcals.api.backport.client.service.
- cern.accsoft.cals.extr.domain. -> cern.nxcals.api.backport.client.service.
This allows you to effortlessly use both, the old api and the new api in a single project.
Authentication
Prerequisites:
- The backport-api uses Kerberos for authentication. If you are unfamiliar with kerberos please consult getting started with kerberos.
- You must request access to NXCALS as described here
Once you have your Kerberos and your account setup, you can continue.
There are two main ways of authenticating into NXCALS:
Authenticating with Kerberos shared state
NXCALS provides seamless Kerberos integration. In essence, all you need to do prior to running your code is to create your Kerberos token:
kinit
We will pick up the Kerberos token and authenticate you automatically. For as long as your token is valid, you can freely run backport-api methods. The advantage of this method is the simplicity. In addition, you can setup a cron job to renew the token indefinitely.
Authenticating with .keytab file
If you would like to authenticate using your .keytab file, you have to include the following statement in your code:
import org.apache.hadoop.security.UserGroupInformation;
(...)
String principle = YOUR PRINCIPLE;
String keytab = YOUR KEYTAB PATH;
UserGroupInformation.loginUserFromKeytab(principle, keytab);
Once this is done, you will have programmatically obtained a Kerberos token. The advantage of this solution is that you rely on your code to obtain the token. It is safer and more reliable.
Token expiry
Please note that kerberos token expires after a time. Regardless of your mode of authentication you must take care of renewing your token.
Configuration
From this point on all you need to configure is the service endpoint for NXCALS. This is done via a system property.
static {
System.setProperty("service.url",
"https://cs-ccr-nxcals6.cern.ch:19093,https://cs-ccr-nxcals7.cern.ch:19093,https://cs-ccr-nxcals8.cern.ch:19093");
}
static {
System.setProperty("service.url",
"https://cs-ccr-testbed2.cern.ch:19093,https://cs-ccr-testbed3.cern.ch:19093,https://cs-ccr-nxcalstbs1.cern.ch:19093");
}
Temporary
We are working on simplifying this step. Soon you will not have to declare the service endpoints.
API differences
We have aimed at maintaining maximum API compatibility with old CALS API. As the systems differ deeply, there is a number of small and unavoidable changes in the Backport project, both in the syntax and logic. However, for the sake of this document the main concern is that we have replaced the old ServiceBuilder method:
public static ServiceBuilder newInstance(String app, String client, DataLocationPreferences prefs)
with:
public static ServiceBuilder getInstance()
The old method lost its meaning, as there is no DataLocationPreference anymore, and the authentication is not performed via app and client name. The new method assumes reasonable defaults with respect to the Spark connection and abstracts the users completely from the spark layer. It is sufficient for most simple use-cases.
Other methods of Spark session creation are presented on dedicated page.
Putting it all together
At this point your project should look something like this:
package cern.nxcals.docs;
// NOTICE THE NEW PACKAGES ON IMPORTS
import cern.nxcals.api.backport.client.service.ServiceBuilder;
import cern.nxcals.api.backport.client.service.TimeseriesDataService;
import cern.nxcals.api.backport.domain.core.metadata.Variable;
import cern.nxcals.api.backport.domain.core.timeseriesdata.TimeseriesDataSet;
import cern.nxcals.api.backport.domain.util.TimestampFactory;
import com.google.common.collect.ImmutableList;
import org.apache.hadoop.security.UserGroupInformation;
import java.io.IOException;
class Main {
static {
// CONFIGURATION
System.setProperty("service.url",
"https://cs-ccr-nxcals6.cern.ch:19093,https://cs-ccr-nxcals7.cern.ch:19093,https://cs-ccr-nxcals8.cern.ch:19093");
}
public static void main(String[] args) throws IOException {
// AUTHENTICATION
String principle = "YOUR PRINCIPLE";
String keytab = "YOUR KEYTAB PATH";
UserGroupInformation.loginUserFromKeytab(principle, keytab);
String variableName = "YOUR VARIABLE";
// below BACKPORT API using a default Spark configuration
ServiceBuilder serviceBuilder = ServiceBuilder.getInstance();
TimeseriesDataService timeseriesDataService = serviceBuilder.createTimeseriesService();
Variable variable = serviceBuilder.createMetaService()
.getVariablesWithNameInListofStrings(ImmutableList.of(variableName)).iterator().next();
TimeseriesDataSet data = timeseriesDataService.getDataInTimeWindow(variable,
TimestampFactory.parseUTCTimestamp("2018-06-19 00:00:00.000"),
TimestampFactory.parseUTCTimestamp("2018-06-19 00:05:00.000"));
System.out.println("Values for variable : " + variable.getVariableName() + " size: " + data.size());
}
}
For many more examples please consult the examples project,
where you will find a fully configured and runnable classes with all the aspects of the backport api.
All you need to do is to checkout the project and navigate to the module backport-api-examples
and explore.