Swagger - Define Max Size Limit for Multipart File Requests - spring

I have an API created with Spring and I use swagger.yaml file (I use openapi 3.0.1) to define the resources.
In my application.yaml I defined the limits for multipart requests such as:
spring.servlet.multipart.max-file-size: 15MB
spring.servlet.multipart.max-request-size: 30MB
My question is, can I define these same limit infos to swagger ? As I researched, I see maxLength and minLength but I guess these are for string limitations

yes you can, have a look at https://docs.swagger.io/swagger-core/v2.0.0-RC3/apidocs/io/swagger/v3/oas/annotations/media/Schema.html
also there is https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#schemaObject
that allows you to specify length of the schema in OpenApi 3.X.X
if you are using spring boot just add #Schema(minLength = YOUR_MIN, maxLength = YOUR_MAX)
to your class
this can be applied to the request body class,
and if you want to define specific field length you can do with
jakarta.validation-api by annotating the property by #Size(min= YOUR_MIN, max= YOUR_MAX)

Related

Create Spring Boot microservice that accepts a given Json?

So the question: i have the following Json:
{
"type": "ipv4",
"value": "1.2.3.4",
"firstSeen": "2020-07-10 15:00:00.000",
"totalCount": 8
}
i need to create a spring boot microservice from it ,with the following restrictions:
TotalCount cannot be less than 0 and cannot be more than 100.
firstSeen date should ALWAYS be converted to ISO 8601 format. The user can enter the date
in any string format. Return error if it is not well formed.
Expose the following RESTful APIs
Create a new record (as shown above, id auto-generated)
Get record by value
as this is my first time working with microservice,i can not understand this problem,is there anyone can help me with this please?
You will need to create a basic Spring Boot project using Spring Initializer, if you are using Intellij you can use this link as reference https://www.jetbrains.com/help/idea/your-first-spring-application.html#create-new-spring-boot-project.
Then add a new controller method which accepts a Json Request. Since you are trying to create a new record, I suggest you use POST method. Json Request will accept the 4 input parameters you mentioned. This is very basic and you should be able to find it in pretty much any Spring boot tutorial online. you can refer for example https://dzone.com/articles/simple-spring-boot-post
This Json Request can have validator annotations which check for the criteria you give. For example you can have #Size(min=0, max=100, message="TotalCount cannot be less than 0 and cannot be more than 100"). https://www.baeldung.com/jpa-size-length-column-differences
For date you might need to write a custom validator to check the specific format you want. For creating a record I guess you mean adding it to database. here you can configure your database using the yaml file, again there are lot of online resources on how to configure a Database in your spring boot project. https://blog.tericcabrel.com/write-custom-validator-for-body-request-in-spring-boot/
Since its your first time, it might take a while to figure out various details but I assure you once you get a hold of it, its going to be easy.

How do I get templated values in uri tag for http-client-requests metrics using Spring-Boot's RestTemplate?

We are using Spring Boot 2.1.4 and the micrometer-registry-prometheus dependency to capture metrics.
We have a case where a Spring Boot service uses a RestTemplate to call out to another service. The metrics being generated by this call contain the actual values in the URI instead of the templated values.
For example, in the /actuator/prometheus endpoint, I see entries like this:
http_client_requests_seconds_count{clientName="someClient",method="GET",status="200",uri="/person/lookup?firstName=Tony&lastName=Soprano",} 1.0
Based on the documentation, I would expect to see the variable names rather than the values, like this:
http_client_requests_seconds_count{clientName="someClient",method="GET",status="200",uri="/person/lookup?firstName={firstName}&lastName={lastName}",} 1.0
Is there a way to get the default http.client.requests metric values to use the templated values for the URI tag?
The Spring documentation at https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-metrics-http-clients says this about the uri tag:
Request’s URI template prior to variable substitution, if possible (for example, /api/person/{id})
How do we make it possible for the variable substitution to take place?
I assume you are using the RestTemplateBuilder to build your RestTemplate as otherwise you wouldn't be getting the metrics registered.
Are you actually passing a templated url into RestTemplates exchange methods and pass along the params for subsbitution? Works-for-me on 2.1.4.RELEASE and 2.2.1.RELEASE.
template.getForObject("http://localhost:" + this.serverPort + "/hello/{id}",
String.class, Collections.singletonMap("id", "loop"));
Results in:
http_client_requests_seconds_count{application="micrometered2",clientName="localhost",method="GET",outcome="SUCCESS",status="200",uri="/hello/{id}",} 23.0

Spring REST API with swagger - map of values in request param

I have a Spring Boot based REST API application with the following endpoint (Written in Kotlin)
#RequestMapping(value = ["/search"], method = [RequestMethod.GET])
#ApiOperation("Check whether any of the map values exists. Returns string 'true' if stamp exists, else 'false'")
fun checkExists(
#ApiParam("information about the stamp as key-value pairs (example: ds=2017-11-34&hh=05)", required = true)
#RequestParam searchValues: Map<String, String>
): Boolean {
return service.checkExists(searchValues)
}
And I know Spring supports sending a dynamic map of key value pairs as documented here.
I am also using Swagger to document the API definitions, and further more, I am using swagger-codegen-cli to generate the client library using which someone can connect with this REST API.
Now, the issue is, I am not able to send a map of values from the swagger generated client to the Spring REST API (even though Spring supports it). Starting from Swagger OpenAPI 3, they've added support for Object types in the specification. But this works in a different way than I need. For example with just Spring and RequestParam of type Map
http://localhost:8080/search?foo=A&bar=B
is parsed as a map of key value pairs
key="foo",value="A"
key="bar",value="B"
But, When I send a Map Object from the swagger client with the same key-value pairs
Map<String, String> values = new HashMap<>();
values.put("foo","A");
values.put("bar","B");
return out = clientApi.checkExistsUsingGET(values);
This sends a request to the REST API in form of
http://localhost:8080/search?searchValues={foo=A,bar=B}
and the map in Spring side ends up as
key="searchValues",value="{foo=A,bar=B}"
I've been struggling to get the swagger client api to send the request in a way the Spring API is intended to work with Map of values, but I am not able to figure a solution.
Am I doing using the client API in a wrong way?, or this just can't be done with swagger?
Any suggestions/opinions appreciated!
This is not yet supported by swagger-ui. See this issue https://github.com/swagger-api/swagger-ui/issues/2241

How does json String to Object auto conversion works in Spring cloud Stream?

I am looking at this example - https://github.com/spring-cloud/spring-cloud-stream-samples/blob/master/kafka-streams-samples/kafka-streams-product-tracker/src/main/java/kafka/streams/product/tracker/KafkaStreamsProductTrackerApplication.java
Trying to do something similar, but for me it is not working. How does product json string is received as Product Object ?
By default, the deserialization on the inbound KStream is done by Spring Cloud Stream. The default content-type used is application/json (equivalent to providing the property: spring.cloud.stream.bindings.input.contentType: application/json). This is why the product json string is properly converted.
You can disable the framework level conversion and let Kafka do that in which case you need to provide the Serdes through properties. In order to enable native deserialization, you can set the property - spring.cloud.stream.bindings.input.consumer.useNativeDecoding: true. Then you need to provide the appropriate Serdes. More on all these are here: https://docs.spring.io/spring-cloud-stream/docs/Elmhurst.BUILD-SNAPSHOT/reference/htmlsingle/#_message_conversion

How to use resources instead of strings for swagger api annotations in servicestack

I'd like to create servicestack api and use swagger for autoupdatable documentation. The problem is that I need this documentation to be i18n-azied, so the question is, is it possible to do in servicestack?
It's not natively supported but ServiceStack's SwaggerFeature does provide model and property filters that let you modify the returned swagger models, i.e. providing an opportunity to substitute the text in the returned models, e.g:
Plugins.Add(new SwaggerFeature {
ModelFilter = model => myLocalize(model),
ModelPropertyFilter = property => myLocalize(property)
});
Whilst it's not heavily used yet, ServiceStack's approach to localizing strings is to route text through to AppHost.ResolveLocalizedString() which can be overridden in your AppHost to change what string is returned.

Resources