I have to 4 objects, Group, sections and Questions and their options. Every Group has different Sections and Sections have Multiple Questions and Questions have options. Now I have to design form input system so that every group and sections can be covered up step by step. I’m doing all this in spring mvc.
Can you tell me a way, how can I solve this problem?
You can surely do that in Spring MVC thanks to easy list binding.
Spring MVC allows a big lot of freedom, so basically if you only use this framework, you will have to come up with a solution from scratch.
Here is a use case and a solution. It is a bit tough to implement, as it is from scratch. Feel free to adapt it to your specific needs, add whatever fancy UI framework you want, but you should get a general idea. You can skip to part III for a quick answer.
Let's say you want to create/edit a group in one single page :
you want to edit/add sections to the group
you want to edit/add questions to any section
you want to edit/add options to any question
I. Page design :
You have a JSP Group page with one big single form (again this is just an example)
There will be buttons to add nested stuff. When clicked, some javascript will show a blank form allowing with the information of the stuff. This blank form will itself have buttons to add nested nested stuff to it, and so on (until the stuff is an option).
The design is the same for existing stuff that you want to display/edit, except that the forms won't be blank
You are able to tell whether you are creating or editing the current group (context of the page or javascript/html tricks).
There may be a list of existing sections you could "drag & drop" inside a group thanks to some javascript/jQuery
II. Code design :
You have a GroupController corresponding to the JSP
The Group object has a List<Section> sections attribute, the Section object has a List<Questions> questions attribute, etc.
You have methods createGroup and editGroup
When submitting your JSP form and calling createGroup or editGroup, you are able to know if the submitted elements of the group already exist, so you can decide to add or edit/update them in the DB. All this logic could be done in another class, like a Spring service.
You always provide a possible list of existing sections (by adding this list to the model in both methods, or better yet, by doing a single method annotated with #ModelAttribute). This list could be computed in another class (a Service/DAO/both which taps the DB in the end).
III. The magic : binding the JSP form with the Java controller :
In the page you'll have a <form:form commandName="group">, and in the controller methods parameters you'll have a #ModelAttribute("group") Group group.
Now, to submit the name of the very first option, you would have this in the JSP :
<form:input path="sections[0].questions[0].options[0].name" />
(or the equivalent in html generated by some javascript).
Related
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'm building a page that has a search box that will populate a grid on the same page. There is also a button the user can select to bring up a "window" (JQuery UI "pop-up" in the same page) that lets the user configure said grid.
These are two separate forms but I don't want what was submitted as part of one to undo the other (so when the user submits to change the grid layout the search needs to re-run as well.
I'd rather not store things in session for this since that brings with it its own issues (search results may be large, shouldn't be saved when the page is re-entered later, etc.).
I've considered doing "one large form" (i.e. surrounding all the inputs) for the entire page that is backed by a form backing bean. I would then use which button is clicked to determine the action to take. There will eventually be other buttons on the page as well to add more functionality. This would be similar to how .NET (non-MVC) handles things.
I'm interested in how others may have solved similar challenges. Are there potential issues with my approach that I'm not seeing? Better ways that work with the framework?
What do you mean with:
but I don't want what was submitted as part of one to undo the other
. Are you referring to posting the form and loading the whole page, which in turn will "reset" the other form?
If that is the case I would still keep one page with two forms and make the posts using Ajax (as you may know jQuery makes this a breeze). Upon receiving a response for either call you will need to update the other form accordingly.
Note that you may still have your forms in two separate views if it helps keeping the code clean and then pull their html with Ajax calls into another view. But my point is that at the end I would still keep both in one page since it sounds like they depend on each other so updating one when the other changes may be easier this way,
Let me know if I misunderstood your question.
Basic problem
I've come across a bit of a problem while writing my own custom JSP tags to "wrap" the spring MVC form tags. I've wrapped other tags successfully but come unstuck with the select and options tags, this throws an IlleagalStateException. I've debugged the spring code and found that the options tag looks for an ancestor select tag. I'm doing this with tag files so the spring select tag is actually in a different tag file. I guess that's why it doesn't find it.
So the questions is what can I do to get round this?
Possible solutions
I've tried looking for solutions but all I've found is other people having the same problem but no solution posted. I did ponder writing my own select and options tags without using the spring tags but I don't really want to have to replicate the binding that it gives you for free. I don't mind changing to use Java classes rather than tag files but I found previously that the output won't be evaluated as a JSP so you can't output another JSP tag.
Reasons for doing this
Having thought about this for a week since first asking the question I am now clearer on what I want to achieve.
To simplify the markup needed in my JSP's
Factoring out common code (e.g. form:errors after an input or getting a translation from spring:message)
To encapsulate look and feel (CSS goes a long way but often you need to change the markup too)
To be able to build enhanced components that extend the functionallity of the spring tags (e.g. render a multi-select as a picklist or display readonly inputs as text labels)
I'll be interested to hear what people think.
Thanks
Firstly, I'm not sure what you mean by wanting control over styling. I thought you could pass-in class and id attributes to Spring tags and they were copied through (? - although I might be getting confused with Grail tags, as I've been writing Grails apps lately). Edit: plus you can style Spring generated tags by referencing an outer element. E.g. surround your form elements with a div and then style the form elements like: #myDiv input { color: red; }.
From my experience (10+ years webapp dev), its not worth the extra effort to try and future proof your app. When you choose a framework like Spring MVC you are getting a lot of stuff for free, that you would normally have to write yourself. The cost of this free stuff is a certain amount of lock-in (as you said). Spring is pretty good when it comes to this aspect - you can use as little or as much as you want and its usually pretty straight forward to engineer it out if needs be in the future.
So my take is: use the Spring tags "as is". The likelihood of you needing to remove the Spring aspect in the future is very small. As such its a worthwhile risk to "put off" if/until that scenario arrises. You have likely already spent as much time and code trying to engineer your future-proof solution as you would've spent removing the Spring tags - that it outweighs any benefit it might have provided. And add to that - you've written that code and you and/or someone else will have to maintain that code now - versus letting the Spring developers maintain the code for you.
Lastly, if you really don't want to have this lock-in and want full control over styling, then write your form elements by hand.
<select name="foo_select">
<option value="">-- select a foo type --</option>
<c:forEach var="foo" items="${fooGroups}">
<option value="${foo}">${foo}</option>
</c:forEach>
</select>
I've thought about this for a good week now and this is the shortlist:
Give up and directly use the spring tags in my JSP's
Don't use the spring tags at all and replicate their logic in my own tags
Possibly write a tag class that extends or makes use of the spring tag class
Expand the scope of my tags to wrap both the select and options tags
Given the reasons for wanting to do this (which I have now clarified in the question), I've decided to go for the last option. I wasn't keen on this originally because I thought I might end up with hundreds of parameters but it's actually not too bad. The tag files are designed for wrapping common bits of markup so this is what they're for. I've also wrapped my own tag further so there is a picklist tag which outputs my custom select tag and then writes the JS needed to initialise it.
I think this is the best of the possible solutions I've come across based on what I wanted to achieve. This is what I'm going with but I'd still be interested to hear of other peoples solutions if they think they have something better.
I am writing a web application using JSP/Spring MVC and would need to customize the UI based on the customer using it. I would need to hide/show certain sections of the screen, hide show certain labels and their text boxes and also modify labels based on different customers. Currently we are controlling the hide/show in the JSPs by elements and divs based on the logged in customer. For example:
if (customer= "A")
show this
else
hide this
The code gets cluttered and the JSP will get bloated as we add more customers.
Another alternative I have thought is split a page into sections and control the sections in the same way, but might end up in code repetition accross the JSPs.
For example
if (customer = "A")
jsp:include headerA.jsp
else
jsp:include genericheader.jsp
Another alternative would be to write different JSPs and route based on the client.
Is there a better way to handle this kind of situations. Can someone suggest the best practices to implement such a solution?
Thanks.
A UI that chooses what to do for each user can't possibly scale beyond your users A and B. You need a role-based authentication and authorization system.
Since you're already using Spring, I'd recommend looking at Spring Security and its role based capabilities. There are tags that can help you.
Another way to look at it is that role-based logic like this does not belong in tags. I'd recommend putting it in controllers and let them assemble pages for you.
Another possibility is something like SiteMesh, which allows you to create composite views.
One more: jQuery was born to manipulate the DOM. Use it along with CSS.
First thing it should be based on Role and not based on customer, and each customer will have certain role. It may possible that many customers will have same role and screen access and UI.
Based on role, you can use Spring Secutiry for Authentication and Authorization.
If you need to use Layout differently as per customer role, preferably you should use some Layout Manager such as Tiles, SiteMesh etc.
or use portlets for different login views to different customers
You just stated if person A logs in from one store, vs person B logs in from another. Hate to say it, but that's a role, no matter how you want to spin it, this is related to user authorization.
In terms of how you want to implement it, you could do a variety of things, you could intercept the login request and set a session variable which prepends a string to determine the correct view (i.e. when user a logs in you get customerA, vs customerB, so when rendering the view you'd retrieve the value and render "customerA/index" vs. "customerB/index", etc.
You could also determine the person's roles within the controller and render the appropriate view, although this couples your user roles to your controller logic, which wouldn't be recommended in my opinion.
If this app is going to have a lot of different backends, I'd recommend portlets that way you can write a new backend for each app, rather than bloating your web application with every new store backend.
Those are just a couple ways, hope this helps.
Consider a simple POJO Java Object:
class MyObj {
String a, b;
Integer c;
}
My application executes a Struts action and sets a Collection of these on the Http Request:
request.setAttribute("myObjects", getCollectionOfMyObj());
The action then forwards to a JSP page, and this is where my questions centres:
What is the simplest way I can
bind this collection into a grid,
such that is renders a table with
three columns (a, b, c) and one row
per object in the passed collection.
A key characteristic I require,
is that I can add a new field to the
Java object and it requires no (or
minimal) changes to the UI code,
i.e. the object is being
introspected and displayed so that I don't have D-R-Y
violations in the UI?
How can I make the grid
editable, so that any changes to a
row are reflected back into a new (or the existing)
Collection of Java objects in the
request for use by other Actions
(e.g. to persist the changes)?
Many thanks in advance for your help, please let me know if you need further clarification.
Arun
If you need to display only your data without editing it I recommend using displaytag, its a custom tag that is used to render tabulated data, and its highly customizable.
However, If you want to edit your data, I advise you to move to some javascript solutions, dhtmlxgrid is one good option, there are many many other solutions in javascript that you could use, however here you will be working with XML data and AJAX, this would be easier to you, and it will make your table more dynamic to changes. After mastering your chosen javascript-solution that best fits you, you could wrap it into a custom tag and generalize it ;-).
There are tons of different ways you can achieve the above. But since you are already using Struts I would recommend stick to Struts UI Tags . It will make things little bit easy to start with