Skip to content

Commit

Permalink
Java API invocation flexibility (#18078)
Browse files Browse the repository at this point in the history
* add direct invocation methods for java (httpclient)

* add direct invocation methods for java (resttemplate)

* handle methods only if endpoints exist for api client

* preserve previous newline to minimize changes

* update httpclient/resttemplate samples

* add common methods in base class

* regenerate samples with base class
  • Loading branch information
l3ender authored Mar 18, 2024
1 parent da1187f commit b59957a
Show file tree
Hide file tree
Showing 70 changed files with 2,500 additions and 590 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,10 @@ public void processOpts() {
supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java"));
}

if (APACHE.equals(getLibrary()) || RESTTEMPLATE.equals(getLibrary())) {
supportingFiles.add(new SupportingFile("BaseApi.mustache", invokerFolder, "BaseApi.java"));
}

if (FEIGN.equals(getLibrary())) {
if (getSerializationLibrary() == null) {
LOGGER.info("No serializationLibrary configured, using '{}' as fallback", SERIALIZATION_LIBRARY_JACKSON);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -916,15 +916,11 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
}

/**
* Build full URL by concatenating base path, the given sub path and query parameters.
* Returns the URL of the client as defined by the server (if exists) or the base path.
*
* @param path The sub path
* @param queryParams The query parameters
* @param collectionQueryParams The collection query parameters
* @param urlQueryDeepObject URL query string of the deep object parameters
* @return The full URL
* @return The URL for the client.
*/
private String buildUrl(String path, List<Pair> queryParams, List<Pair> collectionQueryParams, String urlQueryDeepObject) {
public String getBaseURL() {
String baseURL;
if (serverIndex != null) {
if (serverIndex < 0 || serverIndex >= servers.size()) {
Expand All @@ -936,6 +932,20 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
} else {
baseURL = basePath;
}
return baseURL;
}

/**
* Build full URL by concatenating base URL, the given sub path and query parameters.
*
* @param path The sub path
* @param queryParams The query parameters
* @param collectionQueryParams The collection query parameters
* @param urlQueryDeepObject URL query string of the deep object parameters
* @return The full URL
*/
private String buildUrl(String path, List<Pair> queryParams, List<Pair> collectionQueryParams, String urlQueryDeepObject) {
String baseURL = getBaseURL();
final StringBuilder url = new StringBuilder();
url.append(baseURL).append(path);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{{>licenseInfo}}
package {{invokerPackage}};

import com.fasterxml.jackson.core.type.TypeReference;

import java.util.Collections;
import java.util.Map;

{{>generatedAnnotation}}
public abstract class BaseApi {
protected ApiClient apiClient;
public BaseApi() {
this(Configuration.getDefaultApiClient());
}

public BaseApi(ApiClient apiClient) {
this.apiClient = apiClient;
}

public ApiClient getApiClient() {
return apiClient;
}

public void setApiClient(ApiClient apiClient) {
this.apiClient = apiClient;
}

/**
* Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests.
* @param url The URL for the request, either full URL or only the path.
* @param method The HTTP method for the request.
* @throws ApiException if fails to make API call.
*/
public void invokeAPI(String url, String method) throws ApiException {
invokeAPI(url, method, null, null, Collections.emptyMap());
}

/**
* Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests.
* @param url The URL for the request, either full URL or only the path.
* @param method The HTTP method for the request.
* @param additionalHeaders Additional headers for the request.
* @throws ApiException if fails to make API call.
*/
public void invokeAPI(String url, String method, Map<String, String> additionalHeaders) throws ApiException {
invokeAPI(url, method, null, null, additionalHeaders);
}

/**
* Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests.
* @param url The URL for the request, either full URL or only the path.
* @param method The HTTP method for the request.
* @param request The request object.
* @throws ApiException if fails to make API call.
*/
public void invokeAPI(String url, String method, Object request) throws ApiException {
invokeAPI(url, method, request, null, Collections.emptyMap());
}

/**
* Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests.
* @param url The URL for the request, either full URL or only the path.
* @param method The HTTP method for the request.
* @param request The request object.
* @param additionalHeaders Additional headers for the request.
* @throws ApiException if fails to make API call.
*/
public void invokeAPI(String url, String method, Object request, Map<String, String> additionalHeaders) throws ApiException {
invokeAPI(url, method, request, null, additionalHeaders);
}

/**
* Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests.
* @param url The URL for the request, either full URL or only the path.
* @param method The HTTP method for the request.
* @param returnType The return type.
* @return The API response in the specified type.
* @throws ApiException if fails to make API call.
*/
public <T> T invokeAPI(String url, String method, TypeReference<T> returnType) throws ApiException {
return invokeAPI(url, method, null, returnType, Collections.emptyMap());
}

/**
* Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests.
* @param url The URL for the request, either full URL or only the path.
* @param method The HTTP method for the request.
* @param request The request object.
* @param returnType The return type.
* @return The API response in the specified type.
* @throws ApiException if fails to make API call.
*/
public <T> T invokeAPI(String url, String method, Object request, TypeReference<T> returnType) throws ApiException {
return invokeAPI(url, method, request, returnType, Collections.emptyMap());
}

/**
* Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests.
* @param url The URL for the request, either full URL or only the path.
* @param method The HTTP method for the request.
* @param request The request object.
* @param returnType The return type.
* @param additionalHeaders Additional headers for the request.
* @return The API response in the specified type.
* @throws ApiException if fails to make API call.
*/
public abstract <T> T invokeAPI(String url, String method, Object request, TypeReference<T> returnType, Map<String, String> additionalHeaders) throws ApiException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.fasterxml.jackson.core.type.TypeReference;

import {{invokerPackage}}.ApiException;
import {{invokerPackage}}.ApiClient;
import {{invokerPackage}}.BaseApi;
import {{invokerPackage}}.Configuration;
{{#models.0}}
import {{modelPackage}}.*;
Expand All @@ -24,25 +25,14 @@ import java.util.StringJoiner;

{{>generatedAnnotation}}
{{#operations}}
public class {{classname}} {
private ApiClient apiClient;
public class {{classname}} extends BaseApi {
public {{classname}}() {
this(Configuration.getDefaultApiClient());
super(Configuration.getDefaultApiClient());
}

public {{classname}}(ApiClient apiClient) {
this.apiClient = apiClient;
}

public ApiClient getApiClient() {
return apiClient;
}

public void setApiClient(ApiClient apiClient) {
this.apiClient = apiClient;
super(apiClient);
}

{{#operation}}
Expand Down Expand Up @@ -201,6 +191,48 @@ public class {{classname}} {
);
}

{{#-last}}
@Override
public <T> T invokeAPI(String url, String method, Object request, TypeReference<T> returnType, Map<String, String> additionalHeaders) throws ApiException {
String localVarPath = url.replace(apiClient.getBaseURL(), "");
StringJoiner localVarQueryStringJoiner = new StringJoiner("&");
List<Pair> localVarQueryParams = new ArrayList<Pair>();
List<Pair> localVarCollectionQueryParams = new ArrayList<Pair>();
Map<String, String> localVarHeaderParams = new HashMap<String, String>();
Map<String, String> localVarCookieParams = new HashMap<String, String>();
Map<String, Object> localVarFormParams = new HashMap<String, Object>();
localVarHeaderParams.putAll(additionalHeaders);
final String[] localVarAccepts = {
{{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}
};
final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);

final String[] localVarContentTypes = {
{{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}}
};
final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);

String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} };

return apiClient.invokeAPI(
localVarPath,
method,
localVarQueryParams,
localVarCollectionQueryParams,
localVarQueryStringJoiner.toString(),
request,
localVarHeaderParams,
localVarCookieParams,
localVarFormParams,
localVarAccept,
localVarContentType,
localVarAuthNames,
returnType
);
}
{{/-last}}
{{/operation}}
}
{{/operations}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package {{invokerPackage}};

import org.springframework.web.client.RestClientException;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;

{{>generatedAnnotation}}
public abstract class BaseApi {
protected ApiClient apiClient;
public BaseApi() {
this(new ApiClient());
}

public BaseApi(ApiClient apiClient) {
this.apiClient = apiClient;
}

public ApiClient getApiClient() {
return apiClient;
}

public void setApiClient(ApiClient apiClient) {
this.apiClient = apiClient;
}

/**
* Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests.
* @param url The URL for the request, either full URL or only the path.
* @param method The HTTP method for the request.
* @return ResponseEntity&lt;Void&gt;
* @throws RestClientException if an error occurs while attempting to invoke the API
*/
public ResponseEntity<Void> invokeAPI(String url, HttpMethod method) throws RestClientException {
return invokeAPI(url, method, null, new ParameterizedTypeReference<Void>() {});
}

/**
* Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests.
* @param url The URL for the request, either full URL or only the path.
* @param method The HTTP method for the request.
* @param request The request object.
* @return ResponseEntity&lt;Void&gt;
* @throws RestClientException if an error occurs while attempting to invoke the API
*/
public ResponseEntity<Void> invokeAPI(String url, HttpMethod method, Object request) throws RestClientException {
return invokeAPI(url, method, request, new ParameterizedTypeReference<Void>() {});
}

/**
* Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests.
* @param url The URL for the request, either full URL or only the path.
* @param method The HTTP method for the request.
* @param returnType The return type.
* @return ResponseEntity in the specified type.
* @throws RestClientException if an error occurs while attempting to invoke the API
*/
public <T> ResponseEntity<T> invokeAPI(String url, HttpMethod method, ParameterizedTypeReference<T> returnType) throws RestClientException {
return invokeAPI(url, method, null, returnType);
}

/**
* Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests.
* @param url The URL for the request, either full URL or only the path.
* @param method The HTTP method for the request.
* @param request The request object.
* @param returnType The return type.
* @return ResponseEntity in the specified type.
* @throws RestClientException if an error occurs while attempting to invoke the API
*/
public abstract <T> ResponseEntity<T> invokeAPI(String url, HttpMethod method, Object request, ParameterizedTypeReference<T> returnType) throws RestClientException;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package {{package}};

import {{invokerPackage}}.ApiClient;
import {{invokerPackage}}.BaseApi;

{{#imports}}import {{import}};
{{/imports}}
Expand Down Expand Up @@ -31,26 +32,17 @@ import org.springframework.http.ResponseEntity;
@Component("{{package}}.{{classname}}")
{{/generateClientAsBean}}
{{#operations}}
public class {{classname}} {
private ApiClient apiClient;
public class {{classname}} extends BaseApi {
public {{classname}}() {
this(new ApiClient());
super(new ApiClient());
}

{{#generateClientAsBean}}
@Autowired
{{/generateClientAsBean}}
public {{classname}}(ApiClient apiClient) {
this.apiClient = apiClient;
}

public ApiClient getApiClient() {
return apiClient;
}

public void setApiClient(ApiClient apiClient) {
this.apiClient = apiClient;
super(apiClient);
}

{{#operation}}
Expand Down Expand Up @@ -159,6 +151,33 @@ public class {{classname}} {
{{#returnType}}ParameterizedTypeReference<{{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}}{{/returnType}}> localReturnType = new ParameterizedTypeReference<{{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}}{{/returnType}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference<Void> localReturnType = new ParameterizedTypeReference<Void>() {};{{/returnType}}
return apiClient.invokeAPI("{{{path}}}", HttpMethod.{{httpMethod}}, {{#hasPathParams}}uriVariables{{/hasPathParams}}{{^hasPathParams}}Collections.<String, Object>emptyMap(){{/hasPathParams}}, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localReturnType);
}
{{#-last}}

@Override
public <T> ResponseEntity<T> invokeAPI(String url, HttpMethod method, Object request, ParameterizedTypeReference<T> returnType) throws RestClientException {
String localVarPath = url.replace(apiClient.getBasePath(), "");
Object localVarPostBody = request;
final Map<String, Object> uriVariables = new HashMap<String, Object>();
final MultiValueMap<String, String> localVarQueryParams = new LinkedMultiValueMap<String, String>();
final HttpHeaders localVarHeaderParams = new HttpHeaders();
final MultiValueMap<String, String> localVarCookieParams = new LinkedMultiValueMap<String, String>();
final MultiValueMap<String, Object> localVarFormParams = new LinkedMultiValueMap<String, Object>();
final String[] localVarAccepts = { {{#hasProduces}}
{{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}
{{/hasProduces}} };
final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
final String[] localVarContentTypes = { {{#hasConsumes}}
{{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}}
{{/hasConsumes}} };
final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);

String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} };

return apiClient.invokeAPI(localVarPath, method, uriVariables, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, returnType);
}
{{/-last}}
{{/operation}}
}
{{/operations}}
Loading

0 comments on commit b59957a

Please sign in to comment.