0

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 Answer 1

0

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; 
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.