Swagger for Kotlin - kotlin

Has anyone used a swagger tool with Kotlin?
In our organization, we have create most of our REST services using Java and SpringMVC (#RestController classes). We have used springfox to generate the Swagger API documentation. The swagger JSON representation is also used to automatically feed a searchable service catalog, so the swagger format for service metadata is important to us.
Some dev teams are now beginning to use Kotlin. We're looking for recommendations or comments related to using springfox or other swagger lib with Kotlin.

Here is sample spring boot app with swagger:
#RestController
class MyController {
#ApiOperation(value = "doc header...", notes = "detailed doc...")
#RequestMapping(value = "/double", method = arrayOf(RequestMethod.GET))
fun doubleValue(number: Int) = 2 * number
}
#Configuration
#EnableSwagger2
class SwaggerConfig {
#Bean
fun api(): Docket {
return Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
}
}
dependencies are
compile("io.springfox:springfox-swagger2:2.7.0")
compile("io.springfox:springfox-swagger-ui:2.7.0")
If you browse http://localhost:8080/swagger-ui.html it is all there...

I recently had a similar requirement. As a result I created a template project that integrates Kotlin, Webflux, and Swagger. It provides interactive API doc and automatic request validation.
See here -> https://github.com/cdimascio/kotlin-swagger-spring-functional-template
Validation is functional. It's used as such:
validate.request(req) {
// Do stuff e.g. return a list of names
ok().body(Mono.just(listOf("carmine", "alex", "eliana")))
}
with body
validate.request(req).withBody(User::class.java) { body ->
// Note that body is deserialized as User!
// Now you can do stuff.
// For example, lets echo the request as the response
ok().body(Mono.just(body))
}
It utilizes openapi 2 and 3 validation provided by atlassian.

Related

How to start on ServiceStack?

Can you help me point out how should I start on this:
I'm new to API , and I'm currently working on ASP.NET Core 3.1 MVC paired with Microsoft SQL Server. I have requirement that I should use API (ServiceStack) for a certain method.
My question are :
how or where do I start from my existing project solution?
If I use API should it be calling on SQL also? (I supposed the data will stay on db)
with regards to first question : they gave me a link where I can see this.
Where should I start , I'm just so confused.
I've looked up on youtube but there's no similar case to mine, they all use in-memory.
Suggestions and advice are welcome !
Go through ServiceStack's Getting Started Section starting with Create your first Web Service.
Configure OrmLite in your AppHost
To configure OrmLite, start with the OrmLite Installation tells you which package to download whilst the OrmLite Getting Started docs lists all the available SQL Server Dialects which you'd use to configure the OrmLiteConnectionFactory in your IOC.
E.g. for SQL Server 2012:
public class AppHost : AppHostBase
{
public AppHost() : base("MyApp", typeof(MyServices).Assembly) { }
// Configure your ServiceStack AppHost and App dependencies
public override void Configure(Container container)
{
container.AddSingleton<IDbConnectionFactory>(
new OrmLiteConnectionFactory(connectionString,
SqlServer2012Dialect.Provider));
}
}
Using OrmLite in Services
Then inside your ServiceStack Services you can access your ADO .NET DB connection via base.Db which you can use with OrmLite's extension methods, e.g:
public class MyServices : Service
{
public object Any(GetAllItems request) => new GetAllItemsResponse {
Results = Db.Select<Item>()
};
}
Checkout the OrmLite APIs docs for different APIs to Select, Insert, Update & Delete Data.
Creating effortless RDBMS APIs using AutoQuery
As you're new I'd highly recommend using AutoQuery RDBMS since it lets you create RDBMS APIs with just Request DTOs.
You can enable it by adding the AutoQueryFeature plugin in the ServiceStack.Server" NuGet package:
public override void Configure(Container container)
{
Plugins.Add(new AutoQueryFeature { MaxLimit = 100 });
}
Then you can create an AutoQuery API for your Item table with just:
[Route("/items")]
public class QueryItems : QueryDb<Item> {}
Which will now let you query each Item column using any of AutoQuery's implicit conventions, e.g by exact match:
/items?Id=1
Or by any of the query properties:
/items?NameStartsWith=foo
Creating Typed Request DTO
Once you know which Query APIs your client Apps needs I'd recommend formalizing them by adding them as strong typed properties in your Request DTO, e.g:
[Route("/items")]
public class QueryItems : QueryDb<Item>
{
public int? Id { get; set; }
public string NameStartsWith { get; set; }
}
Calling from Service Clients
Which will enable an end-to-end Typed API using any of ServiceStack's Service Clients, e.g:
var client = new JsonServiceClient(BaseUrl);
var response = client.Get(new QueryItems { NameStartsWith = "foo" });
response.PrintDump(); // quickly view results in Console
There's also AutoQuery CRUD APIs that will let you create APIs that modify your RDBMS tables using just Request DTOs.

Swagger showing no parameters to controller actions that have paramters

Swagger not showing parameters in UI and JSON, even tho my method has parameters, This particularly happens when I add the [FromBody] tag
swagger UI no parameters
JSON file no parameters
The action method:
[HttpPost("Action")]
public IActionResult Action([FromBody] string message)
{
return Ok(message);
}
I used fresh Asp.net core 3.1 and 2.2 web app with API template to test this,
I configured it exactly like the documnetaiton
ConfigureServices:
services.AddMvc();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
}
Configure:
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
It does work when I use other attributes like [FromRoute]&[FromHeader] so on... I looked at the examples and swagger does show parameters from a post method
I also tried objects like this :
public class Message
{
public int ID { get; set; }
public string body { get; set; }
}
With this action :
[HttpPost("Action")]
public IActionResult Action([FromBody] Message message)
{
return Ok(message);
}
same result (no parameters) but it does show the schema
So what am I doing wrong? how can I document post parameters like the examples
I had a similar problem on AspNetCore 5.0, where "complex" types would be completely ignored, both as parameters and output types.
The problem was caused by switching input/output formatters to a different JSON serializer (legacy code, due to newtonsoft being slow in certain situations). The new swashbuckle can work either with System.Text.Json or Newtonsoft, but not a 3rd solution.
So check .AddMvcOptions() in ConfigureServices, if there is anything done with InputFormatters or OutputFormatters, that might be the culprit
You should look into this code sample as you are working with OpenAPI 3.0 : http://petstore.swagger.io:8080/
OpenAPI 3.0 provides the requestBody keyword to describe request bodies. It distinguish the payload from parameters (such as query string and PATH). The requestBody is more flexible in that it lets you consume different media types, such as JSON, XML, form data, plain text, and others, and use different schemas for different media types:
https://swagger.io/docs/specification/describing-request-body/
That is default UI and if you click "Try it out" , the sample value will auto fill Request body area to help create a test request body .

Different JSON (de)serialization configs on different endpoints using Spring WebFlux

My micro service needs to communicate with 2 different services over HTTP. 1 has an API contract with snake_case JSON, while the other uses camelCase. How can I configure WebFlux to deserialize and serialize JSON with a certain Jackson ObjectMapper on a set of functional endpoints, while use another one on different endpoints?
The WebFlux documentation shows how to wire in another ObjectMapper, but this applies to all the endpoints of my API. So right now either all my JSON in snake_case or in camelCase. Cant find any resource to solve this issue, but it must be doable right?
Update: to make it clear I want to configure the web server which receives the requests from other services, not the webclient for sending http requests myself. I know how to do the latter.
you can use the #JsonNaming annotation on the classes you want to serialize/deserialize and specify what type of naming strategy you want.
jackson-advanced-annotations
Okay, so this is not the cleaned up solution, I will use this solution from our library, but the basic gist of my work around looks like this:
#Controller
public class Handler {
private ObjectMapper mapper;
public Handler(#Qualifier("snakeCaseWrapper") ObjectMapper mapper) {
this.mapper = mapper;
}
Mono<ServerResponse> returnUser(final ServerRequest request) {
//REQUEST DESERIALIZATION
var messageReader = new DecoderHttpMessageReader<>(new Jackson2JsonDecoder(mapper));
var configuredRequest = ServerRequest.create(request.exchange(), List.of(messageReader));
//RESPONSE SERIALIZATION
return configuredRequest.bodyToMono(UserDto.class)
.map(userDto -> {
try {
return mapper.writeValueAsString(userDto);
} catch (JsonProcessingException e) {
e.printStackTrace();
//properly handle the error here
return "";
}
})
.flatMap(json -> ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject(json))
);
}
}
This is the only way I could find to programatically choose which kind of ObjectMapper I want to use for a specific endpoint/handler method for request deserialization. For response serialization, the trick was to first use the ObjectMapper to serialize the response body to a String, and put that String into the response with BodyInserters.fromObject(json) .
It works, so I'm happy with it.

Swagger api listing is empty

Recently I have configure swagger with one of my project. Its using jersey2 and JAX-WS on tomcat for restful API. I have used following manual to configure
https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5
${basepath}/swagger.json response with following
{"swagger":"2.0","info":{"version":"1.0.0","title":""},"host":"localhost:8080","basePath":"/myapi","schemes":["http"]}
Unfortounately it does not contain any api which is under my resource package.
I have tried with the answer of following question
swagger - empty listing with no API
But it didn't help either.
The above answer using com.wordnik.swagger.* package(s)
But with the manual I got io.swagger.* package(s), which doesn't have
JaxrsApiReader class
My assumption is swagger couldn't scan my api list from Resource package.
But could not figure out which configuration or which code snippet I have missed.
Any help?....
It looks like you forgot to mark the rest endpoints with #Api
I had the same issue, I used a different approach that worked for me, by adding information only in my Application class. In case you have one, that might help you:
public class MyApi extends Application {
public MyApi() {
super();
BeanConfig beanConfig = new BeanConfig();
beanConfig.setTitle("MyApi");
beanConfig.setVersion("0.0.1");
beanConfig.setSchemes(new String[]{"http", "https"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/mypath");
//putting only the path to my api unblocked me, I removed "io.swagger.resources"
beanConfig.setResourcePackage("system.organization.api");
beanConfig.setScan(true);
beanConfig.setPrettyPrint(true);
}
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<>();
s.add(MyApis);
//for swagger
s.add(ApiListingResource.class);
s.add(SwaggerSerializers.class);
return s;
}
}
Then, the links of classes with #API annotation appeared in swagger.json
Mostly done with the same manual you used: https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-1.X-Project-Setup-1.5

RESTful framework alternatives to WCF

Looking for alternatives to the WCF REST start kit, ideally OSS frameworks.
Anyone got a list?
Cheers
Ollie
OpenRASTA is the most mature
ASP.NET MVC is a good alternative when it comes to generating REST XML and JSON feeds.
To build a rest architecture in .net you can use GenericHandlers. You can create a GenericHandler that will receive a HTTP message (POST, GET or..) and return a message of the content-type you specify.
For example I create a generic handler on the url:
http://site/getpeople.ashx?gender=female
And call it with the parmeter gender=female, as above the handler will return the following
<people>
<person>...</person>
...
<people>
And the content type would be text/xml.
This is the simplest way to implement REST web services in .NET
I also provide ServiceStack, a modern, code-first, DTO-driven, WCF replacement web services framework encouraging code and remote best-practices for creating DRY, high-perfomance, scalable REST web services.
There's no XML config, or code-gen and your one clean C# web service is enabled on all JSON, XML, SOAP, JSV, CSV, HTML endpoints out-of-the-box, automatically. It includes generic sync/async service clients providing a fast, typed, client/server communication gateway end-to-end.
It also includes generic sync/async service clients providing a fast, typed, client/server communication gateway end-to-end.
This is the complete example of all the code needed to create a simple web service, that is automatically without any config, registered and made available on all the web data formats on pre-defined and custom REST-ful routes:
public class Hello {
public string Name { get; set; }
}
public class HelloResponse {
public string Result { get; set; }
}
public class HelloService : IService<Hello> {
public object Execute(Hello request) {
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
Above service can be called (without any build-steps/code-gen) in C# with the line below:
var response = client.Send<HelloResponse>(new Hello { Name = "World!" });
Console.WriteLine(response.Result); // => Hello, World
And in jQuery with:
$.getJSON('hello/World!', function(r){
alert(r.Result);
});