Helpers and the Semantic Layer in Java
Use the helper methods (ensure, find, update, resolve, createApi …) for multi-call tasks, and Plan.planRotation / Plan.planEscalation plus ao.semantic().applyBlueprint to build a verified on-call stack that rolls back on failure.
Overview
Relevant for Developers automating multi-step AlertOps configuration
Helpers are composite operations that sit on the same resources as the endpoints. Examples:
- ao.groups().ensure (find or create).
- ao.schedules().updateFields (read, merge, write the whole shift).
- ao.alerts().resolve (close, or cancel what cannot be closed).
The semantic layer goes further. Pure planners turn intent ("after-hours rotation, primary then secondary after 15 minutes") into exact payloads that follow AlertOps' scheduling and escalation invariants. An executor then applies them, verifies every write by reading it back, and rolls back on failure. All of it is ported from the Python reference and replays Python's recorded traces.
Key benefits:
- Fewer calls to get right: whole-record writes, alert_type naming and member sequencing are handled for you.
- Invariants enforced:
- Shifts end on :59.
- Starts align to the prior Monday.
- End dates are 5 years out.
- The escalation ladder starts with Primary.
- Safe to apply: drift is reported, and a failed blueprint deletes what it created.
Helper conventions
Relevant for Developers calling helpers
Helpers take Python's positional parameters as arguments, where null means "the Python default". Keyword-only parameters and extra fields go in one trailing Map of options, keyed by the Python names. Overloads without the trailing arguments are there for the common cases. Examples:
- ao.alerts().listRecent(3, Map.of("view_all", false, "status", "Open")).
- ao.inbound().createApi("Prod API", Map.of("escalation_policy_id", 5, "recipient_groups", List.of("NOC"))).
| Helper | What it does |
| ao.groups().ensure(name[, fields]) | Returns Shared.Ensured: the record() and whether it was created(). |
| ao.users().findByUsername(name) | The user, or null (maps 400 "Invalid User" and 404). |
| ao.escalationPolicies().update(id, changes) | GET basic, then merge, then PUT the whole record. Returns the re-read record. |
| ao.schedules().createShift(groupId, name, users, options) | Builds an invariant-clean shift (GroupsHelpers.shiftPayload) and resolves an IANA time_zone option. |
| ao.inbound().createApi(name, options) | API integration with a unique source. A random one is used if omitted. |
| ao.ingest().postToUrl(apiUrl, payload) | Posts an alert payload to an integration URL. Returns the request id. |
| ao.alerts().resolve(alertId, userId[, resolution]) | Closes the alert, or cancels it when it cannot be closed. |
| ao.auth().actOnLink(link) | Runs the action behind a notification link (acknowledge, assign, escalate, close). Returns the action and the alert after it. This is how acknowledgement works end to end. |
The inbound integration URL routes by source
Two integrations with the same source share an ingest URL, and alerts can land on the wrong one. createApi and cloneUnique always give each integration its own source.
Plan a rotation and an escalation
Relevant for Developers turning on-call intent into configuration
Planners make no API calls. Inspect their output before you apply it. Plans are records that serialise with the Python field names (review_items …), so Json.toNode(plan) gives the same JSON as the Python SDK.
import com.alertops.sdk.semantic.Plan;
import java.util.List;
Plan.RotationPlan rotation = Plan.planRotation(Plan.RotationSpec.of("NOC",
List.of(new Plan.Member(Json.toNode(101), "Ann", "Lee"), new Plan.Member(Json.toNode(102), "Bo", "Ma")),
Plan.Coverage.of("after_hours"))); // Mon–Fri 17:00 → 07:59, weekly rotation
Plan.EscalationPlan escalation = Plan.planEscalation(List.of(
Plan.Step.of(0, "primary", 101), Plan.Step.of(5, "primary", 102), Plan.Step.of(15, "secondary", 101)));
System.out.println(escalation.mode() + " " + escalation.reason()); // escalation_policy, "Escalation policy Primary → Secondary …"
System.out.println(Plan.validateDesign(rotation, escalation)); // [] when clean
planEscalation chooses an escalation policy when the timeline fits its four timing levers. It falls back to a response play, with per-step waits, when it doesn't: more than 4 distinct intervals, or unequal gaps within one role.
Apply a verified stack
Relevant for Developers creating an on-call setup in a tenant
import com.alertops.sdk.semantic.Blueprint;
import com.alertops.sdk.semantic.Report;
Report report = ao.semantic().applyBlueprint(
Blueprint.of("NOC", rotation, escalation, Blueprint.IntegrationSpec.of("NOC API")));
System.out.println(report.summary()); // OK: created 4 … (+ group, + schedule, + escalation_policy, + inbound_integration)
if (!report.ok()) {
System.out.println(report.drift);
}
ao.semantic().rollback(report); // remove everything the report created
| Report member | Meaning |
| created / reused | Objects made by this call, and objects it found and reused. Rollback only deletes created. |
| drift | Differences between the plan and what the tenant read back. ok() is false when there is any drift. |
| reviewItems | Planner and validator notes. block items stop the apply. |
| rolledBack() | True after rollback. |
Blocking review items stop the apply
A blueprint whose integration has no escalation policy, or a rotation with no Primary in week 1, throws ValueError before anything is created.
Troubleshooting
Relevant for Anyone whose helper or apply fails
ValueError: group has a shift: roles are set on the shift
- Once a group has a shift, AlertOps rejects Primary and Secondary on members. Call ao.semantic().ensureMembers(groupId, userIds) without roles, or with List.of("Manager").
The report shows drift
- Read the drift line: it names the field, the planned value and the value read back. A shift that reads back continuous=True was saved differently by the server. Adjust the plan and apply again.
Related Articles
- Calling the API from Java
- Getting Started with the AlertOps Java SDK
- Testing the Java SDK
- Planning On-Call Setups with the AlertOps Semantic Layer
Need help?
Email support@alertops.com or contact your AlertOps representative.