How to pass MultipartFile param in JUNIT testing? - java

I want to upload a multipartfile. When I use my REST request everything works just fine. When I want to test in JUnit the multipartfile param is not transmitted, I think (because I can't reach the main breakpoint in the debugger).
Error log:
Expected MultipartHttpServletRequest: is a MultipartResolver configured?
spring-common-test.xml:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- max upload size in bytes -->
<property name="maxUploadSize" value="20971520" /> <!-- 20MB -->
<!-- max size of file in memory (in bytes) -->
<property name="maxInMemorySize" value="1048576" /> <!-- 1MB -->
</bean>
Controller
#RequestMapping(value = "/services/tasks/addDocument", method = RequestMethod.POST, produces = "application/json")
#ResponseBody
public String set(#RequestParam("idTask") Long idTask,#RequestParam("descriere") String descriere,#RequestParam("name") String name, #RequestParam("file") MultipartFile file){
//things}
Test
#Test
public void testAddDocController() throws Exception {
FileInputStream fis = new FileInputStream("C:/HaxLogs.txt");
MockMultipartFile multipartFile = new MockMultipartFile("file", fis);
HashMap<String, String> contentTypeParams = new HashMap<String, String>();
contentTypeParams.put("boundary", "265001916915724");
MediaType mediaType = new MediaType("multipart", "form-data", contentTypeParams);
String resp = mockMvc.perform(post("/services/tasks/addDocument").param("idTask", "141").param("descriere","vadfadfad").param("name", "C:/HaxLogs.txt").content(multipartFile.getBytes()).contentType(mediaType))
.andReturn().getResponse().getContentAsString();
//.andExpect(status().isOk());
System.out.println(resp);
}

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>

Springboot: redirect and reverse-proxy

I'm having a SpringBoot and SpringMVC internal application (internal meaning hidden from the internet by a firewall) and a public authentication (OAuth2) service in the DMZ.
I'm accessing the landing page from the from a client in the internal area.
This page has a login button. When I press it, I'm forwarding the client to the auth server (in the DMZ), that I can access only going through a proxy.
I tried setting the VM env variables:
-Dhttp.proxyHost=xx -Dhttp.proxyPort=yy -Dhttp.proxySet=true
and setting them in the System.properties
System.setProperty("http.proxyHost", "http://xx");
System.setProperty("http.proxyPort", "xx");
System.setProperty("http.nonProxyHosts", "localhost|127.0.0.1");
but both with no effect.
I also tried to define a SimpleClientHttpRequestFactory bean :
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="requestFactory"
class="org.springframework.http.client.SimpleClientHttpRequestFactory">
<property name="proxy">
<bean id="proxy" class="java.net.Proxy">
<constructor-arg>
<util:constant static-field="java.net.Proxy.Type.HTTP" />
</constructor-arg>
<constructor-arg>
<bean class="java.net.InetSocketAddress">
<constructor-arg value="xx" />
<constructor-arg value="yy" />
</bean>
</constructor-arg>
</bean>
</property>
</bean>
</beans>
without anymore success.
Question
How can I configure Spring to proxify my redirect ?
Thanks!
Got it work as follow (see restTemplateProxy)
private final String server = "xx";
private final int port = yy;
private final SimpleClientHttpRequestFactory clientHttpReq = new SimpleClientHttpRequestFactory();
private final Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(server, port));
private RestTemplate restTemplateProxy = null;
{
clientHttpReq.setProxy(proxy);
restTemplateProxy = new RestTemplate(clientHttpReq);
}
#RequestMapping(value = "getLightToken", method = RequestMethod.GET)
private String getLightToken(Model model) throws JsonProcessingException, IOException {
/* Header */
headers.clear();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
/* Body */
MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();
body.add(CLIENT_ID.key, CLIENT_ID.val);
body.add(CLIENT_SECRET.key, CLIENT_SECRET.val);
body.add(GRANT_TYPE.key, GRANT_TYPE.val);
body.add(SCOPE.key, SCOPE.val);
/* Set the body and header of the request */
HttpEntity<?> request = new HttpEntity<>(body, headers);
/* Request Authorisation */
ResponseEntity<String> response = restTemplateProxy.exchange(BASE_URL + TOKEN_URI, HttpMethod.POST, request, String.class);
return response.getBody();
}

RestTemplate no suitable HttpMessageConverter found

I'm using spring 4. I'm trying to call restTemplate.postForEntity but keep getting
no suitable HttpMessageConverter found for response type [class java.lang.Object] and content type [text/html]
My rest template configuration:
<bean id="restTemplate" name="restTemplate"
class="org.springframework.web.client.RestTemplate"
autowire-candidate="true">
<constructor-arg ref="httpClientFactory" />
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</bean>
<bean class="org.springframework.http.converter.FormHttpMessageConverter" />
<bean
class="org.springframework.http.converter.StringHttpMessageConverter" />
</list>
</property>
</bean>
My function call:
protected <T> T doExecute(String suffixUrl, MultiValueMap<String, String> requestBody, Class<T> responseType) {
String prefixUrl = "https://blabla.com/api/bla/";
ResponseEntity<T> responseEntity = null;
HttpHeaders headers = new HttpHeaders();
headers.add(
"Content-type",
"application/x-www-form-urlencoded");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(
requestBody, headers);
responseEntity = restTemplate.postForEntity(
prefixUrl + suffixUrl,
request,
responseType);
return responseEntity.getBody();
}
I have a feeling its connected to the response "Content-Encoding: gzip", I've been looking for a gzip converter but it only exists in spring android.
Edit:
This works but its just a workaround:
String templateList = this.doExecute(
"list.json",
map,
String .class);
ObjectMapper mapper = new ObjectMapper();
TemplateResponse[] tr = mapper.readValue(
templateList,
TemplateResponse[].class);

JSON response from SpringMVC controller is not working

I want to response JSON object or array from Spring MVC controller. From these two beingjavaguys and mkyoung tutorial, i tried.
I could success only in when the response is string. But when the response is in object or in list, it doesn't work for me.
//It works
#RequestMapping(value = "/angular", method = RequestMethod.GET)
public #ResponseBody String getAllProfiles( ModelMap model ) {
String jsonData = "[{\"firstname\":\"ajitesh\",\"lastname\":\"kumar\",\"address\":\"211/20-B,mgstreet\",\"city\":\"hyderabad\",\"phone\":\"999-888-6666\"},{\"firstname\":\"nidhi\",\"lastname\":\"rai\",\"address\":\"201,mgstreet\",\"city\":\"hyderabad\",\"phone\":\"999-876-5432\"}]";
return jsonData;
}
Output is:
But the problem is in it,
#RequestMapping(value = "mkyoung", method = RequestMethod.GET)
public #ResponseBody Shop getShopInJSON() {
Shop shop = new Shop();
shop.setName("G");
shop.setStaffName(new String[] { "mkyong1", "mkyong2" });
return shop;
}
It shows,
HTTP ERROR 406
Problem accessing /mkyoung.html. Reason:
Not Acceptable
But if i change it toString() ,
It works but not with right output
#RequestMapping(value = "mkyoung", method = RequestMethod.GET)
public #ResponseBody String getShopInJSON() {
Shop shop = new Shop();
shop.setName("G");
shop.setStaffName(new String[] { "mkyong1", "mkyong2" });
return shop.toString();
}
But i need JSON object or array of object as response. What is the probelm ? I have added jsckson dependency in my pom.xml
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.10</version>
</dependency>
UPDATE:
Now i am sending request from angular js by adding
headers: {
"Content-Type": "application/json"
}
My dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.sublime.np.controller" />
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/defs/general.xml</value>
</list>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.tiles3.TilesView" />
</bean>
</beans>
As Sotirios Delimanolis's Answer suggesion.
$http({
url: '/mkyoung.html',
method: 'GET',
data: id,
headers: {
"Content-Type": "application/json"
}
}).success(function(response){
$scope.response = response;
console.log($scope.response);
/* $scope.hideTable = false;
$scope.hideButton = false ; */
}).error(function(error){
$scope.response = error;
console.log("Failed");
});
But it shows same error.
Also add jackson core
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>2.5.1</version>
</dependency>
For List use method return type Object
#RequestMapping(value = "mkyoung", method = RequestMethod.GET)
public #ResponseBody Object getShopInJSON() {
Shop shop = new Shop();
shop.setName("G");
shop.setStaffName(new String[] { "mkyong1", "mkyong2" });
Shop shop1 = new Shop();
shop1.setName("G1");
shop1.setStaffName(new String[] { "mkyong1", "mkyong2" });
List<Shop> shops = new ArrayList<Shop>();
shops.add(shop1);
shops.add(shop);
return shops;
}
Given #ResponseBody with a POJO type return type, a default MVC configuration with #EnableWebMvc or <mvc:annotation-driven />, and Jackson on the classpath, Spring will try to serialize the POJO to JSON and write it to the response body.
Since it's writing JSON, it's going to attempt to write application/json as the Content-type header. The HTTP specification requires that the server only responds with content types that are part of the Accept header in the request.
It seems you're sending your request with an inappropriate Accept header that doesn't contain application/json. Fix that.
Note that you are sending your request to
/mkyoung.html
Spring, by default, uses content negotiation based on some extensions. For example, with .html, Spring will think the request should produces text/html content, which is contrary to the application/json you want to send.
Since your handler is already mapped to
#RequestMapping(value = "/mkyoung", method = RequestMethod.GET)
just send the request to the corresponding URL, ending in /mkyoung. (Get rid of the .html extension.)

Passing JSON Map into Spring MVC Controller

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) {

Categories

Resources