google / google/guice

Non-exposed RequestScoped objects leak out of private modules

Open
#1,450 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
12.7k
Forks
1.7k
Avg merge
11m
Merged PRs (30d)
2

Description

As I understand, non-exposed objects should not be injectable outside of a private module. However, it looks like RequestScoped objects leak out of private modules.

The example below explains the issue. Given two PrivateModules where each provides a service and an object of shared type `SomeObject`. The service is exposed, `SomeObject` is not. All provided objects are RequestScoped.
I would assume that each service is provided with the "local" instance of `SomeObject`.

```
public class Module1 extends PrivateModule {

@Provides
@RequestScoped
public SomeObject provideSomeObject () {
return new SomeObject("Provided by Module1");
}

@Provides
@Exposed
@RequestScoped
public Module1Service provideService (SomeObject someObject) {
return new Module1Service(someObject);
}

@Override
protected void configure () {
// empty
}

@Data
public static final class Module1Service {
private final SomeObject object;
}

}
```
```
public class Module2 extends PrivateModule {

@Provides
@RequestScoped
public SomeObject provideSomeObject () {
return new SomeObject("Provided by Module2");
}

@Provides
@Exposed
@RequestScoped
public Module2Service provideService (SomeObject someObject) {
return new Module2Service(someObject);
}

@Override
protected void configure () {
// empty
}

@Data
public static final class Module2Service {
private final SomeObject object;
}

}
```
```
@Data
public final class SomeObject {

private final String info;

}
```

As a test, both services are being injected into a consumer that retrieves the `SomeObject` from the services:
```
// module1Service and module2Service have been injected
System.out.println("Module1Service -> " + module1Service.getObject().getInfo());
System.out.println("Module2Service -> " + module2Service.getObject().getInfo());
```
Surprisingly, this returns:
```
Module1Service -> Provided by Module1
Module2Service -> Provided by Module1
```
whereas I expected:
```
Module1Service -> Provided by Module1
Module2Service -> Provided by Module2
```

This means that non-exposed objects of a private module get injected into other (private) modules which should not be possible.
Tested with Guice 4.2.3.
I assume that other scopes besides RequestScope (probably SessionScoped) might also be affected.
A potential explanation could be that RequestScoped objects are stored in the request attributes without the context of their module. But that's just guesswork - I'm not that familiar with guice internals.

Please excuse me if this is already known. I could not find any related issues. Thanks for looking into this.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.