Skip to content

Added default non-endpoint methods - #51327

Merged
shawkins merged 2 commits into
keycloak:mainfrom
edewit:non-default-endpoint
Aug 4, 2026
Merged

Added default non-endpoint methods#51327
shawkins merged 2 commits into
keycloak:mainfrom
edewit:non-default-endpoint

Conversation

@edewit

@edewit edewit commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

fixes: #50221
Signed-off-by: Erik Jan de Wit erikjan.dewit@gmail.com

fixes: keycloak#50221
Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
@edewit
edewit requested a review from a team as a code owner July 31, 2026 09:46
Copilot AI review requested due to automatic review settings July 31, 2026 09:46
@edewit
edewit requested a review from a team as a code owner July 31, 2026 09:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds typed convenience methods to Admin API v2 while preserving access to raw JAX-RS responses.

Changes:

  • Introduces TypedResponse<T> with typed deserialization and resource cleanup.
  • Adds typed create and upsert convenience methods.
  • Covers wrapper behavior and endpoint integration.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
rest/admin-v2/api/src/main/java/org/keycloak/admin/api/TypedResponse.java Adds the typed response wrapper.
rest/admin-v2/api/src/main/java/org/keycloak/admin/api/client/ClientsApi.java Adds typed client creation.
rest/admin-v2/api/src/main/java/org/keycloak/admin/api/client/ClientApi.java Adds typed client upsert.
rest/admin-v2/api/src/test/java/org/keycloak/admin/api/TypedResponseTest.java Tests wrapper behavior.
rest/admin-v2/tests/src/test/java/org/keycloak/tests/admin/client/v2/ClientApiV2Test.java Tests typed methods end to end.

@michalvavrik michalvavrik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I didn't find anything wrong about this PR, except that IMO it is not useful and I would not go there. The linked issue says:

To stick with Resteasy classic compatibility

I don't think we need this compatibility. I am -1 for this PR.

@vmuzikar

vmuzikar commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

@michalvavrik This is mostly for convenience if the API is consumed through the Java Admin Client, i.e. RestEasy proxy. That's the main motivation for this.

@vmuzikar vmuzikar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, thanks @edewit.

@shawkins Do you want to give this a look too?

@michalvavrik

Copy link
Copy Markdown
Member

@michalvavrik This is mostly for convenience if the API is consumed through the Java Admin Client, i.e. RestEasy proxy. That's the main motivation for this.

However, it doesn't give you any advantage, you don't get value directly, you still need to get entity and you still get entity of requested type (as Response also returns type var). I think you didn't provide enough arguments. Can you describe what is that advantage specifically?

@vmuzikar

vmuzikar commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

@michalvavrik The advantage is that the response has a typed entity - you don't need to cast the type.

@michalvavrik

Copy link
Copy Markdown
Member

@michalvavrik The advantage is that the response has a typed entity - you don't need to cast the type.

  1. casting is not required more than this PR does (see example below)
  2. this PR introduces new methods create that does same thing as createClient which I think doesn't add on clarity, users will need to check actual implementation to understand (PR contains no javadoc either)
  3. if users decide to use these new methods, in fact they have to cast if they need anything protocol-specific which how do we know they don't?
// shared part
ClientsApi clientsApi = getClientsApi(manageClientsAdminClient);

// without this PR
OIDCClientRepresentation oidcClientRepresentation = clientsApi.createClient(baseRep).readEntity(OIDCClientRepresentation.class);

// with this pr
BaseClientRepresentation baseClientRepresentation = clientsApi.create(baseRep).readEntity();

Anyway, I don't mind and I did approve. I just consider all these arguments weak, that is all.

@michalvavrik

Copy link
Copy Markdown
Member

Quarkus REST has it better solved, they have org.jboss.resteasy.reactive.RestResponse which would avoid extra methods, but we are using RESTEasy client in client...

@vmuzikar vmuzikar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this PR introduces new methods create that does same thing as createClient which I think doesn't add on clarity, users will need to check actual implementation to understand (PR contains no javadoc either)

@michalvavrik Actually, this is a good point I missed in my reviews. The new methods should have the same name, the only difference in the signature should be the return type. @edewit Could you please fix this?

@vmuzikar

vmuzikar commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

if users decide to use these new methods, in fact they have to cast if they need anything protocol-specific which how do we know they don't?

Sure but casting from BaseClientRepresentation is expected and is required also for other methods that use this type directly, and you can't even avoid instanceof check in some cases (which is true with or without this PR). I consider the Typed Response still as more user/API friendly as the consumer doesn't need to completely guess what type is the returned entity - they'll know it's a client.

Quarkus REST has it better solved, they have org.jboss.resteasy.reactive.RestResponse which would avoid extra methods, but we are using RESTEasy client in client...

Right, that's what Steve meant by "Resteasy classic compatibility".

@michalvavrik

Copy link
Copy Markdown
Member

..ame name, the only difference in the signature should be the return type. @edewit Could you please fix this?

impossible

Right, that's what Steve meant by "Resteasy classic compatibility".

Feels like I opened too long discussion, but nothing forces us to use this wrapper, we could create similar interface (delegate pattern) as Quarkus REST has. So we would need no new methods.

Anyway. I am OK now. Thanks for the patience.

vmuzikar
vmuzikar previously approved these changes Aug 3, 2026

@vmuzikar vmuzikar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

impossible

Right, it won't compile because of type ambiguity. :D Sorry, for the noise, never mind.

})
Response createClient(@Valid BaseClientRepresentation client);

default TypedResponse<BaseClientRepresentation> create(BaseClientRepresentation client) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Instead of just BaseClientRepresentation, can you update the methods to use something that extends that:

<T extends BaseClientRepresentation> TypedResponse<T> create(T client)

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
Copilot AI review requested due to automatic review settings August 3, 2026 17:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

@edewit
edewit requested a review from shawkins August 4, 2026 06:36

@shawkins shawkins left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, thanks @edewit

@shawkins
shawkins merged commit 3b354c6 into keycloak:main Aug 4, 2026
91 checks passed
eryx12o45 pushed a commit to eryx12o45/keycloak that referenced this pull request Aug 6, 2026
* Added default non-endpoint methods

fixes: keycloak#50221
Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* changed types

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

---------

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
alehhu pushed a commit to alehhu/keycloak that referenced this pull request Aug 8, 2026
* Added default non-endpoint methods

fixes: keycloak#50221
Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* changed types

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

---------

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
Signed-off-by: alehhu <159355663+alehhu@users.noreply.github.com>
@edewit
edewit deleted the non-default-endpoint branch August 10, 2026 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add default non-endpoint methods to the admin api v2 interfaces as needed for typing

5 participants