I'd like to configure bean validation (JEE6) constraints via a properties file or database.
So for instance the Max value below would get pulled from the properties file or database.
Is this possible in ?
#Max(value = 1)
private int elvis;
Any suggestions on a possible approach.
It is not possible via standard Bean Validation. The default as per specification are annotations or as alternative XML.
In theory, Hibernate Validator has the (internal) concept of a MetaDataProvider and one could think of plugging in a DbMetaDataProvider. However, that would be quite some work and I am not sure that it would be worth the effort.
What is you use case anyways? Why don't you use XML?
You can write your own constraint and validator for that. The constraint’s argument could be some identifier of the validation parameters stored in database and the validator could query database for these parameters to validate a value according to them.
Some hints:
See this validator for an idea how to reuse existing validators from your “über validator”.
See this question and this answer for a hint how to inject bean to a validator.
Related
I am using bean validation to validate my entity,
it works fine according to different locales and it shows region-specific error messages, but I want to internationalize a field 'ContactNo' according to the region like my error messages #NotBlank(message="{contactNo.size}").
So how to achieve
#Pattern(regexp="(^$|[0-9]{10})")
private String contactNo;`
where the regexp value changes according to the region?
The the value for the regexp attribute has to be constant i.e. it needs to be available at compile time. So, either it needs to be a string literal as you do now or externalized into a static final variable.
I guess what you need has to be implemented in a custom Bean Validation constraint.
#WebInitParam is an annotation that goes at class level.
It defines initialization parameters for the servlet.
I would like to know, what is the difference between doing this and using static variables, and why do it the #WebInitParam way rather than using statics?
What does defining k/v pairs as #WebInitParams allow you to do that you couldn't do if you declared static variables instead?
I have looked and all I can find is a million people saying how to define #WebInitParams. Well yes that's the easy bit. It's what I can do with that that is really what is of interest.
Thanks very much.
From a "raison d'etre" perspective, the annotation exists as a better design and architecture alternative to just peppering a class with static fields. #WebInitParam is a self-documenting approach to the initialization parameters a servlet or filter class needs, available via web.xml as well. It serves this purpose for the end developers as well as the JavaEE platform as a whole.
Think about it this way: in a vanilla project, you have the option of hardcoding a bunch of parameters in the class as static fields, or defining the same parameters in a property file. Which would you pick? Under what circumstances?
From a purely functional angle, apart from the function of using the annotation to override defaults set in web.xml, one other major reason is that you will sometimes need to get a hold of those initialization parameters from another component in your application. Using the annotation essentially increases the visibility of the parameter. In JSF for example, the API allows you to retrieve FacesServlet initialization parameters with:
//get all the parameters
FacesContext.getCurrentInstance().getExternalContext().getInitParameterMap()
//get a specific parameter
FacesContext.getCurrentInstance().getExternalContext().getInitParameter("aParameter");
In JSF-2.3 , it gets even more convenient with the following CDI-enabled injection:
#InitParameterMap Map<String,String> servletParameterMap;
Bear in mind that because it's CDI, it means this facility is available throughout the JavaEE platform, not just in web applications/JSF.
It's going to be a hassle to retrieve init parameters if the only mechanism available is a static field in the servlet class - you'll need to obtain an instance of the filter or servlet to get the static fields in it.
Separately, one could make the argument that maybe one should favour context-params over servlet-params because then, you get even more flexibility that isn't tied to any given servlet. That's a separate matter entirely :)
Background
With ef core code first approach, validation is robust and simple: https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/validation
With the database first approach, it seems like any validation is happening behind the scenes by the database when dbcontext.SaveChanges(); is called. What's worse, these exceptions are nebulous and entirely unhelpful, for example, SqlException: String or binary data would be truncated can be thrown if any of the string properties of any of the entities have too many chars (ours is a legacy app riddled with char(10) and such), or even if a key that is a string is left null.
Question
I want to know if there is any reasonable or accepted way of enforcing the validation. I've found this question which might help debugging, but I would like to enforce the constraints in code
Is there any better method than changing every auto property to one that throws if it's constraints aren't met?
EntityFramework Core does not enforce any validation at all. The validation rules you see in the example are enforced by MVC and not EF. One of the main reason for EF Core to remove validation check was that only. Validation are run in UI and then in EF and then again in database which is just redundant. Hence client side validation is left to the front-end (MVC in this case) and server side is done by database engine.
When you use database first approach, EF core does not generate any annotation for validation because it does not reason about them anyway. That means you would get only server side validation which means error during SaveChanges.
The only way to enforce constraint in the code (client side) is to write those annotations so that MVC can enforce them or write custom code to deal with it. The whole validation mechanism is transparent to EF.
I ended up going with a psuedo extension to the generator tooling. Since the DBContext is a partial class, I made a new class that has a main
public partial class DBContext{
public static void Main(string[]args){
DBContext context = new DBContext();
var modelbuilder = new Microsoft.EntityFrameworkCore.ModelBuilder(new Microsoft.EntityFrameworkCore.Metadata.Conventions.ConventionSet());
context.OnModelCreating(modelbuilder);
IMutableModel model=modelbuilder.Model;
from there I used Linq to transform the various info about each entity's properties and the annotations on them into List<KeyValuePair<string,List<KeyValuePair<Regex,string>>>> where the first pair's key is the entity name, and the value is a list of find and replace pairs to edit the code that had already been generated with the corresponding validation, one per property. Then all I had to do was abuse the fact that the tooling generates the classes in <className>.cs files, and iterate over my list, executing the replacements for each entity source code file.
I'd have preferred doing something a little less hacky, because I'm relying on format that the ef tooling outputs, but it works
If I'm using JavaBean Validation 1.0 (JSR 303), and I extract my validation messages into a property file how does Spring become aware of my property file? I know I need to declare a ResourceBundleMessageSource bean but I'm just not clear on how Spring/JavaBean validation becomes aware of this file?
That is main idea of "Framework". It makes lots of magic/setups behind of scenes, so you don't have to write thousands rows of boilerplate code for every project. You can follow with default path/settings (messages.properties) or switch to something else using Configuraton or application.properties file (which also can be changed). But for sure, you don't want to do that in most cases, but you can.
Coming from play 1.x. I like the possibilities of OVal. How ever actual I'm evaluating to setup a stack with Spring MVC. There the default for validation is JSR-303. One problem I see with JSR-303 is to get the context of a property or adjust the message. See JSR303 Validation - Bean's property as Message Parameter and javax Bean Validation based on variables?. One problem I have in converting a constraint, that checks if the text a user entered only contains valid variables. So the use can add "The member ${name} does an excellent job." If he wrote "The member ${nmae} does an excellent job." he should get a message like: "Your text contains the invalid variable >nmae<, you can only use >name, firstname<".
With Oval this can easily be done. So I wonder if there are disadvantages to use OVal instead of JSR-303.
Personally I think it is a good idea to stick to a standard. This ensures portable applications and by using a standard you are using something many developers are familiar with. You are right that your particular use case it not supported atm by Bean Validation. However, Bean Validation 1.1 is on its way and interpolating the validated value is on the roadmap - see BVAL-219.
In the meantime you can use Hibernate Validator's ValueFormatterMessageInterpolator. Yes you are using a custom extension of Bean Validation, but only for this specific feature.