Created
December 16, 2015 10:59
-
-
Save psamsotha/4db6a710b615d6c40504 to your computer and use it in GitHub Desktop.
Jerse bug: Request scoped object should fail on injection into @singleton unless it is proxiable.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javax.inject.Inject; | |
import javax.inject.Singleton; | |
import javax.ws.rs.GET; | |
import javax.ws.rs.Path; | |
import javax.ws.rs.QueryParam; | |
import javax.ws.rs.core.MultivaluedMap; | |
import javax.ws.rs.core.Response; | |
import org.glassfish.hk2.utilities.binding.AbstractBinder; | |
import org.glassfish.jersey.process.internal.RequestScoped; | |
import org.glassfish.jersey.server.ContainerRequest; | |
import org.glassfish.jersey.server.ResourceConfig; | |
import org.glassfish.jersey.server.internal.inject.AbstractContainerRequestValueFactory; | |
import org.glassfish.jersey.test.JerseyTest; | |
import org.junit.Test; | |
import static junit.framework.Assert.assertEquals; | |
/** | |
* Jersey bug. | |
* | |
* Request scoped object should fail on injection into {@code @Singleton}, but | |
* since the {@code @Singleton} is not created until the first request, the | |
* first request scope object gets injected on the first request and remains the | |
* same throughout the lifetime of the singleton. | |
* | |
* The only way to make it fail as expected is to register an instance of the | |
* singleton. This way during start up injection process, it will see the | |
* request scoped object can't be injected and signal a failure. | |
* | |
* The solution is to make the request scoped object proxiable, but this is | |
* probably not obvious to most. | |
*/ | |
public class ScopeInjectTest extends JerseyTest { | |
public static interface HeadersService { | |
String getHeader(String header); | |
} | |
public static class HeadersServiceImpl implements HeadersService { | |
private final MultivaluedMap<String, String> headers; | |
public HeadersServiceImpl(MultivaluedMap<String, String> headers) { | |
this.headers = headers; | |
} | |
@Override | |
public String getHeader(String header) { | |
return headers.getFirst(header); | |
} | |
} | |
public static class HeadersServiceFactory | |
extends AbstractContainerRequestValueFactory<HeadersService> { | |
@Override | |
public HeadersService provide() { | |
ContainerRequest request = getContainerRequest(); | |
return new HeadersServiceImpl(request.getHeaders()); | |
} | |
} | |
@Singleton | |
@Path("headers") | |
public static class HeadersResource { | |
@Inject | |
HeadersService service; | |
@GET | |
public String get(@QueryParam("header") String header) { | |
return service.getHeader(header); | |
} | |
} | |
@Override | |
public ResourceConfig configure() { | |
return new ResourceConfig(HeadersResource.class) | |
.register(new AbstractBinder() { | |
@Override | |
protected void configure() { | |
bindFactory(HeadersServiceFactory.class) | |
//.proxy(true) | |
//.proxyForSameScope(false) | |
.to(HeadersService.class) | |
.in(RequestScoped.class); | |
} | |
}); | |
} | |
private static final String HEADER = "X-Header"; | |
private static final String HEADER_1_VALUE = "value1"; | |
private static final String HEADER_2_VALUE = "value2"; | |
@Test | |
public void headers_should_be_different() { | |
Response response = target("headers").queryParam("header", HEADER) | |
.request().header(HEADER, HEADER_1_VALUE).get(); | |
String message = response.readEntity(String.class); | |
assertEquals(HEADER_1_VALUE, message); | |
response.close(); | |
response = target("headers").queryParam("header", HEADER) | |
.request().header(HEADER, HEADER_2_VALUE).get(); | |
message = response.readEntity(String.class); | |
assertEquals(HEADER_2_VALUE, message); | |
response.close(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment