Spring MVC: ModelAndViewContainer: View is [null]; default model{Some-Object}

此生再无相见时 提交于 2019-12-02 17:38:17

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!