SpringMVC - Naming strategy for #RequestParam - java

I would like all my APIs to use lower-case request parameters, but I would still like to use camel-case in my Java code.
For example, consider the following code:
#GetMapping("/ping")
public String ping(
String responseMessage)
{
return "PONG " + responseMessage;
}
To contact this endpoint and supply a response message, I would have to call: localhost:8080/ping?responseMessage=Hello. However, I would like spring to automatically bind the variable name responseMessage to a request parameter named responsemessage. I specifically do not want to manually write #RequestParam(name="responsemessage") in my controller, but rather configure a global naming strategy for request parameters. Is this possible?
There are a couple of other threads on SO that talks about making the request parameters or url mappings case-insensitive:
RequestParam value in spring MVC to be case insensitive
Is there any way we make PathVariable name case insensitive in Spring?
Spring mvc. case insensitive get parameters mapping
Making a request parameter binding case insensitive
However, the answers in these questions strikes me as quite hacky or requires manual codeing. Is there no simple setting for the behaviour I am after? I know this is possible when using JSON bodies, by configuring the Jackson propertyNamingStrategy. Is there an equivalent for request parameters?

Related

Spring boot and validation of param in url

#RequestParam(value = "param") String param
How to validate this param in elegant way ? More exactly I must check if param is some value in database. My stack is: spring-boot+mybatis
This might be a duplicate of that one but anyway.
There's a difference in the way you validate forms and separate parameters. With POST it's actually impossible to break the request into separate parameters and you get the whole post body, and you use #Valid to process it. With GET it is possible to have separate parameters as arguments in method, and in this case Spring proprietary #Validated annotation should be used.

Spring MVC map controller with trailing string of url

Is it possible to map a spring mvc controller by trailing keyword of a url. e.g, lets suppose I have following urls:
example.com/{cityName}
example.com/{cityName}/{categoryName}
example.com/{cityName}/ping
example.com/{cityName}/{categoryName}/ping
I want to have 3 controller methods. 1st url should be handled by controller "X", 2nd url should be handled by method "Y" and 3rd, 4th url should be handled by single method "Z". This means that any url ending by /ping should be handled by method "Z" only. No matter what is leading content of that url.
Is this feasible in Spring MVC?
Is it possible to map a spring mvc controller by trailing keyword of a
url?
Yes, you can use Ant-style path patterns. Following controller will handle any request to URLs ending with /ping, with arbitrary number of levels:
#RequestMapping(path = "**/ping")
public String Z(HttpServletRequest request) {
return request.getRequestURI();
}
In order to extract those Path Variables, e.g. cityName and categoryName, you should inject the HttpServletRequest to the method handler.
In addition to URI templates, the #RequestMapping annotation also supports Ant-style path patterns. You can read more on Spring Documentation.
It looks like you're asking to match a slash as part of the controller mapping. This isn't supported in Spring MVC, and the maintainers have no plans to add it. As a special case, if you are limited to only two levels of "directories", you can just specify the mappings explicitly as above.

Any simple way to test a #RequestBody method?

If I have a #Controller method whose parameter is a #RequestBody param, I usually have to write some jQuery script or something similar to perform an AJAX request with JSON object in order to call that method. If I tried calling that method via a web browser directly, it returns with a Error 415 Unsupported Media Type.
Is there any alternative to just quickly call such method using browser without having to write some jQuery code? Like perhaps a way to write the JSON object in the URL/address bar?
code:
#RequestMapping("testCall")
#ResponseBody
public List<TestObject> getTestCall (#RequestBody TestParams testParams) {
return stuff;
}
public class TestParams {
private Integer testNumber;
//getter/setter for testNumber
}
I thought maybe I could just do:
http://localhost/testCall?testNumber=1
maybe Spring would auto populate a new TestParams instance with that property set to 1 but that didnt work...
maybe I need to do something extra for that?
The whole point of a #RequestBody annotated parameters is for the Spring MVC stack to use the HTTP request body to produce an argument that will be bound to the parameter. As such, you need to provide a request body. Sending a request body is very atypical for a GET request. As such, browsers don't typically support it, at least not when simply entering an address in the address bar and submitting the request.
You'll need to use a different HTTP client, like jQuery. I typically have a small Java project in Eclipse that's setup with an Apache HTTP components client which can send HTTP requests to whatever server. It takes a few seconds/minutes to setup the correct request body and run.
I have spent the last year building a REST API, and by far the best way to exercise that API manually is using the Chrome Extension, Postman. I cannot recommend this tool enough.
https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en
To test your simple example you'll need to invoke a POST (I assume that as you have a request body, but your controller method doesn't define a HTTP Verb) using POSTMAN to your Url (like the following example):
POST /contextRoot/testCall
{
"testNumber": 1
}
If you want to test your API automatically (which I recommend), you can use the excellent Spring Mvc Test project. This allows your to call your API via a rest-like DSL and assert that the response is in the shape you want. More details can be found here:
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/testing.html#spring-mvc-test-framework
you can add request params to the getTestCall method:
#RequestParam(value = "testNumber", required = false, defaultValue = "") String testNumber
There is a chrome app called Advanced REST client. You can pass the data in form of json to your controller using this chrome app. For eg. json data is
id:1,
name:"xyz"
whereas the controller can have #RequestBody Person form.
The Person class would be a POJO having id and name as instance variables. The Spring would automatically map the json data to the form.
I think this is the easiest and simplest way of checking your spring controller.
Check the extension Advanced REST client here
From what I know You can send JSON object to the webbrowser and it will be displayed without further need of AJAX.
useful tutorial:
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/

Spring MVC RequestMapping ParamRequest collection/array

I have a #Controller with a #RequestMapping functions that accept collections.
Imagine something like:
requestHandler(Collection<Long> param){
...
}
This mapping only matches when I send requests such as:
http://www.domain.com/mapping/funct?param=1&param=2&param=3
I'd like to match it as well when I send a comma sepparated value:
http://www.domain.com/mapping/funct?param=1,2,3
Is there a way without using .split ? I'd like it to be automatically parsed to a collection.
You would have to write a custom Converter and register it in your Spring MVC context.
It is better to access all query parameters and parse according to your needs in this type of scenarios
You should have access to the requests query string via request.getQueryString().
In addition to getQueryString, the query parameters can also be retrieved from request.getParameterMap() as a Map.

Can I find the URL for a spring mvc controller in the view layer?

I think what I need is called reverse url resolution in Django. Lets say I have an AddUserController that goes something like this:
#Controller
#RequestMapping("/create-user")
public class AddUserController{ ... }
What I want is some way to dynamically find the url to this controller or form a url with parameters to it from the view (JSP), so I don't have to hardcode urls to controllers all over the place. Is this possible in Spring MVC?
Since Spring 4 you can use MvcUriComponentsBuilder.
For the most type-safe method:
String url = fromMethodCall(on(MyController.class).action("param")).toUriString();
Note this example requires that the method returns a proxyable type - e.g. ModelAndView, not String nor void.
Since 4.2, the fromMappingName method is registered as a JSP function called mvcUrl:
Login
This method does not have the proxy restriction.
Have you considered having a bean that aggregates all of the controller URLs you need into a HashMap and then adding this controller/URL Map to any model that requires it? Each Spring controller has the ability to call an init() method, you could have each controller add it's name and URL to the controller/URL map in the init() methods so it would be ready to use when the controllers go live.
Can solve with Java Reflection API. By Creating Custom Tag library. methods looks like this
Class c = Class.forName("Your Controller");
for(Method m :c.getMethods()){
if(m.getName()=="Your Method"){
Annotation cc = m.getAnnotation(RequestMapping.class);
RequestMapping rm = (RequestMapping)cc;
for(String s:rm.value()){
System.out.println(s);
}
}
}
Possible Problem You Can Face is
1.Path Variable > Like this /pet/show/{id} so set of path name & value should be support then replace this String.replace() before return url
2.Method Overriding > only one method is no problem. if Method override Need to give support sequence of Parameter Type That you really want like Method.getParametersType()
3.Multiple Url to Single Method> like #RequestMapping(value={"/", "welcome"}). so easy rule is pick first one.
4.Ant Like Style Url > Like this *.do to solve this is use multiple url by placing ant like style in last eg. #RequestMapping(value={"/pet","/pet/*.do"})
So Possible link tag style is
<my:link controller="com.sample.web.PetController" method="show" params="java.lang.Integer">
<my:path name="id" value="1" />
</my:link>
Where parmas attribute is optional if there is no method override.
May be I left to think about some problem. :)
I would probably try to build a taglib which inspects the annotations you're using in order to find a suitable match:
<x:url controller="myController">
<x:param name="action" value="myAction"/>
</x:url>
Taglib code might be something roughly like
Ask Spring for configured beans with the #Controller annotation
Iterate in some suitable order looking for some suitable match on the controller class or bean name
If the #RequestMapping includes params, then substitute them
Return the string
That might work for your specific case (#RequestMapping style) but it'll likely get a bit hairy when you have multiple mappings. Perhaps a custom annotation would make it easier.
Edit:
AbstractUrlHandlerMapping::getHandlerMap, which is inherited by the DefaultAnnotationHandlerMapping you're most likely using, returns a Map of URL to Handler
Return the registered handlers as an
unmodifiable Map, with the registered
path as key and the handler object (or
handler bean name in case of a
lazy-init handler) as value.
So you could iterate over that looking for a suitable match, where "suitable match" is whatever you want.
You can get access to the request object in any JSP file without having to manually wire in or manage the object into the JSP. so that means you can get the url path off the request object, have a google into JSP implicit objects.
Here is a page to get you started http://www.exforsys.com/tutorials/jsp/jsp-implicit-and-session-objects.html
The problem with this is that there's no central router in SpringMVC where all routes are registered and ordered. Then reverse routing is not a static process and route resolution in the view layer can be hard to integrate.
Check out this project for a centralized router (like rails) and reverse routing in the view layer.

Categories