-
Notifications
You must be signed in to change notification settings - Fork 6k
Java Template: Make ApiInvoker more pluggable #684
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Just to clarify this: the future will have something like And why is there a separate Android client? Maybe both should just use okhttp and they will work fine and could share 100% code. |
I was more think to something like |
@wing328 what do you think of this? It does solve the static issue |
@fehguy if you've time, I would recommend you to take a look at the PR #765 [PHP] Add authentication support (API key, HTTP basic) The approach I used is a Configuration class to store authentication related setting. The benefit is that
If this approach looks good, we can extend this to other languages (Java, Ruby, Python, C#, etc) |
FYI. Here is what the code (PHP) looks like:
|
Well for me this looks very similar as I need to pass the config to every API like I would need to do it with the ApiInvoker too: ApiInvoker iv = new ApiInvoker();
PetApi vrpApi = new PetApi(iv); |
@karussell I believe your change aims to allow different apiInvoker instances to have different set of default headers. Is your goal to support authentication using default headers ? What if not all methods (e.g. within PetApi) require authentication ? The solution I proposed above will only apply the authentication setting based on the Swagger spec. |
The intend is not really to allow different apiInvokers but to make it possible in the Java world to intercept every call.
It is up to you as you can decide on demand which header you add for which method. |
I agree your proposed change would make ApiInvoker more pluggable (compared with current approach that uses a static ApiInvoker). Consider the following code:
Can both (Personally I would recommend not to use default header or query parameter for authentication) |
Yes, the will break. but using static objects hidden behind the scene is not the way to go for the future IMO
Why? Or what do you recommend? |
For the REST API SDKs I used before, none of them would require me to add a default header/query parameter for authentication. Usually the API key or other authentication setting is passed when constructing an object or via a configuration block and the SDK should be smart enough to tell which methods require the authentication parameter (header/query). |
Now I know what you mean. This change here would enable such a convenience, it is not an "api key implementation", just making it possible. |
To avoid confusion: the clients won't break e.g. when releasing the java module, because you would need to specify the new version where the developers then can easily change the minor code to inject the apiInvoker |
From a developer perspective, I would prefer the proposed change to be as transparent as possible since I do not have a need to customize apiInvoker as the default one is good enough for me. In other words, it would be nice if your proposed change is backward compatible so that developers do not need to update their code to make it work. |
You cannot make the ApiInvoker with static pluggable, really :) (If you really wanted you could, but only with dangerous & ugly code like ApiInvoker.set(customApiInvoker) but I refuse to provide such code ;)) |
Well I'm just sharing my view with you from a developer perceptive. I'll let @fehguy to decide as this change would require developers who are already using the Java SDK to update their code. |
@karussell regarding backward compatibility, what about providing a default public class ApiInvoker {
public static final ApiInvoker DEFAULT = new ApiInvoker();
} public class PetApi {
public PetApi() {
this(ApiInvoker.DEFAULT);
}
public PetApi(ApiInvoker apiInvoker) {
this.apiInvoker = apiInvoker;
}
} |
Good point, and better approach, still I wouldn't design my code this way as every static variable could lead to problems. E.g. here several instances could be used and some use the default and some the custom ... personally I would just break the compatibility e.g. when upgrading to 2.2 Another better approach in my eyes would be to have something like: // this class contains the default apiInvoker which is not static
// and a custom one can be provided via the constructor
MyApi api = new MyApi(/*new ApiInvoker(){...}*/);
PetApi petApi = petapi.getPetAPI();
OtherApi otherApi = petapi.getOtherAPI(); |
@xhh @karussell are we all set to merge here? |
@olensmar my PR #791 includes the changes of making ApiInvoker (renamed to ApiClient) more pluggable as well as other improvements, such as changing static methods to instance methods so that those behaviors of the api client are customizable via overriding those instance methods. So please consider merging that one. |
@xhh I would like to merge yours but also agree with @karussell that we should avoid static variables as much as possible - perhaps you could refactor in line with his suggestions? |
@olensmar I can see your concerns on static variables, but if we do this public class PetApi {
public PetApi() {
this(new ApiInvoker());
}
public PetApi(ApiInvoker apiInvoker) {
this.apiInvoker = apiInvoker;
}
} then every time Could you share more details on avoiding static variables here and generally? Then I'm happy to make the changes to avoid it. |
I would either avoid the default constructor or better have a management class (SwaggerApi) which creates all the XYApi classes: public class SwaggerApi {
public SwaggerApi() {
this(new ApiInvoker());
}
public SwaggerApi(ApiInvoker apiInvoker) {
this.petApi = new PetApi(apiInvoker);
}
public PetApi getPetApi() {
return this.petApi;
}
} |
@karussell @xhh that sounds good to me - we need to merge this today though so we can get it into the upcoming release - would either of you have time to do something in the line of this? |
We needed simple key authentication and with this change you can easily extend the ApiInvoker and e.g. hook into ApiInvoker.invokeAPI to modify the queryParams. And for header based authentication you could change the headers there too.
Example usage: