I created a class named Person. Then I pass an object of this class via Spring controller to JSP page, say abc.htm.
Now I want it to transfer back from abc.htm to another controller.
How could I do that?
Also tell me if any other class object (say Address class object) uses that person object as parameter, then how would I pass that Address class object to the controller.
I am very confused, please help me.
After the page is rendered you are no longer in the "Java realm", so you don't have your objects. You can rebuild them based on the parameters that are sent back in the next request.
This is called "binding". In Spring MVC this is done automatically (more or less) if you are using the <form:x> tags. Then in your controller your objects will be accessible as method attributes:
#RequestMapping(..)
public String foo(YourObject object) {..}
You might need a #ModelAttribute annotation if the name of your param and the one in the JSP are not the same. The MVC docs write:
Command or form objects to bind parameters to: as bean properties or fields, with customizable type conversion, depending on #InitBinder methods and/or the HandlerAdapter configuration. See the webBindingInitializer property on AnnotationMethodHandlerAdapter. Such command objects along with their validation results will be exposed as model attributes by default, using the non-qualified command class name in property notation. For example, "orderAddress" for type "mypackage.OrderAddress". Specify a parameter-level ModelAttribute annotation for declaring a specific model attribute name.
I'd suggest you review the PetClinic Sample Application to see how this works in practice.
Related
I have web services developed using Jersey, and a service take as parameter a Java Bean annotated with #QueryParam annotations on fields. It works fine when the service is invoked directly via its URL. Now I wish to call that service programatically from another piece of code (a JSP in the same WAR, say). I wish to have the bean parameter filled in with the query parameters of my current request, basically doing myself what Jersey does for me automatically when I call the service URL.
I want really to be able to take the request parameters and inject them into the relevant bean fields. I know I could do that myself with BeanUtils and reading the annotations myself, but surely there is an easier way?
Example code:
My service defines this method
#GET
public Response generate(#BeanParam Options options){...}
And Options is a Bean that has fields like
#QueryParam("format")
private String format="pdf";
I want to be able to write something like:
Options myoptions=new Options();
???.inject(myoptions,request);
in my JSP.
Does it make sense?
I'm using Spring MVC Framework and I'd like all the .jsp pages of the View to have access to the User's attributes(name, sex, age...). So far, I use the addAttribute method of the Model(UI) in every Controller to pass the current User's attributes to the View. Is there a way to do this only once and avoid having the same code in every Controller?
You can use Spring's #ControllerAdvice annotation on a new Controller class like this:
#ControllerAdvice
public class GlobalControllerAdvice {
#ModelAttribute("user")
public List<Exercice> populateUser() {
User user = /* Get your user from service or security context or elsewhere */;
return user;
}
}
The populateUser method will be executed on every request and since it has a #ModelAttribute annotation, the result of the method (the User object) will be put into the model for every request through the user name, it declared on the #ModelAttribute annotation.
Theefore the user will be available in your jsp using ${user} since that was the name given to the #ModelAttribute (example: #ModelAttribute("fooBar") -> ${fooBar} )
You can pass some arguments to the #ControllerAdvice annotation to specify which controllers are advised by this Global controller. For example:
#ControllerAdvice(assignableTypes={FooController.class,BarController.class})
or
#ControllerAdvice(basePackages={"foo.bar.web.admin","foo.bar.web.management"}))
If it is about User's attributes, you can bind the model bean to session as an attribute which can be accessed on every view. This needs to be done only once.
Another option could be is to implement a HandlerInterceptor, and expose the model to every request.
let's assume we have a signup form. When some input of the form is changed, I want to validate its value on the fly by using the ajax call to the server. Is there a chance to validate only some particular property of the bean by using the JSR 303 validation?
The signup form handler validates the received bean just fine, but I want to find out the way to check the property before submit the whole bean.
The straight forward approach is just to create a server-side method to receive the property name and value and based on the name check the value, but I hope there is a way to use already defined constraints for the bean.
For example, the user entered the email address and moved forward to the next property. The client makes a call and the server method checks if the provided email is already exist. If so, it returns an error and I do show it up on the client side. I believe it may make the signup process more flexible and user friendly
Any comments are really appreciated.
The jsr-303 Validator does have a method right on it to validate just one property:
<T> java.util.Set<ConstraintViolation<T>> validateProperty(T object,
java.lang.String propertyName,
java.lang.Class<?>... groups)
You just need to inject the validator so that you can use it directly, rather than relying on Spring to call it automatically via putting #Valid on a method parameter.
In ASP.NET MVC in the controller I can just have an object from my model be a parameter in one of my methods, and a form submission that gets handled by that method would automatically populate the object.
eg:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(User u){...}
The user object will automatically be populated for be from the form submission.
Is there a way to have this automatically happen using Spring MVC, and if so how do I do it?
In Spring MVC (with Spring MVC 2.5+ annotation-based configuration) it looks exactly the same way:
#RequestMapping(method = RequestMethod.POST)
public ModelAndView edit(User u) { ... }
The User object will be automatically populated. You may also explicitly specify the name of the corresponding model attribute with #ModelAttribute annotation (by default attribute name is a argument's class name with first letter decapitalized, i.e. "user")
... (#ModelAttrbiute("u") User u) ...
http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/web/portlet/mvc/SimpleFormController.html#onSubmitAction(java.lang.Object)
Create a Form Controller, for example PriceIncreaseFormController and make it extend SimpleFormController
override the method public ModelAndView onSubmit(Object command)
there are many variants of the above. look for the right method that suits your need. For simple flow the above method should be sufficient.
Inside the method, you can typecast command and get your Command class.
commandObj = ((PriceIncrease) command)
commandObj will have the parameters populated by spring.
in your springapp-servlet.xml you should tell spring about the PriceIncrease command class as follows and also you should have a POJO for your command class created.
<bean name="/priceincrease.htm" class="springapp.web.PriceIncreaseFormController">
<property name="commandClass" value="springapp.service.PriceIncrease"/>
....
In Servlets no, but in Spring MVC absolutely. Take a look at the web framework docs.
Specifically Section 13.11.4, 9th bullet point.
I think what I need is called reverse url resolution in Django. Lets say I have an AddUserController that goes something like this:
#Controller
#RequestMapping("/create-user")
public class AddUserController{ ... }
What I want is some way to dynamically find the url to this controller or form a url with parameters to it from the view (JSP), so I don't have to hardcode urls to controllers all over the place. Is this possible in Spring MVC?
Since Spring 4 you can use MvcUriComponentsBuilder.
For the most type-safe method:
String url = fromMethodCall(on(MyController.class).action("param")).toUriString();
Note this example requires that the method returns a proxyable type - e.g. ModelAndView, not String nor void.
Since 4.2, the fromMappingName method is registered as a JSP function called mvcUrl:
Login
This method does not have the proxy restriction.
Have you considered having a bean that aggregates all of the controller URLs you need into a HashMap and then adding this controller/URL Map to any model that requires it? Each Spring controller has the ability to call an init() method, you could have each controller add it's name and URL to the controller/URL map in the init() methods so it would be ready to use when the controllers go live.
Can solve with Java Reflection API. By Creating Custom Tag library. methods looks like this
Class c = Class.forName("Your Controller");
for(Method m :c.getMethods()){
if(m.getName()=="Your Method"){
Annotation cc = m.getAnnotation(RequestMapping.class);
RequestMapping rm = (RequestMapping)cc;
for(String s:rm.value()){
System.out.println(s);
}
}
}
Possible Problem You Can Face is
1.Path Variable > Like this /pet/show/{id} so set of path name & value should be support then replace this String.replace() before return url
2.Method Overriding > only one method is no problem. if Method override Need to give support sequence of Parameter Type That you really want like Method.getParametersType()
3.Multiple Url to Single Method> like #RequestMapping(value={"/", "welcome"}). so easy rule is pick first one.
4.Ant Like Style Url > Like this *.do to solve this is use multiple url by placing ant like style in last eg. #RequestMapping(value={"/pet","/pet/*.do"})
So Possible link tag style is
<my:link controller="com.sample.web.PetController" method="show" params="java.lang.Integer">
<my:path name="id" value="1" />
</my:link>
Where parmas attribute is optional if there is no method override.
May be I left to think about some problem. :)
I would probably try to build a taglib which inspects the annotations you're using in order to find a suitable match:
<x:url controller="myController">
<x:param name="action" value="myAction"/>
</x:url>
Taglib code might be something roughly like
Ask Spring for configured beans with the #Controller annotation
Iterate in some suitable order looking for some suitable match on the controller class or bean name
If the #RequestMapping includes params, then substitute them
Return the string
That might work for your specific case (#RequestMapping style) but it'll likely get a bit hairy when you have multiple mappings. Perhaps a custom annotation would make it easier.
Edit:
AbstractUrlHandlerMapping::getHandlerMap, which is inherited by the DefaultAnnotationHandlerMapping you're most likely using, returns a Map of URL to Handler
Return the registered handlers as an
unmodifiable Map, with the registered
path as key and the handler object (or
handler bean name in case of a
lazy-init handler) as value.
So you could iterate over that looking for a suitable match, where "suitable match" is whatever you want.
You can get access to the request object in any JSP file without having to manually wire in or manage the object into the JSP. so that means you can get the url path off the request object, have a google into JSP implicit objects.
Here is a page to get you started http://www.exforsys.com/tutorials/jsp/jsp-implicit-and-session-objects.html
The problem with this is that there's no central router in SpringMVC where all routes are registered and ordered. Then reverse routing is not a static process and route resolution in the view layer can be hard to integrate.
Check out this project for a centralized router (like rails) and reverse routing in the view layer.