-
Notifications
You must be signed in to change notification settings - Fork 549
RESTWS-963: Add a swagger autogeneration util to scan through resource handlers and generate the swagger spec #638
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
base: master
Are you sure you want to change the base?
Conversation
|
It is a recommended practice to include the ticket id in the commit message. |
67dbf47 to
a3de500
Compare
|
I was not expecting the new approach to change any existing methods. I expected to only inspect the resources to do the needful without touching them in any way. |
it doesn't change any existing method, to get this working i have to make changes within |
| public static boolean getRepresentationDescription = false; | ||
|
|
||
| @Override | ||
| public Model getGETModel(Representation rep) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is mainly to fix the test that depends on this class.
e234eac to
9a6ee8e
Compare
b00e48b to
fb399b3
Compare
|
@dkayiwa @ibacher Herman and I want to bring attention to this PR. It affects, among other things, the scope of the GSoC Project. I haven't given this a thorough review, but this approach to stop relying on |
| * @param resourceClass the resource class e.g PatientIdentifier.class | ||
| * @return the resource handler for the provided class e.g PatientIdentifierResource1_8 | ||
| */ | ||
| Resource getResourceHandlerForSupportedClass(Class<?> resourceClass); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where are you using this method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be removed. Oversight
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this method handles cases where the field is a List or Set. It extracts the element type and, if it's an OpenMRS resource, references its Swagger definition. If no resource definition is found, it defaults to a StringProperty. Otherwise, it returns a generic ArrayProperty.
if (Set.class.equals(type) || List.class.equals(type)) {
Class<?> elementType = getGenericTypeFromField(field);
if (isOpenMRSResource(elementType)) {
String resourceName = getSubResourceNameBySupportedClass(elementType);
if (resourceName == null) {
return new StringProperty();
}
return new ArrayProperty(new RefProperty("#/definitions/" + StringUtils.capitalize(resourceName) + operationType));
}
return new ArrayProperty();
}cc: @dkayiwa
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you point me to where it is currently used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to put it here if it is only used in a utility class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not necessarily, i can just put it within the SwaggerGenerationUtil.java
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not necessarily, i can just put it within the SwaggerGenerationUtil.java
|
|
||
|
|
||
| @Override | ||
| public DelegatingResourceDescription getCreatableProperties() throws ResourceDoesNotSupportOperationException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did we add this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class has a getCREATEModel method that needs to be removed. I wanted to replace that with getcreatableproperties since the new mechanism depends on that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not seem to see where you removed it in this pull request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True dat. Will fix that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you address the above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried addressing it in this commit but it fails some tests in swaggerspecificationcreatortest so I decided to put it back in this most recent commit.
Its really because we need that method to add SubDetailsResource to the swagger documentation. When I remove it, the tests fail because that resource is not added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still somehow feel we should not add this new method just for the sake of the swagger docs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we just replace the test with one adapted to this new model? I.e., if getCREATEModel() is no longer what Swagger is using to create docs, then the test is no longer valid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dkayiwa @ibacher, Are you suggesting i remove even the SubDetailsResource? because that's the only way the existing tests especially this one will pass?.
And to be frank, SubDetailsResource is just a test class that shouldn't appear in our swagger spec but apparently does so i am okay with removing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm... it shouldn't appear in the production spec, but I thought it was there so the tests have something to work with. I don't think we should remove it, but I do think we should re-work the SwaggerSpecificationCreatorTest class so that it tests whatever mechanism we're using to generate the Swagger Specification now.
We don't need existing tests to pass if we're changing the mechanism, but we need an equivalent set of tests to pass. Does that make sense?
Also, when actually generating the spec, we should ensure that none of the test modules are on the classpath.
| @Override | ||
| public Model getGETModel(Representation rep) { | ||
| public DelegatingResourceDescription getRepresentationDescription(Representation rep) { | ||
| getGETCalled = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you intentionally leave in the getGETCalled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @Override | ||
| public Model getCREATEModel(Representation rep) { | ||
| public DelegatingResourceDescription getCreatableProperties() { | ||
| getCREATECalled = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you intentionally leave in the getCREATECalled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @Override | ||
| public Model getUPDATEModel(Representation rep) { | ||
| public DelegatingResourceDescription getUpdatableProperties() throws ResourceDoesNotSupportOperationException { | ||
| getUPDATECalled = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you intentionally leave in the getUPDATECalled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be fixed in next commit
| } | ||
| } | ||
|
|
||
| private void initializeResources() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mind explaining why you moved this from a private method to the base interface?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oversight. To be fixed in next commit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scratch that, it was actually intentional to move it to the base interface because i need to use it in this method as can be seen at https://github.com/mherman22/openmrs-module-webservices.rest/blob/08b817fd98e0c15f81f021d4e856b0c2b598c125/omod-common/src/main/java/org/openmrs/module/webservices/docs/swagger/SwaggerGenerationUtil.java#L408
cc: @dkayiwa
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any reason why you did not just use RestService.initialize()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
|
|
||
| volatile Map<String, ResourceDefinition> resourceDefinitionsByNames; | ||
|
|
||
| volatile Map<Class<?>, Resource> resourcesBySupportedClasses; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you intentionally change the access modifier?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not a good practice for outsiders to directly access internal implementation details of a class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True dat. Let me get a finer way of doing it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed!
| volatile Map<Class<?>, Resource> resourcesBySupportedClasses; | ||
|
|
||
| static volatile Map<Class<?>, Resource> resourcesBySupportedClasses; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Originally, this was not static. Is this just a typo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you see the above comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed!
|
|
||
| /** | ||
| * Retrieves the resource handler for the given supported class. | ||
| * |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we already have a way of getting this without modifying this interface by adding a new method simply for swagger docs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i have been trying out this method https://github.com/mherman22/openmrs-module-webservices.rest/blob/08b817fd98e0c15f81f021d4e856b0c2b598c125/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/api/impl/RestServiceImpl.java#L440 but it is not giving me what i want.
i dont want to touch the existing tests in https://github.com/mherman22/openmrs-module-webservices.rest/blob/08b817fd98e0c15f81f021d4e856b0c2b598c125/omod-2.0/src/test/java/org/openmrs/module/webservices/rest/doc/SwaggerSpecificationCreatorTest.java#L65
And yet when i use the above method i get the failure below: https://pastebin.com/WknBFXSD which is that it fails with Caused by: org.openmrs.api.APIException: Unknown resource: class org.openmrs.AllergyReaction. AllergyReaction is a dummy class which was added just for the sake of making SwaggerSpecificationCreatorTest pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What parameter did you pass into getResourceBySupportedClass?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here is the method. i gave it a Class<?> resourceClass.
/**
* <strong>Should</strong> return search resources for given resource class
* @param resourceClass the resource class e.g. PatientIdentifier
*/
public static org.openmrs.module.webservices.rest.web.resource.api.Resource getResourceHandlerForSupportedClass(Class<?> resourceClass) {
if (Context.getService(RestService.class).getResourceBySupportedClass(resourceClass) == null) {
Context.getService(RestService.class).initialize();
}
return Context.getService(RestService.class).getResourceBySupportedClass(resourceClass);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was the exact value contained in resourceClass?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dkayiwa i have added a fix by simply using getResourceHandlers() and then use each of the returned resourcehandlers to get its annotation and ensure that the annotation supportedClass is equal to the class i am providing at public static String getSubResourceNameBySupportedClass(Class<?> supportedClass).
f222c40 to
d60be17
Compare
7f68a6c to
fae9fdc
Compare
…rs and generate the swagger spec
… making it public
fae9fdc to
5b01a90
Compare
Description of what I changed
Issue I worked on
see https://issues.openmrs.org/browse/RESTWS-963
Checklist: I completed these to help reviewers :)
My IDE is configured to follow the code style of this project.
No? Unsure? -> configure your IDE, format the code and add the changes with
git add . && git commit --amendI have added tests to cover my changes. (If you refactored
existing code that was well tested you do not have to add tests)
No? -> write tests and add them to this commit
git add . && git commit --amendI ran
mvn clean packageright before creating this pull request andadded all formatting changes to my commit.
No? -> execute above command
All new and existing tests passed.
No? -> figure out why and add the fix to your commit. It is your responsibility to make sure your code works.
My pull request is based on the latest changes of the master branch.
No? Unsure? -> execute command
git pull --rebase upstream master