I am using a MVC framework which is a bit like struts.
So, say I have a "Edit Store" link in my application this is how the url would look like:
http://localhost:9080/test?action=editStore&storeNum=10
Now, action determines my Action (analogous to Struts Action) to be run. The corresponding action here is: EditStoreAction. Clicking this would open a pop up with different attributes of a store for edit.
My question here is:
How do I write my actions? Do I write two actions in this context?
EditStoreAction which will render
edit.jsp
StoreSaveAction which
will invoked when user presses
accept on the rendered response of
edit.jsp.
OR Do I just write one action? EditStoreAction and submit form to the same action, I would know that the user has pressed the accept button for changes on submission. So, I would execute a different flow in the Action, which would save updates to database and redirect to a diff page.
What is the best pratice here? Create as many actions as possible coz it keeps the code modular? OR just write one action to handle everthing in a jsp?
I know this question sounds a bit trivial, however, sometimes you just want to get everything right. Hence, the question. Appreciate your help.
The idea is, similar to Spring MVC, to map your actions to the methods of a specific class, say it controller.
So, in your case, these two actions will be mapped on two different methods of the same class. You can call the class StoreFormController and two methods, editStore() and saveStore().
Better still if you make two controllers for each entity. May be one for all GET requests and another is for POST requests. So, in your case there would be two controllers StoreController for all other requests and StoreFormController for all form submissions, namely post requests. Now, your first action being GET will go to editStore() method of StoreController, whereas the second being POST request will go to saveStore() method of StoreFormController. You can define as many methods as needed in any of these two classes based on the request type.
You can easily see, where I am coming from, if you know Spring MVC API.
I like to use struts DispatchAction class because I could define more than one method in the action class (the "execute") method. Behind the hood, all it does is to find the method that it has to execute (submitted in the form or passed in the URL), find the method using reflection, invoke it with the right set of arguments (the method must have the same signature of the "execute" method), gets it result and pass it along. The DispatchAction simply overrides the "execute" method of the Action class to implement that behavior.
That being said, in your case, I would define only one class - let's say "DispatchStoreAction", and I would define two methods, probably "prepare" and "save". I like doing it that way because I still have a good class abstraction (and you don't put the "action" you're executing in the class name), because your methods can clearly identify what they are supposed to do, and also because, by definition, action classes tend to be small. You will probably have a "StoreLogic" or "StoreBusiness" defined somewhere, and this class will handle the business logic related to the entity that you're working on. I personally think that it's nice if you have one "StoreAction" and then one "StoreLogic", one "UserAction" and one "UserLogic" and so on - the relationship doesn't need to be 1 to 1 but I think it helps maintaining the code.
Check the source code of the DispatchAction class for ideas on how to do this, but the implementation should be trivial.
Related
I'm trying to write a REST interface to manage one of the resources in my application. Following best practice only I want to only use nouns as resource names.
I need the ability update the resource (a PUT operation) in one of several different ways. I imagine my user would call something like:
/resource/{name}?Operation=DO&time=1&Unit=HOUR
/resource/{name}?Operation=REDO&time=1&Unit=HOUR
/resource/{name}?Operation=UNDO
(I'll probably have more then 3 operations, but this is enough to show what's going on). One of the important things that the operations have different arguments. Logically time and Unit do not make sense to the UNDO operation.
In my Java back end I'd like to implement this with two different methods each of which will have it's own #RequestMapping annotation. The differentiator will be the value of the Operation parameter. I can't find any documentation that tells me how to do this
The alternative is to have a single method at the backend, but this is really ugly as I'll have to work out what combination of parameters is valid and throw my own 404 errors if they don't match!
If you absolutely need 2 controllers then do something like
/resource/do/{name}/{time}/{unit}
/resource/undo/{name}
With all the tutorial out there, I managed to make a view displayed by a controller. However, I don't understand how do I allow the user to navigate through the site with MVC. Every request to the server must go through the controller? If every request must go through the controller, how am I supposed to let the controller define the type of response it should forward the request to.
Edit: I'm doing a school project which required me to convert my current not reusable code to MVC pattern but I'm not understanding the navigation part of different views. How to get from one view to another view. For example, the navbar element should point to the controller or the view?
The controller comes first, it comunicate with the model and send you to the view you want.
So, for what you need, in the view, just put some link with the url mapped in the controller you want...
The short answer is that all actions "point" to the controller with a parameter telling it what the action is supposed to be, together with any other necessary parameters.
Suppose you have a simple registration form. You may have the following two actions: showRegistration and Register. MVC is not specific to the web, but I will provide the examples in that context (based on your comments). These two actions will point to your controller (say index.jsp) with URLs like this: /index.jsp?act=showRegistration and /index.jsp?act=Register.
Your controller will then have different logic for the different actions (you can do it in many ways yourself, or use some framework which does this switching logic for you). At the end of the day the logic in the controller will boil down to something like this:
if showRegistration:
model.getCountries //to populate a dropdown maybe
view.showRegistrationForm
if Register:
model.validateRegistrationForm
if not valid
view.showRegistrationNotValid
else
model.createUser
if userCreated
view.showSuccess
else
view.showCouldNotCreate
The idea is that the Controller contructs the full action using reusable model and view components. You can use the same model.getCountries in many different places, thus reusing the logic of retrieving a country list.
In practice, it requires a nontrivial effort to generalize the model and view actions. I've seen many projects decent into a chaos of hundreds of components created for a single purpose and used only once, and many components which are essentially duplicates because the developer did not know a similar one already exists, or needed slightly different logic and did not want to bother modifying the old code.
I am trying to implement an MVC type pattern in my Eclipse plugin, but I'm stuck. I can't figure out how to have my controls tell the form that they belong to that they have changed. There's no isDirty() method and no firePropertyChanged() method like I am using in the form/editor relationship.
In your FormPage derived class you add form page parts based on SectionPart or AbstractFormPart or IFormPart which contain the controls for the page.
AbstractFormPart has a markDirty method (also markStale, refresh and commit) which are intended to be the main ways to manage the form state.
This is the flow:
Initially JSP-1 is displayed having certain links, then after clicking on a link preprocess() method of Action class is called which sets certain session variables.
Then JSP-2 is displayed which has a form to be filled.
So my question is:
Shall I use the same Action class having more functions methods or create a new Action class after form is submitted ??
If the actions are independent of each other, meaning they accomplish completely different goals and share no duplicate code I would create an action class for each action. If the actions perform similar operations and share several functions I would create multiple methods in the action class.
If they are very independent of each other but share similar code you may want to abstract out the codependent methods into their own class which is utilized by multiple action classes. Its pretty much a judgement call and depends on the size of your application.
In frameworks such as Spring MVC "actions" are routed to different "controllers" by their URL. Each controller contains a set of methods that loosely forms a cohesive unit, meaning their methods are related.
I have a struts2 form.
In this form the user is asked to fill several fields.
2 of those fields are filled by picking an object from another action.
In fact :
main form => pickup button => new action with a new form to fill => return to the main form and filling the corresponding field.
My problem is that after the user finished the subaction, I want to return to the main form but not lose everything he filled before ...
I don't know how to handle this, should I pass to the subaction every field from the main form ?
Several ways come to mind, depending on factors will determine the best one for you.
1) Send out all the parameters you want to keep each time. Easiest way to do this is use hidden fields. Model driven may also make sense here or placing several actions into one class, either way it highlights that those actions share a common set of properties.
2) Store the value in the session like Vasily recommended however Struts2 has the scope interceptor... If you need to do this often it is worth looking at (see last example on page): http://struts.apache.org/2.3.1.2/docs/scope-interceptor.html however to do this right is a little tricky, because if this is an office application and the users are anything like me they we'll have a dozen windows open at any given time. In this situation you'll want to consider also adding a token (see: struts2 token tag) to to each "flow" which will prevent one of a dozen windows when doing a refresh to pick up the latest data from what I would expect rather than, get polluted from some global store that all actions use. There are some other ways to handle flows/conversations... for instance someone wrote a plugin which I suppose would implement what was just explained: http://code.google.com/p/struts2-conversation/
It's always worth a quick look over the struts2 plugins to make sure you aren't reinventing the wheel, although I must say I can't vouch for that plugin.
3) Don't have them leave the page at all. This is very slick... If you need to select additional parameters, when they click on the "pickup" button have the form expand with the required fields then when they click "update" in this subsection, it is close and update the rest of the fields. You will need a combination of JS on the client side with generally an XML or JSON response. For your own pages JSON is the easier way to go, to produce JSON responses see the struts2-json-plugin.
I would go with #3 in most cases. Possibly #1 if I knew the action would only be used from the calling action and/or I wanted a very bookmark safe form(pass all parameters if possible with GET). #2 in more complicated scenarios where multiple actions needed to collaborate and I could not use ajax for some strange reason. Note #3 and #2 are not very book mark friendly, and they are in general not very state friendly without using client side storage.
Store your mainform in session.
public class Test extends ActionSupport implements Preparable {
private MainForm form;
public void prepare(){
form = (MainForm)ServletActionContext.getRequest().getSession().getAttribute("mainForm");
if(form == null) {
form = new MainForm();
}
}
public String execute(){
//Do something useful
//Do something useful
//Do something useful
return SUCCESS;
}
public MainForm getForm() {
return form;
}
public void setForm(MainForm form) {
this.form = form;
}
"prepare" method is a part of Preparable interfeice. It will be executed before all parameters readings and before "execute" method every time when your call the acton.
You need the following to have a working struts2 platform:
2 struts form classes with fields
A struts action class
A jsp page
A struts config file
Then go through the below process:
When the first form is loaded save its bean in the second form
through a field
After you return from the first form load its fields in the second
form through the above field