I'm looking for a proper way to use property name inside validation messages, like {min} or {regexp}.
I've googled this question a few times now and apparently there isn't a native method for doing this.
#NotNull(message = "The property {propertyName} may not be null.")
private String property;
Has anyone experienced this before and has managed to find a solution for this?
UPDATE 1
Using a custom message interpolator should be something like:
public class CustomMessageInterpolator implements MessageInterpolator {
#Override
public String interpolate(String templateString, Context cntxt) {
return templateString.replace("{propertyName}", getPropertyName(cntxt));
}
#Override
public String interpolate(String templateString, Context cntxt, Locale locale) {
return templateString.replace("{propertyName}", getPropertyName(cntxt));
}
private String getPropertyName(Context cntxt) {
//TODO:
return "";
}
}
One solution is to use two messages and sandwich your property name between them:
#NotBlank(message = "{error.notblank.part1of2}Address Line 1{error.notblank.part2of2}")
private String addressLineOne;
Then in your message resource file:
error.notblank.part1of2=The following field must be supplied: '
error.notblank.part2of2='. Correct and resubmit.
When validation fails, it produces the message "The following field must be supplied: 'Address Line 1'. Correct and resubmit."
As another workaround, you may also pass the property name to the message text as shown below:
Add the validation message to the properties file (e.g. text.properties):
javax.validation.constraints.NotNull.message=may not be null.
Then define the annotation in the code as shown below:
#NotNull(message = "propertyName {javax.validation.constraints.NotNull.message}")
private String property;
Related
I am creating a custom annotation for firebase events. My inspiration comes from official android docs and other #StringDef annotations. It looks like this:
#Retention(SOURCE)
#StringDef({
EVENT_1, EVENT_2
})
#Size(max = 32) // firebase limit
public #interface UserActivityEvents {
String EVENT_1 = "ev_1";
String EVENT_2 = "really_long_event_name_that_exceeds_32_chars_limit";
...
}
The class that encapsulates the logging is defined as follows:
public class UserActivityEvent {
private #UserActivityEvents String eventName;
private UserActivityEvent() {
}
public UserActivityEvent(#UserActivityEvents String eventName) {
this.eventName = eventName;
}
...
}
The problem is that the AS lint is never triggered, no matter what I specify in the constructor, even if I do something like this:
new UserActivityEvent("asd");
My expectations for #UserActivityEvents are:
The parameter in constructor of UserActivityEvent can only be one of the strings defined in #StringDef
Event length doesn't exceed the 32 chars limit
If one of these rules are violated, the code is underlined (classic AS error highlight) and the error message is displayed when hovering over the code.
Edit: I found out that if I define a new event EVENT_3 in UserActivityEvents but don't include it in #UserActivityEvents and I try to reference it as new UserActivityEvent(UserActivityEvents.EVENT_3), the lint is properly triggered and says this: "Must be one of: EVENT_1, EVENT_2 or length must be at most 32". In case of using new UserActivityEvent("asd") it doesn't work
Colleagues in my office are developping a web system with JAX-RS(JSR339).
I need to get values by name(string) and I asked them to. But they have few idea.
I'm quite new to JAX-RS and googled it and I learned that
JAX-RS injects values to variables by annotations like
#Path("/sample")
public interface SampleResource {
#GET
#Path("/hello/{message}")
String sayHello(#PathParam("message") String message);
}
However I want to get values by name at runtime like
#Path("/sample")
public interface SampleResource {
String name = "message"; // dynamic value
#GET
#Path("/hello/{" + name + "}")
String sayHello(#PathParam(name) String message);
}
Perhaps this is a wrong code. My question is how to get values by name like the example above.
(I'm afraid the sample codes aren't correct ones but I hope you grasp my idea and concerns. Thanks.)
Try something like this.
Example of the bean which will be used as #BeanParam
public class MyBeanParam {
#PathParam("p")
private String pathParam;.
public String getPathParam() {
return pathParam;
}
}
Injection of MyBeanParam as a method parameter:
#GET
String sayHello(#BeanParam MyBeanParam beanParam, String entity){
final String pathParam = beanParam.getPathParam(); // contains injected path parameter "p"
...
}
OR
You can use UriInfo to get QueryParam. For example application see this
I have similar problem like this [Hibernate Exception: Unknown name value for enum class
But in my case,
Unable to filter, so returning non filtered results.Unknown name value for enum class com.xxxx.enums.Status: DELIVERED
java.lang.IllegalArgumentException: Unknown name value for enum class com.xxxx.enums.Status: DELIVERED
at org.hibernate.type.EnumType.nullSafeGet(EnumType.java:128)
at org.hibernate.type.CustomType.nullSafeGet(CustomType.java:109)
at org.hibernate.type.AbstractType.hydrate(AbstractType.java:104)
#Enumerated(value = EnumType.STRING)
#Column(name = "status", length = 10)
#AuditableField
private Status status;
public enum ReleaseStatus {
DL("Delivered"),
}
Everything seems fine, still I am getting that exception.
You have the String DELIVERED in your table. And this string is supposed to be the name() of one of the ReleaseStatus instances. And ReleaseStatus doesn't have any instance named DELIVERED. The only one you posted is named DL.
So what should be in the table is DL not DELIVERED. Or you should rename your enum instance to DELIVERED, to match what is stored in the database table.
You could define a custom Hibernate user type and use it for this enum as well, so that when getting "DELIVERED" from the database, Hibernate finds the enum instance constructed with this value (and ignoring the case). But storing the correct value from the start looks like a betteridea to me.
I prefer defining a custom converter like:
#Column
#Convert(converter = StatusFirmaDocumentoConverter.class) <<<<< :)
#AuditableField
private Status status;
(note: do not include the #Enumerated attribute) and creating a converter to process the enumerator value like:
public class CustomConverter implements AttributeConverter<Status, String> {
#Override
public String convertToDatabaseColumn(Status attribute) {
return attribute.getValue() ;
}
#Override
public Status convertToEntityAttribute(String dbData) {
return StatusFirmaDocumento.fromString(dbData);
}
}
yeah, it's a shame that you can't tell to hibernate "translate DL to DELIVERED" and viceversa
Let's say I have a model class like this:
public class User {
#NotEmpty(message = "Email is required")
private String email;
}
I want to be able to unit test for the custom error message "Email is required"
So far, I have this Unit Test code which works, but does not check for the error message.
#Test
public void should_respond_bad_request_with_errors_when_invalid() throws Exception
{
mock().perform(post("/registration/new"))
.andExpect(status().isBadRequest())
.andExpect(view().name("registration-form"))
.andExpect(model().attributeHasFieldErrors("user", "email"));
}
Seems you can't.
But I suggest you work around through the attributeHasFieldErrorCode method.
Having the following:
#NotNull(message="{field.notnull}")
#Size(min=3, max=3, message="{field.size}")
public String getId() {
return id;
}
I have in my test methods the following (in case my data fails for Minimum or Maximum constraints, it belongs to the #Size annotation)
.andExpect(model().attributeHasFieldErrorCode("persona", "id", is("Size")))
or with
.andExpect(model().attributeHasFieldErrorCode("persona", "id", "Size"))
The method has two versions, with and without Hamcrest
Even when you use message = "Email is required" (raw/direct content) and I use message="{field.size}") the key to be used from a .properties file, our message attribute content belongs practically for a unique kind of annotation. In your case for a #NotNull and in my case for a Size.
Therefore, in some way does not matter what is the message (raw or key), the important is that the owner of that message (in this case the annotation) did its work and it has been validated through the attributeHasFieldErrorCode method.
Do not confuse with the similar methods names: attributeHasFieldErrors and attributeHasFieldErrorCode.
I have had the same issue. I have found some solution described below. The main idea is to check error code, not the error message.
BindingResult bindingResult = (BindingResult)
mock().perform(post("/registration/new")).andReturn().getModelAndView().getModelMap().get("org.springframework.validation.BindingResult.user");
assertEquals(bindingResult.getFieldError(email).getCode(), "error.code");
Since upgrading my webapplication from Spring 3.0.5 to 3.1.1 I have to face some serious errors when validating my form-beans. My previously configured validator(s) doesn't work any more like they should. The problem is that the method getFieldValue(String fieldname) from Class org.springframework.validation.Errors does not return the original binded bean value like it should (and was before).
This is what my form-bean looks like:
public class PersonBean extends BaseFormBean {
private String firstname; // getters and setter omitted...
private String lastname; // getters and setter omitted...
private Integer age; // getters and setter omitted...
public PersonBean() {}
#Override
public void validateForm(Errors errors) {
WebValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstname", "validator.requiredvalidator.lbl", "field required");
WebValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastname", "validator.requiredvalidator.lbl", "field required");
WebValidationUtils.rejectInvalidIntValue(errors, "age", "validator.std.age", "invalid age", false);
}
}
The WebValidationUtils-class that gets invoked has some standard methods for checking bean properties. The error occurcs only on non-String values, like the property age which is of type Integer. It also happens on Collection(s).
The following snippet shows how Integer values are validated in my utils-class:
import org.springframework.validation.Errors;
...
public abstract class WebValidationUtils {
...
public static void rejectInvalidIntValue(Errors errors, String field, String errorCode, String defaultMessage){
Assert.notNull(errors, "Errors object must not be null");
Object value = errors.getFieldValue(field); // returns the string value (type: java.lang.String)
Class<?> fieldType = errors.getFieldType(field); // returns the class Integer!
if (value == null || !value.getClass().equals(Integer.class) || ((Integer)value).intValue() <= 0){
errors.rejectValue(field, errorCode, null, defaultMessage);
}
}
}
The bean itself has the correct value bound...
Do I have to configure some additonal spring beans in my context-servlet.xml do achieve the same bevahior like it was in 3.0.5?
Edit: The official Spring Doku for the method "getFieldValue(...)" says
Return the current value of the given field, either the current bean property value or a rejected update from the last binding.
So I don't have a clue why this method returns a String-value instead of the propagated bean value of type Integer...
Seem like you have a binding error so getFieldValue() return FieldError.getFieldValue() that return the value that causes the binding error. This is the expected behavior.
You can get the value that hold the property using getRawFieldValue() instead. This method always return the value using the PropertyAccessor.