Skip to content

docs: rewrite README for third-party developers - #33

Merged
qeeqez merged 2 commits into
mainfrom
docs/readme-rewrite
Aug 29, 2026
Merged

docs: rewrite README for third-party developers#33
qeeqez merged 2 commits into
mainfrom
docs/readme-rewrite

Conversation

@TheBraveByte

@TheBraveByte TheBraveByte commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

The quickstart in this README did not work. It called symbols that do not exist in the generated client, so anyone following it hit a compile or import error before their first request.

This rewrite follows the same structure as the Go SDK README (rixlhq/rixl-go#26): intro → Installation → Getting started → Authentication → What you can do → Working with resources → Uploading files → Pagination → Handling errors → Timeouts → Versioning → Support.

  • Every code sample uses symbols verified against the generated code in this repo. Anything that could not be verified was left out rather than guessed.
  • The API is presented as the six domains from gateway/docs/domains.yaml — Media, Content, Analytics, Billing, Accounts, Platform — instead of three media resources.
  • Authentication now covers all three paths: API keys for your own backend, client credentials for acting on behalf of one of your users, and the endpoints that need no credentials at all.
  • Maintainer content — regeneration, codegen notes, release process — moved out of the README into CONTRIBUTING.md. Third-party users should not be reading our build instructions.

The dashboard link points at https://rixl.com; that and api.rixl.com are the only URLs attested in the repos. Worth replacing with the API-keys page once we have the URL.

Summary by CodeRabbit

  • Documentation
    • Added contributor guidance for SDK generation, builds, and release/versioning procedures.
    • Expanded the README with installation, setup, authentication, API usage, uploads, pagination, error handling, timeouts, versioning, and support guidance.
    • Updated examples to reflect current request paths, authentication options, upload workflows, and error behavior.

@TheBraveByte
TheBraveByte requested a review from qeeqez as a code owner August 3, 2026 15:14
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The PR adds contributor guidance and replaces the README with SDK 1.1.0 documentation. It covers generation, builds, releases, installation, authentication, API resources, uploads, pagination, errors, timeouts, and support.

Changes

SDK Documentation

Layer / File(s) Summary
Contributor and release workflow
CONTRIBUTING.md, README.md
Contributor guidance describes generated SDK ownership, Kiota regeneration, Java builds, release versioning, and SemVer guidance.
Installation and authentication
README.md
The README documents Java 17, Maven and Gradle installation, client setup, API-key authentication, client credentials, bearer tokens, revocation, and anonymous access.
API operations and runtime behavior
README.md
The README documents resource areas, request bodies, uploads, pagination, nullable fields, ApiException, IOException, timeouts, and request interception.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: qeeqez

Poem

A rabbit taps docs with a soft little hop,
New SDK paths make confusion stop.
Keys, uploads, and pages now shine,
Errors and timeouts fall into line.
“Regenerate cleanly!” the bunny sings,
While release notes flutter on springtime wings.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main README documentation rewrite for third-party developers.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/readme-rewrite

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (1)
CONTRIBUTING.md (1)

9-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Pin the SDK regeneration inputs.

CONTRIBUTING.md documents Kiota 1.34.1, but gen.sh runs the kiota executable on PATH instead of validating or wrapping that version. gen.sh also downloads the OpenAPI spec from refs/heads/main, which can change after merge. Pin the Kiota version and use an immutable OpenAPI commit or release reference for regeneration.

Also applies to: gen.sh:5, CONTRIBUTING.md:23.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CONTRIBUTING.md` around lines 9 - 10, Pin the SDK regeneration inputs
consistently: update gen.sh to invoke or validate Kiota 1.34.1 instead of
relying on an arbitrary PATH executable, and replace the OpenAPI spec’s
refs/heads/main URL with an immutable commit or release reference. Keep
CONTRIBUTING.md aligned with the exact pinned Kiota version and spec reference.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Around line 292-294: Update the pagination explanation in the README to match
the implementation: replace “short page” with “empty page” if the loop stops
only when no items are returned, or revise the loop to stop when the item count
is less than limit if that is the intended behavior.
- Around line 296-300: Update the README “Handling errors” section to state that
4xx and 5xx responses are thrown as com.microsoft.kiota.ApiException, while 3xx
responses are returned without throwing. Keep the existing status-code and
response-header details for thrown errors.
- Around line 253-258: Update the README upload example around the `put` request
and `HttpClient.send` call to retain the `HttpResponse`, validate that its
status code is in the 2xx range, and surface an error before continuing when the
upload fails.
- Around line 108-110: Update the README sample around the credential creation
flow to remove the System.out.println call for created.getClientSecret(). Do not
expose the secret in terminal or CI output; direct it to the project’s
established secret-manager handling if one is available, while preserving the
client ID output.
- Around line 143-147: Update the AccessTokenProvider documentation to explain
that an empty AllowedHostsValidator allowlist permits every host, then show
getAllowedHostsValidator() returning an allowlist containing only the provider’s
configured trusted API hosts instead of new AllowedHostsValidator(). Keep the
bearer-token and token-caching guidance unchanged.
- Around line 278-286: Update the pagination loop around images.get so it checks
whether page is null before calling page.getImages(). Break when page is null or
its image collection is null or empty, while preserving the existing image
iteration for valid non-empty pages.

---

Nitpick comments:
In `@CONTRIBUTING.md`:
- Around line 9-10: Pin the SDK regeneration inputs consistently: update gen.sh
to invoke or validate Kiota 1.34.1 instead of relying on an arbitrary PATH
executable, and replace the OpenAPI spec’s refs/heads/main URL with an immutable
commit or release reference. Keep CONTRIBUTING.md aligned with the exact pinned
Kiota version and spec reference.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b300e772-111a-441d-a1d8-11fac95d059b

📥 Commits

Reviewing files that changed from the base of the PR and between 958a73a and 4c07578.

📒 Files selected for processing (2)
  • CONTRIBUTING.md
  • README.md

Comment thread README.md
Comment on lines +108 to +110
var created = client.platform().clientauth().v1().credentials().post(request);
System.out.println(created.getCredential().getClientId());
System.out.println(created.getClientSecret());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not print the client secret.

The sample writes created.getClientSecret() to standard output. CI logs and terminal capture can retain this credential. Store it directly in a secret manager and never log it.

Proposed change
- System.out.println(created.getClientSecret());
+ // Store created.getClientSecret() in a secret manager. Never log it.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 108 - 110, Update the README sample around the
credential creation flow to remove the System.out.println call for
created.getClientSecret(). Do not expose the secret in terminal or CI output;
direct it to the project’s established secret-manager handling if one is
available, while preserving the client ID output.

Comment thread README.md
Comment on lines +143 to +147
`AccessTokenProvider` has two methods. `getAuthorizationToken(URI, Map)` is
where you return `getAccessToken()` from a mint call and cache it until
`getExpiresAt()`, and `getAllowedHostsValidator()` can return
`new AllowedHostsValidator()` to allow every host. Tokens go out as
`Authorization: Bearer`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n 'microsoft-kiota|<version>' pom.xml
curl -fsSL \
  https://raw.githubusercontent.com/microsoft/kiota-java/main/components/abstractions/src/main/java/com/microsoft/kiota/authentication/AllowedHostsValidator.java \
  | rg -n 'AllowedHostsValidator|validHosts\.isEmpty'

Repository: rixlhq/rixl-java

Length of output: 1217


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '\n--- README lines 130-160 ---\n'
sed -n '130,160p' README.md | nl -ba -v130

printf '\n--- AllowedHostsValidator v1.9.3 ---\n'
curl -fsSL \
  https://raw.githubusercontent.com/microsoft/kiota-java/v1.9.3/components/abstractions/src/main/java/com/microsoft/kiota/authentication/AllowedHostsValidator.java \
  | nl -ba

printf '\n--- Authentication middleware references ---\n'
rg -n 'AllowedHostsValidator|getAllowedHostsValidator|addAuthentication|Authentication' .github pom.xml README.md src 2>/dev/null || true

printf '\n--- Kiota Java source evidence for allowed hosts ---\n'
python3 - <<'PY'
import urllib.request, sys
url='https://raw.githubusercontent.com/microsoft/kiota-java/v1.9.3/src/main/java/com/microsoft/kiota/RequestInformation.java'
try:
    data=urllib.request.urlopen(url, timeout=20).read().decode('utf-8','replace')
    for needle in ['getAllowedHostsValidator','AllowedHostsValidator']:
        print(f'-- {needle}')
        idx=data.find(needle)
        if idx != -1:
            start=max(0,idx-1500)
            end=min(len(data),idx+2500)
            print(data[start:end])
            print('---')
except Exception as e:
    print(f'[{needle}: ERROR {e}]')
PY

Repository: rixlhq/rixl-java

Length of output: 224


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '\n--- README lines 130-160 ---\n'
sed -n '130,160p' README.md

printf '\n--- AllowedHostsValidator v1.9.3 ---\n'
curl -fsSL \
  https://raw.githubusercontent.com/microsoft/kiota-java/v1.9.3/components/abstractions/src/main/java/com/microsoft/kiota/authentication/AllowedHostsValidator.java

printf '\n--- RequestInformation references ---\n'
curl -fsSL "https://raw.githubusercontent.com/microsoft/kiota-java/v1.9.3/components/abstractions/src/main/java/com/microsoft/kiota/authentication/AllowedHostsValidator.java" -o /tmp/AllowedHostsValidator.java
curl -fsSL "https://raw.githubusercontent.com/microsoft/kiota-java/v1.9.3/components/abstractions/src/main/java/com/microsoft/kiota/http/HttpRequestMessage.java" -o /tmp/HttpRequestMessage.java
curl -fsSL "https://raw.githubusercontent.com/microsoft/kiota-java/v1.9.3/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java" -o /tmp/RequestInformation.java
for f in /tmp/AllowedHostsValidator.java /tmp/HttpRequestMessage.java /tmp/RequestInformation.java; do
  printf '\n#### %s ####\n' "$f"
  grep -n "AllowedHostsValidator\|allowedHostsValidator\|validHosts.isEmpty\|getAllowedHostsValidator\|setAllowedHostsValidator" "$f" || true
done

printf '\n--- Repository references ---\n'
grep -RIn "new AllowedHostsValidator\\(\\)|getAllowedHostsValidator\\(|AllowedHostsValidator" . || true

Repository: rixlhq/rixl-java

Length of output: 3738


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '--- RequestInformation v1.9.3 snippet ---\n'
curl -fsSL "https://raw.githubusercontent.com/microsoft/kiota-java/v1.9.3/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java" |
sed -n '1,220p' | grep -n -C 4 "AllowedHostsValidator\|allowedHostsValidator\|getAllowedHostsValidator\|setAllowedHostsValidator\|AuthProvider"

printf '\n--- Repository references ---\n'
grep -RIn "new AllowedHostsValidator\\(\\)|getAllowedHostsValidator\\(|AllowedHostsValidator" . || true

printf '\n--- README lines 130-160 ---\n'
sed -n '130,160p' README.md

Repository: rixlhq/rixl-java

Length of output: 245


🏁 Script executed:

#!/bin/sh
set -euo pipefail

printf '%s\n' '--- RequestInformation v1.9.3 snippet ---'
curl -fsSL "https://raw.githubusercontent.com/microsoft/kiota-java/v1.9.3/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java" | \
  sed -n '1,240p' | grep -n -C 4 "AllowedHostsValidator\|allowedHostsValidator\|getAllowedHostsValidator\|setAllowedHostsValidator\|AuthProvider" || true

printf '%s\n' ''
printf '%s\n' '--- Repository references ---'
grep -RIn "new AllowedHostsValidator\\(\\)|getAllowedHostsValidator\\(|AllowedHostsValidator" . || true

printf '%s\n' ''
printf '%s\n' '--- README lines 130-160 ---'
sed -n '130,160p' README.md

Repository: rixlhq/rixl-java

Length of output: 1563


🏁 Script executed:

#!/bin/sh
set -euo pipefail

printf '%s\n' '--- Kiota Java versions containing setAllowedHostsValidator/getAllowedHostsValidator ---'
python3 - <<'PY'
import urllib.request, re, json, sys
for p in ['microsoft/kiota-java/master/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java',
          'microsoft/kiota-java/v1.9.3/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java',
          'microsoft/kiota-java/v1.8.3/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java',
          'microsoft/kiota-java/v1.7.0/components/abstractions/src/main/java/com/microsoft/kiota/RequestInformation.java']:
    url='https://raw.githubusercontent.com/'+p
    try:
        text=urllib.request.urlopen(url, timeout=20).read().decode('utf-8','replace')
        hits=re.findall(r'.{0,120}(AllowedHostsValidator|allowedHostsValidator|isUrlHostValid|getAllowedHostsValidator|setAllowedHostsValidator).{0,260}', text, re.S)
        print(f'[{p}: hits={len(hits)}]')
        for h in hits[:3]:
            print(re.sub(r'\s+', ' ', h.strip()))
    except Exception as e:
        print(f'[{p}: ERROR {e}]')
PY

printf '%s\n' ''
printf '%s\n' '--- Repository AllowedHostsValidator references ---'
grep -RIn 'new AllowedHostsValidator' . || true
grep -RIn 'getAllowedHostsValidator(' . || true
grep -RIn 'AllowedHostsValidator' . || true

Repository: rixlhq/rixl-java

Length of output: 1636


🏁 Script executed:

#!/bin/sh
set -euo pipefail

printf '%s\n' '--- BaseBearerTokenAuthenticationProvider v1.9.3 ---'
curl -fsSL "https://raw.githubusercontent.com/microsoft/kiota-java/v1.9.3/components/abstractions/src/main/java/com/microsoft/kiota/authentication/BaseBearerTokenAuthenticationProvider.java" | \
  sed -n '1,260p'

printf '%s\n' ''
printf '%s\n' '--- AuthenticationProvider v1.9.3 ---'
curl -fsSL "https://raw.githubusercontent.com/microsoft/kiota-java/v1.9.3/components/abstractions/src/main/java/com/microsoft/kiota/authentication/AuthenticationProvider.java" | \
  sed -n '1,180p'

printf '%s\n' ''
printf '%s\n' '--- OkHttpRequestAdapter v1.9.3 references ---'
curl -fsSL "https://raw.githubusercontent.com/microsoft/kiota-java/v1.9.3/components/http-okHttp/src/main/java/com/microsoft/kiota/http/OkHttpRequestAdapter.java" | \
  grep -n -C 3 "RequestInformation\|authenticateRequest\|sendAsync\|setHeaders\|getHeaders" || true

Repository: rixlhq/rixl-java

Length of output: 3419


Restrict bearer tokens to trusted hosts.

new AllowedHostsValidator() creates an empty allowlist, and isUrlHostValid() treats an empty allowlist as valid for every host. Document this behavior safely and show getAllowedHostsValidator() returning an allowlist that contains only the API hosts that this provider is configured for.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 143 - 147, Update the AccessTokenProvider
documentation to explain that an empty AllowedHostsValidator allowlist permits
every host, then show getAllowedHostsValidator() returning an allowlist
containing only the provider’s configured trusted API hosts instead of new
AllowedHostsValidator(). Keep the bearer-token and token-caching guidance
unchanged.

Comment thread README.md
Comment on lines +253 to +258
var put = HttpRequest.newBuilder(URI.create(upload.getUploadUrl()))
.header("Content-Type", "image/jpeg")
.PUT(HttpRequest.BodyPublishers.ofFile(Path.of("photo.jpg")))
.build();

HttpClient.newHttpClient().send(put, HttpResponse.BodyHandlers.discarding());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Check the storage upload response.

The sample discards the HttpResponse. A 403 or 5xx response is therefore treated as a successful upload. Check for a 2xx status and surface the failure before continuing.

Proposed change
- HttpClient.newHttpClient().send(put, HttpResponse.BodyHandlers.discarding());
+ var response = HttpClient.newHttpClient()
+         .send(put, HttpResponse.BodyHandlers.discarding());
+ if (response.statusCode() < 200 || response.statusCode() >= 300) {
+     throw new IllegalStateException(
+             "Storage upload failed: HTTP " + response.statusCode());
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var put = HttpRequest.newBuilder(URI.create(upload.getUploadUrl()))
.header("Content-Type", "image/jpeg")
.PUT(HttpRequest.BodyPublishers.ofFile(Path.of("photo.jpg")))
.build();
HttpClient.newHttpClient().send(put, HttpResponse.BodyHandlers.discarding());
var put = HttpRequest.newBuilder(URI.create(upload.getUploadUrl()))
.header("Content-Type", "image/jpeg")
.PUT(HttpRequest.BodyPublishers.ofFile(Path.of("photo.jpg")))
.build();
var response = HttpClient.newHttpClient()
.send(put, HttpResponse.BodyHandlers.discarding());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new IllegalStateException(
"Storage upload failed: HTTP " + response.statusCode());
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 253 - 258, Update the README upload example around
the `put` request and `HttpClient.send` call to retain the `HttpResponse`,
validate that its status code is in the 2xx range, and surface an error before
continuing when the upload fails.

Comment thread README.md
Comment on lines +278 to +286
var page = images.get(config -> {
config.queryParameters.paginationLimit = limit;
config.queryParameters.paginationOffset = currentOffset;
});
if (offset + page.getData().size() >= page.getPagination().getTotal()) break;

if (page.getImages() == null || page.getImages().isEmpty()) {
break;
}
page.getImages().forEach(image -> System.out.println(image.getId()));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate README and relevant snippets =="
git ls-files | rg '(^|/)README\.md$' || true

if [ -f README.md ]; then
  echo "== README lines 250-300 =="
  sed -n '250,300p' README.md | nl -ba -v250
fi

echo "== search for 'images.get' and Post image examples =="
rg -n "images\.get|\\.getImages\\(|queryParameters|paginationLimit|paginationOffset|Kiota|collection requests" README.md || true

echo "== git status/stat =="
git status --short
git diff --stat || true

Repository: rixlhq/rixl-java

Length of output: 273


🌐 Web query:

Kiota Java response values are nullable collection requests nullable get returns null example

💡 Result:

In Kiota, Java code generation for response values, including collections, is designed to be resilient against ambiguous or imprecise OpenAPI descriptions [1]. Kiota typically generates models and response types that account for potential nullability, even when a property might be marked as required in an OpenAPI specification [1][2]. Key points regarding Kiota Java nullability and response handling: 1. Nullability and Annotations: Kiota uses Jakarta annotations (e.g., @jakarta.annotation.Nullable, @jakarta.annotation.Nonnull) to indicate the nullability of properties and return values [3][2]. If a schema is marked as nullable, or if Kiota determines the potential for a null value during generation, it will typically mark the field as @Nullable [2]. Conversely, fields explicitly required and non-nullable in the specification are marked with @Nonnull [2]. 2. Collection Requests: When a request returns a collection (e.g., List), the collection itself or the elements within it may be treated as nullable depending on the OpenAPI definition. Because many API descriptions lack precise nullability information, Kiota often adopts an opinionated approach to ensure that clients do not crash if a server returns a null response where one was not explicitly expected [1]. 3. Handling Null Returns: If a GET request returns null, it often corresponds to scenarios such as an empty response body (HTTP 204) or an API design where the response might be absent [1]. Developers can use a custom IResponseHandler if they need to override default behavior, such as returning a native HTTP response object or handling specific status codes differently [4]. 4. Recommended Pattern: To isolate your application code from potential nullability changes or to handle nullable collections effectively, it is recommended to implement a service adapter layer [1]. This adapter can translate the Kiota-generated nullable types into non-nullable types or defaults that are more appropriate for your application's domain logic, effectively creating an isolation boundary [1]. If you find that your generated Java code is more permissive (nullable) than you desire, ensure your OpenAPI specification explicitly marks properties as required and non-nullable (e.g., by excluding "null" from the type list and including the field in the required array), though Kiota's default generation logic remains intentionally cautious to prevent runtime exceptions [1][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== README lines 250-300 =="
sed -n '250,300p' README.md

echo
echo "== relevant README snippets =="
rg -n "images\\.get|getImages\\(|queryParameters|paginationLimit|paginationOffset|Kiota|Kiota Java|collection requests|response values are nullable" README.md || true

echo
echo "== README line count =="
wc -l README.md

Repository: rixlhq/rixl-java

Length of output: 2362


🌐 Web query:

site:raw.githubusercontent.com/microsoft/kiota-samples main get-started quickstart java kiotatesto PostsRequestBuilder images get collection requests

💡 Result:

The Kiota Java quickstart is located at:

microsoft/kiota-samples/get-started/quickstart/java

The sample uses the JSONPlaceholder Posts API; completed quickstart code is referenced by Microsoft Learn. (learn.microsoft.com)

The previously guessed kiotatesto/PostsRequestBuilder.java path appears to be outdated or incorrect.

Citations:


🌐 Web query:

microsoft learn Kiota Java list collection request builder get returns null response values nullable

💡 Result:

In Kiota-generated Java SDKs, request builder methods (such as those for collection requests) are frequently marked with @Nullable annotations [1][2][3]. This design follows the OpenAPI specification provided to the Kiota generator; if the specification does not explicitly mark a response as required, Kiota defaults to generating nullable types [1][4]. If you are experiencing unexpected null response values, consider the following technical points: 1. OpenAPI Specification: The generated code reflects the source OpenAPI document. If an endpoint's response schema is not defined as required, the generated getter method will be nullable [1][4]. 2. Handling Untyped Data: In some scenarios, particularly when an API returns generic or loosely typed JSON (such as with certain Microsoft Graph actions), the value may not be null but rather nested within an UntypedNode structure [5][6]. In such cases, standard getters might return null or a generic node object because the SDK lacks specific type information [5][6]. You can verify this by checking if the returned object can be cast to an UntypedNode or by using KiotaJsonSerialization.serializeAsString to inspect the raw structure [5][6]. 3. Collection Responses: For collection endpoints, the SDK typically returns a response object (e.g., UserCollectionResponse) which contains a list [1]. Even if no results are found, the API often returns an empty list rather than a null response object [1]. Always perform a null check on the response object itself before calling methods like getValue to avoid NullPointerException [1]. 4. Defensive Programming: Given the @Nullable annotation, it is standard practice to treat the return value as potentially null, especially if the underlying API can return different status codes (e.g., 204 No Content) [1][7]. If you believe a null response is occurring where data is expected, verify the actual HTTP response using a tool like Fiddler or Postman to ensure the server is returning the expected payload, and check if the API response includes a 204 No Content status [1][6].

Citations:


🌐 Web query:

site:github.com microsoft kiota Java ResponseHandler returns null null collection get()

💡 Result:

In Microsoft Kiota, receiving a null value or encountering issues when using a ResponseHandler with collection requests often relates to how HTTP responses—particularly "no content" (e.g., 204) or empty responses—are handled [1][2]. If you are seeing a null result or a NullPointerException (NPE) when performing a collection get operation, consider the following technical context: 1. Handling Empty Responses: Historically, some versions of Kiota-based SDKs (such as the Microsoft Graph SDK for Java) would throw a NullPointerException when processing a collection response that returned an HTTP 204 (No Content) or an empty body [1][2]. This has been addressed in later versions, which are designed to return null or an empty collection safely rather than throwing an exception [3]. Ensure your SDK and core libraries are updated to the latest versions [4]. 2. Role of the ResponseHandler: The ResponseHandler is an extensibility point that allows you to bypass default request adapter behavior and access the native HTTP response object [5][6][7]. If you are implementing a custom ResponseHandler, you are responsible for checking the state of the response (e.g., checking for nulls or successful status codes) before attempting to parse the body [5][8]. 3. Default Behavior vs. Custom Logic: When no custom ResponseHandler is provided, the Kiota RequestAdapter automatically handles the response: - If the response indicates "no content" (e.g., status 204), it typically returns null or a default empty value [9]. - If you require specific handling for different HTTP status codes, you should ensure your implementation of HandleResponseAsync correctly checks the response status before deserializing [8]. If you are experiencing a null return when you expect data, verify that the API request is successfully returning a non-empty, valid JSON response. You can debug this by implementing a temporary custom ResponseHandler that logs the status code and raw response body to confirm whether the server is sending an empty response [5][7]. Top search results for reference: [1] microsoftgraph/msgraph-sdk-java#595 [2] microsoftgraph/msgraph-sdk-java#599 [9] https://github.com/microsoft/kiota-dotnet/blob/main/src/http/httpClient/HttpClientRequestAdapter.cs [3] microsoft/kiota-java#1132 [8] microsoft/kiota#3136

Citations:


🌐 Web query:

"Kiota Java" "@nullable" "request builder" "get()" "collection"

💡 Result:

In the Java SDKs generated by Kiota, request builder get() methods are often annotated with @Nullable (typically from jakarta.annotation) because Kiota's generation logic defaults to marking responses as nullable if the underlying OpenAPI specification does not explicitly define them as required [1]. Key details regarding this behavior: 1. Rationale for @Nullable: Kiota is designed to be safe and conservative with its type annotations [1]. If the OpenAPI document lacks explicit "required" constraints for a response, the generator defaults to @Nullable to ensure developers are aware that a null return is theoretically possible based on the schema definition [1]. 2. Practical Usage: Even when a method is marked as @Nullable, many API implementations (like the Microsoft Graph SDK) will return an empty collection or a response object containing an empty list rather than null when no items are found [1]. Developers often perform null checks on the response object itself, but frequently find that the service returns a populated response wrapper even for empty result sets [1]. 3. Nullable Annotations: Kiota uses jakarta.annotation.Nullable (or sometimes javax.annotation.Nullable in older versions) to communicate these expectations to static analysis tools and IDEs [2][3]. 4. Best Practice: Because the annotation is present, it is standard practice to treat the returned object as potentially null during development, particularly if you are writing code that must strictly adhere to null-safety requirements, even if the runtime behavior of the specific API you are calling consistently provides non-null responses [1]. If you are encountering a scenario where you are unsure if you need a null check, relying on the presence of the annotation is the safest path to avoid NullPointerException errors [1]. If you are working with a collection specifically, remember to also check the contents of the response wrapper (e.g., response.getValue()) for nullability as well [1].

Citations:


Handle a null page before calling getImages().

Kiota Java collection request results can be nullable, so images.get(...) may return null. If it does, this reads page.getImages() before the null guard and can throw.

Proposed change
-    if (page.getImages() == null || page.getImages().isEmpty()) {
+    var items = page == null ? null : page.getImages();
+    if (items == null || items.isEmpty()) {
         break;
     }
-    page.getImages().forEach(image -> System.out.println(image.getId()));
+    items.forEach(image -> System.out.println(image.getId()));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var page = images.get(config -> {
config.queryParameters.paginationLimit = limit;
config.queryParameters.paginationOffset = currentOffset;
});
if (offset + page.getData().size() >= page.getPagination().getTotal()) break;
if (page.getImages() == null || page.getImages().isEmpty()) {
break;
}
page.getImages().forEach(image -> System.out.println(image.getId()));
var page = images.get(config -> {
config.queryParameters.paginationLimit = limit;
config.queryParameters.paginationOffset = currentOffset;
});
var items = page == null ? null : page.getImages();
if (items == null || items.isEmpty()) {
break;
}
items.forEach(image -> System.out.println(image.getId()));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 278 - 286, Update the pagination loop around
images.get so it checks whether page is null before calling page.getImages().
Break when page is null or its image collection is null or empty, while
preserving the existing image iteration for valid non-empty pages.

Comment thread README.md Outdated
Comment on lines +292 to +294
Nothing pages for you — ask for the next offset yourself. Responses also carry
`getTotal()`, but it deserialises as an untyped node rather than a number, so
stopping on a short page is the simpler test.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Match the pagination text to the code.

The loop stops on an empty page. It does not stop on a short page. Replace “short page” with “empty page”, or change the loop to stop when the item count is less than limit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 292 - 294, Update the pagination explanation in the
README to match the implementation: replace “short page” with “empty page” if
the loop stops only when no items are returned, or revise the loop to stop when
the item count is less than limit if that is the intended behavior.

Comment thread README.md
Comment on lines +296 to 300
## Handling errors

Anything that is not a 2xx is thrown as `com.microsoft.kiota.ApiException`,
which carries the status code and the response headers:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n 'microsoft-kiota|<version>' pom.xml
curl -fsSL \
  https://raw.githubusercontent.com/microsoft/kiota-java/main/components/http/okHttp/src/main/java/com/microsoft/kiota/http/OkHttpRequestAdapter.java \
  | rg -n 'throwIfFailedResponse|statusCode >= 300|shouldReturnNull'

Repository: rixlhq/rixl-java

Length of output: 2148


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== pom.xml relevant section =="
sed -n '45,60p;220,312p;368,472p;510,570p;615,665p' pom.xml

echo
echo "== README Handling errors section =="
sed -n '288,306p' README.md

Repository: rixlhq/rixl-java

Length of output: 1319


Document that 3xx responses do not throw ApiException.

The Kiota Java adapter version in pom.xml returns 3xx responses instead of throwing ApiException, so the README text “Anything that is not a 2xx is thrown as com.microsoft.kiota.ApiException” is inaccurate. Restrict this to the thrown 4xx/5xx behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 296 - 300, Update the README “Handling errors”
section to state that 4xx and 5xx responses are thrown as
com.microsoft.kiota.ApiException, while 3xx responses are returned without
throwing. Keep the existing status-code and response-header details for thrown
errors.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

253-258: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Set a timeout for the direct storage upload.

The read-only upload client code uses HttpClient.newBuilder()? No, the snippet uses HttpClient.newHttpClient() and sets no timeout(Duration), so the request has no timeout. Set a request timeout on HttpRequest.newBuilder(...), and use a client with connectTimeout(Duration) so network stalls do not block indefinitely.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 253 - 258, Update the direct storage upload snippet
around the put HttpRequest and HttpClient.newHttpClient() call to set a request
timeout via HttpRequest.Builder.timeout(Duration) and use an HttpClient builder
with connectTimeout(Duration). Add or reuse the required Duration import while
preserving the existing upload request and response handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Around line 188-202: Update the prose in the Account management description to
use “organization” instead of “organisation,” while preserving the existing
client.organizations() API spelling and all other documentation unchanged.
- Around line 204-205: Update the README Platform entry to remove the alternate
platform auth paths, including client.platform().auth() and clientauth().v1();
retain only the API-key path there. Keep client.auth().v1() documented in the
Account section, and do not describe it as a Platform path.

---

Outside diff comments:
In `@README.md`:
- Around line 253-258: Update the direct storage upload snippet around the put
HttpRequest and HttpClient.newHttpClient() call to set a request timeout via
HttpRequest.Builder.timeout(Duration) and use an HttpClient builder with
connectTimeout(Duration). Add or reuse the required Duration import while
preserving the existing upload request and response handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5a60da3f-c6e8-4246-8188-4c46ad844559

📥 Commits

Reviewing files that changed from the base of the PR and between 4c07578 and 9a3c51d.

📒 Files selected for processing (2)
  • CONTRIBUTING.md
  • README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • CONTRIBUTING.md

Comment thread README.md
Comment on lines +188 to +202
configuration, and `client.organizations().byOrg_id(id).projects()` for the
projects everything else hangs off. That is why so many calls take a project ID.

**Analytics**: `client.analytics().v1()`: `dashboard()`, `events()`, `posts()`,
`videos()`, `feeds()`, `funnels()`, `retention()`, `realtime()`, `top()`. Track
events and read back engagement, playback and live activity.

**Billing**: `client.billing().v1()`: `plans()`, `subscription()`,
`invoices()`, `paymentMethods()`, `checkout()`, `storageUsage()`,
`bandwidthUsage()`, `tax()`, `address()`.

**Account management**: `client.auth().v1()`: `register()`, `login()`, `token()`,
`users()`, `passkey()`, `password()`, `providers()`, `memberships()`,
`policies()`, `email()`, `blog()`. Sign-in flows including passkeys and TOTP,
organisation membership and roles, and transactional email.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use one spelling for “organization.”

At Line 202, the prose uses organisation, while the surrounding documentation uses organization. Keep client.organizations() unchanged and standardize the prose spelling.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~188-~188: Do not mix variants of the same word (‘organization’ and ‘organisation’) within a single text.
Context: ...d).feeds()for feed configuration, andclient.organizations().byOrg_id(id).projects()` for the proj...

(EN_WORD_COHERENCY)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 188 - 202, Update the prose in the Account management
description to use “organization” instead of “organisation,” while preserving
the existing client.organizations() API spelling and all other documentation
unchanged.

Source: Linters/SAST tools

Comment thread README.md
Comment on lines +204 to +205
**Platform**: `client.platform()` for `auth().v1()` and `clientauth().v1()`,
and `client.organizations().byOrg_id(id).apiKeys()` for API keys.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
rg -n --glob '*.java' 'class RixlClient|platform\(\)|auth\(\)|clientauth\(\)' .

Repository: rixlhq/rixl-java

Length of output: 550


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
sed -n '1,130p' sdk/RixlClient.java
printf '\n--- platform ---\n'
sed -n '1,80p' sdk/platform/PlatformRequestBuilder.java
printf '\n--- README relevant ---\n'
sed -n '190,212p' README.md

Repository: rixlhq/rixl-java

Length of output: 7922


Remove the alternate platform auth paths from the README.

RixlClient exposes auth() directly, but platform().auth() and platform().clientauth() are separate generated builders at /platform/auth and /platform/clientauth. Keep the Account section using client.auth().v1() unless the Platform section documents the actual /platform path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 204 - 205, Update the README Platform entry to remove
the alternate platform auth paths, including client.platform().auth() and
clientauth().v1(); retain only the API-key path there. Keep client.auth().v1()
documented in the Account section, and do not describe it as a Platform path.

@qeeqez
qeeqez merged commit a8e8b09 into main Aug 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants