Optional parameter in #PathParam annotation - java

We are facing issue related with making a path parameter optional.
original URL /expire/{token}
What we are trying to do is have the same service work for the URL's below.
1. /expire/{token}
2. /expire
Ex:- #Path("/expire/{token}")
We have already applied other solutions from SO,but no luck so far.

What about adding another method annotated with only:
#Path("/expire")
And let this method pass a null value into the original method.

Logically, it doesn't seem to make sense to have it optional. Your URI should handle the type of request it's supposed to do. But, I came across a post to make the #PathParam to be optional with a small hack using regular expressions.
http://www.nakov.com/blog/2009/07/15/jax-rs-path-pathparam-and-optional-parameters/
I would go with having separate endpoint method in Controller where it can pass the call to your services with optional parameter.

We can use regular expressions,
"#Path("/add/{a:([0-9.]*)}/{b:([0-9.]*)}{p:/?}{c:([0-9.]*)}")"
here path can be
add/2/3
add/2/3/4
my case I am using regular expressions for allowing only numbers

Related

custom annotation on RequestParam and PathVariable

I have created a custom annotation
annotation class UserControl(
val userIdentifier: String
)
I wan to apply this annotation on query parameters, and path variables in different controllers.
fun userWithMobile(
#UserControl("PhoneNumber")
#RequestParam mobile: String
): RegisteredUser {
return userManager.getUserWithPhoneNumber(mobile))
}
How can i check if the query parameters have the UserControl annotation or not, and do some processing on that. Is there standard way to write a global handler , or a processor for that?
Would appreciate any help
AspectJ can directly match parameter annotations, but not bind them to advice method values like class or method annotations. So if you only want to match them, a simple pointcut is enough. If you want to access the annotations and maybe their parameter values, you need a little bit of reflection magic. I have answered related questions many times already, which is why I am going to close this one as a duplicate. But first, here are the resources you want to read. They all related to your question, showing examples of how to handle different specific situations:
https://stackoverflow.com/a/38162279/1082681
https://stackoverflow.com/a/10595712/1082681
https://stackoverflow.com/a/50540489/1082681
https://stackoverflow.com/a/49872132/1082681
https://stackoverflow.com/a/61284425/1082681
https://stackoverflow.com/a/16624766/1082681
Basically, the pointcut you want the following or some variation of it:
execution(* *(.., #my.package.UserControl (*), ..))
The naive, less efficient approach without matching the parameter in the pointcut, using only relfection:
https://stackoverflow.com/a/27784714/1082681
https://stackoverflow.com/a/42561014/1082681

Calling service activator vs bean methods in Spring Integration

There're few ways one can manipulate the message in Spring Integration. One way is calling a bean's method inside <int:enricher> that will return an object and assign it to the given name, e.g:
<!-- calls getKey method of IdGenerator bean which returns String with some value -->
<int:enricher input-channel="a.channel" output-channel="b.channel" id="preTranslator">
<int:header name="Key" expression="#IdGenerator.getId(payload)"/>
</int:enricher>
Same can be utilized in filtering:
int:filter discard-channel="d.channel" input-channel="b.channel" output-channel="c.channel"
expression="#Cache.hasKey(headers.Key) == false"/>
On the other hand I can call the <int:service-activator> on a class implementing MessageProcessor interface. It would take the original message and return a copy with a new header field. That requires my class's method to always build a new message with MessageBuilder though.
Currently I use the first way for simple field enrichment and service-activator for requesting data from DB/external services. What's the right way of picking the correct approach?
First of all, the <filter> doesn't change message at all. The given name should be read as header, looking to your case.
The <service-activator> always return a new message. Yes, you can populate new headers there as well and right you have to use MessageBuilder.
It is fully unclear what is your problem. If you can achieve the solution with expressions in the config, so be that. But if you do something with the message in the code and would like to add/edit/remove headers you use MessageBuilder.
That's really fine. I think you should just read more documentations and right more code in your application.
Eventually you will find the most convenient style for yourself. Fro example I end up once with expressions and Groovy scripts. No Java code at all. But right now I prefer Spring Integration Java DSL, because it is much faster, cleaner, fluent and lets get rid of any other configs like XML or Groovy. Everything is Java now and that MessageBuilder is still on the horse!

Spring controller regex mapping

I have a url say /prefix/part1/part2/.../partN/suffix and in a controller i want to map anything between /prefix/ and /suffix to one variable.
Approaches tried
#RequestMapping(value = "/prefix/{store:[\s\S]*}/suffix",
method = RequestMethod.GET)
Also, tried regex : (.*), The interesting part is i don't know what N is. So, cant explicitly specify number of slashes possible.
I have an open JIRA issue requesting this ability, but the Spring core team apparently doesn't think that it's useful and is not interested in supporting it. You might make a note there.
In the meantime, the only option is to get the entire string from the request and parse it yourself.

Distinguish empty value from empty string ("") in Url query parameter

How to distinguish URL without value like this /url?var from /url?var="" in Spring MVC?
Method HttpServletRequest::getParameterMap() in controller returns "" in both ways.
I need this to separate commands from queries to specified resource.
One simple way of going about doing what you want to is use the getQueryString() of HttpServletRequest. You would just check and see if the returned String contains the pattern you are looking for.
If you need something like that often (as in many controller methods) you could also easily create a custom HandlerMethodArgumentResolver that will indicate the presence of a String in the URL.
Here is the relevant Javadoc and here is an example
/url?var is a valid URL which states that you have a parameter var which is not initialized.
So by default it is initialized to empty string. That's the framework behavior.
If you don't want to see that parameter coming in HttpServletRequest::getParameterMap(), just don't use it with URL (i.e. /url should be your call)

RestEasy #Path Question with regular expression

Is it possible to define path with optional path variables.
like the uri below:
/app/make/{make}/model/{model}/year/{year}/mileage/{mileage}/fuelType/{fuelType}/maxPrice/{maxprice}/transmission/{transmission}/engineSize/{engineSize}
URI may be composed of any 0 or more combinations of the parameters? Is there a way to tell resteasy that all those paths are optional?
cheers.
Why bother using path segments? If they are optional parameters then it can't be a real hierarchy so why not just use query string parameters. They work much better for this type of parameter.
#Path("/make/{make}{model:(/model/[^/]+)?}{fuel : (/fuel/[^/]+)?}{gearbox : (/gearbox/[^/]+)?}/cars")
app/{make:(/make/[^/]+)?}{model:(/model/[^/]+)?}{year:(/year/[^/]+)?}{mileage:(/mileage/[^/]+)?}
I came up with the above workaround which works but inside the method I need to remove the pathname.

Categories