Unable to set header as optional in OpenApi using Spring with annotations - spring

I'm using Java 11.0.2, Spring Boot 2.2.6 and Spring OpenApi Core 1.1.49 to create an OpenApi documentation using annotations.
During the request for creating a merchant in the Controller I need to have a custom header property, but which needs to be optional. Based on Swagger documentation for Parameter Object, the field "required" (Determines whether this parameter is mandatory. If the parameter location is "path", this property is REQUIRED and its value MUST be true. Otherwise, the property MAY be included and its default value is false.) by default for header is false, but below you can see that for some reason is true (nevertheless that I configured this option to "false").
Java - part ot Controller method
public ResponseDto create(#Parameter(in = ParameterIn.HEADER, required = false, schema = #Schema(type = "string", format = "uuid"), name = "X-Request-Correlation-Id", #RequestHeader("X-Request-Correlation-Id") #Nullable String headerXRequestId, ... <
This result in OpenApi yaml file - autogenerated with the information from the annotations
parameters:
- name: X-Request-Correlation-Id
in: header
required: true
schema:
type: string
format: uuid
Can you point out the problem, because I can't find a solution in the documentation or anywhere else?!

Found the solution - the problem wasn't in OpenApi annotation #Parameter, but in Spring binding annotation #RequestHeader, which binds the header field to the method parameter. #RequestHeader has also field "required" and by default, it's set on "true" and it overrides the one in #Parameter. So the solution was the following syntax - #RequestHeader(name = "X-Request-Correlation-Id", required = false).

Related

How to add additional text in annotation parameter value

I want to create a StudentApiController annotation for RequestMapping. It needs to add auto prefix for the RequestMapping.
Example usage 1:
#StudentApiController(value="/payment")
class PaymentEndpoint
mapping value needs to be "/student/payment"
Example usage 2:
#StudentApiController(value="/exam")
class ExamEndpoint
mapping value needs to be "/student/exam"
This is my code:
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#RequestMapping
annotation class StudentApiController(
val value: String = "",
#get:AliasFor(annotation = RequestMapping::class, attribute = "value")
val aliasValue: String = "/student" + value
)
I am getting this error:
Default value of annotation parameter must be a compile-time constant
Are you expecting all your endpoints to start with /student?
If yes then you can use spring.mvc.servlet.path=/student or server.servlet.context-path=/student property in your application.properties.
If not then may be you can add logic in interceptor to prefix annotation value provided through your annotation. I haven't tried this for prefixing something in preHandle(), but I have tried it for postHandle() and it works.
Refer this link it appends thymeleaf's custom layout using custom annotation through interceptor. You can implement same logic for your requirement.
Edit 1
You may refer this answer which provides another approach/es to handle your requirement.

Spring boot model class property validation

I am trying to map a json object to a Spring boot model class now the contract says for a property it have only a certain set of allowed values(not more than 3).
Example:
Suppose that json has field "name" and the contract says allowed values for field "name" are john,todd,phil
Anything other than john,todd,phil wont be accepted.
Is there any way to achive this constraint using any annotations
You can use following solutions
Solution 1:
Using #Pattern annotation with regex , if you want to use case insensitive use appropriate flags
#Pattern(regexp = "john|todd|phil", flags = Pattern.Flag.CASE_INSENSITIVE)
Solution 2:
By creating a enum class type with allowed values
public enum {
JOHN, TODD, PHIL
}
In your model class use #Enumerated(EnumType.STRING) on name filed

Validate URL Parameters in an Openapi 3.0 Spring Boot RESTful API?

In my openapi spec I specify URL parameters for a specific resource path like so:
paths:
/some/path:
get:
summary: some summary
parameters:
name: usefulParameter
description:
schema:
type: string
maxLength: 15
Using openapi 3.0 codegen I generate a Spring Boot RESTful API which automatically generates an interface with a name like xxxxDelegate, which has methods that must be implemented like:
default ResponseEntity<Object> somePathGet(String usefulParameter) {
getRequest().ifPresent(request -> {
for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
String exampleString = "null";
ApiUtil.setExampleResponse(request, "application/json", exampleString);
break;
}
}
});
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
Which has a comment at the top of the interface stating:
A delegate to be called by the {#link YourApiController}}.
Implement this interface with a {#link org.springframework.stereotype.Service} annotated class.
So I do exactly that, which results in my own class which looks like this:
#Service
public class MyCustomClass implements xxxxDelegate {
#Override
public ResponseEntity<Object> somePathGet(String usefulParameter) {
}
}
So far this works perfectly. I can invoke it and log the input parameter. The issue that I'm having is that I can't seem to find documentation anywhere on how to assign validation to that input parameter - the Openapi 'maxLength' is not being applied, and Spring/Spring Boot doesn't seem to provide a way to apply validation to these parameters unless you use Model type classes and annotate the members. I would prefer to avoid that and instead simply tell the API that this URL parameter requires specific validation, such as min/max length, or a certain character set.
Is this possible?
You can use
x-field-extra-annotation: "#Email"
in field definitions of the api-defining yaml. Self-defined validators are possible if you put them into the org.openapitools.model package.
In the server-side API-implementation you need to put the #Valid annotation in front of any parameter you want to have validated.
Here is an example for an UUID scheme with custom validation (note that the validation rules defined in the yaml have no effect on the generated Spring-Java-Code):
schemas:
UUID:
description: "Format: UUID"
type: "string"
pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
minLength: 36
maxLength: 36
example: "097c9a34-ec4c-4766-b29b-f528db4a3ef8"
x-field-extra-annotation: "#UUID"

Swagger override #JsonProperty("") annotation

In my code I am using #JsonProperty("") for naming fields in JSON response.
Like
#JsonProperty(value = "UserData")private List<UserEntity> userEntities;
And I am getting API response correctly ( that filed name is 'UserData')
but in swagger HTML file the filed name is getting as 'user_data'
In my application.properties following properties are set SNAKE_CASE as default.
spring.jackson.property-naming-strategy=SNAKE_CASE
Could you please tell me how to resolve this. I need the field name as in the #JsonProperty(value = "UserData")
Could you try this?
#ApiModelProperty(name = "UserData")
Have you tried #JsonProperty("UserData")? as per this post

Renaming APIs in swagger with Spring

I understand that when documenting an API with Swagger in Spring, I can change the description for the API by adding #Api annotation, but when I add it as follows
#Api(value= "NEW_NAME", description="NEW_DESCRIPTION")
Only the description is changed, not the name.
as seen here
Further, I'm not sure where the default name and description are coming from, before adding the API, the name seems to be derived from the controller name, but the description; which to me looks natural and human like almost like hard coded String with capitalization and all.
I ran a search on the code, and I wasn't able to find those Strings. Where's Swagger getting those values from?
thanks
The attribute you are looking for is: tags. So you can avoid grouping by controller name.
From Javadoc of #Api tags:
Tags can be used for logical grouping of operations by resources or any other qualifier.
For example:
#Api(value = "/customers", tags = "customers", description = "Manage Customer")
By default Springfox creates API with name as {controller-name}-controller and description as {Controller Name} Controller (cf. How to change the default Controller Name in Swagger Spring ).
It seems that the current way to do this is:
#Api(description = "Manage cars", tags = { "Cars" })
Default -
{controller-name}-controller
For Custom Name Add -
#Tag(name="YOUR CUSTOM NAME HERE")
on the Controller Class
Example -
#RestController
#Tag(name="1. Project Resource")
public class ProjectResource {...}
Result -

Resources