How SpringMVC #SessionAttributes sends session object to JSP - html

I am learning SpringMVC framework and I have got the following example from here. Java Controller:
SessionController.java
package javabeat.net.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
#Controller
#RequestMapping("/sessiontest")
#SessionAttributes("sessionValue")
public class SessionController {
#RequestMapping(method = RequestMethod.GET)
public String getForm(#RequestParam("param") String paramVal, ModelMap map){
System.out.println("Param Value : " + paramVal);
map.addAttribute("sessionValue", "Test Object");
return "hello";
}
}
JSP page:
hello.jsp
<%# page contentType="text/html; charset=UTF-8" %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<%
String value = (String)session.getAttribute("sessionValue");
out.print(value);
%>
</body>
</html>
I am trying to understand the flow of the execution:
to the best of my knowledge, it assumes that in the execution flow the URL /sessiontest?param=paramVal is going to be hit first. Then paramVal is screened to the console. Then the collection map is enriched with the key-value pair "sessionValue"/"Test Object". Then "hello" is returned . So when hello.jsp is being hit, it retrieves the just added value, and the html body screens Test Object.
If my above interpretation is correct, I would like to know:
1) who is passing ModelMap map object to the method getForm?
2) what is the purpose of returning hello to nowhere?
3) how session object in the JSP is tied with the ModelMap map where the new key-value pair is being added?

I guess I'm not really good at explaining things since my words are clumsy.
But here is the thing :
1) who is passing ModelMap map object to the method getForm?
Spring container generates this model object and (behind the scene) invokes it as the argument to the method , it's working just like JSP Implicit Objects (request, response, .etc) where JSP Container makes them available in each page and these objects can be called directly without being explicitly declared .
ModelMap is used to wrap some attributes (key & value) so that you can deliver these values to the view returned from the method. So later, you can access these values in the view via its corresponding keys.
2). what is the purpose of returning hello to nowhere?
hello is the view name (hello.jsp) forwarded from the method where you can access the previous wrapped attributes in the map
3) how session object in the JSP is tied with the ModelMap map where
the new key-value pair is being added?
Spring’s #SessionAttributes is used on a controller to designate which model attributes (think these attributes as keys & values wrapped in the map) should be stored in a session.
In simple explanation : Since this controller is annotated with #SessionAttributes("sessionValue") so whenever a map wrap a value mapped with a key of "sessionValue" then the value will be available in HttpSession.
So then later you access this session attribute via implicit session object in your view.
String value = (String)session.getAttribute("sessionValue"); // gives you "Test Object"

Related

How to convert json to associative array in JSP

I'm trying to make a dynamic jsp page based on the json.
For example, if my json is look like this:
{
'page1':'true',
'page2':'true',
'page3':'false'
}
In php, I could get my associative array easily by one line:
$data = json_decode($json_str);
Then I could access whichever that I wanted at the place I needed, (i.e)
If($data['page1'] == 'true')
echo #page link#;
But in jsp, it doesn't goes so easily because it don't have much documents like php. I find the gson but still not sure. how to use it to achieve it.
Please give me some example that I could turn json to associative array, then get and access it in jsp.
A Java Map is an associative array. You can ask Gson to deserialize your json input with this:
Map<String,String> map = new Gson().fromJson(inputJson, new TypeToken<Map<String,String>>() {}.getType());
Example code:
package net.sargue.gson;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Map;
public class SO36859440 {
public static void main(String[] args) {
String inputJson = "{\n" +
" 'page1':'true',\n" +
" 'page2':'true',\n" +
" 'page3':'false'\n" +
"}";
Type type = new TypeToken<Map<String, String>>() {}.getType();
Map<String,String> map = new Gson().fromJson(inputJson, type);
System.out.println(map.get("page2"));
System.out.println(map.get("page3"));
}
}
The output is:
true
false
Then, your question is about converting it in JSP. Well, best practices for JSP advice you to move this kind of processing to a Servlet that acts as a controller and passes attributes to the JSP in order to build the view. You can put code directly on the JSP using <% ... %> but I highly discourage you to do so. But that's an entirely different question.

Reflectively save domain class instances in Grails

The problem is as follows: I want to handle a POST request with JSON body. The body consists of an array of JSON Objects, without further nesting, i.e. simple HashMaps. All of these objects represent JSON-serialized domain classes from an Android Application, which will have their counterpart in my Grails app. I am thinking of parsing the JSON body, iterating through every element and saving each node as its corresponding domain class instance.
a) How should I save the instance? I am quite new to Grails/Groovy so please excuse any huge mistakes. Code so far is
public static Object JSONArray2Instances(String json, Class type) {
def slurper = new JsonSlurper()
def result = slurper.parseText(json)
//we only want to parse JSON Arrays
if (!(result instanceof JSONArray))
return null
result.each {
def instance = it.asType(type)
// now I need to save to domain class!
}
}
b) where do I place the corresponding code? Currently it is in /grails-app/src/groovy. Where do the tests go? (Since it is not a 'real' Grails component)
c) Is an intermediate command object more appropriate?
Your code should go in to the controller which is handling the request. Please take a look at
gson-grails plugin which has examples of how to serialize and deserialze objects and map them to domain objects. Please take a look at the grails basics where they talk about the conventions used in the grails application and the layout. There are good examples at grails site. Hope this helps
I solved my problem as follows, based on help provided by the comment from allthenutsandbolts. : (Grails-Gson plugin was not needed)
Let N2696AdminAction be the name of a Domain Class
in my controller:
class N2696AdminActionController extends RestfulController{
static responseFormats = ['json', 'xml']
def JSONHandlerService
N2696AdminActionController() {
super(N2696AdminAction)
}
#Override
#Transactional
def save(){
if (request!=null)
JSONHandlerService.instancesfromJSON(request.JSON)
}
}
then I delegate persisting to my service as follows
class JSONHandlerService {
def instancesfromJSON(Object request){
//we only want to parse JSON Arrays
if (!(request instanceof JSONArray))
return null
request.each {
def domainClass = Class.forName("${it.type}",
true, Thread.currentThread().getContextClassLoader())
def newDomainObject = domainClass.newInstance(it)
newDomainObject.save(failOnError:true, flush:true, insert: true)
}
}
}
type is a Json attribute which holds the full (package inclusive) name for my class. This way, I can save to multiple Domain Classes with the same POST request.

Spring MVC: How to respond a http request with JSON object and view together?

It's like user click a link and in the Spring controller class a method will respond to the request with a JSON object and also a view name (meaning, it should return but not only a JSON object but also a HTTP view which hold that JSON object, so #ResponseBody may not enough)? Do we have to split it up into two methods (one for view and the other for JSON object)? Any ideas will be appreciated.
Normally we have
#RequestMapping(value="/someValue")
public #ResponseBody someMethod1(#RequestParam String param){
.....
return someJSONObject
}
To handle JSON object, and
#RequestMapping(value="/someValue")
public String someMethod2(#RequestParam String param){
.....
return someViewInString;
}
To return the view.
How can we combine them together?
You should return the view with a placeholder for the JSON.
In the controller code, create the JSON programatically, convert it to String format and then put it in the model (let's call it json_string)
In the view there should be a placeholder for the JSON string, something like:
<!-- other view stuff -->
var v = ${json_string};
<!-- more view stuff -->

spring3mvcportlet populate JSON dojo select

I am new to Spring mvc3 portlet and dojo. I am trying to populate select dropdown with JSON data when jsp is loaded. I want to use dojo and give ajax call to controller and return JSON when jsp is loaded. Any tips will be helpful.
#Controller
#RequestMapping("/yourController")
public class YourController
{
#RequestMapping(value="/combo/{id}", method=ReqestNethod.GET)
public String getDropDownData(#ParamValue("id") long id)
{
List<Combo> combos = commonDao.getCombos(id);
String json = JsonUtil.toJson(combos); // or whichever way you use
return json;
}
}
Send requests from dojo to this url
<your-context-path>/yourController/combo/1
where 1 is your combo id.
I haven't checked the syntax here.. Wrote it blind. You might get compilation errors.
I get data in below format
How do I populate dojoType="xwt.widget.form.FilteringSelect"
{"ValuesDTO": {"items": [{},{"default": {"size": 5},"int": 10,"string": "Product1","string": "Product1 ","string": "product3","string": "product4","string": "product5"}]}}
I am sending dat in bean--->DTO--->List

Spring MVC Request URLs in JSP

I am writing a web application using Spring MVC. I am using annotations for the controllers, etc. Everything is working fine, except when it comes to actual links in the application (form actions, <a> tags, etc.) Current, I have this (obviously abbreviated):
//In the controller
#RequestMapping(value="/admin/listPeople", method=RequestMethod.GET)
//In the JSP
Go to People List
When I directly enter the URL like "http://localhost:8080/MyApp/admin/listPeople", the page loads correctly. However, the link above does not work. It looses the application name "MyApp".
Does anyone know if there is a way to configure Spring to throw on the application name on there?
Let me know if you need to see any of my Spring configuration. I am using the standard dispatcher servlet with a view resolver, etc.
You need to prepend context path to your links.
// somewhere on the top of your JSP
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>
...
Go to People List
The c:url tag will append the context path to your URL. For example:
<c:url value="/admin/listPeople"/>
Alternately, I prefer to use relative URLs as much as possible in my Spring MVC apps as well. So if the page is at /MyApp/index, the link <a href="admin/listPeople"> will take me to the listPeople page.
This also works if you are deeper in the URL hierarchy. You can use the .. to traverse back up a level. So on the page at/MyApp/admin/people/aPerson, using <a href="../listPeople"> will like back to the list page
I prefer to use BASE tag:
<base href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/" />
Then, all your links can be like:
Go to People List
As i have just been trying to find the answer to this question and this is the first google result.
This can be done now using the MvcUriComponentsBuilder
This is part of the 4.0 version of Spring MVC
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.html
The method needed is fromMappingName
From the documentation :
Create a URL from the name of a Spring MVC controller method's request mapping.
The configured HandlerMethodMappingNamingStrategy determines the names of controller method request mappings at startup. By default all mappings are assigned a name based on the capital letters of the class name, followed by "#" as separator, and then the method name. For example "PC#getPerson" for a class named PersonController with method getPerson. In case the naming convention does not produce unique results, an explicit name may be assigned through the name attribute of the #RequestMapping annotation.
This is aimed primarily for use in view rendering technologies and EL expressions. The Spring URL tag library registers this method as a function called "mvcUrl".
For example, given this controller:
#RequestMapping("/people")
class PersonController {
#RequestMapping("/{id}")
public HttpEntity getPerson(#PathVariable String id) { ... }
}
A JSP can prepare a URL to the controller method as follows:
<%# taglib uri="http://www.springframework.org/tags" prefix="s" %>
Get Person
I usually configure tomcat to use context root of "/" or deploy the war as ROOT.war. Either way the war name does not become part of the URL.
You could use a servletRelativeAction. I'm not sure what versions this is available in (I'm using 4.0.x currently) and I haven't seen much documentation on this, but if you look at the code backing the spring form you can probably guess. Just make sure the path you pass it starts with a "/".
Example:
<form:form class="form-horizontal" name="form" servletRelativeAction="/j_spring_security_check" method="POST">
See org.springframework.web.servlet.tags.form.FormTag:
protected String resolveAction() throws JspException {
String action = getAction();
String servletRelativeAction = getServletRelativeAction();
if (StringUtils.hasText(action)) {
action = getDisplayString(evaluate(ACTION_ATTRIBUTE, action));
return processAction(action);
}
else if (StringUtils.hasText(servletRelativeAction)) {
String pathToServlet = getRequestContext().getPathToServlet();
if (servletRelativeAction.startsWith("/") && !servletRelativeAction.startsWith(getRequestContext().getContextPath())) {
servletRelativeAction = pathToServlet + servletRelativeAction;
}
servletRelativeAction = getDisplayString(evaluate(ACTION_ATTRIBUTE, servletRelativeAction));
return processAction(servletRelativeAction);
}
else {
String requestUri = getRequestContext().getRequestUri();
ServletResponse response = this.pageContext.getResponse();
if (response instanceof HttpServletResponse) {
requestUri = ((HttpServletResponse) response).encodeURL(requestUri);
String queryString = getRequestContext().getQueryString();
if (StringUtils.hasText(queryString)) {
requestUri += "?" + HtmlUtils.htmlEscape(queryString);
}
}
if (StringUtils.hasText(requestUri)) {
return processAction(requestUri);
}
else {
throw new IllegalArgumentException("Attribute 'action' is required. " +
"Attempted to resolve against current request URI but request URI was null.");
}
}
}
Since it's been some years I thought I'd chip in for others looking for this. If you are using annotations and have a controller action like this for instance:
#RequestMapping("/new") //<--- relative url
public ModelAndView newConsultant() {
ModelAndView mv = new ModelAndView("new_consultant");
try {
List<Consultant> list = ConsultantDAO.getConsultants();
mv.addObject("consultants", list);
} catch (Exception e) {
e.printStackTrace();
}
return mv;
}
in your .jsp (view) you add this directive
<%#taglib uri="http://www.springframework.org/tags" prefix="spring"%>
and simply use
<spring:url value="/new" var="url" htmlEscape="true"/>
New consultant
where
value's value should match #RequestMapping's argument in the controller action and
var's value is the name of the variable you use for href
HIH