11

I have the following class:

public class MyDTO { 

       private String kiosk;
       ...
}

and following url:

http://localhost:1234/mvc/controllerUrl?kiosk=false

and following controller method:

@RequestMapping(method = RequestMethod.GET, produces = APPLICATION_JSON)
@ResponseBody
public ResponseEntity<List<?>> getRequestSupportKludge(final MyDTO myDTO, BindingResult bindingResult) {
    ...
}

Now it is working nice and boolean field resolves properly.

Now url parameter has changed like this:

http://localhost:1234/mvc/controllerUrl?new_kiosk=false

I don't want to change parameter name inside the DTO. Is there way to say spring to understand that new_kiosk request parameter value should be put into kiosk field ?

gstackoverflow
  • 34,819
  • 98
  • 304
  • 641
  • What is the data type(JSON/XML etc) that you are accepting from front end? – dReAmEr May 05 '15 at 18:04
  • @RE350 It is just get parameters. url like this **controllerUrl?new_kiosk=false** – gstackoverflow May 05 '15 at 19:43
  • 1
    I strongly suggest a read of the java bean specification. A property is just the name of the getter/setter how the field is named internally doesn't matter. If your field is named `foo` and you have a `setBar` method that sets the value of `foo` you have a `bar` property. Property != field. – M. Deinum May 06 '15 at 13:51
  • @M. Deinum it is surprise for me. I always use IDE set get generator. By default it generates set and get methids accordin field names. – gstackoverflow May 06 '15 at 21:29
  • @M. Deinum Do you suggest to create methods with names **setNew_kiosk** and **getNew_kiosk** ? – gstackoverflow May 06 '15 at 21:51
  • Ofcourse it does as that is in 99% of the cases correct. However as mentioned the property name doesn't have to match the field name (I strongly suggest a read of the java beans spec. which explains all of that). – M. Deinum May 07 '15 at 07:04

2 Answers2

15

Apart from setting an additional setter you can hande the case by making a custom argument resolver. There's a few ways you can go about it, but there's already a well discussed post. If I were you I would focus on the jkee's answer. Follow it step by step, and than all you should do is annotate your DTO with something like,

public class MyDTO { 

       @ParamName("new_kiosk")
       private String kiosk;
       ...
}

Note that even if you can't change MyDTO class, you can still follow a custom resolver route. In this post I've answered how you can write a parameter type annotation. Combining the two post you can easily come up with an annotation e.g. @ParamMapper that would define the mapping from request to properties. Think of something like

 getRequestSupportKludge(@ParamMapper("new_kiosk;kiosk") MyDTO myDTO, BindingResult bindingResult)
Community
  • 1
  • 1
Master Slave
  • 26,268
  • 4
  • 56
  • 55
4

There different ways to do that.

If you can change MyDTO class the simplest way is to add a setter as suggested by M.Deinum :

public class MyDTO { 

       private String kiosk;
       ...
       public void setNew_kiosk(String kiosk) {
           this.kiosk = kiosk;
       }
}

That way, you can process http://localhost:1234/mvc/controllerUrl?kiosk=false as well as http://localhost:1234/mvc/controllerUrl?new_kiosk=false

If you are not allowed to do that (because the DTO is part of a library you are not allowed to change or ...), you can use a filter mapped to /mvc/controllerUrl, that would wrap the request with a custom HttpServlerRequestWrapper that will override following methods :

String  getParameter(String name)
Map<String,String[]>    getParameterMap()
Enumeration<String>     getParameterNames()
String[]    getParameterValues(String name)

calling the underlying request methods and processing the special parameter name. Example :

String[]    getParameterValues(String name) {
    String[] values = req.getParameterValues(name); // req is the wrapped request
    if ("kiosk".equals(name) && (values == null) {  // will accept both names
        values = req.getParameterValues("new_kiosk"); // try alternate name
    }
    return values;
}

This will be much harder to write and test, so only go that way if you cannot modify MyDTO class.

You could also try to use a custom implementation of WebBindingInitializer. From Spring Framework Reference Manual :

To externalize data binding initialization, you can provide a custom implementation of the WebBindingInitializer interface, which you then enable by supplying a custom bean configuration for an AnnotationMethodHandlerAdapter, thus overriding the default configuration.

Beware : the recommended usage of that is to register custom editors for a whole application - not your use case. And Spring Framework is oftern described as easy to extend but not to override. Caveat emptor ...

Summary : try to use method 1, if you cannot, then use method2, and only try method3 if you have other reasons to use a custom WebBindingInitializer

Serge Ballesta
  • 136,215
  • 10
  • 111
  • 230