NoAutoGeneratedIdViewHandler catches generated viewState id's #83

Closed
MSzturc opened this Issue Dec 15, 2014 · 4 comments

Projects

None yet

2 participants

@MSzturc
MSzturc commented Dec 15, 2014

It looks like NoAutoGeneratedIdViewHandler is not compatible to javax.faces.view.ViewScoped beans since the ViewState is saved in a hidden field thats id gets autogenerated.

For example:

<input type="hidden" name="javax.faces.ViewState" id="j_id1:javax.faces.ViewState:0" value="8786734053775064602:4306533153707701537" autocomplete="off" />
@arjantijms
Member

With which JSF implementation did you get this and using what kind of page?

@MSzturc
MSzturc commented Dec 15, 2014

Mojarra 2.2.7 OmniFaces 2.0 PrimeFaces 5.1 on GlassFish Server Open Source Edition 4.1

The Exception i got:

java.lang.IllegalStateException: Auto generated ID 'j_id1' encountered on component type: 'javax.faces.component.UIViewRoot'.
    at org.omnifaces.viewhandler.NoAutoGeneratedIdViewHandler$NoAutoGeneratedIdResponseWriter.writeAttribute(NoAutoGeneratedIdViewHandler.java:154)
    at com.sun.faces.renderkit.ServerSideStateHelper.writeState(ServerSideStateHelper.java:270)
    at com.sun.faces.renderkit.ResponseStateManagerImpl.writeState(ResponseStateManagerImpl.java:126)
    at com.sun.faces.application.StateManagerImpl.writeState(StateManagerImpl.java:113)
    at com.sun.faces.application.view.WriteBehindStateWriter.flushToWriter(WriteBehindStateWriter.java:225)
...

Here my JSFView

<ui:define name="content">
            <div style="margin-top: 30px">

                <h:form id="login">
                    <div class="form-group">
                        <o:outputLabel for="username" value="Username"/>
                        <h:inputText class="form-control" id="username" value="#{loginView.username}"/>
                    </div>
                    <div class="form-group">
                        <o:outputLabel for="password" value="Password"/>
                        <h:inputSecret class="form-control" value="#{loginView.password}" id="password"/>
                    </div>  
                    <b:commandButton id="submit" look="primary" value="Login" action="#{loginView.doLogin}" ajax="true" update="login"/>
                    <div class="form-group" />
                </h:form>
            </div>
        </ui:define>

The generated HTML Code

<form id="login" name="login" method="post" action="/SNR/login" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="login" value="login" />

                    <div class="form-group"><label for="login:username">Username</label><input id="login:username" type="text" name="login:username" class="form-control" />
                    </div>
                    <div class="form-group"><label for="login:password">Password</label><input id="login:password" type="password" name="login:password" value="" class="form-control" />
                    </div><button type="submit" id="login:submit" name="login:submit" class="btn btn-primary" onclick="return BsF.ajax.cb(this, event,'login');">Login</button>
                    <div class="form-group"></div><input type="hidden" name="javax.faces.ViewState" id="j_id1:javax.faces.ViewState:0" value="7780056425491557099:-3873095009780239749" autocomplete="off" />
</form>

And the backing bean:

@Named
@ViewScoped
public class LoginView implements Serializable {

    private static final long serialVersionUID = 7765876811740798583L;


    @NotEmpty
    private String username;

    @NotEmpty
    private String password;

    @Inject
    UserService userService;

    public String doLogin() {
        return userService.login(username, password);
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
@arjantijms
Member

Thanks for the quick reply.

Okay, I did some quick scanning and in my test code I happened to have com.sun.faces.enableViewStateIdRendering set to false:

<context-param>
    <param-name>com.sun.faces.enableViewStateIdRendering</param-name>
    <!-- Prevent duplicate javax.faces.ViewState element IDs. -->
    <param-value>false</param-value> 
</context-param>

(that last comment isn't true for JSF 2.2 anymore)

For my own reference, this ID is written out in case of Mojarra in ServerSideStateHelper:

if (webConfig.isOptionEnabled(EnableViewStateIdRendering)) {
    String viewStateId = Util.getViewStateId(ctx);
    writer.writeAttribute("id", viewStateId, null);
}

I'll take a look at this soon. Thanks for reporting!

@MSzturc
MSzturc commented Dec 16, 2014

Thanks for the tip.

Setting com.sun.faces.enableViewStateIdRendering to false solved this issue for me. The viewstate field not longer contains the id attribute:

<input type="hidden" name="javax.faces.ViewState" value="-6851369401135225018:723157282747351055" autocomplete="off" />

Thanks for your support

@BalusC BalusC added a commit that closed this issue Mar 2, 2015
@BalusC BalusC Fix #83: Skip javax.faces.ViewState hidden inputs in
NoAutoGeneratedIdViewHandler.
8ad3e66
@BalusC BalusC closed this in 8ad3e66 Mar 2, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment