Comments (20)
I've just started to implement a GraphValidator like in RichFaces. https://access.redhat.com/site/documentation/en-US/Red_Hat_JBoss_Web_Framework_Kit/2/html/RichFaces_Component_Reference_Guide/sect-Component_Reference-Validation-richgraphValidator.html
This will allow cross field validation.
I think this validator is a good candidate for OmniFaces. Would the OmniFaces team accept my pull request when the validator is ready to use?
Thanks. Oleg.
from omnifaces.
If I understand you correctly, you're looking for the same functionality as available by <o:validateBean validationGroups>
. See also http://showcase.omnifaces.org/validators/validateBean
from omnifaces.
Where is the class level validation in the o:validateBean?
from omnifaces.
It's the default already when using JSR303 bean validation, right? The o:validateBean just enables more finer grained control over that.
Or perhaps I misunderstood both of you. Having a real world use case would probably help in a better understanding.
from omnifaces.
JSF can not validate class or method level constraints. Only constraints on fields. What I need in my project:
Execution of a method annotated with @AssertTrue in the JSF Validation Phase (not in the Invoke Application Phase).
That means, we need a similar construct as in the mentioned above GraphValidator. It clones the bound bean while PostValidate, set local values into the cloned bean (or what ever is set in this phase) and invokes validate() on the bean via JSR303 API.
Probably we have also to consider first available constraint annotation like PrimeFaces does it (cann't remember the internal class name in PrimeFaces).
from omnifaces.
<f:validateBean>
and <o:validateBean>
is not validating a "bean", it only validates a single property that is bound to an UIInput.
A simple example with custom validators would be:
/* validate if barcode is valid for given type*/
@ValidateProduct(groups = {BarcodeType.class, Default.class})
public class Product
{
private String barcode;
private BarcodeType barcodeType;
@Valid
private ProductDim dimension;
}
/* or use new @AssertTrue or other extended validation annotations */
@ValidProductDim
public class ProductDim
{
private int width;
private int height;
private int depth;
}
JSF:
Imagine a wizard with following step:
<h:form>
<p:tab id="tabBarcode">
<p:messages/>
<p:inputText value="#{bean.product.barcode}"/>
<p:selectOneMenu value="#{bean.product.barcodeType}"/>
<!-- on submit or tab-change lets validate the combination -->
<o:validateBean value="#{bean.product} groups="BarcodeType"/>
</p:tab>
<!-- other tabs -->
</h:form>
Currently this must be handled in backing bean after each step or complete form submit:
/* Primefaces tab flow eventhandler */
public String onFlowProcess(final FlowEvent event)
{
final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
switch (event.getOldStep())
{
case "tabBarcode":
final Set<ConstraintViolation<Object>> cvs = validator.validate(object, BarcodeGroup.class);
if (!cvs.isEmpty())
// add error message or throw new ConstraintViolationException(cvs);
}
}
This is much code to write some something thats supposed to be a java-ee standard.
This would be very helpfull.
from omnifaces.
Agree. And this is not only much code. This is the wrong JSF phase too. The listener onFlowProcess is fired much later than validation phase. Wrong values are already set in bean!
from omnifaces.
As it appears, a spec issue was logged for this over half a decade ago: https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-543
from omnifaces.
Guys, I did a basic implementation of the class level constraint validation as per the commits shown above. There's a demo at omnifaces/showcase@ff430bd#diff-1
This now works much like djmj's example. What it does not (yet) do is what Oleg talked about; cloning of the bean, simulating update model on the cloned bean during the VALIDATION phase, and then doing the class level validations.
from omnifaces.
A possible algorithm for the simulating of update model mentioned above:
- Check all components in parent form of o:validateBean
- component == editableValueHolder?
- get target base/property of value expression (e.g. #{validateClassLevelBean.product.number1} -> product/number1)
- base == o:validateBean's value? (E.g. #{validateClassLevelBean.product}" == product)
- Add extra "validator" -> just captures value for that property (e.g. "number1" = [value])
- component == editableValueHolder?
- At end of validate phase:
- Clone base
- Set base's properties based on captured values
- Do bean validation against base
I was thinking of doing this as an optional behavior.
So default is then the basic behavior as is happening now: validation against the actual instance in the post update model phase. Disadvantage: not really JSF like, model is updated with invalid values and the user has to check if there was a validation error. Advantage: Simple, lightweight, and no cloning of the model object needed.
The cloning option has basically the opposite advantages/disadvantages.
To do the cloning/copying a couple of strategies could be used:
- Cloning via the Cloneable interface
- The old Serialization/deserialization trick
- A copy constructor of the bean
- A user provided type that knows how to copy the bean
Examples of the last one in action:
<o:validateBean value="#{validateClassLevelBean.product}" method="validateCopy" copier="com.me.MyBeanCopier" />
And/or:
<o:validateBean value="#{validateClassLevelBean.product}" method="validateCopy" copier="#{someBean.someCopier}" />
The Copier itself may just be an implementation of a simple interface like:
public interface Copier {
Object copy(Object in);
}
from omnifaces.
I would clone the base object to validate in the proper JSF phase and don't pollute model with invalid values. All what I need is a working @AsserTrue in JSF.
I don't know if we really need a copier. Checking Cloneable interface and old Serialization/deserialization trick (as fallback) would be enough in my opinion.
from omnifaces.
Thanks for the feedback Oleg :)
I was wondering about the copier, but the reason I thought it might be handy is to give the user some control over the process.
For instance, the bean might not be cloneable or serializable, and could come from another package (module) that the UI people do not directly have access to. If the bean is a model object this may not be entirely unthinkable.
Also, the bean could theoretically have some expensive dependencies (maybe some large array) that the UI developer knows does not have to be cloned/copied for the simulation.
Thinking of it, another option may be:
- new Instance - don't clone/copy the class but create a new instance based on its type
Anyway, it will all be optional of course ;)
from omnifaces.
Hallo Arjan,
"... and could come from another package (module) that the UI people do not directly have access to" - the copier makes sense then. Thanks.
from omnifaces.
Hi guys,
Per the last commits I implemented the plan as outlined above. There's a demo available at http://snapshot.omnifaces.org/validators/validateBean
One design choice; when validation fails in the post validation phase event listener, the code skips directly to render response, so that the invoke application phase won't be executed. I think that's the only sane option, but let me know what you think.
I'll push a new snapshot to the sonatype repo later today.
from omnifaces.
"when validation fails in the post validation phase event listener, the code skips directly to render response, so that the invoke application phase won't be executed. I think that's the only sane option, but let me know what you think."
That's correct. Thanks a lot Arjan.
P.S. The model class Product.java is missing in the showcase, the source tab.
from omnifaces.
Thanks for the feedback Oleg, appreciate it :)
I've added Product.java in the showcase as well as a few other important classes for the example. I also published the new OmniFaces 2.0-snapshot that contains all these changes.
If there's nothing else to be done and no bugs are found then I think we can finally close this issue.
from omnifaces.
Good stuff, thanks a lot. I think you can close this issue. I will probably mention this in the PrimeFaces Cookbook, 2. Edition, while writing about validation :-).
from omnifaces.
Cool! Looking forward to that :)
All right, I'll close the issue now then. Both you and djmj, thanks a lot again for this great feature suggestion.
from omnifaces.
Thank you all for implementing it! Did not had time to test it yet, but I trust you.
Don't know what I would do without omnifaces :),
from omnifaces.
This bean validation ticket looks related to the cloning / proxy problem.
https://hibernate.atlassian.net/browse/HV-653
from omnifaces.
Related Issues (20)
- Missing list attribute in converter tag HOT 1
- FullAjaxExceptionHandler => OmniExceptionHandler HOT 20
- Question: A lot of AtomicReference in heapdump HOT 19
- VersionedResourceHandler doesn't support non-String values such as Long timestamp
- idea: why not rename the OmniFaces' @ViewScoped => @PageScoped ? HOT 6
- Feature Request: New component <o:criticalStylesheet> for Critical CSS HOT 1
- Faces.sendFile() inside p:columns logs jakarta.servlet.ServletException HOT 6
- ViewScopeManager - NPE - Weld bug? HOT 2
- LruCache - Lock is null HOT 4
- OnLoadScript: Behavior difference in MyFaces/Mojarra HOT 3
- unload not working after update form HOT 3
- POST-Parameters omitted in AJAX request when using execute with id of parent component HOT 3
- conditionally rendered deferredScript and CombinedResourceHandler bug? HOT 2
- ToCollectionConverter with List of Enum HOT 4
- Json: Encode Java14 Record objects HOT 8
- 5.0: Use URN instead of URL as XML namespace URI HOT 3
- Zeef Page? HOT 2
- ToCollectionConverter with inheritance HOT 4
- BrotliResponsFilter similar to GzipResponseFilter HOT 8
- Feature Request: o:link HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from omnifaces.