问题
I am using Spring-mvc with ContentNegotiatingViewResolver
for handle my response objects and parse into a specific format. When i return the object from controller, in response it add my response object but also add the object which i used to map the request parameter. My controller is act as rest controller. Because i want to create rest-services using spring with ContentNegotiatingViewResolver
. After debugging, i found InvocableHandlerMethdod
class in which invokeForRequest
method contain following argument:
public final Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
...............................................
In ModelAndViewContainer
argument contain following detail:
ModelAndViewContainer: View is [null]; default model {oauthClientDetail=com.netsol.entities.OauthClientDetail@9ac35e, org.springframework.validation.BindingResult.oauthClientDetail=org.springframework.validation.BeanPropertyBindingResult: 0 errors}
I am not able to figure, why OauthClientDetail
object set in ModelAndViewContainer
and how i prevent this.
Follwing is my controller code:
@RequestMapping(value = "/changePassword", method = RequestMethod.POST)
public ApiResponse<UserDetail> changePassword(@Valid OauthClientDetail clientDetail,
BindingResult bindingResult,
@RequestParam(value = "password", required = true) String password) {
logger.info("In changePassword Service...... ");
if(bindingResult.hasErrors()){
throw new InvalidRequestException("Error", bindingResult);
}
UserDetail detail = userService.changeUserPassword(password, clientDetail, encoder);
ApiResponse<UserDetail> response = new ApiResponse<UserDetail>();
if(detail != null){
response.setErrorCode(CommonUtility.API_RESPONSE_STATUS.SUCCESS.getValue());
response.setErrorMessage(CommonUtility.API_RESPONSE_STATUS.SUCCESS.getMessage());
response.setResponse(detail);
}else{
response.setErrorCode(CommonUtility.API_RESPONSE_STATUS.FAIL.getValue());
response.setErrorMessage(CommonUtility.API_RESPONSE_STATUS.FAIL.getMessage());
response.setResponse(null);
}
return response;
}
rest-servlet.xml configuration:
bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="true" />
<property name="parameterName" value="mediaType" />
<property name="ignoreAcceptHeader" value="true" />
<property name="useJaf" value="false" />
<property name="defaultContentType" value="application/json" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
</bean>
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="contentNegotiationManager" ref="contentNegotiationManager" />
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
<entry key="html" value="text/html" />
</map>
</property>
<property name="defaultViews">
<list>
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="autodetectAnnotations" value="true" />
<property name="aliases">
<map>
<entry key="list" value="java.util.List" />
<entry key="string" value="java.lang.String" />
<entry key="hsahmap" value="java.util.HashMap" />
<entry key="object" value="java.lang.Object" />
<entry key="hashSet" value="java.util.HashSet" />
</map>
</property>
<property name="supportedClasses">
<list>
<value>java.util.List</value>
<value>java.lang.String</value>
<value>java.util.Map</value>
<value>java.lang.Object</value>
<value>java.util.Set</value>
<value>java.lang.Long</value>
<value>java.util.Date</value>
</list>
</property>
</bean>
</constructor-arg>
</bean>
</list>
</property>
<property name="defaultContentType" ref="htmlMediaType" />
<property name="ignoreAcceptHeader" value="true" />
</bean>
<bean id="htmlMediaType" class="org.springframework.http.MediaType">
<constructor-arg value="text" />
<constructor-arg value="html" />
</bean>
My request from chrome postman
client:
POST /empirecl-api/api/changePassword HTTP/1.1
Host: localhost:8080
Authorization: Bearer b3f46274-b019-4d7b-a3bd-5c19e9660c2f
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
clientId=my-client-with-secret&clientSecret=12345678&clientSecretConfirm=12345678&password=12345678
My Response is:
{
"oauthClientDetail": {
"userId": null,
"clientId": "my-client-with-secret",
"additionalInformation": null,
"authorities": null,
"authorizedGrantTypes": null,
"autoapprove": null,
"clientSecret": "12345678",
"clientSecretConfirm": "12345678",
"resourceIds": null,
"scope": null,
"webServerRedirectUri": null,
"createdOn": null,
"updatedOn": null,
"active": null,
"lastLogin": null
},
"apiResponse": {
"errorCode": 0,
"errorMessage": "Success",
"response": {
"userName": "my-client-with-secret",
"dateCreated": null,
"dateUpdated": null,
"active": "true"
}
}
}
In response the oauthClientDetail
object contain values that, i send with request and map into the object. From this, i assume that, my map object is set in the response. How i prevent this object to set in the response.
回答1:
I found the Solution from this MappingJacksonJsonView return top-level json object link. Need to add @ResponseBody
annotation in controller and set produces={"application/json"}
. Follwoing is my new code:
@RequestMapping(value = "/changePassword", method = RequestMethod.POST, produces={"application/json"})
public @ResponseBody ApiResponse<UserDetail> changePassword(@Valid OauthClientDetail clientDetail,
BindingResult bindingResult,
@RequestParam(value = "password", required = true) String password) {
logger.info("In changePassword Service...... ");
if(bindingResult.hasErrors()){
throw new InvalidRequestException("Error", bindingResult);
}
UserDetail detail = userService.changeUserPassword(password, clientDetail, encoder);
ApiResponse<UserDetail> response = new ApiResponse<UserDetail>();
if(detail != null){
response.setSuccess(CommonUtility.API_RESPONSE_STATUS.SUCCESS.getValue());
response.setMessage(CommonUtility.API_RESPONSE_STATUS.SUCCESS.getMessage());
response.setResponse(detail);
}else{
response.setSuccess(CommonUtility.API_RESPONSE_STATUS.FAIL.getValue());
response.setMessage(CommonUtility.API_RESPONSE_STATUS.FAIL.getMessage());
response.setResponse(null);
}
return response;
}
来源:https://stackoverflow.com/questions/25037473/spring-mvc-modelandviewcontainer-view-is-null-default-modelsome-object