Struts session form bean doesn't retain state - java

I am creating a wizard-like interface consisting of 3 jsp pages and 3 Struts actions using Struts 1.3. The flow is like below:
page1>action1 ->page2>action2 -> page3>action3
I use a session form bean (an action form with session scope) to share data between requests. The problem I am having is that the data I submitted in page2 is available in action 2, but not in action 3. I am in doubt it might be I don't have a form on page3 to hold those data, or because I call action3 via jQuery post method instead of a regular form submit, but I am really not sure.
I have been digging all the internet for almost a day and still no luck. Could anyone offer some help. Thanks a lot.

The reset() method on the form is being called with each request and thus you are losing state. You can programmatically control this.
public class MyForm extends ActionForm {
boolean reset = true;
private String[] checkboxes = {};
#Override
public void reset(ActionMapping mapping, HttpServletRequest request) {
if (reset) {
this.checkboxes = new String[];
// etc
}
reset = true;
}
public void doNotReset() {
reset = false;
}
}
Have action2 call doNotReset() on the form.

I suppose that you might have assigned a same form to both the action in StrutsConfig.xml and hence it is not giving the ClassCastException. By the way, if you want to access the same form bean which was filled on action 2 stuff, do the following
Look at the strutsConfig file for actionMapping of both the actions (2 and 3). keep the name of form different for separate action (e.g. form2 for action2 and form3 for action3).
In Action3, instead of casting the form, use this form2 = (FormBean2) session.getAttribute("form2");
The reason for above is since both the actions are using the same form, struts might have overwriting it. Hopefully above will solve your problem.

Thank you for all your inputs. Here is how I solved my problem. I don't really like this solution, but it possibly the neatest one I can find.
In page 3 I added hidden fields for what ever property I want to be available in action 3. Struts will store the values in those hidden field and when the form is submitted again, the data will then re-populated to the action form.
It seems to me that Struts works like this: when it loads page 3, it try to populate the form in page 3 with values of myForm. When the form is submitted, the process is reversed, it populate myForm with values from the user's form. The problem is that, before populating myForm with values submitted by user, it resets myForm's properties. And because after reseting, it doesn't find the value for those fields, it leaves it empty.
I don't think it makes sense for Struts to work that way, but... so be it.

How are you accessing the form bean of page2 in action2 as well as in action3.
I suppose you are accessing the wrong way. Are you getting an exception regarding invalidCast or something.

Related

Handle Concurrency in Spring Controller Instance variables

I am using Spring 5 for a web application. Here to check whether my search query based on some inputs from html page is returning Empty value or NOT. If empty then I am showing a no Data found notification.
I have used two methods in controller for this.
After filling the search fields I make an ajax call to the controller on button click. If data is found the controller method returns a flag which i check in the JavaScript code to check data is available or not.
If data is present then I change the attribute of form element like action to another URL and target="_blank" and make a form submit.
I have to generate a jasper report on final submit.
BUT to avoid two query hits on DATABASE , while making the first query hit on database I am storing the value to a INSTANCE VARIABLE in spring controller,
Which I am retrieving on final form submit and generating the report from the data.
I searched for answers but not getting a perfect idea how to apply in my code,
It would be of great on your part to share me with right way to implement.
******JAVA CODE*******
public class HrmsSalarySlipSummaryReportController {
List<Object[]> allowanceDetails;
List<Object[]> deductionDetails;` #PostMapping(value = "/reportIsEmptyCheckSal", headers = "Accept=application/json", produces = "application/json;charset=UTF-8")
public ResponseEntity<String> summaryListIsEmpty(#RequestBody HrmsSalarySlipReportDTO slipReportDTO) {
allowanceDetails = summarySalReportServ.getAllowanceDetails(slipReportServ.getIntParameters(slipReportDTO, userSession.getUlbId()));
deductionDetails = summarySalReportServ.getDeductionDetails(slipReportServ.getIntParameters(slipReportDTO, userSession.getUlbId()));
return ResponseEntity.ok(summarySalReportServ.isJsonEmpty(allowanceDetails, deductionDetails));
}`
How to handle concurrency issue along with checking the empty returned result
Thanks.

How to redirect from SpringFormController based on input parameters?

Here's the basic requirement:
An http request is received by page A that may have parameters defined.
If parameters are defined, page A processes the request and automatically forwards to page B. If parameters are not defined, display page A with a form for the user to fill in and submit. On submit, process the request and forward to page B.
Basically, I want to bypass the need for the user to enter data via onSubmit() if the data has already been provided as input parameters to page A. How can I do this?
Page A and B are implemented by extending the (deprecated) SimpleFormController. One way I've done this before is to place a "hidden" page (A′) that accepts the request and, if parameters are defined, processes the data and redirects to B. If the parameters are not provided, then I redirect to A where the processing is done.
This doesn't seem efficient to me, as it duplicates a lot of the processing code.
I'm not providing any code, since it doesn't easily explicate the question.
I hope I understand but you want a method in controller that will direct based on information provided.
Here is something i knocked up quickly that i hope will help solve the problem:
#RequestMapping("/pageA/{parameter}")
public String displayPageA(Model model, #PathVariable String parameter) {
if(parameter == null)
{
model.addAttribute("your_form", new YourForm());
return "pageA";
}
else {
return "redirect:/pageB/"+parameter; // this is if you want the parameter passed on
}
}

Struts2 - Different browsers, different machines, same form data

I believe it has something to do with Struts2 ValueStack, but if you guys could give me a hand with that would be great.
I have the following setup: Spring 3 + Struts 2.
My struts actions are pretty much like this:
#ParentPackage("struts-default")
public class StepOneAction extends ActionSupport {
...
}
Such Action has a method that is my forward:
#Action(value = "/bla", results = { #Result(name = "ble", location = "/bli.jsp") })
public String populate() {
...
return BLE;
}
Finally such Action is #Autowired.
What's puzzling me is that if I open, say Firefox, navigate to the first page - it's a 3 step wizard - fill the form and submit THEN open another browser, say Opera, and navigate to the first page, Opera has the data populated from Firefox.
How's that possible? What am I missing?
The ValueStack is per-request, so I don't see how it could possibly be a factor here.
It sounds like Spring is treating StepOneAction as a singleton, which would account for the behavior you are seeing. Actions need to be instantiated per-request.
Check that you haven't defined a member on the JSP page or Servlet that keep the same value among multiple sessions

Passing a Java object from one Struts action to another

In one of my Struts action I've got the following code in a method:
...
List<Object> retrievedListOfObjects = c.getListOfObjects();
return mapping.findForward("view");
}
fw_view leads to a new Struts action with another Struts form. Let's say this form has got among others the following field
List<Object> listOfObjects;
I now want to pass the retrievedListOfObjects from within the first Struts action to the form of the following Struts action.
Is this possible without storing it in the session?
you can store it as a request attribute.
request.setAttribute("listOfObjects", listOfObjects);
and then in the Action that is forwarded to
List<Object> listOfObjects = (List<Object>)request.getAttribute("listOfObjects");
Given that when setting request attributes you can give them meaningful names, you should consider setting many attributes rather than setting one big list of objects.
Correction of krock code.
Setting object to request:
request.setAttribute("listOfObjects", listOfObjects);
Getting the object in an other action.
List<Object> listOfObjects = (List<Object>)request.getAttribute("listOfObjects");

How to control submit url action in Wicket form?

I have a wicket web application with Page mounted to bookmarkable alias. The page contains a form object with submit action.
The problem is that though the form belongs to the page the action url doesn't contain page alias, but rather created in cryptic form of wicket action.
Is there a way to adjust that behavior, so link will be like page_alias/submit ?
...
setRenderStrategy(IRequestCycleSettings.ONE_PASS_RENDER);
mountBookmarkablePage("/resetpwd", ResetPasswordPage.class);
...
public ResetPasswordPage(final String id, final PageParameters parameters) {
final Form form = new StatelessForm();
form.add(new Button("submit") {
public void onSubmit() {
...
});
add(form);
If you subclass StatelessForm instead of Form, this will take you part of the way. Rather than having something like
action="myapp/?wicket:interface=:1:eventEditor::IFormSubmitListener::"
with the page containing the form mounted at a bookmarkable URL, you'll get something like, for example,
action="myapp/mount/path/some/params/?wicket:interface=:0:eventEditor::IFormSubmitListener::"
This uses a MixedParamUrlCodingStrategy for the mount in WebApplication.init()
You can then override encodeUrlInHiddenFields() to return true, which will give you a clean URL in the action attribute.
However, all this doesn't really change the way Wicket works with forms, i. e., you still have some Wicket-specific state data in the client's markup. The reason why this is so hard, I believe, is that Wicket is meant to help you build a web app that has state. I noticed that Wicket does a lot of stuff (like comparing submitted form values with what the model's getters return before the setters are called) behind the scenes, that I know too little about to be comfortable when just cutting it out.
You can use Wicket to provide RESTful web services, though, as outlined in this blog post. There's also a project on Google code called wicket-rest that expands on this idea. Note that this seems to work as simple as it does because it just never uses the whole component based UI building stuff.
The guy who wrote this post had a different problem, but it helped me understand Wicket forms a little better anyway.
you can hide a lot of the request mumbo jumbo by using a HybridUrlCodingStrategy like so:
mount(new HybridUrlCodingStrategy("/resetpwd", ResetPasswordPage.class));
Then when the click submit, assuming you don't redirect to a new page, the url would change from
mysite.com/DocRoot/resetpwd
to
mysite.com/DocRoot/resetpwd.1
or if you really want it to be mysite.com/DocRoot/resetpwd/submit you could create a new bookmarkable page, say ResetPasswordResult.class, set your response page to that and mount it at "/resetpwd/submit"
You might look at other encoding strategies to see if their is another that suits you better:
http://cwiki.apache.org/WICKET/url-coding-strategies.html
You can take a look at http://day-to-day-stuff.blogspot.com/2008/10/wicket-extreme-consistent-urls.html and try to adapt that for Forms.

Categories