Overview of the Splunk SDK for Java

Welcome to the Splunk® Software Development Kit (SDK) for Java!

This SDK is open source and uses the Apache v2.0 license. If you want to make a code contribution, go to the Open Source page for more information.

This overview tells you more about:

 

What you can do with the Splunk SDK for Java

This SDK contains library code and examples designed to enable developers to build applications using Splunk. With the Splunk SDK for Java you can write Java applications to programmatically interact with the Splunk engine. The SDK is built on top of the REST API, providing a wrapper over the REST API endpoints. So with fewer lines of code, you can write applications that:

  • Search your data, run saved searches, and work with search jobs.
  • Manage Splunk configurations and objects.
  • Integrate search results into your applications.
  • Log directly to Splunk.
  • Present a custom UI.

With the Splunk SDK for Java, you can use different tools and IDEs. We even have a plug-in for the Eclipse IDE that makes development even easier. Here's an example application that was created using NetBeans (of course, we also have project-level support for Eclipse and IntelliJ). This Splunk Explorer application shows the values of various settings in your local Splunk instance:

Splunk Explorer app

For more examples of applications created with Splunk SDKs, see the Splunk Developer Application Gallery.

 

The Splunk SDK for Java components

The Splunk developer platform consists of three primary components: Splunkd, the engine; Splunk Web, the app framework that sits on top of the engine; and the Splunk SDKs that interface with the REST API and extension points.

The Splunk SDK for Java lets you target Splunkd by making calls against the engine's REST API and accessing the various Splunkd extension points such as custom search commands, lookup functions, scripted inputs, and custom REST handlers.

Read more about:

 

Namespaces

To account for permissions to view apps, system files, and other entity resources by users throughout a Splunk installation, Splunk provides access to entity resources based on a namespace. This is similar to the app/user context that is used by the Splunk REST API when accessing resources using endpoints.

The namespace is defined by:

  • An owner, which is the Splunk username, such as "admin". A value of "nobody" means no specific user. The "-" wildcard means all users.
  • An app, which is the app context for this resource (such as "search"). The "-" wildcard means all apps.
  • A sharing mode, which indicates how the resource is shared. The sharing mode can be:
    • "user": The resource is private to a specific user, as specified by owner.

      "app": The resource is shared through an app, as specified by app. The owner is "nobody", meaning no specific user.

      "global": The resource is globally shared to all apps. The owner is "nobody", meaning no specific user.

      "system": The resource is a system resource (owner is "nobody", app is "system").

In general, when you specify a namespace you can specify any combination of owner, app, and sharing the SDK library will reconcile the values, overriding them as appropriate. If a namespace is not explicitly specified, the current user is used for owner and the default app is used for app.

Here are some example combinations of owner, app, sharing:

  • List all of the saved searches for a specific user named Kramer: kramer, -, user
  • Create an index to be used within the Search app: nobody, search, app
 

The Service class

The Service class is the primary entry point for the client library. Construct an instance of the Service class and provide the login credentials that are required to connect to an available Splunk server. There are different ways to construct the instance and authenticate—here's one way:

// Create a map of arguments and add login parameters
ServiceArgs loginArgs = new ServiceArgs();
loginArgs.setUsername("admin");
loginArgs.setPassword("changeme");
loginArgs.setHost("localhost");
loginArgs.setPort(8089);

// Create a Service instance and log in with the argument map
Service service = Service.connect(loginArgs);

For additional examples, see How to connect to Splunk.

Once the Service instance is created and authenticated, you can use it to navigate, enumerate, and operate on a wide variety of Splunk resources.

 

Entities and collections

The Splunk REST API consists of over 160 endpoints that provide access to almost every feature of Splunk. The majority of the Splunk SDK for Java API follows a convention of exposing resources as collections of entities, where an entity is a resource that has properties, actions, and metadata that describes the entity. The entity/collection pattern provides a consistent approach to interacting with resources and collections of resources.

For example, the following code prints all Splunk users:

Service service = Service.connect(...);
for (User user : service.getUsers().values())
    System.out.println(user.getName());

Similarly, the following code prints all the Splunk apps:

Service service = Service.connect(...);
for (Application app : service.getApplications().values())
    System.out.println(app.getName());

Collections use a common mechanism to create and remove entities. Entities use a common mechanism to retrieve and update property values, and access entity metadata. Once you're familiar with this pattern, you'll have a reasonable understanding of how the SDK and underlying REST API work.

The SDK contains the base classes Entity and EntityCollection, both of which derive from the common base class Resource. Note that Service is not a Resource, but is a container that provides access to all features associated with a Splunk instance.

The class hierarchy for the core SDK library is as follows:

Service
Resource
    Entity
    ResourceCollection
        EntityCollection

When you retrieve a collection, you can limit the number of items you retrieve at a time by specifying count and offset arguments when you instantiate a collection object. Set count to the number of items to retrieve, and use offset to indicate where in the collection to retrieve them. For example, to page through 30 items at a time in the configuration file collection, you'd set the count to 30, and the offset to increments of 30:

int count = 30;
int offset = 0;
ConfCollection confs;
CollectionArgs collargs = new CollectionArgs();
collargs.setCount(count);
collargs.setOffset(offset);

confs = service.getConfs(collargs);
// Got the first 30 elements

offset = offset + 30;
collargs.setOffset(offset);
confs = service.getConfs(collargs);
// Got the next 30 elements
 

Managing state between the client and server

When you create an object for an entity, the entity's properties are read and copied from the server, creating a local snapshot of those values. Any set operations on the object are only made to the local object. Your changes are not made on the server until you explictly call the object's update method, which uploads all the changes you've made to that object. And, changes made on the server don't affect your local copy unless you call the object's refresh method, which replaces any changes you have made with an updated snapshot from the server.

The SDK does not perform validation on values when you set them, but rather passes these values to the server for validation. Any error messages from the server are then sent back to you through the SDK.

There are two ways to set values for an entity:

  • Use the setter methods that are available for the entity, then call update to upload all the changes you've made to this entity. For example:
  • EventTypeCollection eventTypeCollection = service.getEventTypes();
    EventType eventType = eventTypeCollection.create("test", "index=_internal *");
    eventType.setDescription("This is a test");
    eventType.setPriority(3);
    eventType.update();
    
  • Create a map of arguments, and then call update(args) to upload all of the specified arguments for this entity. For example:
  • EventTypeCollection eventTypeCollection = service.getEventTypes();
    Args args = new Args();
    args.put("description", "This is a test");
    args.put("priority", 3);
    EventType eventType = eventTypeCollection.create("test", "index=_internal *", args);
    

    A call to update(args) also includes any changes you made using the setter methods. For example:

    EventTypeCollection eventTypeCollection = service.getEventTypes();
    EventType eventType = eventTypeCollection.create("test", "index=_internal *");
    Args args = new Args();
    
    eventType.setPriority(3);
    args.put("description", "This is a test");
    eventType.update(args); // Updates both the description and priority
    

    Argument maps require a little more work because you must know which arguments are allowed for that entity, carefully specifying the case-sensitive argument name with a value in the expected format. However, using an argument map also lets you set values for any argument that is allowed for a given entity—even if there isn't a corresponding setter method for it. In addition, you must use an argument map if you want to initialize an object with values, because setters aren't available until after an object has been created.