I'd like to use an URL like http://www.example.com/rest/foo?bar
where the bar
query parameter has no value and its presence alone should denote if a variable is true
or false
.
Currently the missing value is assumed to be ""
(empty) and passed to new Boolean()
which treats it as false
.
Is there a more elegant way of defining it than declaring the parameter to be String and converting it myself?
Like e.g. a class javax.rs.BooleanFlag
or similar?
For query parameters that are defined as a boolean type in our documentation, the case-insensitive strings true and 1 will be handled as a true value, and the case-insensitive strings false and 0 will be handled as the false value. Other values will be defaulted to false , if provided.
Annotation Type QueryParamBinds the value(s) of a HTTP query parameter to a resource method parameter, resource class field, or resource class bean property. Values are URL decoded unless this is disabled using the Encoded annotation. A default value can be specified using the DefaultValue annotation.
As query parameters are not a fixed part of a path, they can be optional and can have default values.
If you make request http://test.com?id=123, then id is a QueryParam (to be more precise this is GET request parameter), if you make POST request with a form inside body, then these form parameters (filled usually by user) are translated to FormParam-s.
Note: upon seeing Phoste's answer, I'd go with his/her solution. I'm leaving this answer up, as there is still some useful information here.
Is there a more elegant way of defining it than declaring the parameter to be String and converting it myself? Like e.g. a class
javax.rs.BooleanFlag
or similar?
No such type (BooleanFlag
), If you look at the javadoc for @QueryParam, you'll see a list of options for how we can create a custom type to use a @QueryParam
value (for the most part the same holds true for other @XxxParam
s also)
- Have a constructor that accepts a single String argument
- Have a
static
method namedvalueOf
orfromString
that accepts a single String argument (see, for example,Integer.valueOf(String)
)- Have a registered implementation of
ParamConverterProvider
JAX-RS extension SPI that returns aParamConverter
instance capable of a "from string" conversion for the type.
So from the first option, in theory, you should be able to do something like
public class Flag {
private final boolean isPresent;
public Flag(String param) { isPresent = param != null; }
public boolean isPresent() { return isPresent; }
}
@GET
public String get(@QueryParam("bar") Flag bar) {
if (bar.isPresent()) {
return "bar is present";
} else {
return "bar is not present";
}
}
Now this works when the query flag is present. But when it's not, it acts like any other non-primitive type; it's null. So the call to bar.isPresent
give an NPE. Tested with a fromString
and valueOf
with the same result. We could check if (bar == null)
, but that's no better that just using a String and checking if the String is null. It's not pretty.
So the last option is the ParamConverterProvider
. Which does actually work. Below is the implementation.
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;
@Provider
public class FlagParamConverterProvider implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(
Class<T> rawType, Type genericType, Annotation[] annotations) {
if (rawType != Flag.class) {
return null;
}
return new ParamConverter<T>() {
@Override
public T fromString(String value) {
return (T)new Flag(value);
}
@Override
public String toString(T value) { return null; }
};
}
}
Just make sure the provider is registered. It's a pretty clean solution in my opinion.
You could try the following:
@GET
@Path("/some-path")
public Response myMethod(@Context HttpServletRequest request) {
boolean isParameterPresent = request.getParameterMap().contains("bar");
...
}
But the solutions shown in peeskillet's answer are the cleverest ways to achieve it.
I know it's an old question but I had the same trouble.
To solve my problem, I used the Annotation @DefaultValue :
@GET
@Path("/path")
public Response myMethod(@DefaultValue("true") @QueryParam("foo") boolean foo) {
if (foo) {
...
}
}
So, when the request contains the parameter foo
the boolean value will be false and if not it will be true. It shows the opposite of reality but if you're aware of it, it's quite simple to use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With