Reputation: 13081
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.
Upvotes: 6
Views: 3996
Reputation: 4041
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.
Upvotes: 3