I tried searching for quite sometime and couldn't find the solution thus posting this question.
I have a Java Web project where we generate REST APIs programmatically(ie WITHOUT Jersey annotations like #Path/#Get etc) based on files(proprietary xml) provided by another tool which is kind of a standard in my organization through Jersey(ResourceConfig eg https://docs.huihoo.com/jersey/2.13/resource-builder.html) and we have a need of generating its corresponding SWAGGER docs.
All the tutorials that I found were using declarative API including page eg. https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5
I also looked into Swagger-Inflector which makes use of swagger.yaml file but in my case we need to generate it runtime with no manual work.
This is how(similar sample) we generate REST api:
final Resource.Builder resourceBuilder = Resource.builder();
resourceBuilder.path("helloworld");
final ResourceMethod.Builder methodBuilder = resourceBuilder.addMethod("GET");
methodBuilder.produces(MediaType.TEXT_PLAIN_TYPE)
.handledBy(new Inflector<ContainerRequestContext, String>() {
#Override
public String apply(ContainerRequestContext containerRequestContext) {
return "Hello World!";
}
});
final Resource resource = resourceBuilder.build();
registerResources(resource);
Is this feasible? Can we generate Swagger docs for programmatically generated REST APIs?
Related
I am trying to create an open API spec for an existing vert.x based application, and since there is no library to generate the open API spec automatically for vert.x based apis, I am wondering if there is a plugin or a tool that can help me generate at least the corresponding schemas for my data classes since I have a lot of them and it is really painful to manually create the corresponding schema for each one of them?
I am using kotlin and Jackson for serialization/deserialization.
I know of no such library. Usually I would recommend to choose the reverse procedure which is to generate the model classes from your open api specification. For that, there is a really usefull library called openapi-generator.
The additional advantage of this approach would be, that you can use a fully api-first approach by also using the Vert.x extension called Web OpenAPI
You can use swagger java tools directly. Generation of swagger model from classes/annotations provides swagger-core library - see github or maven repo.
If you for example have annotated method:
public interface EndPoints {
#Operation(summary = "Delete product by ID ", method = "DELETE", operationId = "product/:deleteProductId",
tags = {
"Product"
},
parameters = {
#Parameter(in = ParameterIn.PATH, name = "deleteProductId",
required = true, description = "The ID for the Product", schema = #Schema(type = "string"))
},
responses = {
#ApiResponse(responseCode = "404", description = "Not found."),
#ApiResponse(responseCode = "200", description = "Product deleted."),
#ApiResponse(responseCode = "500", description = "Internal Server Error.")
}
)
void deleteProduct();
}
you can generate API doc using following code:
Reader openApiReader = new Reader();
Operation operation = openApiReader.parseMethod(EndPoints.class..getDeclaredMethod("deleteProduct"), Lists.newArrayList(), null);
And for your specific use-case, if you want to only generate Schema for given class (and use it for example as request body or return value), you can do for example:
public class ErrorApiResponse {
public String error;
public String severity;
public String message;
}
ResolvedSchema resolvedSchema = ModelConverters.getInstance()
.resolveAsResolvedSchema(new AnnotatedType(ErrorApiResponse.class));
You can construct io.swagger.v3.oas.models.OpenAPI manually, add generated Schemas to respective places. To construct JSON version of this API model, you simple call:
io.swagger.v3.core.util.Json.pretty(openAPI)
I need to add a code snippet (javascript, for instance) with some implementation details to a desired method description.
I've tried to use ApiOperation(value = "method name", notes = "the actual code which I want to show goes here"), but It doesn't allow to format string in notes parameter.
Is it possible to use formatted code blocks using annotations in Swagger in Spring Boot application?
We have a stateless backend Java app running on Google App Engine (GAE). The engine takes in a string-A (json) and returns a different string-B (json).
The examples on the Google Cloud Endpoints are around creating an Entity - to define the CloudEndpoint Class. Most of the examples seems to be tied to the DataStore - a backend DB.
In our case, the data is not persisted and there are no primary keys. We were successful in creating an entity - with Input and Output string as two fields. It worked, however the resp payload also consisted of a copy of input string.
We have a solution using a standard servlet(req. string and a different resp string) using doPost Method.
Any suggestions - for our scenario - is CloudEndPoint necessary and/or if there is an easy way to conduct this within Cloud Endpoint?
Thanks
There is nothing that forces you to use the datastore. If you don't need it, don't use it.
You can transform from one Pojo into another for example
public class Input {
public String inputValue;
}
public class Output {
public String outputValue;
}
#Api(name = "myApi", version = "v1")
public class MyApi {
#ApiMethod(name = "hello")
public Output hello(Input input) {
Output response = new Output();
response.resultValue = "Hello " + input.inputValue;
return response;
}
}
which via APIs explorer (http://localhost:8888/_ah/api/explorer for me) shows that it results in a POST request / response of equivalent JSON objects:
POST http://localhost:8888/_ah/api/myApi/v1/hello
{
"inputValue": "Hans"
}
which returns
200 OK
{
"resultValue": "Hello Hans"
}
The big plus of endpoints is that you can write simple Java methods like Output hello(Input input) and use them from auto-generated (Java) client code that does not "see" that those methods are called over HTTP.
You can use them via regular http if you figure out what the URL is but that's not the intended use.
A more generic way to do JSON methods in app-engine would be to use a JAX-RS implementation like Jersey. That way you don't have to have_ah/api/vN/apiname/methodname methods and the restrictions that come with them (like a specific error response in case of exceptions).
Code with JAX-RS would probably look like
#Path("/whatEverILike")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class MyApi {
#POST
public Output hello(Input input) {
Output response = new Output();
response.resultValue = "Hello " + input.inputValue;
return response;
}
}
but it's a little difficult to set such a project up since you'll need a lot of dependencies. For Jersey for example you'll probably want the following 2 including several transitive dependencies:
org.glassfish.jersey.containers:jersey-container-servlet-core:2.22
org.glassfish.jersey.media:jersey-media-json-jackson:2.22
which unfolds into
aopalliance-repackaged-2.4.0-b31.jar jackson-core-2.5.4.jar javassist-3.18.1-GA.jar jersey-client-2.22.jar jersey-media-jaxb-2.22.jar
hk2-api-2.4.0-b31.jar jackson-databind-2.5.4.jar javax.annotation-api-1.2.jar jersey-common-2.22.jar jersey-media-json-jackson-2.22.jar
hk2-locator-2.4.0-b31.jar jackson-jaxrs-base-2.5.4.jar javax.inject-1.jar jersey-container-servlet-core-2.22.jar jersey-server-2.22.jar
hk2-utils-2.4.0-b31.jar jackson-jaxrs-json-provider-2.5.4.jar javax.inject-2.4.0-b31.jar jersey-entity-filtering-2.22.jar osgi-resource-locator-1.0.1.jar
jackson-annotations-2.5.4.jar jackson-module-jaxb-annotations-2.5.4.jar javax.ws.rs-api-2.0.1.jar jersey-guava-2.22.jar validation-api-1.1.0.Final.jar
I'm writing an API using the HalBuilder library for HAL representations.
As it stands now, I need to have two different methods for the JSON and HAL representations. As an example, my VersionResource includes the following two methods:
#GET
#ApiOperation(value = "Find all versions", response = Version.class, responseContainer = "List")
#Produces({MediaType.APPLICATION_JSON})
public Response getAsJson() {
List<Version> versions = repository.selectAll();
return Response.ok().entity(versions).build();
}
#GET
#ApiOperation(value = "Find all versions", notes="Returns HAL format", response = Representation.class, responseContainer = "List")
#Produces({RepresentationFactory.HAL_JSON})
public Representation getAsHalJson() {
List<Version> versions = repository.selectAll();
return this.versionRepresentationFactory.createResourceRepresentation(versions);
}
(Note: I'm sure there's a better way of collapsing these methods, and I'm looking into a way to do that)
But my immediate problem is that using two methods causes duplicate entries in my Swagger documentation:
Those two GET /versions are effectively the same thing, but they have different return types, so Swagger wants them to be different.
I'd like to collapse those two. What are my options here?
[It's probably worth pointing out that I'm using the Swagger Maven plugin to generate my documentation. The application is also using Guice for DI and Jersey for JSON representations.]
I read in https://github.com/swagger-api/swagger-spec/issues/146#issuecomment-59082475:
per design, we don't overload response type definitions for the same response code.
So I think the Maven plugin creates an invalid Swagger document.
What are your options?
Be patient and watch these Swagger issues: https://github.com/swagger-api/swagger-spec/issues/146 and https://github.com/swagger-api/swagger-spec/issues/182
Don't use Swagger
I am actually trying to build a process for refactoring a large number of existing webservices.
The idea is to use JAXB/JAXWS tools to automate this as much as possible.
Most of our issues are resolved except for one blocking problem :
JAXB by default serializes boolean types as "true"/"false". I need those values to be "0"/"1".
On the existing classes of our codebase, I'm trying to use as much annotations as possible, and of course not modifying at all what is auto generated by JAX tools.
After adding correct annotations, I run wsgen so it generates JAX-WS necessary classes for deployment.
Here is a concrete example of an annotated webservice method:
public #WebResult(name = "success")
#XmlJavaTypeAdapter(value = lu.ept.common.xmlSerializers.BooleanAdapter.class, type = boolean.class)
boolean modifyStatus(#WebParam(name = "processActionId") String processActionId, #WebParam(name = "newStatus") int newStatus)
throws BusinessMessage, SystemMessage {
When running wsgen, it picks up correctly the WebResult and WebParam attributes, but it refuses to use my XmlJavaTypeAdapter.
My question is very simple : has someone managed to use XmlJAvaTypAdapter annotation on a webservice method return value? Is it possible?
(on the documentation I read, I haven't seen anything concerning the use of that annotation on return values)
Actually the only solution I have found is to manually add the XmlJavaTypeADapter annotation to the classes generated by wsgen. This is not a viable solution, because those classes will be generated after each build...