Java: Enum case insensitive Jersey Query Param Binding
If you're doing it right it shouldn't be a problem. For example in case 3, using a fromString
public static enum Color { RED, GREEN, BLUE; public static Color fromString(String param) { String toUpper = param.toUpperCase(); try { return valueOf(toUpper); } catch (Exception e) { // default behavior is to send 404 on error. // do something else if you want throw new WebApplicationException(400); } }}
Every enum already has a static valueOf
method which tries to match the enum value exactly, so we override this behavior by defining the fromString
. We first call toUpperCase()
then call valueOf
as it's looking for upper case. If anything fails, like a wrong enum value, we send a 400. You can send something else or stick with the normal 404. Up to you.
I already did this, it is not working
Here is a complete test case.
import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.QueryParam;import javax.ws.rs.WebApplicationException;import javax.ws.rs.core.Response;import org.glassfish.jersey.server.ResourceConfig;import org.glassfish.jersey.test.JerseyTest;import static org.junit.Assert.assertEquals;import org.junit.Test;public class EnumTest extends JerseyTest { public static enum Color { RED, GREEN, BLUE; public static Color fromString(String param) { String toUpper = param.toUpperCase(); try { return valueOf(toUpper); } catch (Exception e) { // default behavior is to send 404 on error. // do something else if you want throw new WebApplicationException(400); } } } @Path("enum") public static class ColorResource { @GET public String color(@QueryParam("color") Color color) { return color.toString(); } } @Override public ResourceConfig configure() { return new ResourceConfig(ColorResource.class); } @Test public void doit() { Response response = target("enum").queryParam("color", "blue").request().get(); assertEquals(200, response.getStatus()); assertEquals("BLUE", response.readEntity(String.class)); response.close(); response = target("enum").queryParam("color", "gReEn").request().get(); assertEquals(200, response.getStatus()); assertEquals("GREEN", response.readEntity(String.class)); response.close(); response = target("enum").queryParam("color", "RED").request().get(); assertEquals(200, response.getStatus()); assertEquals("RED", response.readEntity(String.class)); response.close(); response = target("enum").queryParam("color", "orange").request().get(); assertEquals(400, response.getStatus()); response.close(); }}
Use this dependency
<dependency> <groupId>org.glassfish.jersey.test-framework.providers</groupId> <artifactId>jersey-test-framework-provider-grizzly2</artifactId> <version>2.19</version> <scope>test</scope></dependency>
UPDATE
Test using @BeanParam
import javax.ws.rs.BeanParam;import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.QueryParam;import javax.ws.rs.WebApplicationException;import javax.ws.rs.core.Response;import org.glassfish.jersey.server.ResourceConfig;import org.glassfish.jersey.test.JerseyTest;import static org.junit.Assert.assertEquals;import org.junit.Test;public class EnumTest extends JerseyTest { public static enum Color { RED, GREEN, BLUE; public static Color fromString(String param) { String toUpper = param.toUpperCase(); System.out.println("--- toUpper " + toUpper + "---"); try { return valueOf(toUpper); } catch (Exception e) { System.out.println(" --- ERROR ---"); // default behavior is to send 404 on error. // do something else if you want throw new WebApplicationException(400); } } } public static class FooQueryParam { @QueryParam("color") private Color color; public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } } @Path("enum") public static class ColorResource { @GET public String color(@BeanParam FooQueryParam foo) { return foo.getColor().toString(); } } @Override public ResourceConfig configure() { return new ResourceConfig(ColorResource.class); } @Test public void doit() { Response response = target("enum").queryParam("color", "blue").request().get(); assertEquals(200, response.getStatus()); assertEquals("BLUE", response.readEntity(String.class)); response.close(); response = target("enum").queryParam("color", "gReEn").request().get(); assertEquals(200, response.getStatus()); assertEquals("GREEN", response.readEntity(String.class)); response.close(); response = target("enum").queryParam("color", "RED").request().get(); assertEquals(200, response.getStatus()); assertEquals("RED", response.readEntity(String.class)); response.close(); response = target("enum").queryParam("color", "orange").request().get(); assertEquals(400, response.getStatus()); response.close(); }}
The only thing that fails is the error case where I am sending a bad color. It seems with @BeanParam
the behavior is different. Instead of the expected 400, there is a 500. The other case sentiviity issues are fine