How to reset in jsf? - jsf

I am using liferay and jsf. In my portlet I tried to reset after submitting page by setting new values to the backing bean. I got blank fields but when I refreshed the page, I got my old values again which I have submitted earlier and it submit again with old values.
I tried to get new viewroot but it also gave me same result.
public void reset(AjaxBehaviorEvent event){
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
ViewHandler viewHandler = application.getViewHandler();
UIViewRoot viewRoot = viewHandler.createView(context, context
.getViewRoot().getViewId());
context.setViewRoot(viewRoot);
context.renderResponse(); //Optional
this.MyBean = new MyBean();
}
P.S. After submit I call this method as reset(null);

If you want the bean to be reset after each request; in that case instead of using the function you can make use of the scope(s) provided by the jsf.
Using the bean in request scope
tutorial on bean scopes

It seems that the scope of your bean is neither request nor viewscope as you want it to be reset even before view is destroyed.
You can make use of ConversationScoped in CDI which will be created when you start the conversation and you can mark it to end by calling conversation.end().
How does JSF 2 ConversationScope work?
Alternatively , if you want to reset the View Scope bean then you can also do it by using below in your Ajax Event,
Map<String, Object> viewMap = FacesContext.getCurrentInstance().
getViewRoot().getViewMap();
viewMap.put("MyBean",new MyBean());

It's really that simple: Just annotate with #RequestScoped and a button:
#ManagedBean
#RequestScoped
public class MyBean{
public void resetEvent(ActionEvent actionEv) {
}
}

It is not issue with refresh, but its the browser which sends previous submitted data. I found some solutions which are pretty good.
From BalusC blog POST-Redirect-GET pattern
From rohit salecha blog Liferay Refresh bug
Since I am using Liferay, I have to put only
<action-url-redirect>true</action-url-redirect>
in liferay-portlet.xml like this
<portlet>
<portlet-name>booksportlet</portlet-name>
<icon>/icon.png</icon>
<action-url-redirect>true</action-url-redirect>
<instanceable>false</instanceable>
</portlet>
So I chose this.

Related

How do I get JSF to redirect to the default 401 page from within a managed bean? [duplicate]

In a JSF managed bean constructor, I load a entity from database usint a request parameter. Some times, the entity is not in database and I want to show other JSF (.xhtml) page with 404 message.
This is a sample of managed bean:
#ManagedBean(name = "someBean")
#RequestScoped
public class SomeBean implements Serializable {
private static final long serialVersionUID = 1L;
private SomeData someData;
public SomeBean() throws IOException {
someData = ... loads from database using JPA features
if(someData == null){
HttpServletResponse response = (HttpServletResponse) FacesContext
.getCurrentInstance().getExternalContext().getResponse();
response.sendError(404);
}
}
public SomeData getSomeData(){
return someData;
}
}
I configured the web.xml file something like that:
<error-page>
<error-code>404</error-code>
<location>/404.xhtml</location>
</error-page>
I have a JSF page to handle the entity loaded by managed bean. When the entity exists, I will use it in the page. Like that:
<h1>#{someBean.someEntity.name}</h1>
<h2>#{someBean.someEntity.description}</h2>
<ui:repeat value="#{someBean.someEntity.books}" var="book">
// ..........
</ui:repeat>
The page above works when the managed loads the data successfully.
The Problem
When the entity not exists and I send a 404 ERROR CODE, the JSF still process methods defined in the expression language of the first page.
This behavior makes the managed bean throws a NullPointerException, and a HTTP 500 ERRO CODE.
My 404 error page is not called. I do not know why.
I try send the 404 error even when the entity is found in database and the 404 error page works.
Enyone can explain this JSF behavior to this happiness? Or offer some kind to show the 404 error page without URL change ?
You're basically trying to perform front controller logic while rendering the view. You should do it before rendering the view. Because, once you start rendering the view, it's already too late to change the view to a different destination, e.g. an error page as in your case. You namely cannot take the already sent response back from the client.
In JSF 2.2 you can use <f:viewAction> for this.
<f:metadata>
<f:viewAction action="#{bean.init}" />
</f:metadata>
public void init() {
// ...
if (someCondition) {
context.getExternalContext().responseSendError(404, "some message");
context.responseComplete();
}
}
(note that whenever you need to import javax.servlet.* classes into your JSF backing bean, you should absolutely stop and look if the functionality isn't already available in ExternalContext or otherwise think twice if you're doing things the right way, e.g. perhaps you needed a servlet filter; also note that you need to explicitly tell JSF that you've completed the response, otherwise it will still attempt to render the view)
In JSF 2.0/2.1 you can use <f:event type="preRenderView"> for this. See also among others What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
In case you're actually trying to validate a HTTP request parameter and you also happen to use OmniFaces, you may consider using <f:viewParam> with a true JSF validator and control the sendError with OmniFaces <o:viewParamValidationFailed>.

JSF calls methods when managed bean constructor sends 404 ERROR CODE

In a JSF managed bean constructor, I load a entity from database usint a request parameter. Some times, the entity is not in database and I want to show other JSF (.xhtml) page with 404 message.
This is a sample of managed bean:
#ManagedBean(name = "someBean")
#RequestScoped
public class SomeBean implements Serializable {
private static final long serialVersionUID = 1L;
private SomeData someData;
public SomeBean() throws IOException {
someData = ... loads from database using JPA features
if(someData == null){
HttpServletResponse response = (HttpServletResponse) FacesContext
.getCurrentInstance().getExternalContext().getResponse();
response.sendError(404);
}
}
public SomeData getSomeData(){
return someData;
}
}
I configured the web.xml file something like that:
<error-page>
<error-code>404</error-code>
<location>/404.xhtml</location>
</error-page>
I have a JSF page to handle the entity loaded by managed bean. When the entity exists, I will use it in the page. Like that:
<h1>#{someBean.someEntity.name}</h1>
<h2>#{someBean.someEntity.description}</h2>
<ui:repeat value="#{someBean.someEntity.books}" var="book">
// ..........
</ui:repeat>
The page above works when the managed loads the data successfully.
The Problem
When the entity not exists and I send a 404 ERROR CODE, the JSF still process methods defined in the expression language of the first page.
This behavior makes the managed bean throws a NullPointerException, and a HTTP 500 ERRO CODE.
My 404 error page is not called. I do not know why.
I try send the 404 error even when the entity is found in database and the 404 error page works.
Enyone can explain this JSF behavior to this happiness? Or offer some kind to show the 404 error page without URL change ?
You're basically trying to perform front controller logic while rendering the view. You should do it before rendering the view. Because, once you start rendering the view, it's already too late to change the view to a different destination, e.g. an error page as in your case. You namely cannot take the already sent response back from the client.
In JSF 2.2 you can use <f:viewAction> for this.
<f:metadata>
<f:viewAction action="#{bean.init}" />
</f:metadata>
public void init() {
// ...
if (someCondition) {
context.getExternalContext().responseSendError(404, "some message");
context.responseComplete();
}
}
(note that whenever you need to import javax.servlet.* classes into your JSF backing bean, you should absolutely stop and look if the functionality isn't already available in ExternalContext or otherwise think twice if you're doing things the right way, e.g. perhaps you needed a servlet filter; also note that you need to explicitly tell JSF that you've completed the response, otherwise it will still attempt to render the view)
In JSF 2.0/2.1 you can use <f:event type="preRenderView"> for this. See also among others What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
In case you're actually trying to validate a HTTP request parameter and you also happen to use OmniFaces, you may consider using <f:viewParam> with a true JSF validator and control the sendError with OmniFaces <o:viewParamValidationFailed>.

JSF View Scoped Bean Reconstructed Multiple Times [duplicate]

This question already has an answer here:
#ViewScoped calls #PostConstruct on every postback request
(1 answer)
Closed 6 years ago.
I thought #ViewScoped was supposed to prevent the bean from being reconstructed while the user is on the same page... So why is my #ViewScoped JSf controller bean being created multiple times even before the action handler causes the browser to navigate away from that view?
Can anyone point me in the right direction here?
Here is my code:
The View (domain/edit.xhtml)
<h:form prependId="false">
<h:inputText id="descriptionField" value="#{domainEdit.domain.description}" />
<h:commandButton id="saveButton" value="save" action="#{domainEdit.save}" />
</h:form>
The ViewScoped controller (DomainEdit.java)
#Named("domainEdit")
#ViewScoped
public class DomainEdit implements Serializable {
private static final long serialVersionUID = 1L;
protected DomainEdit() {
}
#PostConstruct
protected void init() {
System.out.println("post construct called.");
}
#PreDestroy
public void destroy() {
System.out.println("pre destroy called.");
}
public DomainEntity getDomain() {
System.out.println("displaying domain...");
// some code to return the domain
return domain;
}
public String save() {
System.out.println("saving...");
// some saving code
return "view";
}
}
Output
I get the following output when I deploy this and perform the following:
Navigate to the edit view (edit.xhtml)
post construct called.
displaying domain...
pre destroy called.
Change the content of the domainDescriptionField input text
nothing logged
Click 'save'
post construct called.
displaying domain...
pre destroy called.
post construct called.
displaying domain...
pre destroy called.
post construct called.
displaying domain...
pre destroy called.
post construct called.
displaying domain...
pre destroy called.
post construct called.
displaying domain...
saving domain...
pre destroy called.
Unless you're using JSF 2.2 (which is still not out yet at this moment) or MyFaces CODI (which I'd have expected that you would explicitly mention that), the #ViewScoped doesn't work in CDI. This also pretty much matches your problem symptoms.
Manage the bean by JSF instead of CDI. Replace #Named("domainEdit") by #ManagedBean from javax.faces.bean package. Or, install MyFaces CODI to bridge JSF #ViewScoped to CDI.

How to pass a parameter to JSF dataTable's value attribute

In a JSF 2.1 application, I need to build a JSF dataTable (using PrimeFaces) that shows only the db records belonging to the logged in user.
So, I need to pass the username to the bean associated to the dataTable's value attribute:
value="#{tableBuilder.records}"
Here is the table bean:
#ManagedBean
#ViewScoped
public class TableBuilder {
private List<MyRecord> records;
private String username;
// getters and setters
}
It's useful to know that the application consists of a single web page, with container-managed authentication implemented through LoginBean, a SessionScoped ManagedBean. This implies the additional effort of notifying to TableBuilder when the user logs in.
The only way I am thinking of is to inject the LoginBean into the TableBuilder through #ManagedProperty annotation, and checking on every request of getRecords if the username property of LoginBean has changed.
Maybe there are better ways?
If your environment supports EL 2.2 (your question history confirms Java EE 6), then "just do it":
<h:dataTable value="#{bean.getModel(user)}">
with
public List<Item> getModel(User user) {
// ...
}
Whether it's the right way or there are better ways, I'll leave in the middle. Keep in mind that a getter is invoked as many times as EL evaluates the value expression.

Reset JSF Backing Bean(View or Session Scope)

I want to reset by JSF backing bean when some method is invoked. Assume that there is a command button, someone press it and after succesfull transaction, my View or Session scope JSF bean should be reseted. Is there a way to do that?
Thank
I found the solution for View scope.
public static void removeViewScopedBean(String beanName)
{
FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(beanName);
}
A view scoped bean will be recreated when you return non-null or non-void from the action method, even if it would go back to the same view. So, just return a String from the action method, even if it's just an empty string:
public String submit() {
// ...
return "";
}
To make it complete, you could consider sending a redirect by appending the ?faces-redirect=true query string to the returned outcome.
public String submit() {
// ...
return "viewId?faces-redirect=true";
}
A session scoped bean is in first place the wrong scope for whatever you're currently trying to achieve. The bean in question should have been be a view scoped one. Ignoring that, you could just recreate the model in the action method, or very maybe invalidate the session altogether (which would only also destroy all other view and session scoped beans, not sure if that is what you're after though).
just clear all views:
FacesContext.getCurrentInstance().getViewRoot().getViewMap().clear();
and remember to implements Serializable in all views
You could also refresh the page from javascript, so the ViewScoped Bean will be reseted, for example in a primefaces commandButton:
<p:commandButton value="Button" action="#{bean.someAction()}" oncomplete="location.reload()"/>
I solve the problem with code like this:
((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()).getSession().removeAttribute("bean name");
By this way I enter to session scoped bean and reset it without the data that was there before

Resources