This may be a very naive question to ask but I would like to know as a beginner in Spring MVC framework instead of returning ModelAndView Object can we just return a jsp name from a Controller's method definitions ? Also Apparently all the methods seem to take Model model as a argument. What does they mean ?
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.debug("Entering renderShoeStoreApplication method");
//model.addAttribute("orderList", orderList);
logger.debug("Exiting renderShoeStoreApplication method");
return "home";
}
Instead of we could also write I suppose
/*
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView home(Locale locale, Model model) {
logger.debug("Entering renderShoeStoreApplication method");
//model.addAttribute("orderList", orderList);
logger.debug("Exiting renderShoeStoreApplication method");
ModelAndView homeModel = new ModelAndView("home");
return homeModel ;
}*/
Please explain the basics . Thanks in advance.
i think you have got two question
All the methods seem to take Model model as a argument
this is necessarily not required, you can get http request as param and you can derive your model from the request parameters. eventually spring mvc does this for you to make the work much simpler using binding-result after bean validation.
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, HttpRequest request) {
String name = request.getParamter("name");
// you can manually derive your model here
}
can we just return a jsp name from a Controller's method definitions ?
you can pass the just jsp name in your controller method, provided if you have configured your view resolver to handled this.
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
if you return string from controller, by default controller direct to view resolver to resolve the view. pls check this SO post
You can go through the below resources to understand the basics of Spring MVC, first and foremost the official docs from spring MVC community and some of the quick heads up of the POC's using below links
http://earldouglas.com/publications/barebones-spring-mvc/
http://spring.io/guides/gs/serving-web-content/
http://www.mkyong.com/tutorials/spring-mvc-tutorials/
Why model is passed as a parameter to controller method and what is the purpose of ModelView object?..All such questions will get answered once you will get the basic understanding of Spring MVC architecture.
And Yes, In the event that there isn't any data to be returned by the method, the controller method can simply return a String that represents the view that should be rendered.
Related
I am using Spring MVC and Security and I have a controller with 2 methods. One creates a webpage html, and on that will take that and make a PDF out of it.
#RequestMapping(value = "/getPDFhtml", method = RequestMethod.GET)
public ModelAndView getPDFhtml(HttpServletRequest request) throws Exception {
ModelAndView modelAndView = new ModelAndView("myPDFTemplate");
// do stuff
return modelAndView;
}
#RequestMapping(value = "/createPDFFile", method = RequestMethod.GET)
public ModelAndView createPDFFile(HttpServletRequest request) {
String url = "/getPDFHtml";
String viewHtml = HttpUtil.getHttpRequest(url);
// take viewHtml and turn it into a PDF with iText
// other stuff...
}
The only way I could get this to work was to punch a hole in spring security like this (security-app-context.xml)
<intercept-url pattern="/getPDFhtml/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
because tenically, my HttpUtil call is a new sesion. (It is just a wrapper for Apache HttpClitent.jar stuff)
Now I need to not do this. I need access to the AuthenticationTolken in getPDFhtml() and it's not there because it's authenticated ananymousy, and my manager found out about my little sceuity hack and it has to go away now. :(
so I need a way to either:
be able to call getPDFhtml() from createPDFFile() and have the ModelAndView render itself into an html string. (I was told 6 months ago that this is not possable, but who knows)
be able to call getPDFhtml() from createPDFFile() and somehow pass the jsession id or the authentication token or whatever so I can get through the Spring securuity properly.
any ideas?
I went with FreeMarker.
in my main-servlet.xml I create my freemarker config:
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath"><value>/WEB-INF/freemarker/</value></property>
</bean>
#Autowired it into my controller and easy:
Template template = freemarkerConfig.getConfiguration().getTemplate("helloWorld.ftl");
template.process(data, out);
String viewHtml = out.toString();
and off to iText it goes! Thanks for all the help.
This seems to be a common issue. I have gone all the answers given in SO but could not make it work.I am trying to integrate Spring MVC+Freemarker in already existing web application. It works fine for the GET request and Freemarker Template reads java object provided by Controller without any issue.
But Form submission is not able to hit Controller method. Finally I made log4j work. Here is the error I am getting:
Error
HandlerMethod details:
Controller [application.entry.controller.UserController]
Method [public void application.entry.controller.UserController.handleSave(java.lang.String)]
org.springframework.web.bind.MissingServletRequestParameterException:
Required String parameter 'action' is not present
Freemarker:
<form method="POST" action="save.html">
------------
<input type="submit" class="btnnew" name="saveWithoutValidation" value="Save Without Validation"></input>
<input type="submit" class="btnnew" name="submit" value="Submit"></input>
</form>
context-root is PORTAL.
spring-servlet.xml
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".ftl"/>
web.xml
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Controller
#RequestMapping(value="/save", method=RequestMethod.POST)
public void handleSave(#RequestParam String action){
if( action.equals("submit") ){
System.out.println("Damn! You clicked submit");
}
else if( action.equals("saveWithoutValidation") ){
System.out.println("Sweet! You want no string attached.");
}
}
For logs I have tried to add log4j.logger.org.springframework.web=DEBUG to my existing log4j.properties but it didn't work.
I also had this issue and my solution was different, so adding here for any who have similar problem.
My controller had:
#RequestMapping(value = "/setPassword", method = RequestMethod.POST)
public String setPassword(Model model, #RequestParameter SetPassword setPassword) {
...
}
The issue was that this should be #ModelAttribute for the object, not #RequestParameter. The error message for this is the same as you describe in your question.
#RequestMapping(value = "/setPassword", method = RequestMethod.POST)
public String setPassword(Model model, #ModelAttribute SetPassword setPassword) {
...
}
The #RequestParam String action suggests there is a parameter present within the request with the name action which is absent in your form. You must either:
Submit a parameter named value e.g. <input name="action" />
Set the required parameter to false within the #RequestParam e.g. #RequestParam(required=false)
Another possible cause is to have the wrong order of RequestMapping attributes.
As spring doc says:
An #RequestMapping handler method can have a very flexible signatures.
The supported method arguments and return values are described in the
following section. Most arguments can be used in arbitrary order with
the only exception of BindingResult arguments. This is described in
the next section.
If you scroll down the doc, you will see that the BindingResult has to be immediatelly after the model attribute, since we can have multiple model objects per request and thus multiple bindings
The Errors or BindingResult parameters have to follow the model object
that is being bound immediately as the method signature might have
more than one model object and Spring will create a separate
BindingResult instance for each of them so the following sample won’t
work:
Here are two examples:
Invalid ordering of BindingResult and #ModelAttribute.
#RequestMapping(method = RequestMethod.POST) public String
processSubmit(#ModelAttribute("pet") Pet pet, Model model,
BindingResult result) { ... } Note, that there is a Model parameter in
between Pet and BindingResult. To get this working you have to reorder
the parameters as follows:
#RequestMapping(method = RequestMethod.POST) public String
processSubmit(#ModelAttribute("pet") Pet pet, BindingResult result,
Model model) { ... }
I was facing a similar issue and found that a few fields like Date were not getting a concrete value, once given the values things worked fine. Please make sure you do not have date or any other field present on the form which needs a concrete value.
Based on the error:
Required String parameter 'action' is not present
There needs to be a request parameter named action present in the request for Spring to map the request to your handler handleSave.
The HTML that you pasted shows no such parameter.
Controller trying to find the "action" value in bean but according to your example you have not set any bean name of "action".
try to do name="action".
#RequestParam always find in the bean class.
My problem was the lack of BindingResult parameter after my model attribute.
#RequestMapping(method = RequestMethod.POST, value = "/sign-up", consumes = "application/x-www-form-urlencoded")
public ModelAndView registerUser(#Valid #ModelAttribute UserRegistrationInfo userRegistrationInfo
HttpServletRequest httpRequest,
HttpSession httpSession) { ... }
After I added BindingResult my controller became
#RequestMapping(method = RequestMethod.POST, value = "/sign-up", consumes = "application/x-www-form-urlencoded")
public ModelAndView registerUser(#Valid #ModelAttribute UserRegistrationInfo userRegistrationInfo, BindingResult bindingResult,
HttpServletRequest httpRequest,
HttpSession httpSession) { ..}
Check answer #sashok_bg
#sashko_bg Mersi mnogo
Your request mapping is /save, but your POST is to /save.html. Changing the POST to /save should fix it.
#CookieValue(value="abc",required=true) String m
when I changed required from true to false,it worked out.
Please keep your
<form method="POST" action="XYZ">
#RequestMapping(value="/XYZ", method=RequestMethod.POST)
public void handleSave(#RequestParam String action){
Your form action attribute value must match to value of #RequestMapping, So that Spring MVC can resolve it.
Also, as you told it is giving 404 after changing, for this, can you please check whether control is entering inside handleSave() method.
I think, as you are not returning any thing from handleSave() method, you have to look at it.
if it still not work, can you please post your spring logs.
Also, make sure that your request should come like
/PORTAL/save
if there is anything between like PORTAL/jsp/save the mention in #RequestMapping(value="/jsp/save")
Add BindingResult parameter in your method. For reference please my code below.
save(#ModelAttribute Employee employee,BindingResult bindingResult)
I think the original question was confusing.
I have a HashMap that needs to be a Collection from a database that I'd like to send to a view via a Spring Controller. I don't want to put this HashMap in the model.addAttribute() because the Spring Model object returns a Map and my JSP needs the collection to be a Collection<Object>. If I set my HashMap.values() in a request.setAttribute, how do I go about dispatching that request variable to the view if my method is returning a String?
#RequestMapping(method = RequestMethod.GET)
public String home(Locale locale, Model model, HttpServletRequest request) {
model.addAttribute("surveys", mySurveys); //this is a map and I need a Collection<Object>
//So I'd like to do this, but how do I get to the "evaluations" object in a view if I'm not dispatching it (like below)??
request.setAttribute("evaluations", mySurveys);
//RequestDispatcher rd = request.getRequestDispatcher("pathToResource");
//rd.forward(request, response);
return "home";
}
EDIT: The Spring Tag library cannot be used for this particular usecase.
Thanks.
If mySurveys is a Map, then perhaps you can put mySurveys.values() into the ModelMap instead of mySurveys (Also, are you intending to use a ModelMap instead of a Model?)
In the code below, surveys would be a Collection of Objects and would be accessible in the jsp via ${surveys}
#RequestMapping(method = RequestMethod.GET)
public String home(ModelMap modelMap, HttpServletRequest request) {
Map<String,Object> mySurveys = getMySurveys();
modelMap.addAttribute("surveys", mySurveys.values());
return "home";
}
I think you're confused as to what ModelMap is.
You can annotate whatever variable you want to access in the view by #ModelAttribute and Spring will automatically instantiate it, and add it to the ModelMap. In the view, you can use it like:
<form:form modelattribute="myAttribute">
<form:input path="fieldInAttribute">
</form:form>
Hope this answers your question
I created a controller with method handler as
#RequestMapping( value = {"/membersjson"},method = RequestMethod.GET)
public #ResponseBody String getMembers(Model model) {
List<Member> members = memberService.getMembers();
model.addAttribute("members",members);
return "jsontemplate";
}
<bean id="jsontemplate"
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
I expect the out put to be in json but instead the output is "jsontemplate" instead. Can some one please explain the reason. thanks in advance.
MappingJacksonJsonView, or any other view or view resolver bean, is irrelevant when you're using #ResponseBody. Instead, Spring will try to convert the return value of your method directly into a response. In this case, it's decided to turn it into a String response.
First make, sure you've declared <mvc:annotation-driven/> in your context, and that Jackson is available on the classpath. Also ensure that the browser is sending application/json in its Accept header.
You shouldn't be returning the string "jsontemplate"; you should return either the List<Member> or the Model. The json mapping should occur automatically.
I am using spring mvc with Annotations, see the following snippet
#RequestMapping(value = "/configuration/", method = RequestMethod.GET)
public MyModel viewConfiguration() {
The problem I am having accessing the 'MyModel' class in my JSP.
How can I do this, without using the ModelAndView object?
This shorthand syntax means that MyModel becomes a model attribute named myModel (i.e. class name with the first letter decapitalized).
View name is inferred from the URL.
See also:
15.3.2.3 Supported handler method arguments and return types
15.10.3 The View - RequestToViewNameTranslator
You could set MyModel as a request attribute to be accessed in your JSP. I'm curious, why don't you want to use ModelAndView? After all, it does what you want to do here, which displays the view and provides a container to hold your objects you want to reference in your view.
By the way, if this is an Ajax call, you will need to add #ResponseBody to the API so that your javascript can read the response in the callback function:-
#RequestMapping(value = "/configuration/", method = RequestMethod.GET)
public #ResponseBody MyModel viewConfiguration() {
...
}