Re-execute f:viewAction when ViewScoped bean is recreated following a POST request

╄→尐↘猪︶ㄣ 提交于 2019-12-05 16:54:33

I'm aware of postBack="true" but it's not suitable as bean.onLoad() would be called on every POST request.

You can just use EL in onPostback attribute wherein you check if the model value and/or request parameter is present.

If the model value is required, then just check if it's present or not:

<f:metadata>
    <f:viewParam maxlength="100" name="name" value="#{bean.file}" required="true" />
    <f:viewAction action="#{bean.onLoad}" onPostback="#{empty bean.file}" />
</f:metadata>

If the model value is not required, then check the request parameter too:

<f:metadata>
    <f:viewParam maxlength="100" name="name" value="#{bean.file}" />
    <f:viewAction action="#{bean.onLoad}" onPostback="#{empty bean.file and not empty param.name}" />
</f:metadata>

I cannot call onLoad() in @PostConstruct method because values have not been set by viewParam yet.

Given the presence of <o:form> in your snippet, I see that you're using OmniFaces. The very same utility library offers a CDI @Param annotation for the very purpose of injecting, converting and validating HTTP request parameters before the @PostConstruct runs.

The entire <f:viewParam><f:viewAction> can therefore be replaced as below:

@Inject @Param(name="name", validators="javax.faces.Length", validatorAttributes=@Attribute(name="maximum", value="100"))
private String file;

@PostConstruct
public void onLoad() {
    if (!Faces.isValidationFailed()) {
        // ...
    }
}

Or if you've Bean Validation (aka JSR303) at hands:

@Inject @Param(name="name") @Size(max=100)
private String file;

@PostConstruct
public void onLoad() {
    if (!Faces.isValidationFailed()) {
        // ...
    }
}

Though I havent been struggeling with the numberOfLogicalView I often need to reinitialize beans with a long living scope. Eg a usecase is to (re-) load some detail data from database when the user clicks on some entity in a table-view. Then I simply use some initialized-flag, eg

@SomeLongLivingScope
public class MyBean {

    private boolean initialized = false;

    public void preRenderView() {
        if ( initialized ) return;
        try {
             do_init();
        } finally {
            initialized = true;
        }
    }

    public void someDataChangedObserver( @Observes someData ) {
        ...
        initialized = false;
    }
}

Using this pattern you can use your viewAction with postBack="true".

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!