Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions languages/java/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# STACKIT Java SDK Generator

The `templates` directory contains only our customized Java templates. Beside these customized templates,
the original templates of openapi-generator for Java are used. These can be found in the
official GitHub repo of the [openapi-generator](https://github.com/OpenAPITools/openapi-generator/tree/v7.14.0/modules/openapi-generator/src/main/resources/Java).

If you need to change something in the Java Generator, try always first to add
[user-defined templates](https://openapi-generator.tech/docs/customization#user-defined-templates),
instead of overwriting existing templates. These ensure an easier upgrade process, to newer
versions of the openapi-generator.

If it's required to customize the original templates, you can copy them into this directory.
Try to minimize the customization as much as possible, to ensure, that we can easily upgrade
to newer versions in the future.

## Template adjustments

The following templates were customized but don't need to be adjusted when updating the Java SDK generator to a new a newer upstream version:

- `README.mustache`: This template was entirely overwritten. It has no technical impact on the Java SDK.
- `api_test.mustache`: This template had to be customized because of our changes to the DefaultApi and ApiClient classes.

The following templates were customized and need to be checked for adjustments when updating the Java SDK generator to a newer upstream version:

- `ApiCallback.mustache`: This template was customized use the `ApiException` class from the core module instead of the one generated by default.
- `ApiClient.mustache`: This template was customized to initialize the ApiClient with the CoreConfiguration to easily setup the KeyFlow Authentication and custom endpoints.
- `api.mustache`: This template was customized to initialize the DefaultApi with the CoreConfiguration to easily setup the KeyFlow Authentication and custom endpoints.
- `build.gradle.mustache`: This template was customized to allow the services to be subprojects in one big gradle project.

## Custom templates

The custom templates don't need to be adjusted when updating the Java SDK generator to a new a newer upstream version.

- `ApiClientTest.mustache`: Implements additional test cases.
- `serviceApi.mustache` and `serviceApiTest.mustache`: The classes generated by this template (`IaasApi`, `AlbApi`, ...) just inherit from the corresponding `DefaultApi` class. This way users of the Java SDK can use two STACKIT SDK modules for different STACKIT services within the same file without being forced to use fully qualified names for classes.

2 changes: 2 additions & 0 deletions languages/java/templates/ApiCallback.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
package {{invokerPackage}};

import java.io.IOException;
{{! TEMPLATE CUSTOMIZATION - BEGIN - use the ApiException class from the core module instead of the one generated by default }}
import cloud.stackit.sdk.core.exception.ApiException;
{{! TEMPLATE CUSTOMIZATION - END - use the ApiException class from the core module instead of the one generated by default }}

import java.util.Map;
import java.util.List;
Expand Down
24 changes: 12 additions & 12 deletions languages/java/templates/ApiClient.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ import {{invokerPackage}}.auth.OAuthFlow;
import {{invokerPackage}}.auth.AWS4Auth;
{{/withAWSV4Signature}}

{{! BEGIN - Added imports for core module }}
{{! TEMPLATE CUSTOMIZATION - BEGIN - Added imports for core module }}
import cloud.stackit.sdk.core.auth.SetupAuth;
import cloud.stackit.sdk.core.config.CoreConfiguration;
import cloud.stackit.sdk.core.exception.ApiException;
import cloud.stackit.sdk.core.KeyFlowAuthenticator;
{{! END - Added imports for core module }}
{{! TEMPLATE CUSTOMIZATION - END - Added imports for core module }}

/**
* <p>ApiClient class.</p>
Expand Down Expand Up @@ -120,7 +120,7 @@ public class ApiClient {
protected Map<String, String> defaultCookieMap = new HashMap<String, String>();
protected String tempFolderPath = null;

{{! BEGIN - deleted field authentications, we use our own Authenticator
{{! TEMPLATE CUSTOMIZATION - BEGIN - deleted field authentications, we use our own Authenticator
protected Map<String, Authentication> authentications;
}}

Expand All @@ -139,15 +139,15 @@ public class ApiClient {

protected HttpLoggingInterceptor loggingInterceptor;

{{! BEGIN - Added CoreConfiguration field to ApiClient }}
{{! TEMPLATE CUSTOMIZATION - BEGIN - Added CoreConfiguration field to ApiClient }}
protected CoreConfiguration configuration;
{{! END - Added CoreConfiguration field to ApiClient }}
{{! TEMPLATE CUSTOMIZATION - END - Added CoreConfiguration field to ApiClient }}

{{#dynamicOperations}}
protected Map<String, ApiOperation> operationLookupMap = new HashMap<>();

{{/dynamicOperations}}
{{! BEGIN - Removed ApiClient constructor and replaced it with a custom constructors which create the ApiClient with the CoreConfiguration }}
{{! TEMPLATE CUSTOMIZATION - BEGIN - Removed ApiClient constructor and replaced it with a custom constructors which create the ApiClient with the CoreConfiguration }}
/**
* Basic constructor for ApiClient.
*
Expand Down Expand Up @@ -208,7 +208,7 @@ public class ApiClient {
this.httpClient = httpClient;
}
}
{{! END - Removed ApiClient constructor and replaced it with a custom constructors which create the ApiClient with the CoreConfiguration }}
{{! TEMPLATE CUSTOMIZATION - END - Removed ApiClient constructor and replaced it with a custom constructors which create the ApiClient with the CoreConfiguration }}

{{#hasOAuthMethods}}
{{#oauthMethods}}
Expand Down Expand Up @@ -312,7 +312,7 @@ public class ApiClient {
// Set default User-Agent.
setUserAgent("{{{httpUserAgent}}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}");

{{! BEGIN - delete line setting authentications
{{! TEMPLATE CUSTOMIZATION - BEGIN - delete line setting authentications
authentications = new HashMap<String, Authentication>();
}}
{{#dynamicOperations}}
Expand Down Expand Up @@ -568,7 +568,7 @@ public class ApiClient {
JSON.setLenientOnJson(lenientOnJson);
return this;
}
{{! BEGIN - delete authentications getter, we use our own Authenticator
{{! TEMPLATE CUSTOMIZATION - BEGIN - delete authentications getter, we use our own Authenticator
/**
* Get authentications (key: authentication name, value: authentication).
*
Expand Down Expand Up @@ -614,7 +614,7 @@ public class ApiClient {
}
{{/hasHttpBearerMethods}}

{{! BEGIN - delete auth related methods, we use our own Authenticator
{{! TEMPLATE CUSTOMIZATION - BEGIN - delete auth related methods, we use our own Authenticator
deleted methods:
setUsername
setPassword
Expand Down Expand Up @@ -1461,7 +1461,7 @@ public class ApiClient {

List<Pair> updatedQueryParams = new ArrayList<>(queryParams);

{{! BEGIN - delete updateParamsForAuth, we use our own Authenticator
{{! TEMPLATE CUSTOMIZATION - BEGIN - delete updateParamsForAuth, we use our own Authenticator
// update parameters with authentication settings
updateParamsForAuth(authNames, updatedQueryParams, headerParams, cookieParams, requestBodyToString(reqBody), method, URI.create(url));
}}
Expand Down Expand Up @@ -1585,7 +1585,7 @@ public class ApiClient {
}
}

{{! BEGIN - delete updateParamsForAuth method, we use our own Authenticator }}
{{! TEMPLATE CUSTOMIZATION - BEGIN - delete updateParamsForAuth method, we use our own Authenticator }}

/**
* Build a form-encoding request body with the given form parameters.
Expand Down
14 changes: 0 additions & 14 deletions languages/java/templates/README.md

This file was deleted.

8 changes: 0 additions & 8 deletions languages/java/templates/README.mustache
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
# STACKIT Java SDK for {{appName}}

- API version: {{appVersion}}

{{{appDescriptionWithNewLines}}}

{{#infoUrl}}
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
{{/infoUrl}}

This package is part of the STACKIT Java SDK. For additional information, please visit the [GitHub repository](https://{{gitHost}}/{{{gitUserId}}}/{{{gitRepoId}}}) of the SDK.

## Installation from Maven Central (recommended)
Expand Down
4 changes: 2 additions & 2 deletions languages/java/templates/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class {{classname}} {
private int localHostIndex;
private String localCustomBaseUrl;

{{! BEGIN - Remove default constructor and replaced with constructor which uses CoreConfiguration }}
{{! TEMPLATE CUSTOMIZATION - BEGIN - Remove default constructor and replaced with constructor which uses CoreConfiguration }}
/**
* Basic constructor for DefaultApi
*
Expand Down Expand Up @@ -110,7 +110,7 @@ class {{classname}} {
}
this.localVarApiClient = new ApiClient(httpClient, config);
}
{{! END - Remove default constructor and replaced with constructor which uses CoreConfiguration }}
{{! TEMPLATE CUSTOMIZATION - END - Remove default constructor and replaced with constructor which uses CoreConfiguration }}

public ApiClient getApiClient() {
return localVarApiClient;
Expand Down
2 changes: 1 addition & 1 deletion languages/java/templates/custom/serviceApi.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class {{serviceName}}Api extends DefaultApi {
*
* For production use consider using the constructor with the OkHttpClient parameter.
*
* @param config your STACKIT SDK CoreConfiguration
* @param configuration your STACKIT SDK CoreConfiguration
* @throws IOException
*/
public {{serviceName}}Api(CoreConfiguration configuration)
Expand Down
124 changes: 70 additions & 54 deletions scripts/generate-sdk/languages/java.sh
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ generate_java_sdk() {
mkdir -p "${SERVICES_FOLDER}"

warning=""

# Generate SDK for each service
for service_json in "${ROOT_DIR}"/oas/legacy/*.json; do
service="${service_json##*/}"
for service_dir in "${ROOT_DIR}/oas/services"/*; do
service="${service_dir##*/}"
service="${service%.json}"

service_pascal_case=$(to_pascal_case "${service}")
Expand All @@ -101,63 +101,79 @@ generate_java_sdk() {
continue
fi

# check if the whole service is blocklisted
if grep -E "^$service$" "${ROOT_DIR}/languages/java/blocklist.txt"; then
echo "Skipping blocklisted service ${service}"
warning+="Skipping blocklisted service ${service}\n"
cp -r "${sdk_services_backup_dir}/${service}" "${SERVICES_FOLDER}"
continue
fi

echo ">> Generating \"${service}\" service..."
cd "${ROOT_DIR}"

mkdir -p "${SERVICES_FOLDER}/${service}/"
cp "${ROOT_DIR}/languages/java/.openapi-generator-ignore" "${SERVICES_FOLDER}/${service}/.openapi-generator-ignore"

SERVICE_DESCRIPTION=$(cat "${service_json}" | jq .info.title --raw-output)

# TODO: add to generator below when adding multi-API-version support:
# --inline-schema-options "SKIP_SCHEMA_REUSE=true"

# Run the generator
java -Dlog.level="${GENERATOR_LOG_LEVEL}" -jar "${GENERATOR_JAR_PATH}" generate \
--generator-name java \
--input-spec "${service_json}" \
--output "${SERVICES_FOLDER}/${service}" \
--git-host "${GIT_HOST}" \
--git-user-id "${GIT_USER_ID}" \
--git-repo-id "${GIT_REPO_ID}" \
--global-property apis,models,modelTests=false,modelDocs=false,apiDocs=false,apiTests=true,supportingFiles \
--additional-properties="artifactId=${service},artifactDescription=${SERVICE_DESCRIPTION},invokerPackage=cloud.stackit.sdk.${service},modelPackage=cloud.stackit.sdk.${service}.model,apiPackage=cloud.stackit.sdk.${service}.api,serviceName=${service_pascal_case}" >/dev/null \
--http-user-agent stackit-sdk-java/"${service}" \
--config "${ROOT_DIR}/languages/java/openapi-generator-config.yml"

# Rename DefaultApiServiceApi.java to {serviceName}Api.java
# This approach is a workaround because the file name cannot be set dynamically via --additional-properties or the config file in OpenAPI Generator.
api_file="${SERVICES_FOLDER}/${service}/src/main/java/cloud/stackit/sdk/${service}/api/DefaultApiServiceApi.java"
if [ -f "$api_file" ]; then
mv "$api_file" "${SERVICES_FOLDER}/${service}/src/main/java/cloud/stackit/sdk/${service}/api/${service_pascal_case}Api.java"
fi
api_test_file="${SERVICES_FOLDER}/${service}/src/test/java/cloud/stackit/sdk/${service}/api/DefaultApiTestServiceApiTest.java"
if [ -f "$api_test_file" ]; then
mv "$api_test_file" "${SERVICES_FOLDER}/${service}/src/test/java/cloud/stackit/sdk/${service}/api/${service_pascal_case}ApiTest.java"
fi

# Remove unnecessary files
rm "${SERVICES_FOLDER}/${service}/.openapi-generator-ignore"
rm -r "${SERVICES_FOLDER}/${service}/.openapi-generator/"

# If the service has a wait package, move them inside the service folder
if [ -d "${sdk_services_backup_dir}/${service}/src/main/java/cloud/stackit/sdk/${service}/wait" ]; then
echo "Found ${service} \"wait\" package"
cp -r "${sdk_services_backup_dir}/${service}/src/main/java/cloud/stackit/sdk/${service}/wait" "${SERVICES_FOLDER}/${service}/src/main/java/cloud/stackit/sdk/${service}/wait"
fi

# If the service has a wait test package, move them inside the service folder
if [ -d "${sdk_services_backup_dir}/${service}/src/test/java/cloud/stackit/sdk/${service}/wait" ]; then
echo "Found ${service} \"wait\" test package"
cp -r "${sdk_services_backup_dir}/${service}/src/test/java/cloud/stackit/sdk/${service}/wait" "${SERVICES_FOLDER}/${service}/src/test/java/cloud/stackit/sdk/${service}/wait"
fi
echo -e "\n>> Generating SDK for \"${service}\" service..."
for version_dir in "${service_dir}"/*; do
service_version_json="${version_dir}/${service_dir##*/}.json"
version="${version_dir##*/}"

# check if that specific API version of the service is blocklisted
if grep -E "^${service}-${version}$" "${ROOT_DIR}/languages/java/blocklist.txt"; then
echo "Skipping blocklisted API version ${version} of service ${service}"
warning+="Skipping blocklisted API version ${version} of service ${service}\n"
continue
fi

echo -e "\n>> Generating SDK package \"${version}api\" for \"${service}\" service..."
cd "${ROOT_DIR}"

mkdir -p "${SERVICES_FOLDER}/${service}"
cp "${ROOT_DIR}/languages/java/.openapi-generator-ignore" "${SERVICES_FOLDER}/${service}/.openapi-generator-ignore"

SERVICE_DESCRIPTION=$(cat "${service_version_json}" | jq .info.title --raw-output)

# Run the generator
java -Dlog.level="${GENERATOR_LOG_LEVEL}" -jar "${GENERATOR_JAR_PATH}" generate \
--generator-name java \
--input-spec "${service_version_json}" \
--output "${SERVICES_FOLDER}/${service}" \
--git-host "${GIT_HOST}" \
--git-user-id "${GIT_USER_ID}" \
--git-repo-id "${GIT_REPO_ID}" \
--global-property apis,models,modelTests=false,modelDocs=false,apiDocs=false,apiTests=true,supportingFiles \
--additional-properties="artifactId=${service},artifactDescription=${SERVICE_DESCRIPTION},invokerPackage=cloud.stackit.sdk.${service}.${version}api,modelPackage=cloud.stackit.sdk.${service}.${version}api.model,apiPackage=cloud.stackit.sdk.${service}.${version}api.api,serviceName=${service_pascal_case}" \
--inline-schema-options "SKIP_SCHEMA_REUSE=true" \
--http-user-agent stackit-sdk-java/"${service}" \
--config "${ROOT_DIR}/languages/java/openapi-generator-config.yml"

# Rename DefaultApiServiceApi.java to {serviceName}Api.java
# This approach is a workaround because the file name cannot be set dynamically via --additional-properties or the config file in OpenAPI Generator.
api_file="${SERVICES_FOLDER}/${service}/src/main/java/cloud/stackit/sdk/${service}/${version}api/api/DefaultApiServiceApi.java"
if [ -f "$api_file" ]; then
mv "$api_file" "${SERVICES_FOLDER}/${service}/src/main/java/cloud/stackit/sdk/${service}/${version}api/api/${service_pascal_case}Api.java"
fi
api_test_file="${SERVICES_FOLDER}/${service}/src/test/java/cloud/stackit/sdk/${service}/${version}api/api/DefaultApiTestServiceApiTest.java"
if [ -f "$api_test_file" ]; then
mv "$api_test_file" "${SERVICES_FOLDER}/${service}/src/test/java/cloud/stackit/sdk/${service}/${version}api/api/${service_pascal_case}ApiTest.java"
fi

build_gradle="${SERVICES_FOLDER}/${service}/${version}api/build.gradle"
if [ -f "$build_gradle" ]; then
mv "$build_gradle" "${SERVICES_FOLDER}/${service}/build.gradle"
fi

# Remove unnecessary files
rm "${SERVICES_FOLDER}/${service}/.openapi-generator-ignore"
rm -r "${SERVICES_FOLDER}/${service}/.openapi-generator/"

# If the service version has a wait package, move them inside the service folder
if [ -d "${sdk_services_backup_dir}/${service}/src/main/java/cloud/stackit/sdk/${service}/${version}api/wait" ]; then
echo "Found ${service} \"wait\" package"
cp -r "${sdk_services_backup_dir}/${service}/src/main/java/cloud/stackit/sdk/${service}/${version}api/wait" "${SERVICES_FOLDER}/${service}/${version}api/src/main/java/cloud/stackit/sdk/${service}/${version}api/wait"
fi

# If the service version has a wait test package, move them inside the service folder
if [ -d "${sdk_services_backup_dir}/${service}/src/test/java/cloud/stackit/sdk/${service}/${version}api/wait" ]; then
echo "Found ${service} \"wait\" test package"
cp -r "${sdk_services_backup_dir}/${service}/src/test/java/cloud/stackit/sdk/${service}/${version}api/wait" "${SERVICES_FOLDER}/${service}/${version}api/src/test/java/cloud/stackit/sdk/${service}/${version}api/wait"
fi
done

# If the service has a CHANGELOG file, move it inside the service folder
if [ -f "${sdk_services_backup_dir}/${service}/CHANGELOG.md" ]; then
Expand Down
Loading