Google DLP API — Sample Groovy (Java) integration client code

Hafiz Adewuyi
Google Cloud - Community
5 min readAug 3, 2017

This is my first medium post. I have a blog at http://www.hafiz.com.ng, so it begs the question of why I’m starting to write on Medium as well. Simple. My intention as at this time is to keep posting personal and non-professional stuff on my current blog while my Medium posts would contain only technical and career related content. That said, let’s get straight to the business of this article.

This week at work, I had to integrate a Groovy client to Google’s nascent DLP (Data-loss prevention) API. And I’d have to admit that it’s one of the most difficult things I’ve had to do recently. Funny enough, as difficult as it was working through the main challenge of the integration, the solution turned out to be rather simple.

Text with sensitive-info redacted through Google’s Data Loss Prevention (DLP) API

I’m writing this article, not because the API is difficult to figure out. No. I am because while finding solutions to the integration challenges which were honestly quite daunting at the time, I committed to making a post if I’m able to scale through them. So let’s get right into it.

CHALLENGE 1

It took me quite some time to find the correct client library to facilitate communication with the API. There seems to be so many Google repositories with DLP in their names, so I wasted quite some time playing around with the wrong libraries until I found this DLP API sample on GitHub.

Before I found this sample, I spent several fruitless hours trying to figure out this DLP client library which is the first result I found on Google. Unfortunately, I could not find any sample online that had employed it. So, I towed the arduous path of looking through the JAVADOCs and writing trial-and-error code to see if I could figure out the classes and methods that come together to make a complete solution; all to no avail.

Solution 1

The solution was finding this GitHub repo which contains sample code consuming the Google DLP API. Once I found it, all I had to do was understand the code and adapt it to my use case.

The steps are simple:

compile 'com.google.cloud:google-cloud-dlp:0.21.1-alpha'
  • The earlier referenced sample employs this client library for data inspection and redaction. Feel free to copy and paste the code into your project and adapt it to fit your context. You can find the sample code files in this GitHub repo folder.

CHALLENGE 2

Once I had included the DLP client library in my project successfully, it was time to test it out to see if it actually works for me. With the help of the sample, I quickly strung together some code that satisfied all of the input requirements of the DLP inspect method and ran my project in debug mode. This was the moment of truth.

To my dismay, there was an arcane ‘NoSuchMethod’ exception thrown from within the client library code at the point of sending an HTTP request to the DLP API.

Solution 2

Of course, I hit the search engine once more, this time with unmatched vigor. Fortunately, there were tons of other developers who had gone ahead of me to wage this war and come out alive. It didn’t take me more than 30 minutes to wriggle my way out of this one.

I found out that the exception was due to some issue with the version of the Guava library included in my Grails project (at this StackOverflow page). All I had to do to resolve it was include one more dependency in my project which specified a higher version of the Guava library (20.0) than was included in my scrap project by default (5.***)

compile 'com.google.guava:guava:20.0'

At this point, I was able to test the sample code successfully on my box. Eureka! I felt like the President of the United states when my debugger, instead of throwing up yet another arcane exception while trying to communicate with the DLP API, presented me with the beautiful JSON response whose arrival signaled the end of this episode of the life-long struggle I’ve committed myself to as a programmer.

One line to rule them all

I faced one more challenge during this integration which has nothing to do directly with the Google DLP API or client library.

CHALLENGE 3

After copying the DLP API client library dependency reference from my scrap project to the gradle build script of the main project, I could not build my project anymore (see this StackOverflow link for the exact problem I was facing).

Solution 3

It turns out that the problem was due to a Windows OS restriction on the length of the path to any application which is to be executed on the OS. And the solution was… something I would not waste time talking about because I only have a basic grasp of how it solves the problem. The link to the solution that solved my problem is right here. All I did was paste the next code snippet (verbatim) into the root level of my build.gradle file. By root level, I mean that no portion of the code snippet lives within any other code block.

Hey, before the code , I think it’s worth mentioning that a lot of the other answers to this problem recommended adding a ‘pathingJar’ task (versus the ‘launcherJar’ task in this solution) to the build script. The errors I got from my compiler made it quite clear that the task could not be created because “the task ‘pathingJar’ already exists”.

I spent quite some time trying to see a way to edit or override the default pathingJar task, all to no avail. While at this, I learned how to list all the build tasks and dependencies in my gradle project. I clearly have some reading to do on the Gradle build tool :@

task launcherJar(type: Jar) {
def gradleUserHome = new File(gradle.getGradleUserHomeDir(), "caches")

def relativeClasspathEntries = configurations.runtime.files.collect {
new File(gradleUserHome.getAbsolutePath()).toURI().
relativize(new File(it.getAbsolutePath()).toURI()).getPath()
}
appendix = "launcher"
destinationDir = gradleUserHome
doFirst {
manifest {
attributes "Class-Path": relativeClasspathEntries.join(" ")
}
}
}

compileGroovy{
dependsOn launcherJar
FileCollection collection = files(launcherJar.archivePath);
def finCollection = collection
doLast {
classpath = finCollection
}
}

bootRun{
doFirst{
//The main build directories aren't collected so they are added manually
FileCollection collection = files("${project.rootDir}/build/classes/main") + files("${project.rootDir}/build/resources/main") + files(launcherJar.archivePath)
println collection.files
classpath = collection
}
}

--

--