I've got a function like:
@POST
@Path("/create")
@Produces({MediaType.APPLICATION_JSON})
public Playlist createPlaylist(@FormParam("name") String name)
{
Playlist p = playlistDao.create();
p.setName(name);
playlistDao.insert(p);
return p;
}
I want the "name" parameter to come from the form OR from the query parameter. If the user posts to /playlist/create/?name=bob then I want it to work. (This is mostly to aid with testing the API, but also for consuming it on different non-browser platforms.)
I'd be willing to subclass whatever makes the magic binding work... (@BothParam("name") String name) but would need some help to make that happen as I'm new to Jersey/Java Servlets.
Update: The next day...
I've solved this by implementing a ContainerRequestFilter that merges the form parameters into the query parameters. This isn't the best solution, but it does seem to work. I didn't have any luck merging anything into the form parameters.
Here's the code in case someone comes looking for it:
@Override
public ContainerRequest filter(ContainerRequest request)
{
MultivaluedMap<String, String> qParams = request.getQueryParameters();
Form fParams = request.getFormParameters();
for(String key : fParams.keySet())
{
String value = fParams.get(key).get(0);
qParams.add(key, value);
}
}
I would still appreciate knowing if there is a better way to do this so I'll leave this question open for now.
One way you could do this is with an InjectableProvider
.
First, you'd define a BothParam
annotation:
@Target({ ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface BothParam { String value(); }
Then, define an InjectableProvider
for it:
@Provider
public class BothParamProvider implements Injectable<String>, InjectableProvider<BothParam, Type> {
@Context private HttpContext httpContext;
private String parameterName;
public BothParamProvider(@Context HttpContext httpContext) {
this.httpContext = httpContext;
}
public String getValue() {
if (httpContext.getRequest().getQueryParameters().containsKey(parameterName)) {
return httpContext.getRequest().getQueryParameters().getFirst(parameterName);
} else if(httpContext.getRequest().getFormParameters().containsKey(parameterName)) {
return httpContext.getRequest().getFormParameters().getFirst(parameterName);
}
return null;
}
public ComponentScope getScope() {
return ComponentScope.PerRequest;
}
public Injectable getInjectable(ComponentContext cc, BothParam a, Type c) {
parameterName = a.value();
return this;
}
}
Note, this is not truly a coupling of QueryParam
and FormParam
. Targets annotated with either of those are injected in a much more sophisticated manner. However, if your needs are sufficiently limited, the method outlined above might work for you.
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