Spring / Swagger-UI - Show example of real values in request model when user clicks on "Try it out" button - spring-boot

How do I make swagger-ui to show pre-populated real values in the Example box below? (The box for request model that shows when user clicks on "Try it out" button in swagger-ui).
I am using SpringBoot/Java and I would like it to show some real values rather than data types. It seam to do that for DOB field by default.
I have MyModel defined as below and I was expecting that using "value" in ApiModelProperty will set these values but it is not:
#ApiModel(description="blahblah")
public class MyModel {
#ApiModelProperty(notes = "some notes", name = "name", required = true, value = "Bot")
private String name;
#ApiModelProperty(notes = "Date of birth", name = "dob", required = true)
private OffsetDateTime dob;
#ApiModelProperty(notes="How old", name = "age", required = true, value = "31")
private Integer age;
...
}
I would like above to look like:

Use example:
#ApiModelProperty(notes = "some notes", name = "name", required = true, example = "Bot")
private String name;

Related

OpenApi not picking up 'example' from #Schema

In my request model, I have a field like
#NotNull
#Schema(description = "blahblah", example = "19680228", type = "Date", format = "String", pattern = "([0-9]{4})(?:[0-9]{2})([0-9]{2})", required = true, nullable = false)
#JsonDeserialize(using = CustomDateDeserializer.class)
private OffsetDateTime birthDate;
As you can see, I have example = "19680228" in #Schema.
When I go to https://editor.swagger.io/ and paste my .yaml file into it, I would expect that it would pick the example up and show the birthDate in example section of my endpoint and in my model schema as 19680228. I would else expect that example was generated in yaml when I hit the /api-docs.yaml endpoint but it is not:
Here is how it shows in my model:
And here is how Example value of my controller looks:
As you can see, the format is still getting the format for OffsetDateTime and there is no example at all.
However, if I modify yaml in https://editor.swagger.io/ and add example as below:
, then my schema model shows it
, and also example in controller shows it as 19680210:
So, it looks like OpenApi is not processing #Schema properly.
i had the same problem, and i didn't find proper solution for it, the only solution was using String type with pattern.
like this
#Schema(type = "String" , example = "2022-10-10 00:00:00", pattern = "yyyy-MM-dd HH:mm:ss").

How to generate id field value within specific range in spring data jpa

Is there any way that I can generate ID field as 4 digit number i.e from 1000 to 9999 in my Spring boot application. Current Id field looks like this:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "EMP_ID", nullable = false)
public short getEmp_id() {
return emp_id;
}
As of now id is getting generated from 1. But I wanted to get it generated starting from 1000 and incremented by 1 until 9999.
As suggest by Ishikawa in comments and by referring Sequence Generation from Sequence Generation did below changes:
#Id
#GenericGenerator(
name = "empid-sequence-generator",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
#Parameter(name = "sequence_name", value = "user_sequence"),
#Parameter(name = "initial_value", value = "1000"),
#Parameter(name = "increment_size", value = "1")
}
)
#GeneratedValue(generator = "empid-sequence-generator")
#Column(name = "EMP_ID", nullable = false)
public short getEmp_id() {
return emp_id;
}
but even after that when trying to save the emp getting the below exception:
com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'user_sequence'.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:262)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1624)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:594)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:524)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7194)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2979)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:248)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:223)
NOTE: It's third party database so I can't do any schema/constraint changes.I need to handle this through java code only.
My bad. Forgot to uncomment below line in application.properties.
spring.jpa.hibernate.ddl-auto = update
After uncommenting when I reboot my application it created the "user_sequence".

how to convert the data of value attribute of request parameter to string content in spring

i want to get the value of ticket id in string data Type
#RequestParam(value = "ticketId" , required = false, defaultValue = "false")
how can i get the value of ticketId in any string data.
Earlier i have tried to do this
***#RequestParam(value = "ticketId" String ticketId, required = false, defaultValue = "false")***
Everything except the syntax is correct.Correct syntax:
#RequestParam(value = "ticketId", required = false) String ticketId

Bean validation - validate optional fields

Given a class that represents payload submitted from a form, I want to apply bean validation to a field that may or may not be present, for example:
class FormData {
#Pattern(...)
#Size(...)
#Whatever(...)
private String optionalField;
...
}
If optionalField is not sent in the payload, I don't want to apply any of the validators above, but if it is sent, I want to apply all of them. How can it be done?
Thanks.
So usually all of these constraints consider null value as valid. If your optional filed is null when it's not part of the payload all should work just fine as it is.
And for any mandatory fields you can put #NotNull on them.
EDIT
here's an example:
class FormData {
#Pattern(regexp = "\\d+")
#Size(min = 3, max = 3)
private final String optionalField;
#Pattern(regexp = "[a-z]+")
#Size(min = 3, max = 3)
#NotNull
private final String mandatoryField;
}
#Test
public void test() {
Validator validator = getValidator();
// optonal field is null so no violations will rise on it
FormData data = new FormData( null, "abc" );
Set<ConstraintViolation<FormData>> violations = validator.validate( data );
assertThat( violations ).isEmpty();
// optional field is present but it should fail the pattern validation:
data = new FormData( "aaa", "abc" );
violations = validator.validate( data );
assertThat( violations ).containsOnlyViolations(
violationOf( Pattern.class ).withProperty( "optionalField" )
);
}
You can see that in the first case you don't get any violations as the optional field is null. but in the second exmaple you receive a violation of pattern constraint as aaa is not a string of digits.

How to get an array of objects with spring #RequestParam in ManyToMany relationship?

I have an entity Movies and an entity Genres in a relationship many to many.
#ManyToMany
#JoinTable(name = "movies_genres", joinColumns = #JoinColumn(name = "movies_id"), inverseJoinColumns = #JoinColumn(name = "genres_id"))
private Set<Genres> genresSet = new HashSet<>();
In a rest controller class, I want to do this:
#GetMapping("/search-movies")
public Iterable<Movies> search(
#RequestParam(value = "genresSet", required = false) Set<Genres> genresSet,
#RequestParam(value = "synopsis", required = false) String synopsis,
#RequestParam(value = "title", required = false) String title,
#RequestParam(value = "runtime", required = false) Integer runtime
)
I use axios on front-end to send params to the back-end and genresSet is array of objects, for example
[
{ id: 1, name: 'action'},
{ id: 2, name: 'crime'},
{ id: 3, name: 'comedy'}
]
I thought that Spring would automatically convert array of objects into set of genres, but it gives me null.
How to get values of genres in form of a set of values?
To recap, the user enters more than one genre, where each genre is represented as an object, so front-end sends array of genre objects and back-end needs to bind that array to the set of genres, where set of genres is a many to many property of Movie entity.
You can rethink your parameters and change Set<Genres> either to Set<Integer> or Set<String>. Because you need just ids or just names of genres to use them in search query, you don't need to pass the whole Genres object.
#GetMapping("/search-movies")
public Iterable<Movies> search(
#RequestParam(value = "genresIds", required = false) Set<Long> genresIds,
// ... other parameters without changes
would accept
"genresIds": [1, 2, 3]
or
#GetMapping("/search-movies")
public Iterable<Movies> search(
#RequestParam(value = "genresNames", required = false) Set<String> genresNames,
// ... other parameters without changes
would accept
"genresNames": ['action', 'crime', 'comedy']
Another way you could accomplish this is to create a wrapper class for the Set. For example:
public class GenresWrapper {
Set<Genres> genresSet;
// ... accessors
}
Then your controller method would look like this:
#GetMapping("/search-movies")
public Iterable<Movies> search(
#ModelAttribute GenresWrapper genres,
// ... other parameters
)
Or you could wrap all the request parameters in a single wrapper object.
This answer is based on another SO answer.

Resources