Passing JSON Map into Spring MVC Controller - java

I'm trying to send a JSON representation of a Map into my controller as a POST parameter.
#RequestMapping(value = "/search.do", method = RequestMethod.GET, consumes = { "application/json" })
public #ResponseBody Results search(#RequestParam("filters") HashMap<String,String> filters, HttpServletRequest request) {
//do stuff
}
I found that #RequestParam would just throw a 500 error, so I tried using #ModelAttribute instead.
#RequestMapping(value = "/search.do", method = RequestMethod.GET, consumes = { "application/json" })
public #ResponseBody Results search(#ModelAttribute("filters") HashMap<String,String> filters, HttpServletRequest request) {
//do stuff
}
This would correctly respond to requests, but I realized that the Map was empty. With later experimentation, I found that any object (not just HashMap) would be instantiated, but no fields would be filled in. I do have Jackson on my classpath, and my controllers will respond with JSON. However, it would appear that my current configuration is not allowing Spring to read JSON in via a GET/POST parameter.
How does one pass JSON representations of objects from a client-side AJAX request to a Spring controller as a request parameter and get a Java object out?
EDIT Adding my relevant Spring configuration
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="html" value="text/html" />
<entry key="json" value="application/json" />
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="prefixJson" value="true" />
</bean>
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
</list>
</property>
</bean>
On the suggestion of a commenter, I tried #RequestBody. This will work, so long as the JSON strings are quoted with double quotes.
#RequestMapping(value = "/search.do", method = RequestMethod.POST, consumes = { "application/json" })
public #ResponseBody Results<T> search(#RequestBody HashMap<String,String> filters, HttpServletRequest request) {
//do stuff
}
This does solve my immediate issue, but I'm still curious as to how ou might pass in multiple JSON objects via an AJAX call.

This does solve my immediate issue, but I'm still curious as to how ou might pass in multiple JSON objects via an AJAX call.
The best way to do this is to have a wrapper object that contains the two (or multiple) objects you want to pass. You then construct your JSON object as an array of the two objects i.e.
[
{
"name" : "object1",
"prop1" : "foo",
"prop2" : "bar"
},
{
"name" : "object2",
"prop1" : "hello",
"prop2" : "world"
}
]
Then in your controller method you recieve the request body as a single object and extract the two contained objects. i.e:
#RequestMapping(value="/handlePost", method = RequestMethod.POST,
consumes = { "application/json" })
public void doPost(#RequestBody WrapperObject wrapperObj) {
Object obj1 = wrapperObj.getObj1;
Object obj2 = wrapperObj.getObj2;
//Do what you want with the objects...
}
The wrapper object would look something like...
public class WrapperObject {
private Object obj1;
private Object obj2;
public Object getObj1() {
return obj1;
}
public void setObj1(Object obj1) {
this.obj1 = obj1;
}
public Object getObj2() {
return obj2;
}
public void setObj2(Object obj2) {
this.obj2 = obj2;
}
}

You may use the Jackson library to convert from Json to Map.
#web-context.xml
<bean id="messageAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
</list>
</property>
</bean>
#maven dependencies:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-lgpl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-lgpl</artifactId>
<version>1.9.13</version>
</dependency>
#Controller
#RequestMapping(value = "/method", method = RequestMethod.DELETE)
public String method(
#RequestBody Map<String, Object> obj){
#Request (e.g. jquery Ajax)
$.ajax({"type": "DELETE",
"contentType": "application/json;",
"url": "/method",
"data": JSON.stringify({"key": "Ricardo"}),
"dataType": "json";}
});
It's much easier with Python Frameworks or Play! ufff

I have passed the Map object to Java using below code :
Javascript Code :
var values = {
"object1" : JSON.stringify(object1),
"object2" : JSON.stringify(object2)
};
var response = $http.post(url,data);
Server Side Code :
#RequestMapping(value = "/deleteData",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public Result deleteData(#RequestBody HashMap<String, Object> dataHashMap) {
Object1 object1= (Object1) JsonConvertor.jsonToObject((String) dataHashMap.get("object1"), Object1.class);
Object2 object2= (Object2) JsonConvertor.jsonToObject((String) dataHashMap.get("object2"), Object2.class);
}
JsonConvertor Class :
public class JsonConvertor {
public static <T> Object jsonToObject(String json, Class<T> clazz) {
if (json == null)
throw new IllegalArgumentException("null cannot be converted to Object");
Gson gson = new GsonBuilder().disableHtmlEscaping().setDateFormat("dd-MMM-yyyy").create();
return gson.fromJson(json, clazz);
}
}

You are not getting json correctly.
Do like that ....
/*
* Mapping for Demographics And Profiling Question Filter
*/
#RequestMapping (value = "/generalFilter")
public void ageFilteration(#RequestParam Map <String,String> filterParams,HttpServletRequest request,HttpServletResponse response) throws IOException
{
// System.out.println("Geographies in Controller :"+ filterParams.get("geographies"));
List<FeasibilityBean> feasibilityList = feasibilityDao.getGeneralFeasibilityList(filterParams,request);
// System.out.println(" General Filter List Size:"+feasibilityList.size());
response.getWriter().print(new Gson().toJsonTree(feasibilityList,new TypeToken<List<FeasibilityBean>>(){}.getType()));
}
}
Js Code
var ages='',ageCond='',genders='',genderCond='';
$.ajax({
type: "POST",
url : url,
data : {ages:ages,ageCond:ageCond,genders:genders,genderCond:genderCond},
beforeSend: function() {
$(thisVar).find('i').addClass('fa-spin');
},
success : function(feasibilityJson){
},
error : function(data) {
alert(data + "error");
},
complete:function(){
$(thisVar).find('i').removeClass('fa-spin');
}
});
or you want to bind bean with json....
https://stackoverflow.com/a/21689084/5150781
https://stackoverflow.com/a/37958883/5150781

#RequestMapping(method = RequestMethod.POST)
public HttpEntity<Resource<Customize>> customize(#RequestBody String customizeRequest) throws IOException {
Map<String, String> map = mapper.readValue(customizeRequest, new TypeReference<Map<String,String>>(){});
log.info("JSONX: " + customizeRequest);
Long projectId_L = Long.parseLong(map.get("projectId"));
[...]

As #dario's answer, but for Jackson 2 version:
spring-web-context.xml
<bean id="messageAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" >
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=utf-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
maven pom.xml:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
java controller
#RequestMapping(value = "/search.do", method = RequestMethod.GET, consumes = { "application/json" })
public #ResponseBody Results search(#RequestBody Map<String,Object> filters, HttpServletRequest request) {

Related

How to access Model Attribute's value and set to ModelAndView

I cant seem to find the solution for this.
I have method that returns ModelAndView to view web pages.
I store a webpage filename to model whenever a condition is true.
Example:
#RequestMapping(value = "/process", method = RequestMethod.POST)
public ModelAndView processRequest(HttpServletRequest request,
HttpServletRequest response, Model model,#RequestParam("file") MultipartFile file)
throws IOException {
if (file.isEmpty()) {
model.addAttribute("exception", "web_file1")
} else {
model.addAttribute("exception", "web_file2")
}
How can I retrieve the data stored in "exception" and set it to ModelAndView?
ModelAndView mav = new ModelAndView();
mav.setViewName("exception");
//expected:web_file2
//actual:exception
return mav;
model.addAttribute("exception", "web_file2")
String sModel=model.toString(); //{exception=web_file2}
String returnView = (sModel).substring(11,sModel.length()-1); //web_file2
return new ModelAndView(returnView);
I've found a way to get it,
But I think there's a better way to do this.
1. put your data using
mv.addObject("exception","web_file1");
in your view retrieve data by the key ie exception ${exception}
eg : <input type="text" value="${exception}" />
2. if used spring mvc with jsp/html Ensure you have declared a bean for viewResolver
which has following format
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>abc.jsp</value>
</property>
</bean>

Spring MVC rendering 404 due to wrong view

I'm debugging a controller method in Spring MVC that should return a view, but I'm getting a 404 page.
Error
HTTP Status 404
/WEB-INF/views/responsive/pages/company/myCompanyCreatePurchaseOrderPage.jsp
The view is actually located in
/WEB-INF/views/pages/company/myCompanyCreatePurchaseOrderPage.jsp
Code
#RequestMapping(method = RequestMethod.GET, value = "/admin/getPoNumbers", produces = "application/json")
protected String getPurchaseOrdersFromSettings(#RequestParam(value = "uid")
final String uid, final Model model, final HttpServletRequest request, final RedirectAttributes redirectAttributes) {
// unrelated code omitted
return "pages/company/myCompanyCreatePurchaseOrderPage";
}
Where does this prefix get set?
InternalResourceViewResolver bean on your web.xml or applicationContext.xml
Sample
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.JstlView</value>
</property>
<property name="prefix">
<value>/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>

No exception found but mail not send in Spring MVC

I am new in spring MVC i have got an issue while send email through spring . no exception will occur but mail not send.
my applicationContext.xml
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com" />
<property name="username" value="uname" />
<property name="password" value="pass" />
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.socketFactory.port">465</prop>
<prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
<prop key="mail.smtp.port">465</prop>
</props>
</property>
</bean>
my controller class
#Controller
public class WebController {
// System.out.println("suceees");
#Autowired
private JavaMailSender mailSender;
#RequestMapping(value = "/index", method = RequestMethod.GET)
public String index() {
return "index";
}
#RequestMapping(value = "/redirect", method = RequestMethod.GET)
public String redirect() {
sendMail();
return "redirect:finalPage";
}
#RequestMapping(value = "/finalPage", method = RequestMethod.GET)
public String finalPage() {
return "final";
}
public void sendMail() {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom("sender");
helper.setTo("receiver");
helper.setSubject("hi");
helper.setText("welcome");
// attach the file
FileSystemResource file = new FileSystemResource(new File("/home/ajmal/Pictures/messi.jpg"));
helper.addAttachment("messi.jpg", file);//image will be sent by this name
mailSender.send(message);
} catch (MailException | MessagingException ex) {
System.err.println("error");
}
}
}
thanks in advance .. no exception will occur. but mail not send ?
We had into the same problem sometime back, with Spring Boot 1.2.5. Looks like with the latest version of Java Mail, now another property is needed - spring.mail.properties.mail.smtp.ssl.enable to be set as true. See this post for details.
Also, when I tested my application, I saw that merely giving the regular gmail password didn't anymore work. I needed a 2-step verified account, and had to use an application password.

how to configure ViewResolver for concrete controller

I have spring mvc application. I have 2 controllers -
first uses standart view resolver and render to jsp
second uses resolver for creatin RestFull wev service
How I can configure it?
UPDATE
first controller
#Controller
#RequestMapping("/controllerPath")
public class MyController {
#RequestMapping("/sayHello")
public String sayHello(Model model){
model.addAttribute("name", "Vasya");
return "hello";
}
}
it uses
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
I need to add one more controller which will work as restful webservice and return json to client
You can do a RESTful handler by simply having the Jackson libraries in your classpath and returning the object you want to serialize to JSON, or by using the #ResponseBody annotation to indicate that your returned object should be used as the "body" of the HTTP response directly.
Using Jackson
#RequestMapping("/myRestful")
MyDomainObject myRestfulService() {
// .. do some stuff... //
return new MyDomainObject(); // <- Return some object
}
Using #ResponseBody:
#RequestMapping("/myRestful")
#ResponseBody String myRestfulService() {
// .. do some stuff... //
return new "This is some string that will be returned, as-is, to the client"; // <- Return some data
}
Hope that helps

Getting 415 Unsupported Media Type Error when trying to return a view from a spring controller using an Ajax Request

I have two controller methods
#RequestMapping(value = "/link", method = RequestMethod.GET)
public ModelAndView link(HttpServletRequest httpRequest, #RequestParam(value="name", required=false) String name, #RequestParam(value="id", required=false) String id, #RequestParam(value="type") String type) {
ModelAndView mav=new ModelAndView("ViewPage");
SearchRequest request = new SearchRequest();
request.setName(name);
request.setId(id);
request.setType(type);
mav.addObject("Request", request);
}
#RequestMapping(value="/find", headers="Accept=/", method=RequestMethod.POST)
public #ResponseBody List find(HttpServletRequest httpRequest, #RequestBody SearchRequest searchRequest) {
}
From the 1st controller method link, the control will be passed to ViewPage.jsp, we will pass a ModelView Object to ViewPage.jsp. And the control should again go to find method.
$(document).ready(function(){
var myJSON = {name:"test", id:"test", type:"test"};
myJSON = JSON.stringify(myJSON);
$.ajax({
type: "POST",
url: "../find",
dataType:'JSON',
data: myJSON,
cache: false,
success: function(data){
if(data!=""){
}
)}
}
I am getting below error
"NetworkError: 415 Unsupported Media Type - localhost:8080/myreport/find"
In your Spring XML config, you need to specify the media types that are supported like so...
<beans:property name="mediaTypes">
<beans:map>
<beans:entry key="html" value="text/html" />
<beans:entry key="json" value="application/json" />
</beans:map>
</beans:property>
In order to get JSON working in your Spring MVC application the first thing you need to do is to add these dependencies:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.1.2</version>
<scope>compile</scope>
</dependency>
These dependencies are needed for Spring to managed JSON requests and responses.
Next thing is to define media types by registering ContentNegotiationManagerFactoryBean:
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false"/>
<property name="favorParameter" value="true"/>
<property name="mediaTypes">
<value>
json=application/json
xml=application/xml
</value>
</property>
</bean>
Also you have to define this negotiation manager in your mvc:annotation-driven tag's attribute content-negotiation-manager:
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jsonObjectMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
And create your JSON object mapper or use default. I prefer creating my own so that I can managed the configuration I need. For e.g.:
public class JsonObjectMapper extends ObjectMapper {
public JsonObjectMapper() {
super();
this.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
this.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
this.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
}
Declare it in Spring context:
<bean id="jsonObjectMapper" class="somepackage.JsonObjectMapper"/>
And then your javascript should look something like this:
$(document).ready(function(){
var obj = {};
obj.name = "test";
obj.id = "test";
obj.type = "test";
var request = {};
request.SearchRequest = obj;
$.ajax({
url: "${pageContext.servletContext.contextPath}/find",
type: 'POST',
dataType: 'json',
data: JSON.stringify(request),
contentType: 'application/json'
}).success(
function (data) {
//do something with response
});
});
This should work if I haven't forgotten something else. Hope this helps.

Categories

Resources