h:inputText which is bound to String property is submitting empty string instead of null
Asked Answered
L

2

22

I have a JSF 2.0 application on Tomcat with many <h:inputText> fields to input data in my database. Some fields are not required.

<h:inputText value="#{registerBean.user.phoneNumber}" id="phoneNumber">
    <f:validateLength maximum="20" />
</h:inputText>

When the user leave this field empty JSF sets empty string "" instead of null.

How can I fix this behavior without checking every String with

if (string.equals("")) { string = null; }
Linda answered 4/2, 2010 at 21:23 Comment(3)
are you sure your "user" object doesn't have "" as default value?Speaks
@Bozho: don't you mean phoneNumber? ;) AFAIK this is the default behaviour in JSF 1.x and workaroundable with a Converter in JSF 1.2 (not in 1.1 or older). I just did little test in JSF 2.0 and it's indeed also the default behaviour and workaroundable with a Converter. But I was also almost certain that I've read somewhere before that you can configure JSF 2.x to set null in case of an empty string by some special init-param. I only don't recall anymore which one it is and where I've read it :(Herrle
Finally found it somewhere at the bottom of the JSF 2.0 spec.. See answer ;)Herrle
H
51

You can configure JSF 2.x to interpret empty submitted values as null by the following context-param in web.xml (which has a pretty long name, that'll also be why I couldn't recall it ;) ):

<context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
</context-param>

For reference and for ones who are interested, in JSF 1.2 (and thus not 1.1 or older because it's by design not possible to have a Converter for java.lang.String) this is workaroundable with the following Converter:

public class EmptyToNullStringConverter implements Converter {

    public Object getAsObject(FacesContext facesContext, UIComponent component, String submittedValue) {
        if (submittedValue == null || submittedValue.isEmpty()) {
            if (component instanceof EditableValueHolder) {
                ((EditableValueHolder) component).setSubmittedValue(null);
            }

            return null;
        }

        return submittedValue;
    }

    public String getAsString(FacesContext facesContext, UIComponent component, Object modelValue) {
        return (modelValue == null) ? "" : modelValue.toString();
    }

}

...which needs to be registered in faces-config.xml as follows:

<converter>
    <converter-for-class>java.lang.String</converter-for-class>
    <converter-class>com.example.EmptyToNullStringConverter</converter-class>
</converter>

In case you're not on Java 6 yet, replace submittedValue.empty() by submittedValue.length() == 0.

See also

Herrle answered 4/2, 2010 at 22:58 Comment(9)
@James: so you're using Tomcat (or JBoss or Websphere which uses Tomcat under covers)? If true, add VM argument -Dorg.apache.el.parser.COERCE_TO_ZERO=false. See also stackoverflow.com/questions/3116517Herrle
@BalusC: That fixes it, but I honestly don't understand why since I am binding into a String field, care to explain? Unfortunately it's also a solution that's not going to work for me as we don't direct control over the servers (Tomcat or otherwise) that the client may be running our app under.Jerboa
@James: That's something new in Tomcat 7. See also #6304525Herrle
@BalusC: I'm not using Tomcat 7. I am using 6.0.32. Must be a bug in both.Jerboa
@James: Well, things have changed again in Tomcat between 6.0.17 and 6.0.32 which I am not aware of. I am pretty certain that this didn't affect strings in Tomcat 6.0.20.Herrle
@BalusC: Well that's certainly a pain :). Thanks for your help.Jerboa
Coworker looked at the Tomcat code, COERCE_TO_ZERO is a misleading property. It actually turns off coercion unless the objects don't match (number to string). So when this property is set Tomcat doesn't coerce the null String into a blank String.Jerboa
@BalusC: Why is it necessary to call setSubmittedValue(null)? What does this do?Abfarad
@Craig: this sets the submitted value to null, for the case some (custom) validator extracts it directly from the component instead of from the validate() method argument.Herrle
L
0

i hope this is the right way to say that i can't find a solution for the Problem.

I have add the context-param to my web.xml but it has no result. I use a Tomcat 6.0.24 Server with this two context-param: javax.faces.PROJECT_STAGE = Development javax.faces.VALIDATE_EMPTY_FIELDS = true

Linda answered 8/2, 2010 at 11:0 Comment(4)
In the future, just edit your question :) As to the problem: what if you remove one or both of the other parameters? I have tested it at Glassfish v3 by the way. I'll test at Tomcat later this day when I have chance.Herrle
Yes, i have remove the other parameters but without a result. I wait for your test. ThanksLinda
I was able to reproduce the same problem. The cause seems to be inside Tomcat's EL implementation. We can't do anything against it than hacking in it. Until they get it officially fixed and released, I would suggest to use the Converter as shown in my answer. It works fine.Herrle
Thank you for your Help. I use now Glasfish and it works like a charmLinda

© 2022 - 2024 — McMap. All rights reserved.