Knowledge Management

How to write to kvstore with java sdk?

organus
Explorer

We are trying to inject JSON directly into our KV Store instance while using a defined _key inside the JSON object.

We are not able to connect because of the following error:

2016-09-23 10:25:01 ERROR stderr:71 - com.splunk.HttpException: HTTP 400 -- <?xml version="1.0" encoding="UTF-8"?>
2016-09-23 10:25:01 ERROR stderr:71 - <response>
2016-09-23 10:25:01 ERROR stderr:71 -   <messages>
2016-09-23 10:25:01 ERROR stderr:71 -     <msg type="ERROR">Must supply 'Content-Type' header set to 'application/json'</msg>
2016-09-23 10:25:01 ERROR stderr:71 -   </messages>
2016-09-23 10:25:01 ERROR stderr:71 - </response>

We have looked for a way to add message headers to the RequestMessage object but we do not see a method in the source. Where do we inject message headers?

The method breaks on the following line:

response = service.send(kvStorePath, requestMessage);

Below is our method:

    private void writeToKVStore(File uglyJsonFile) throws IOException {
        String nextJSON = "";
        ResponseMessage response = null;
        BufferedReader br = null;
        ServiceArgs serviceArgs = null;
        Service service = null;
        RequestMessage requestMessage = null;
        int port = params.getKvStorePort();
        String kvStorePath = params.getKvStorePath();
        String kvStoreScheme = params.getKvStoreScheme();
        String kvStoreUsername = params.getkvStoreUsername();
        String kvStorePassword = params.getkvStorePassword();
        String kvStoreHost = params.getKvStoreHost();
        String kvStoreApp = params.getKvStoreApp();

        try {
            HttpService.setSslSecurityProtocol(SSLSecurityProtocol.TLSv1_2);

            serviceArgs = new ServiceArgs();
            serviceArgs.setScheme(kvStoreScheme);
            serviceArgs.setUsername(kvStoreUsername);
            serviceArgs.setPassword(kvStorePassword);
            serviceArgs.setHost(kvStoreHost);
            serviceArgs.setPort(port);
            serviceArgs.setApp(kvStoreApp); // kvStoreApp = "kvstore"


            service = Service.connect(serviceArgs);

            // TODO set up requestMessage
            // Must supply 'Content-Type' header set to 'application/json'
            requestMessage = new RequestMessage("POST");

//          service.send(params.getKvStorePath(), requestMessage);

            br = new BufferedReader(new FileReader(uglyJsonFile));

            while ((nextJSON = br.readLine()) != null) {
                requestMessage.setContent(nextJSON);
                response = service.send(kvStorePath, requestMessage);

            }

        } catch (IOException e) {
            LOGGER.error(e.getMessage());
            e.printStackTrace();
        } catch (Exception ex) {
            LOGGER.error(ex.getMessage());
            ex.printStackTrace();
            if (response != null) {
                String nextLine = "";
                LOGGER.error("Status: " + response.getStatus());
                BufferedReader responseContent = new BufferedReader(new InputStreamReader(response.getContent(), "UTF-8"));
                while((nextLine = responseContent.readLine()) != null) {
                    LOGGER.error(nextLine);
                }
            }
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                LOGGER.error(e.getMessage());
                e.printStackTrace();
                throw e;
            } 
        }

    }
0 Karma
1 Solution

organus
Explorer

We solved this problem by replicating code in the Service class. The Map returned by the RequestMessage.getHeader() method can be modified directly, without using methods in the class:

requestMessage.getHeader().put("Content-Type", "application/json");

The writeToKVStore(File) method now returns without errors. We got it all to work. This should be a fairly pluggable solution. See the working code below:

    private void writeToKVStore(File uglyJsonFile) throws IOException, Exception {
        String nextJSON = "";
        ResponseMessage response = null;
        BufferedReader br = null;
        ServiceArgs serviceArgs = null;
        Service service = null;
        RequestMessage requestMessage = null;
        int port = params.getKvStorePort();
        String kvStorePath = params.getKvStorePath();
        String kvStoreScheme = params.getKvStoreScheme();
        String kvStoreUsername = params.getkvStoreUsername();
        String kvStorePassword = params.getkvStorePassword();
        String kvStoreHost = params.getKvStoreHost();
        String kvStoreApp = params.getKvStoreApp();

        try {
            // Set up service and connect
            // This fixes an issue with conflicting security protocols in v. 1.4
            HttpService.setSslSecurityProtocol(SSLSecurityProtocol.TLSv1_2);

            serviceArgs = new ServiceArgs();
            serviceArgs.setScheme(kvStoreScheme);
            serviceArgs.setUsername(kvStoreUsername);
            serviceArgs.setPassword(kvStorePassword);
            serviceArgs.setHost(kvStoreHost);
            serviceArgs.setPort(port);
            serviceArgs.setApp(kvStoreApp); // kvStoreApp = "kvstore"

            service = Service.connect(serviceArgs);

            // Set up RequestMessage
            requestMessage = new RequestMessage("POST");
            requestMessage.getHeader().put("Content-Type", "application/json");

            // Set up stream input from file
            br = new BufferedReader(new FileReader(uglyJsonFile));

            // Loop through file and commit data to KV Store
            while ((nextJSON = br.readLine()) != null) {
                // batch_save requires an array of JSON objects.  We submit a single record at a time so we need to wrap in brackets.
                requestMessage.setContent("[" + nextJSON + "]");
                // kvStorePath = /servicesNS/nobody/kvstore/storage/collections/data/{your_collection_here}/batch_save
                response = service.send(kvStorePath, requestMessage);

            }

        } catch (IOException e) {
            LOGGER.error(e.getMessage());
            e.printStackTrace();
        } catch (Exception ex) {
            LOGGER.error(ex.getMessage());
            ex.printStackTrace();
            if (response != null) {
                String nextLine = "";
                LOGGER.error("Status: " + response.getStatus());
                BufferedReader responseContent = new BufferedReader(new InputStreamReader(response.getContent(), "UTF-8"));
                while((nextLine = responseContent.readLine()) != null) {
                    LOGGER.error(nextLine);
                }
            }
            throw ex;
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                LOGGER.error(e.getMessage());
                e.printStackTrace();
                throw e;
            } 
        }

    }

View solution in original post

organus
Explorer

We solved this problem by replicating code in the Service class. The Map returned by the RequestMessage.getHeader() method can be modified directly, without using methods in the class:

requestMessage.getHeader().put("Content-Type", "application/json");

The writeToKVStore(File) method now returns without errors. We got it all to work. This should be a fairly pluggable solution. See the working code below:

    private void writeToKVStore(File uglyJsonFile) throws IOException, Exception {
        String nextJSON = "";
        ResponseMessage response = null;
        BufferedReader br = null;
        ServiceArgs serviceArgs = null;
        Service service = null;
        RequestMessage requestMessage = null;
        int port = params.getKvStorePort();
        String kvStorePath = params.getKvStorePath();
        String kvStoreScheme = params.getKvStoreScheme();
        String kvStoreUsername = params.getkvStoreUsername();
        String kvStorePassword = params.getkvStorePassword();
        String kvStoreHost = params.getKvStoreHost();
        String kvStoreApp = params.getKvStoreApp();

        try {
            // Set up service and connect
            // This fixes an issue with conflicting security protocols in v. 1.4
            HttpService.setSslSecurityProtocol(SSLSecurityProtocol.TLSv1_2);

            serviceArgs = new ServiceArgs();
            serviceArgs.setScheme(kvStoreScheme);
            serviceArgs.setUsername(kvStoreUsername);
            serviceArgs.setPassword(kvStorePassword);
            serviceArgs.setHost(kvStoreHost);
            serviceArgs.setPort(port);
            serviceArgs.setApp(kvStoreApp); // kvStoreApp = "kvstore"

            service = Service.connect(serviceArgs);

            // Set up RequestMessage
            requestMessage = new RequestMessage("POST");
            requestMessage.getHeader().put("Content-Type", "application/json");

            // Set up stream input from file
            br = new BufferedReader(new FileReader(uglyJsonFile));

            // Loop through file and commit data to KV Store
            while ((nextJSON = br.readLine()) != null) {
                // batch_save requires an array of JSON objects.  We submit a single record at a time so we need to wrap in brackets.
                requestMessage.setContent("[" + nextJSON + "]");
                // kvStorePath = /servicesNS/nobody/kvstore/storage/collections/data/{your_collection_here}/batch_save
                response = service.send(kvStorePath, requestMessage);

            }

        } catch (IOException e) {
            LOGGER.error(e.getMessage());
            e.printStackTrace();
        } catch (Exception ex) {
            LOGGER.error(ex.getMessage());
            ex.printStackTrace();
            if (response != null) {
                String nextLine = "";
                LOGGER.error("Status: " + response.getStatus());
                BufferedReader responseContent = new BufferedReader(new InputStreamReader(response.getContent(), "UTF-8"));
                while((nextLine = responseContent.readLine()) != null) {
                    LOGGER.error(nextLine);
                }
            }
            throw ex;
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                LOGGER.error(e.getMessage());
                e.printStackTrace();
                throw e;
            } 
        }

    }
Get Updates on the Splunk Community!

Get Inspired! We’ve Got Validation that Your Hard Work is Paying Off

We love our Splunk Community and want you to feel inspired by all your hard work! Eric Fusilero, our VP of ...

What's New in Splunk Enterprise 9.4: Features to Power Your Digital Resilience

Hey Splunky People! We are excited to share the latest updates in Splunk Enterprise 9.4. In this release we ...

Take Your Breath Away with Splunk Risk-Based Alerting (RBA)

WATCH NOW!The Splunk Guide to Risk-Based Alerting is here to empower your SOC like never before. Join Haylee ...