问题
I have a problem with Jersey 2.26 and Spring Boot 2.
I added a factory to inject @Context
variable into methods, but it does it twice, first before the method and then again after the method:
@GET
@Path("/user-entitlements")
public Set<String> getUserEntitlements(@Context User user) {
return service.getUserEntitlements(user);
}
I have a factory that creates those users:
public class UserFactory implements Factory<User> {
private final User user;
@Inject
public UserFactory(HttpServletRequest request, RequestIdentityService requestIdentityService) {
String userName = requestIdentityService.getCurrentUser(request);
user = new User(userName);
}
@Override
public User provide() {
return user;
}
@Override
public void dispose(User instance) {
}
}
And in jersey configuration I register this factory:
register(
new AbstractBinder() {
@Override
public void configure() {
bindFactory(UserFactory.class)
.to(User.class)
.in(RequestScoped.class);
}
}
);
It worked fine previously, but after I upgraded the application to jersey 2.26 and spring boot 2, it stopped working and throws exception:
java.lang.IllegalStateException: Proxiable context org.glassfish.jersey.inject.hk2.RequestContext@3a94c454 findOrCreate returned a null for descriptor SystemDescriptor(
implementation=org.glassfish.jersey.inject.hk2.SupplierFactoryBridge
contracts={javax.servlet.http.HttpServletRequest}
scope=org.glassfish.jersey.process.internal.RequestScoped
qualifiers={}
descriptorType=PROVIDE_METHOD
descriptorVisibility=NORMAL
metadata=
rank=0
loader=org.glassfish.hk2.utilities.binding.AbstractBinder$2@464366a8
proxiable=true
proxyForSameScope=false
analysisName=null
id=20
locatorId=0
identityHashCode=1360647282
reified=true) and handle ServiceHandle(SystemDescriptor(
implementation=com.rest.UserFactory
contracts={org.glassfish.hk2.api.Factory}
scope=org.glassfish.hk2.api.PerLookup
qualifiers={}
descriptorType=CLASS
descriptorVisibility=NORMAL
metadata=
rank=0
loader=org.glassfish.hk2.utilities.binding.AbstractBinder$2@33335025
proxiable=null
proxyForSameScope=null
analysisName=null
id=172
locatorId=0
identityHashCode=790201459
reified=true),1915928862)
The exception shows up because UserFactory is called twice. First it is called before the getUserEntitlements is called, to inject the User. But after the method returns, it is called again (and this time it gets a HttpRequest implementation that doesn't allow some operations).
Why it could be called twice? As if I would asked it to enchance both the request and response.
回答1:
The problem is that in new Jersey they moved away from hk2 into an abstraction layer above it, and made the code Java 8 aware (because it is an implementation of Java EE 8 - https://jersey.github.io/release-notes/2.26.html).
So to fix it I had to:
Import the correct
AbstractBinder
-org.glassfish.jersey.internal.inject.AbstractBinder
(NOT the previous one from HK2 -org.glassfish.hk2.utilities.binding.AbstractBinder
).Update the factory to implement
Supplier<User>
instead ofFactory<User>
.
After that changes everything works as previously, factory is called only once.
来源:https://stackoverflow.com/questions/49454101/jersey-factory-tries-to-create-context-variable-twice