问题
I tried to override/implement all the attribute in JSR311 but the Jersey binding seems case sensitive:
- Be a primitive type
- Have a constructor that accepts a single String argument
- Have a static method named valueOf or fromString that accepts a single String argument (see, for example, Integer.valueOf(String))
- Be List, Set or SortedSet, where T satisfies 2 or 3 above. The resulting collection is read-only.
How can I make Jersey binding for enum case insensitive?
EDIT:
Here's the code:
The enum:
public enum Color {
GREEN,
BLUE;
public Color fromString(String param) {
String toUpper = param.toUpperCase();
try {
return valueOf(toUpper);
} catch (Exception e) {
return null;
}
}
}
Bean Param:
public class FooQueryParam {
@QueryParam(value = "color")
private Color color;
public Color getColor() {
return color;
}
public void setStatus(Color Color) {
this.color = color;
}
}
The resource:
public Response get(@BeanParam FooQueryParam fooQueryParam) {
//...
}
回答1:
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
来源:https://stackoverflow.com/questions/33357594/java-enum-case-insensitive-jersey-query-param-binding