# Java SDK

Install the Java metrics SDK, authenticate with an M2M credential, and send and query metrics with the synchronous client.

The official Java SDK provides typed request builders, response models, validation, and API exceptions for the Metrics API. This guide uses the synchronous `MetricsClient`.

Use the [API reference](/api-reference) when you need the parameters and response schema for a specific operation.

## Requirements

The SDK requires Java 17 or newer and is published to Maven Central. Add the metrics module to your Maven project:

```xml
<dependency>
    <groupId>cloud.omas.sdk</groupId>
    <artifactId>metrics</artifactId>
    <version>0.2.0</version>
</dependency>
```

The shared `core` module and its runtime dependencies are included transitively.

## Configure authentication

Use an exchange-only M2M credential for a service, job, or other unattended workload. On the **API tokens** page, [create a token](/docs/tokens#create-a-token-in-the-ui) and select **Exchange only** as its access mode. Store the credential in your secret manager and expose it to the process as `OMAS_M2M_TOKEN`; never commit it to source control.

`M2mAuthProvider` exchanges the credential for short-lived, metrics-scoped access tokens and refreshes them automatically. A token created in **Direct** mode is sent to service APIs as a bearer token and is not the credential this provider expects.

## Create a client

Create the authentication provider and client once, reuse the client for requests, and close both when the application shuts down. Both types implement `AutoCloseable`, so try-with-resources is a good fit for short-lived programs:

```java
import cloud.omas.sdk.core.M2mAuthProvider;
import cloud.omas.sdk.metrics.MetricsClient;
import cloud.omas.sdk.metrics.model.ListMetricsOperationRequest;
import cloud.omas.sdk.metrics.model.ListMetricsResponse;

try (M2mAuthProvider authProvider = M2mAuthProvider.builder()
        .credential(System.getenv("OMAS_M2M_TOKEN"))
        .build();
     MetricsClient metrics = MetricsClient.builder()
        .authProvider(authProvider)
        .build()) {
    ListMetricsResponse response = metrics.listMetrics(
            ListMetricsOperationRequest.builder()
                    .maxResults(25)
                    .build());

    response.metrics().forEach(metric -> System.out.println(metric.name()));
}
```

Reuse the authentication provider and client instead of creating new instances for every request.

## Send a metric

Every SDK operation accepts one generated operation-request object. Request fields use immutable builder-based models:

```java
import cloud.omas.sdk.metrics.model.DataPoint;
import cloud.omas.sdk.metrics.model.PutMetricDataOperationRequest;

import java.math.BigDecimal;
import java.util.List;

metrics.putMetricData(
        PutMetricDataOperationRequest.builder()
                .metricName("cpu_usage")
                .entries(List.of(DataPoint.builder()
                        .timestamp(System.currentTimeMillis())
                        .value(BigDecimal.valueOf(42.7))
                        .resolution(60)
                        .build()))
                .build());
```

See [Send your first metric](/docs/send-metric) for dimensions and pre-aggregated statistic sets.

## Query metric data

Pass Unix epoch milliseconds for the time range. The response contains the returned data points and pagination token:

```java
import cloud.omas.sdk.metrics.model.GetMetricDataOperationRequest;
import cloud.omas.sdk.metrics.model.GetMetricDataResponse;

long endTimestamp = System.currentTimeMillis();
long startTimestamp = endTimestamp - 3_600_000L;

GetMetricDataOperationRequest request = GetMetricDataOperationRequest.builder()
        .metricName("cpu_usage")
        .startTimestamp(startTimestamp)
        .endTimestamp(endTimestamp)
        .resolution(60)
        .aggregation("avg")
        .build();

GetMetricDataResponse response = metrics.getMetricData(request);
```

Read [Metric rollups and resolution](/docs/metric-rollups-resolution) before choosing an aggregation and resolution for production queries.

## Handle errors

The SDK decodes documented API errors into typed exceptions. Catch a specific exception when the application can recover from that condition, then use `ApiException` as the common fallback for API responses:

```java
import cloud.omas.sdk.core.exception.ApiException;
import cloud.omas.sdk.metrics.exception.ResourceNotFoundException;
import cloud.omas.sdk.metrics.model.GetMetricDataOperationRequest;

GetMetricDataOperationRequest request = GetMetricDataOperationRequest.builder()
        .metricName("cpu_usage")
        .startTimestamp(System.currentTimeMillis() - 3_600_000L)
        .build();

try {
    metrics.getMetricData(request);
} catch (ResourceNotFoundException exception) {
    System.err.println("Metric not found: " + exception.getMessage());
} catch (ApiException exception) {
    System.err.printf(
            "Metrics request failed: status=%d code=%s requestId=%s%n",
            exception.statusCode(),
            exception.errorCode(),
            exception.requestId());
}
```

Generated builders throw `IllegalArgumentException` for invalid input before a request is sent. Authentication, timeout, serialization, and transport failures use SDK exceptions from `cloud.omas.sdk.core.exception`. Log the request ID when it is available and retry only when the failure type and operation make that safe.

## Next steps

- Browse the [API reference](/api-reference) for HTTP and Java examples for every operation supported by the SDK.
- Review the [public SDK repository](https://github.com/omascloud/sdks) for source code and release information.
- Use [Send your first metric](/docs/send-metric) for richer ingestion examples.
- Use [Metric rollups and resolution](/docs/metric-rollups-resolution) to design queries, dashboards, and alarms.
