OPA Java Tutorial: Hello World
This Hello World style tutorial explains how to set up a basic Java project which is able to import the OPA Java SDK and use it to evaluate a policy decision.
Setup
In a new directory, run gradle init
. The prompts should be responded to as follows:
Select type of build to generate:
ApplicationSelect implementation language:
JavaEnter target Java version:
21Project name:
docsampleSelect application structure:
Single application projectSelect build script DSL:
GroovySelect test framework:
JUnit JupiterGenerate build using new APIs and behavior:
no
Gradle should print a message like the one below if everything went right.
BUILD SUCCESSFUL in 3m 56s
1 actionable task: 1 executed
Before proceeding, verify that the project Gradle created for us is able to build and run. The output should look similar to the below.
./gradlew run
> Task :app:run
Hello World!
BUILD SUCCESSFUL in 627ms
2 actionable tasks: 2 executed
Adding the OPA Java SDK
Next, modify the Java code to utilize the OPA Java SDK in app/src/main/java/org/example/App.java
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example;
import com.styra.opa.OPAClient;
import com.styra.opa.OPAException;
import java.util.Map;
import java.util.List;
import static java.util.Map.entry;
public class App {
public String getGreeting() {
return "Hello World!";
}
public static void main(String[] args) {
public static void main(String[] args) throws OPAException {
System.out.println(new App().getGreeting());
// Create an OPA instance, this handles any state needed for interacting
// with OPA, and can be re-used for multiple requests if needed.
String opaURL = "http://localhost:8181";
OPAClient opa = new OPAClient(opaURL);
// This will be the input to our policy.
java.util.Map<String,Object> input = java.util.Map.ofEntries(
entry("subject", "alice"),
entry("action", "read"),
entry("resource", "/finance/reports/fy2038_budget.csv")
);
boolean allowed = false;
// Perform the request against OPA.
try {
allowed = opa.check("authz/allow", input);
} catch (OPAException e ) {
// Note that OPAException usually wraps other exception types, in
// case you need to do more complex error handling.
System.out.println("exception while making request against OPA: " + e);
throw e; // crash the program
}
System.out.println("allowed: " + allowed);
}
}
The app/build.gradle
file must also be updated to pull in the OPA-Java SDK. Under the dependencies
section, add the following:
implementation group: 'com.styra', name: 'opa', version: '+'
Using the version string +
causes Gradle to pull in the latest version of that dependency. In a production environment, it may be preferable to pin a specific version of your dependencies instead.
Creating policies and running OPA
The sample application is almost ready to run, but first an OPA instance is needed for the SDK to communicate with.
Create a policy/
folder and the following two files:
policy/authz/authz.rego
package authz
import rego.v1
default allow := false
allow if input.subject == "alice"
policy/data.json
{
"roles": {
"admin": ["read", "write"]
}
}
Next, launch OPA in a separate terminal window:
opa run --server --bundle ./policy/
In the original terminal window, verify that the data was loaded into OPA correctly:
curl -Ss http://localhost:8181/v1/data/roles
{"result":{"admin":["read","write"]}}
Verify that the policy is working as expected:
curl -Ss http://localhost:8181/v1/data/authz/allow -X POST -d '{"input": {"subject": "alice"} }'
{"result":true}
curl -Ss http://localhost:8181/v1/data/authz/allow -X POST -d '{"input": {"subject": "bob"} }'
{"result":false}
Running the application
Finally, run the Java program:
./gradlew run
> Task :app:run
Hello World!
allowed: true
BUILD SUCCESSFUL in 2s
2 actionable tasks: 2 executed
Notice the addition of the response from OPA.
The project is now prepared for experimenting with the OPA Java SDK locally. Try modifying App.java
or the OPA policy and see how the behavior changes.
Final Code
app/src/main/java/org/example/App.java
:
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example;
import com.styra.opa.OPAClient;
import com.styra.opa.OPAException;
import java.util.Map;
import java.util.List;
import static java.util.Map.entry;
public class App {
public String getGreeting() {
return "Hello World!";
}
public static void main(String[] args) throws OPAException {
System.out.println(new App().getGreeting());
// Create an OPA instance, this handles any state needed for interacting
// with OPA, and can be re-used for multiple requests if needed.
String opaURL = "http://localhost:8181";
OPAClient opa = new OPAClient(opaURL);
// This will be the input to our policy.
java.util.Map<String,Object> input = java.util.Map.ofEntries(
entry("subject", "alice"),
entry("action", "read"),
entry("resource", "/finance/reports/fy2038_budget.csv")
);
boolean allowed = false;
// Perform the request against OPA.
try {
allowed = opa.check("authz/allow", input);
} catch (OPAException e ) {
// Note that OPAException usually wraps other exception types, in
// case you need to do more complex error handling.
System.out.println("exception while making request against OPA: " + e);
throw e; // crash the program
}
System.out.println("allowed: " + allowed);
}
}