0

I have a <h:selectOneMenu>. Depending on what is selected will be shown one of the many <div>s related to the selection and will be hidden the others. Each <div> has some <h:inputText> that write to different @ViewScoped beans. Some of this <div>s even write to the same properties in the beans.

Ex.

<div>
    <h:outputLabel for="list" value="Items"/>
    <div>
        <h:message for="list"/>
        <h:selectOneMenu id="list" value="#{bean.selectedItem}" >
            <f:selectItem itemLabel="Select one"></f:selectItem>
             <f:selectItems value="bean.someItemsList" />
        </h:selectOneMenu>
    </div>
</div>

<div id="item1">
    <!-- some other input fields -->
    <div>
        <h:message for="item1input1"/>
        <h:inputText id="item3input1" value="bean.thisIsTheSameProperty" />
    </div>
</div>
<div id="item2">
    <!-- some other input fields -->
</div>
<div id="item3">
    <!-- some other input fields -->
    <div>
        <h:message for="item3input1"/>
        <h:inputText id="item3input1" value="bean.thisIsTheSameProperty" />
    </div>
</div>

The problem: When I select an item that will display a <div> (ex. <div id="item1">) and there is also another hidden <div> (ex. <div id="item3">) that writes to the same bean properties (ex. value="bean.thisIsTheSameProperty") and this properties are annotated with javax.validation.constraints.@NotNull, even I give a value to this input fields, when I submit the form, I think JSF runs also the hidden <div> (which normally has no input set).

What I see during debugging: When the form will be submited I see the setter of the bean will be called twice. The first time the bean properties will be set with the correct valeus I typed in but the second time the setter will be called with null values. So the validation will fail because of the @NotNull.

My assumption is that JSF tries to set the bean values twice, one for the input fields on the shown <div> and the second time for the hidden <div> (because they point to the same bean properties), but for the hidden bean there are not input fields set (they are null).

I show/hide the <div>s with jQuery depending on the item selected from the <h:selectOneMenu>. Ex.

$('#item1').show();
$('#item1').hide();
$('#item2').show();
$('#item2').hide();
$('#item3').show();
$('#item3').hide();

Is there a way to say JSF to not consider the hidden <div>s at all?

Elio
  • 428
  • 3
  • 20
  • 2
    Your binding 'bean.thisIsTheSameProperty' was transmitted twice, because you have two input fields, that bind this property. You can try to disable the input fields in the hidden
    . Disabled fields will not transferred.
    – drkunibar Feb 06 '19 at 22:29

2 Answers2

3

You seem to be assuming that hidden inputs (hidden via CSS) are not submitted to the server. This assumption is wrong and it is a plain html thing btw, not JSF related at all.

See e.g. Stop an input field in a form from being submitted

But still, it would allow client-side manipulation via a browser developer tool to 'attack' you application. JSF, contrary to all the hyped javascript UI frameworks is a full grown 'MVC framework' that has build in protection against client-side manipulation/tampering and CSRF, XSS for which you'd need OWASP related functionality in other framework. (That and other things makes JSF (with PrimeFaces, OmniFaces and DeltaSpike) for me still a great framework to quickly develop business oriented applications.)

You'd better use ajax to conditionally render one div or the other but you cannot 'update' the divs when they are defined like you have them.

See also:

Kukeltje
  • 12,223
  • 4
  • 24
  • 47
  • What I actually need is hidden inputs (hidden via CSS or some other way) not to be submited. – Elio Feb 07 '19 at 10:08
  • Then use the pure html/javascript 'solution' in the first link in the answer, but as you can see from the upvotes, what I propose is the better solution – Kukeltje Feb 07 '19 at 10:21
0

The answer from @Kukeltje and comment from @drkunibar worked for me. I modified it a little.

Actual solution:

$('#myForm').submit(function() {
            if($('#list').find(':selected').val() === 'itemOption1') {
                $('item3').remove();
            } else if($('#list').find(':selected').val() === 'itemOption3') {
                $('item1').remove();
            }
});

I check to see which option is selected. If option1 is selected then I remove the div with iditem3 from the DOM, or else if the option3 is selected then I remove the div with iditem1 from the DOM. In this way the binding bean.thisIsTheSameProperty is transmitted only one and the values will not be overriden.

Thank you.

Elio
  • 428
  • 3
  • 20
  • 1
    That is what is mentioned in the links in my answer. If this is what you need, it is in **no way** JSF related and effectively a duplicate of https://stackoverflow.com/questions/3008035/stop-an-input-field-in-a-form-from-being-submitted. and there is no need to add it as an answer then. But keep in mind, this is an insecure solution. – Kukeltje Feb 07 '19 at 10:26
  • Yes, your answer is correct. Thank you! But I cannot find out how and why it is an insecure solution. My solution hast nothing to do with CSRF-attacks. Do you see something that I don't? :) – Elio Feb 07 '19 at 11:36
  • 2
    'client-side tampering' is also mentioned in the answer. Not just CSRF and XSS – Kukeltje Feb 07 '19 at 14:10
  • In my case it is up to user to do what he wants. There is no sensitive data or process that I need to secure. Otherwise I would have developed the logic on the server side. But thank you. – Elio Feb 07 '19 at 15:20