I am trying to learn Struts 2.0 and I am trying to understand the concept of actions better. I have a form which I would want to be pre-loaded with values. The user can change the values in the JSP and then submit the form, which will lead to a page displaying the data enetered in the form.
I have got it working, but was not sure if my method/logic is correct.
The Struts.xml is as follows:
<action name="LoadForm" class="actions.Test" method="execute1">
<result>/Test.jsp</result>
</action>
<action name="ShowResult" class="actions.Test" method="execute2">
<result>/TestResult.jsp</result>
</action>
I am using prepare() to preload the values.
When I call LoadForm.action in the browser, Test.jsp is displayed with preloaded data.
Test.jsp has a form whose action is ShowResult.
When I submit the form, it navigates to TestResult.jsp where I display the values from the form.
Is this a right approach or is there a better way to do it?
Also, I am not sure of why would we need more than 2 execute methods in the Action class.
Well almost you are right, except one thing you need to understand that prepare method is something like an init method which can help you to init/ prepare data before the framework call the execute or any other method.
Actions in S2 work as model as well Controller same time and its quite possible that one Controller is doing more than one task. e.g we have a Action which is responsible for handling user related processes which includes
Creating new user
Updating user
Checking any information related to user
So in short we need not to have three different Actions to perform these tasks but we will create a single Action with three methods inside it which will be responsible to handle these tasks.
i hope this might give u an idea
Related
I'm playing around with ASP.NET MVC 4, but I have some problems with understanding. For better explanation I will use a simple "synthetic" situation.
Let's say I have model Person with 2 properties:
string Name
PersonType Type (e.g. Student, Employee, Military...)
Let's say in my controller I have private property Person. I can initialize this object in Index method, pass into View and build html page. Ok.
Now when user updates one of fields of person instance at the client side (he can input a new person name or select new person type using dropdown list), I want to update my model immediately. So, my general question is How can I achieve it?
Obvious solution for me: I can send an ajax request to controller from JS with new data. I thought that I can call controller's method UpdateName(string name) and update manually property Name with new data. BUT my person instance is NULL inside of this method! My second question is Why I can't access to initilized model object from other method? I think it's all about my bad understanding of client server interaction.
The final case of my situation: when user click's on the button "Save" I want to save created person into file on the server side, but I don't want to use any forms and receive all needed data just after clicking this button (because in my real task I can't use forms and also I can't receive all needed fields from html page after button clicking).
I have found the dirty solution. In JS I created another class Person with same properties. Now I can update instance of this class when I want and pass json data to server for saving it.
Is there any better solutions?
Its not that dirty to have javascript objects to represent your model. In fact thats how I do it. I use KnockoutJS to give me a client side model - which is essentially the MVVM pattern.
You are trying to use the MVC model in a way which you can't. However, the Knockout model you can use how you wish. You basically have a javascript representation of your server side model and once you are done with it you send it to the server.
In order for your server side methods to pick up your client side model you simply have to ensure the post request contains the data and as long as properties names are the same in the parameters of the method they will match themselves.
Why I can't access to initilized model object from other method?
Because it's not initialized anymore. Don't use the controller class to store persistent data across requests. The controller object is disposed after a request completes and then re-initialized on a new request. So anything that one action methods saves at the class level is gone when you get to another action method. Each request from the client to the server should be considered a fully isolated event, independent of any previous requests.
When you want to save your model, what you would do in that action is re-fetch it from the database, apply the changes, and save it back to the database.
but I don't want to use any forms
I'm not really sure what you mean here. Do you mean you want to use AJAX instead of POSTing the page directly? If so, that's fine. There are probably a number of tools out there to help you, personally I often just create a form anyway but instead of a submit button I have a plain button and add some JavaScript code (using jQuery) to serialize the form and perform an AJAX POST.
As long as the keys for the POST values map to your model fields in the same way they would in an out-of-the-box form, then your action method will still be able to receive the proper model type. On the server-side it doesn't matter if it's from an AJAX call or a normal POST. The difference, however, is that the response for an AJAX call should probably be in JSON format instead of responding with a view.
So instead of this:
return View(someModel);
You might have something like this:
return Json(someModel);
I am using this in a page:
<f:event type="preRenderView" listener="#{bean.logoutIfNotAuthenticated}"/>
it works. However, the listener is called after a action is called (for example, by clicking by a commandButton).
Is there a system-event which will be called at first?
I have tried it with "preValidate", but this will not work, if the form has no validation requirements.
Why don't you try to use filters to achieve the session management?, that way all request could get automaticly and then being redirected or processed
Although using filter is a good solution, preRenderView event should work properly and the listener should fire before the view is rendered. I used it many times to navigate away from the requested view in the event if the user does not have access to the requested page for example.
I have a dropdown in my form that has a problem to populate when validation failed. I use xml validation with Preparable interface. To access data for dropdown I need to pass some ID from the form. The problem is when validation failed and prepare()/prepareInput() called, none of the variables in class including ID is set. ID is hidden parameter in the form that does not change. Please advice.
Thank you,
Yuri
prepare() in struts2 is rather synonymous with the role of init() in many other frameworks, that is it is called to initialise the action and fills a role very similar to the constructor.
There seems to be something missing... using the default-stack all the parameters on the action should have been set before validation is called. So if the client is indeed passing in the parameters I can not see why or how any would be missing unless some part of your logic clears them.
Sometimes it is necessary to acquire other objects as fields in your action derived from the values set by a form, or otherwise passed in as parameters. In this case you would like prepare to be called after values are set and then validate, if this scenario applies to you then the params-prepare-params stack is appropriate.
Personally, I would put preparation logic into the actions execute method rather than the prepare method. It is only when I put multiple actions into a single class that the prepare method is most appropriate as it factors out what would be repetition. Then the params-prepare-params is a special case that can crop up although I would argue the if you use DI it may never need to be used.
If this is not helpful please expand your question with the action class/xml mapping(if any) and provide the validation xml as well so we can see why this would be happening.
I am in the process of writing a web app that includes a reporting form. This form contains a number of radio buttons that allow the user to specify the return data.
There are about 6 different return data 'formats', and each of those has two variations - html data or JSON data for rendering to a chart.
I have begun coding it up and already my form post action method feels wrong.
I basically have a check on the requested data format and return it as needed. Each return type requires its own partial view / json object so there is little room for reusing code.
It feels like each one should have its own action method. Having the form post to different locations based on a radio button choice also feels wrong though.
Switching on report type and then redirecting to the appropriate action in the controller also feels like its not quite right.
Am I approaching this in the wrong way? As it currently stands my controller action contains a lot of code and a lot of logic...
Hope my query makes sense.
Thanks
I don't think there is anything wrong with your approach. To maximize reuse you could:
include reusable templates inside your views
make sure the business/data layer code is the same everywhere (where possible)
I suppose the views you need to return actually are different for each combination of options so whatever approach you take, you are stuck with that.
I wouldn't opt for the client-side approach. You then have code on both the server and the client that has to be updated whenever you change anything. I would keep the code that receives a set of options and determines what to do with them in one place.
I know what you mean about it feeling like each format should be a separate action, but maybe a hybrid approach would make it feel better.
If you set the value of each radiobutton to the name of the action it relates to, you then, in your main POST action, have a parameter that you can use to call the appropriate action in one line of code. You don't have to fudge anything in Javascript, it's easily extensible, and you get your separate actions.
If I understand your problem right you have a lot of switch code in action.
I think you can use Factory pattern. You can create factory that will accept switch parameter as parameter and will return ActionResult instance.
I have an action that populates the result from the DB. Right now, I see a way of doing it and that is to make the Action ServletRequestAware, set the populated list as a request attribute and show it in jsp.
Since a lot of improvements have been introduced into struts2, is there any other way of doing that? The first thing that comes to my mind is to use displayTag and change the return type of Action to a List, but that does not seem to work.
Thanks for any replies in advance.
You question is unclear, you should read some book about Struts2 to get the general idea.
No need to make the Action ServletRequestAware. The mapping from http parameters to actions fields is automatically done via the Param interceptor (already set in the default configuration). And one of the points of Struts2 is decoupling the action from the http protocol, you should not (typically) do anything related to http in your action.
Tipically, in your action execute() method (or whatever) you'll get the data to display from the DB and set it as one property of your action, so that is accesable from some getter.
Then, in your view page (JSP or whatever) you'll display it. You can use displayTag, but first you'll prefer to display it "manually", to understand what's involved. See for example here http://www.roseindia.net/struts/struts2/struts2controltags/iterator-tag.shtml
For manually displaying a table, also see this example http://www.vaannila.com/struts-2/struts-2-example/struts-2-crud-example-1.html , search for the <table class="userTable> tag.