Skip to content

Conversation

Fyusel
Copy link
Contributor

@Fyusel Fyusel commented Sep 5, 2025

Description

relates to STACKITSDK-232

Checklist

  • Issue was linked above
  • No generated code was adjusted manually
  • Changelogs
    • Changelog in the root directory was adjusted
    • Changelog(s) of the service(s) were adjusted
  • VERSION file(s) of the service(s) were adjusted
  • Code format was applied: make fmt
  • Examples were added / adjusted (see examples/ directory)
  • Unit tests got implemented or updated
  • Unit tests are passing: make test (will be checked by CI)
  • No linter issues: make lint (will be checked by CI)

@Fyusel Fyusel requested a review from a team as a code owner September 5, 2025 06:35
@Fyusel Fyusel force-pushed the ft/java-wait-handler branch 2 times, most recently from 060607e to b4e7330 Compare September 9, 2025 09:13
@Fyusel Fyusel force-pushed the ft/java-wait-handler branch 2 times, most recently from 12a9371 to 49fb05c Compare September 10, 2025 06:29
// the response Body
public static int ApiErrorMaxCharacterLimit = 500;

private int statusCode;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
private int statusCode;
private final int statusCode;

could be final


private int statusCode;
private byte[] body;
private String errorMessage;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
private String errorMessage;
private final String errorMessage;

same here


public class ResourcemanagerWait {
/**
* createProjectWaitHandler will wait for project creation. Uses the deault values for
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* createProjectWaitHandler will wait for project creation. Uses the deault values for
* createProjectWaitHandler will wait for project creation. Uses the default values for

() -> {
try {
GetProjectResponse p = apiClient.getProject(containerId, false);
if (p.getContainerId() == null || p.getLifecycleState() == null) {
Copy link
Member

Choose a reason for hiding this comment

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

This condition will always be false I guess. Both getContainerId() and getLifecycleState() are annotated with Nonnull.

@javax.annotation.Nonnull
public String getContainerId() {
return containerId;
}

@javax.annotation.Nonnull
public LifecycleState getLifecycleState() {
return lifecycleState;
}

() -> {
try {
GetProjectResponse p = apiClient.getProject(containerId, false);
if (p.getContainerId() == null || p.getLifecycleState() == null) {
Copy link
Member

Choose a reason for hiding this comment

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

Same here, always false.

handler.setThrottle(10, TimeUnit.MILLISECONDS);
handler.setTimeout(500, TimeUnit.MILLISECONDS);

assertThrows(Exception.class, () -> handler.waitWithContext(), handler.TimoutErrorMessage);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
assertThrows(Exception.class, () -> handler.waitWithContext(), handler.TimoutErrorMessage);
assertThrows(Exception.class, handler::waitWithContext, handler.TimoutErrorMessage);

Appears multiple times within this class, please check all places

void testCreateProjectNonOpenAPIError() throws Exception {
// Return containerId == null and LifecycleState == CREATING
GetProjectResponse creatingResponse = new GetProjectResponse();
creatingResponse.setContainerId(null);
Copy link
Member

Choose a reason for hiding this comment

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

Parameter is annotated with notnull.

public void setContainerId(@javax.annotation.Nonnull String containerId) {
this.containerId = containerId;
}

// Return containerId == null and LifecycleState == CREATING
GetProjectResponse creatingResponse = new GetProjectResponse();
creatingResponse.setContainerId(null);
creatingResponse.setLifecycleState(null);
Copy link
Member

Choose a reason for hiding this comment

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

same here

activeResponse.setLifecycleState(LifecycleState.ACTIVE);

GetProjectResponse deletingResponse = new GetProjectResponse();
deletingResponse.setContainerId(null);
Copy link
Member

Choose a reason for hiding this comment

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

Same here, param is annotated with notnull.

public void setContainerId(@javax.annotation.Nonnull String containerId) {
this.containerId = containerId;
}

// Wait some seconds for the API to process the request
if (sleepBeforeWaitMillis > 0) {
try {
Thread.sleep(sleepBeforeWaitMillis);
Copy link
Member

Choose a reason for hiding this comment

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

Not sure if it's that nice to set a whole thread asleep.

On the other side we're limited to Java 8 features 😄 Did you do some research if there are better alternatives?

Copy link
Member

@rubenhoenle rubenhoenle Sep 12, 2025

Choose a reason for hiding this comment

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

Will throw in e.g. CompletableFutures here, it was introduced with Java 8.

* @return
* @throws Exception
*/
public T waitWithContext() throws Exception {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
public T waitWithContext() throws Exception {
public T waitWithContext() throws InterruptedException, IllegalArgumentException, TimeoutException {

Throwing Exception is a little bit... to much here. Users of the SDK won't have the chance to handle this properly.

import java.nio.charset.StandardCharsets;
import java.util.HashMap;

public class GenericOpenAPIError extends ApiException {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
public class GenericOpenAPIError extends ApiException {
public class GenericOpenAPIException extends ApiException {

Would keep the "Exception" in the name here instead of "Error". "Error" is a golang thing, Java has Exceptions.

throw new Exception(TimoutErrorMessage);
}

private ErrorResult handleError(int retryTempErrorCounter, Exception err) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
private ErrorResult handleError(int retryTempErrorCounter, Exception err) {
private ErrorResult handleError(int retryTempErrorCounter, Exception exception) {

throw new Exception(TimoutErrorMessage);
}

private ErrorResult handleError(int retryTempErrorCounter, Exception err) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
private ErrorResult handleError(int retryTempErrorCounter, Exception err) {
private ErrorResult handleException(int retryTempErrorCounter, Exception err) {

Copy link
Member

Choose a reason for hiding this comment

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

Overall this feels a little bit to me like taking the Golang waiter implementation and strictly rewriting it in Java. Java and Go have a completely different approach of error raising and handling.

@Fyusel Fyusel force-pushed the ft/java-wait-handler branch from 49fb05c to 59254e9 Compare September 12, 2025 10:01
Signed-off-by: Alexander Dahmen <[email protected]>
@Fyusel Fyusel force-pushed the ft/java-wait-handler branch from 59254e9 to 3a0eea7 Compare September 12, 2025 10:03
+ p.getLifecycleState().getValue()
+ "'"));
} catch (ApiException e) {
return new AsyncActionResult<>(false, null, e);
Copy link
Member

Choose a reason for hiding this comment

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

Maybe I'm wrong here but my understanding is that in Java you don't return exceptions, you throw and catch.

return new AsyncActionResult<>(false, null, null);

} catch (ApiException e) {
GenericOpenAPIException oapiErr = new GenericOpenAPIException(e);
Copy link
Member

Choose a reason for hiding this comment

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

This catch block seems generic to me and could apply to most of our deletion wait handlers. Maybe we can have some general approach for different wait handler types (Interfaces, abstract classes)?

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