Not exactly. Here is what I've got:
https://bitbucket.org/cowwoc/pouch-jersey2/wiki/Home
MyRegistry is really HttpRequestScope and the reason I couldn't bind()
its factory in Application is that I had two entry points for looking up
a HttpRequestScope:
1. ServiceLocator.getService(), and
2. SingletonScope.getHttpRequest() -- The aforementioned Wiki page
doesn't contain this method but I will be adding it shortly.
In any case, the only way I could bind HttpRequestScope to a request
scope was with ServiceLocator (Jersey does not seem to expose any other
hooks). Initially I tried getting ServiceLocator.getService() to
delegate to SingletonScope.getHttpRequest() which would, in turn,
delegate back to ServiceLocator.getService() to look up a secondary
service but this led to problem (and thinking back on it now it was a
dumb approach).
In any case, I ended up solving it by having
SingletonScope.getHttpRequest() delegate to ServiceLocator.getService()
which delegates to SingletonScope.newHttpRequest(). I only figured out
recently how to hide the latter method from end-users.
So to recap: only SingletonScope knew how to construct an
HttpRequestScope but only ServiceLocator knew when a request
started/ended so I was stuck between a rock and a hard place. Thanks for
helping me thinking this through.
Gili
On 12/05/2014 11:16 PM, Robert DiFalco wrote:
> So you are saying if I create a simple test case like my code and
> change MyServiceRegistryImpl to be a class instead of an instance and
> then remove @Singleton from my resource that I will not get a new
> instance of MyRegistryImpl for each request?
>
> If so I can create a test case so I can reproduce this too.
>
>
> On Mon, May 12, 2014 at 6:53 PM, cowwoc <cowwoc_at_bbs.darktech.org
> <mailto:cowwoc_at_bbs.darktech.org>> wrote:
>
> Right, this is similar to what I'm doing, except I need it to be
> request scoped ;)
>
> Any ideas on why it's the latter is not working?
>
> Gili
>
>
> On 12/05/2014 9:04 PM, Robert DiFalco wrote:
>> I do this too I just do it a little differently, I do this in my
>> config:
>>
>> register(new AbstractBinder() {
>> @Override
>> protected void configure() {
>> bind(new
>> MyServiceRegistryImpl()).to(MyServiceRegistry.class);
>> }
>> });
>>
>> Then in my resource I just do this:
>>
>>
>> @Singleton
>> public class UserResource {
>>
>> private final UserService userService;
>>
>> @Inject
>> public UserResource(MyServiceRegistry registry) {
>> this.userService = registry.getService(UserService.class);
>> }
>>
>>
>>
>> There's not a lot of magic going on so it makes it super easy to
>> debug.
>>
>> R.
>>
>>
>>
>> On Mon, May 12, 2014 at 5:56 PM, cowwoc <cowwoc_at_bbs.darktech.org
>> <mailto:cowwoc_at_bbs.darktech.org>> wrote:
>>
>> Hi Robert,
>>
>> I am trying to integrate Jersey with a 3rd-party IoC
>> framework. I've got a class MyRegistry that holds
>> request-scoped values (e.g. a database connection) which I
>> don't want to bind to HK2 directly. Instead, I want to inject
>> MyRegistry into resources and use it to look up the
>> aforementioned values.
>>
>> I bound MyRegistry to ServiceLocator using:
>>
>> bindFactory(RequestFactory.class).to(MyRegistry.class).in(RequestScoped.class);
>>
>> where RequestFactory.provide() invokes something along the
>> lines of:
>>
>> MyRegistry result = serviceLocator.getService(MyRegistry.class);
>> if (registry==null)
>> {
>> MyRegistry result =new MyRegistry(serviceLocator);
>> ServiceLocatorUtilities.bind(serviceLocator,
>> new PerRequestBinder<>(MyRegistry.class,
>> result));
>> }
>>
>> and PerRequestBinder was a Binder that invoked:
>>
>> bindFactory(new
>> MyFactory()).to(MyRegistry.class).in(RequestScoped.class);
>>
>> and MyRegistry.provide() returned "result" passed into
>> PerRequestBinder.
>>
>> So to recap: I bound a preexisting Factory instance (not a
>> class) against a scope, and that factory returned a
>> preexisting instance (again, no construction is taking
>> place). What I was seeing is that most of the time
>> "serviceLocator.getService(MyRegistry.class)" worked fine,
>> but sometimes it would return a non-null value even though
>> the request had no constructed a MyRegistry instance before.
>> Further debugging revealed that the instance being returned
>> actually belonged to the previous HTTP request and was coming
>> from some sort of "cache" in ServiceLocatorImpl.
>>
>> Any ideas?
>>
>> Gili
>>
>>
>> On 12/05/2014 7:49 PM, Robert DiFalco wrote:
>>> What are you binding to? I mean isn't @RequestScoped meant
>>> for your resource? Meaning it will be re-instantiated for
>>> each request? It looks like you are trying to overload what
>>> it is used for in some way.
>>>
>>> Are you saying that you are @RequestScoped annotating your
>>> REST resource and that you sometimes see it not being
>>> instantiated for a request?
>>>
>>> Also, just wondering, what is the high level problem you are
>>> trying to solve? Maybe there is a better way of solving the
>>> problem that does not involve @RequestScoped.
>>>
>>>
>>>
>>> On Mon, May 12, 2014 at 4:41 PM, cowwoc
>>> <cowwoc_at_bbs.darktech.org <mailto:cowwoc_at_bbs.darktech.org>>
>>> wrote:
>>>
>>> Hi,
>>>
>>> How are we supposed to bind @RequestScoped variables in
>>> Jersey?
>>>
>>> 1. The scope @RequestScoped is listed in Jersey's
>>> "internal" package.
>>> 2. When I try to bindFactory().in(RequestScoped.class)
>>> I sometimes get stale values out of
>>> ServiceLocator.getService(). Meaning, the Factory
>>> binding is not getting removed at the end of the
>>> HTTP request.
>>> 3. Using ThreadLocal doesn't seem safe in light of the
>>> fact that threads could be reused across HTTP
>>> requests, and there doesn't seem to be a clean way
>>> to detect the end of a request.
>>>
>>>
>>> Any ideas?
>>>
>>> Thanks,
>>> Gili
>>>
>>>
>>
>>
>
>