I am implementing a controller class in a spring-boot project and want to validate retrieved model of post method. It has a string field and should be validated against an enum value.
I wonder is there any validation annotation which will get enum class and check if value has a valid enum value? For example :
class ModelObject{
#EnumValidator(MyEnumClass.class)
String inputField;
}
If you simply specify the Enum as your #RequestParam, it will validate against the values present in enum.
Additionally, if you are using swagger-ui, this is bound to the values of the enum field.
Related
Due to the fact that I'm using an abstract class, I get such error:
org.springframework.data.mapping.MappingException: Ambiguous field mapping detected!
Both private final com.life.book.domain.event.EventType com.life.book.domain.command.ObjectCommand.eventType
and private final com.life.book.domain.event.EventType com.life.book.domain.command.UpdateObjectCommand.eventType
map to the same field name eventType! Disambiguate using #Field annotation!
My classes:
abstract class ObjectCommand(
open var eventType: EventType?
)
#Document(collection = "COMMAND")
data class UpdateObjectCommand(
val description: String?,
override var eventType: EventType?
) : ObjectCommand(eventType)
enum class EventType {
CREATED, UPDATED
}
The solution might be to use a different name instead of the eventType name in the UpdateObjectCommand class. But then the database will have two fields with the same purpose. Maybe there is another way?
There is Disambiguate using #Field annotation in the description of the error, but I don't understand how to use it.
It's been a sec since I have delt with what looks like Mongo DB and Spring Boot (I could be off base here). The #Field annotation is applied to fields in your class that have the #Document annotation.
You can add information to the #Field annotation like the serialized name of the field, or if its written when null. #Field in most cases does not need to be applied to a field unless you are dealing with enums. Mongo does not know how to store an enum, so you must add the #Field annotation to specify that it needs to be stored as a string.
https://blog.tericcabrel.com/using-mongodb-with-spring-boot-project-part-1/
From tericcabrel.com:
#Field is used to enhance the property by changing the type; like our case, MongoDB doesn't support Enum, so we need to tell Mongo to store this property's value as a string. When retrieving the data from the collection, the value will be returned back as an Enum. You can also provide a different name for the property in MongoDB.
I am using Java's Validator class to validate some input fields from my Spring Object class. I am validating URIs, and they can be in either format, http:/myURL/uri, or "readFromURI.v1". Originally, I was just validating the first part, so my Object class had:
#Pattern(regexp="[\\w\\s.,;:*&#(){}+-=?/|!\\[\\]%#$~]{0,512}", message="incorrect format")
private String URI;
Now, if the user selects a checkbox in my app, they will enter in the value as the second format, so I created a new regexp:
#Pattern.List({
#Pattern(regexp="[\\w\\s.,;:*&#(){}+-=?/|!\\[\\]%#$~]{0,512}", message="incorrect format"),
#Pattern(regexp="^\"(Create|Read|Update|Delete)[a-zA-Z]+.*vd+\"${0,512}", message="incorrect format")
})
private String URI;
The regexp is probably wrong for the second part, and I will probably ask that question at a later time. But now whenever I validate either format it fails both conditions. So I'm assuming that the way I wrote it, it's trying to apply both regex's. How can I choose one based on a value? That value field is in the same Class if that helps:
private String URI;
private boolean useHttp; //if true, validate using [\\w\\s.,;:*&#(){}+-=?/|!\\[\\]%#$~]{0,512}
You should write a custom validator, as explained here:
Create a new annotation CustomConstraint annotated with #Constraint(validatedBy = CustomConstraintValidator.class)
Have some class CustomConstraintValidator implements ConstraintValidator<CustomConstraint, YourType>
Annotate YourType with #CustomConstraint
Do your validation in your CustomConstraintValidator depending on your bean value.
Your validation will be able to check whatever field you want to test (I don't remember if class level constraint pass after each field level annotation pass, so you might have to check if URI is not null).
We are thinking about doing some JQAssistant concepts/rules based on the values of annotation attributes.
Can these values be queried and evaluated with JQAssistant?
Example: Find all classes that have methods that are annotated with
#javax.ejb.TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
The following query returns all types annotated by #TransactionAttribute and the value:
MATCH
(t:Type)-[:ANNOTATED_BY]->(txAttribute)-[:OF_TYPE]->(:Type{fqn:"javax.ejb.TransactionAttribute"}),
(txAttribute)-[:HAS]->(:Value{name:"value"})-[:IS]->(txAttributeType:Field)
RETURN
t.fqn, txAttributeType.signature
The result looks like this:
"your.project.a.impl.ServiceAImpl" "javax.ejb.TransactionAttributeType REQUIRES_NEW"
The returned value is the signature of the according field declared in the enum type TransactionAttributeType.
I am getting the following error when trying to get the enum values for an allowableValues tag.
The value for annotation attribute ApiModelProperty.allowableValues
must be a constant expression
What I am trying to do:
#ApiModelProperty(allowableValues = new Enums().enumToString(SomeEnum.class))
private String someString;
Here is the logic for Enums().enumToString
public class Enums {
public final <E extends Enum<E>> String enumToString(Class<E> inputEnum) {
//inputEnum;
for (Enum enumValues : EnumSet.allOf(inputEnum)) {
//will create a string of the enum values
}
return "will be a formatted string of the enum values";
}
}
Is it possible to do what I am trying to accomplish? I know it is possible to just expose the enum in my API and swagger would then recognize the allowed values automatically, however the field in question needs to be exposed as a string, even though our internal logic has it as an enum.
Thanks in advance for your help!
#ApiModelProperty(value = "embed", dataType = "[Lmodel.request.Embed;")
private final List<String> embed;
the Embed path is a list of enums. This show you something like this in the swagger documentation:
type: "object"
properties:
embed:
type: "array"
description: "embed"
items:
type: "string"
enum:
-SOME
-SOME
-SOME
-SOME
Your problem is not related to Swagger at all but basic Java.
In Java annotations, you can have constant expressions, meaning you can't do method calls there, any other things but only use constant values.
Using java jersey, I have the following #QueryParam's in my method handler:
#Path("/hello")
handleTestRequest(#QueryParam String name, #QueryParam Integer age)
I know if I do:
http://myaddress/hello?name=something
It will go into that method....
I want to make it so that I can call:
http://myaddress/hello?name=something
And it will also go into that same method. Is there any way I can flag an "optional" PathParam? Does it work with #FormParam too? Or am I required to create a separate method with a different method signature?
In JAX-RS parameters are not mandatory, so if you do not supply an age value, it will be NULL, and your method will still be called.
You can also use #DefaultValue to provide a default age value when it's not present.
The #PathParam parameter and the other parameter-based annotations, #MatrixParam, #HeaderParam, #CookieParam, and #FormParam obey the same rules as #QueryParam.
Reference
You should be able to add the #DefaultValue annotation the age parameter, so that if age isn't supplied, the default value will be used.
#Path("/hello")
handleTestRequest(
#QueryParam("name") String name,
#DefaultValue("-1") #QueryParam("age") Integer age)
According to the Javadocs for #DefaultValue, it should work on all *Param annotations.
Defines the default value of request meta-data that is bound using one of the following annotations: PathParam, QueryParam, MatrixParam, CookieParam, FormParam, or HeaderParam. The default value is used if the corresponding meta-data is not present in the request.
You can always wrap return type in optional, for example: #QueryParam("from") Optional<String> from