Giter Site home page Giter Site logo

Comments (20)

ova2 avatar ova2 commented on June 9, 2024

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.

BalusC avatar BalusC commented on June 9, 2024

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.

ova2 avatar ova2 commented on June 9, 2024

Where is the class level validation in the o:validateBean?

from omnifaces.

BalusC avatar BalusC commented on June 9, 2024

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.

ova2 avatar ova2 commented on June 9, 2024

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.

djmj avatar djmj commented on June 9, 2024

<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.

ova2 avatar ova2 commented on June 9, 2024

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.

arjantijms avatar arjantijms commented on June 9, 2024

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.

arjantijms avatar arjantijms commented on June 9, 2024

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.

arjantijms avatar arjantijms commented on June 9, 2024

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])
  • 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.

ova2 avatar ova2 commented on June 9, 2024

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.

arjantijms avatar arjantijms commented on June 9, 2024

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.

ova2 avatar ova2 commented on June 9, 2024

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.

arjantijms avatar arjantijms commented on June 9, 2024

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.

ova2 avatar ova2 commented on June 9, 2024

"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.

arjantijms avatar arjantijms commented on June 9, 2024

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.

ova2 avatar ova2 commented on June 9, 2024

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.

arjantijms avatar arjantijms commented on June 9, 2024

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.

djmj avatar djmj commented on June 9, 2024

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.

djmj avatar djmj commented on June 9, 2024

This bean validation ticket looks related to the cloning / proxy problem.

https://hibernate.atlassian.net/browse/HV-653

from omnifaces.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.