I am migrating a project from struts 1.3 to struts 2.0. Now I have read through various resources available on web but could not find a struts 1.3 reset() form method alternative in struts 2.0.
My action class extends ActionSupport and implements Modeldriven. I have implemented the validate method in action class and that works perfect. However, when the form has no errors and the submission is done properly, the page reloads with initial values.
I expected that I will receive a blank form. I looked for a reset() form method but could find none. Currently, I am explicitly setting all form values to blank. I don't see this as a good programming practice. Please suggest how to implement form reset() in struts 2.0.
EDIT: ok, you are working with Tiles (that I've never used), then I'll try another solution:
if you have an empty JSP tile, and after the user compiled its fields and submitted the form, you want to ALWAYS clear those fields... what about declaring only SETTERS in the Action, and not the GETTERS ?
You could only set from JSP to Action, but not read them from the JSP... then your fields will be always empty in the page, and always rewritten by setters in the Action.
If i got it, you are on JSP, you call the method saveStuff() of the Action (or of another action), then you come back to the page...
in this case, you can use a RedirectAction return type, that will strip all params from the request, and redirecting your request to the execute() method of your Action.
So, instead of
<action name="myAction" class="com.blabla.myAction">
<result name="success">/myPage.jsp</result>
</action>
just do
<action name="myAction" class="com.blabla.myAction">
<result name="success">/myPage.jsp</result>
<result name="stuffSaved" type="redirectAction">
<param name="actionName">myAction</param>
</result>
</action>
This way you re-enter in the initial state (assuming you are not putting anything in session that is read by the JSP).
Because your Action and Form are in the same class in Struts2, you have to implement your own reset() method to clear any data that you would like.
Related
I have a request scoped bean which is filled with various properties from a form. These properties are then used to update another view scoped bean. Now I want to give the user the possibility to the reset the form in such a way that all form fields are holding the values they had when the page was loaded the first time. These values are defined through the bean itself:
#ManagedBean
#RequestScoped
public class ItemSearchBean {
private Rarity minRarity = Rarity.None;
private Rarity maxRarity = Rarity.None;
...
}
Notice though that the form submiting button actually invokes a ajax request, therefor no full page reload goes on.
The submitting button:
<p:commandButton value="Search"
actionListener="#{itemSearchBean.refreshTable}"
update="itemTable,notify"/>
I already tried to use a simple reset button, but it only reseted the form to the last submitted values:
<p:commandButton type="reset" value="Reset"/>
One has to somehow ask the server for a fresh new bean (or prevent it to fill the bean), but I have no clue how to do this.
You should be able to do that with a plain HTML link to the same view:
Reset
or let JSF create the link for you:
<h:link value="Reset" />
This way you'll have a new GET request that will create a new UIViewRoot, just like if you were accessing the same view in a new browser tab.
If you want a button instead, you can use an h:button
<h:button value="Reset" />
This button will rely on a Javascript that will reload the page on click.
you could also do a two phase setup. a little more work, but allows all sorts of Undo workflows if you take it further.
basically, have two beans that encapsulate your form with the usual accessor/mutator pairs. then in your controller, expose only one (either x, or y) and that is your "form bean". in y, you store the pristine copy that is retrieved from the repository, that way you can do field level or bean level reversion without having to reload the page or do a full data remarshall from the repo.
so, simply:
2 beans to encapsulate the form (you might even be able to re-use your entity if it maps onto the form).
fill both from the repo during data marshall
expose one to the user in the facelets
keep the second as a backup for resetting/reverting either fields or the entire form
there are other ways to skin the "undo" cat, and this is only another.
I did a lot of researching on the matter but cannot seem to find the answer to my question, so I hope you guys can help me out.
We have a struts 1.2.7 web app that we converted to a JSR-168 portlet using the Apache Struts Portlet Bridge.
This is all working very well except for one thing: the actionforwards that specify a redirect do not actually redirect to the specified action. These redirects DO work when running the app as a normal struts web app. Hence, we have a double submit problem in the portlet variant.
We make use of action chaining that ends with an action forwarding to a tile definition. For example:
<action path="/CreateIdmAccountSubmit" validate="true" input="catalog.createaccount.page" type="com.konakart.actions.login.CreateIdmAccountSubmitAction" name="CreateIdmAccountForm">
<forward name="FillRegistrationData" path="/FillRegistrationData.do" redirect="true"/>
</action>
<action path="/FillRegistrationData" validate="false" type="com.konakart.actions.registration.FillRegistrationDataAction" name="FillRegistrationDataForm">
<forward name="FillRegistrationDataPage" path="/FillRegistrationDataPage.do" redirect="false"/>
</action>
<action path="/FillRegistrationDataPage" forward="order.registrationdata.page"/> (tiles-def)
In this example the action /CreateIdmAccountSubmit processes a submitted form (POST) and creates an account in the db. After successfull creation the user is redirected to another action (/FillRegistrationData) which inits an order object and, on its turn, forwards to the orderregistration page which layout is defined in the tiles-defs.xml.
As I said this all works very well, form a functional perspective, but when a user hits f5 on the rendered order-registration-page the action /CreateIdmAccountSubmit is again invoked causing the account to be created double. As I said also this is not happening when running the app as a normal web app. Here, the mechanism works perfectly :)
I think that the problem is being caused by the fact that the redirect is done in the wrong phase but i am really not sure as why this does not work :)
Based on what I read I tried the fowllowing things to fix the redirect problem:
* specified the action that does the form submit as "actionUrl" in struts-portlet-config.xml (hoping that redirect is done in wrong phase?)
* replaced the normal html tag library by the struts-portlet variant (hoping that a valid url actionUrl was produced by my html:form that in some way made the redirect possible?)
These two steps did not seem to help and I am lost at how to accomplish a simple redirect in the portlet so that we can prevent the double submit problem.
Hope you guys can help me out!
I found the answer: the mechanism is dependent on the portal implementation. We use Liferay which does not work with redirects by default.
However, you can switch this on by declaring an element in liferay-portlet.xml called
<action-url-redirect>true</action-url-redirect>
This fixed the problem for us!
I know it maybe sounds a basic question but I'm having a hard time figuring this out.
First of all I have this form:
<h:form>
<h:inputText value="#{movies.name}"/>
<a4j:commandButton id="mybutton" value="Modify" immediate="true" action="#{movies.testModify}"/>
</h:form>
I want to catch the value from the input text from within my testModify() method from movies bean.
My problem is that testModify doesn't get called at all. The odd behaviour that I noticed is that when I remove h:form tag the method does get called but I still don't know how to get the value from my input text.
From what I've read, a4j:commandButton needs h:form for it to work properly.
Any help will be highly appreciated!
Use an h:commandButton instead of an a4j:commandButton. The first is the standard JSF button that will submit your form, the latter performs an ajax request.
First of all, as stated by Markos Fragkakis, use a basic <h:commandButton> instead of an ajaxified <a4j:commandButton>, as in your case, you have no interest of using an Ajax action here.
Second, remove the immediate="true" attribute on this button. Using this attribute means that the default ActionListener should be executed immediately (i.e. during Apply Request Values phase of the request processing lifecycle), rather than waiting until the Invoke Application phase.
If your action on Java bean is still not called, maybe something wrong happend before the Invoke Application JSF lifecycle phase. Adding a <h:messages> will display the possible issues:
<h:form>
<h:messages/>
<h:inputText value="#{movies.name}"/>
<h:commandButton id="mybutton" value="Modify" action="#{movies.testModify}"/>
</h:form>
My common usecase for my Struts2 application is that I have Actions that collect data which are presented on an JSP page. I'll call these view-actions.
But then I also have logic actions, which "do" something in the background (like registering a user). These might also have a bean that needs to be shown on an JSP, but I need to redirect the result to one of the view-actions.
Sadly, the bean I need from the first action doesn't get transferred to the ValueStack, but only values from getters from the view action. Example:
<action name="mailConfirm" class="de.abelssoft.updateyeti.Frontend.MailConfirmer">
<result name="login" type="redirectAction">
<param name="actionName">register</param>
<param name="email">${person.email}</param>
</result>
<result name="input" type="redirectAction">
<param name="actionName">register</param>
</result>
</action>
What is the pattern I'm missing here? Or do I have to store everything I need in the response context?
I got no answer to this question, so I'll tell you what I've done. Sorry for not providing a "good answer".
I wrote two interceptors. One for the logical action that would store message-objects in the user session temporarily and one for my view actions that would take and remove them out of the usersession.
I used the logical action interceptor where needed and used the viewaction interceptor for all other action to make sure that when an action redirection has happened before the view action, the message-objects will be found and used.
* Unable to find matching navigation case with from-view-id '/home.xhtml' for action 'MemoServlet' with outcome 'MemoServlet'
I try to accomplish it through:
<h:commandButton type="submit" value="add" action="MemoServlet"/>
but all the tutorials in the world only do it with a bean, which i don't want. I've come across any navigation rule that accomplishes my request.
Why a servlet? What exactly is the functional requirement? Doesn't the servlet contain "too much" code which you could just refactor into a separate class and import/call that in both the original servlet and the JSF bean action method?
Anyway, to fix the particular problem, you need either a plain vanilla HTML <form> element whose action points to the servlet URL or to call ExternalContext#dispatch() on the servlet URL inside the bean's action method.