User Root Resource: Use CDI Provider for subresources.

Resources are request scoped and we need only one sub resource per
request. That is, injecting all subresources (and their transitive
inejctions)in the constructor builds a lot of objects that are never
used.

Solution: Inject provider, that lazily inject the needed subresources
on demand.
This commit is contained in:
Johannes Schnatterer
2018-06-21 11:54:54 +02:00
parent 0df7156da0
commit ab290a78d9
3 changed files with 33 additions and 10 deletions

View File

@@ -2,28 +2,30 @@ package sonia.scm.api.v2.resources;
import com.google.inject.Inject; import com.google.inject.Inject;
import javax.inject.Provider;
import javax.ws.rs.Path; import javax.ws.rs.Path;
@Path(UserRootResource.USERS_PATH_V2) @Path(UserRootResource.USERS_PATH_V2)
public class UserRootResource { public class UserRootResource {
public static final String USERS_PATH_V2 = "v2/users/"; public static final String USERS_PATH_V2 = "v2/users/";
private final UserCollectionResource userCollectionResource; private final Provider<UserCollectionResource> userCollectionResource;
private final UserResource userResource; private final Provider<UserResource> userResource;
@Inject @Inject
public UserRootResource(UserCollectionResource userCollectionResource, UserResource userResource) { public UserRootResource(Provider<UserCollectionResource> userCollectionResource,
Provider<UserResource> userResource) {
this.userCollectionResource = userCollectionResource; this.userCollectionResource = userCollectionResource;
this.userResource = userResource; this.userResource = userResource;
} }
@Path("") @Path("")
public UserCollectionResource getUserCollectionResource() { public UserCollectionResource getUserCollectionResource() {
return userCollectionResource; return userCollectionResource.get();
} }
@Path("{id}") @Path("{id}")
public UserResource getUserResource() { public UserResource getUserResource() {
return userResource; return userResource.get();
} }
} }

View File

@@ -0,0 +1,22 @@
package sonia.scm.api.v2.resources;
import javax.inject.Provider;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* A mockito implementation of CDI {@link javax.inject.Provider}.
*/
class MockProvider {
private MockProvider() {}
static <I> Provider<I> of(I instance) {
@SuppressWarnings("unchecked") // Can't make mockito return typed provider
Provider<I> provider = mock(Provider.class);
when(provider.get()).thenReturn(instance);
return provider;
}
}

View File

@@ -64,8 +64,6 @@ public class UserRootResourceTest {
@InjectMocks @InjectMocks
private UserToUserDtoMapperImpl userToDtoMapper; private UserToUserDtoMapperImpl userToDtoMapper;
private UserCollectionToDtoMapper userCollectionToDtoMapper;
private ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class); private ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);
@Before @Before
@@ -76,10 +74,11 @@ public class UserRootResourceTest {
when(userManager.get("Neo")).thenReturn(dummyUser); when(userManager.get("Neo")).thenReturn(dummyUser);
doNothing().when(userManager).create(userCaptor.capture()); doNothing().when(userManager).create(userCaptor.capture());
userCollectionToDtoMapper = new UserCollectionToDtoMapper(userToDtoMapper, uriInfoStore); UserCollectionToDtoMapper userCollectionToDtoMapper = new UserCollectionToDtoMapper(userToDtoMapper, uriInfoStore);
UserCollectionResource userCollectionResource = new UserCollectionResource(userManager, dtoToUserMapper, userToDtoMapper, userCollectionToDtoMapper); UserCollectionResource userCollectionResource = new UserCollectionResource(userManager, dtoToUserMapper, userToDtoMapper,
userCollectionToDtoMapper);
UserResource userResource = new UserResource(dtoToUserMapper, userToDtoMapper, userManager); UserResource userResource = new UserResource(dtoToUserMapper, userToDtoMapper, userManager);
UserRootResource userRootResource = new UserRootResource(userCollectionResource, userResource); UserRootResource userRootResource = new UserRootResource(MockProvider.of(userCollectionResource), MockProvider.of(userResource));
dispatcher.getRegistry().addSingletonResource(userRootResource); dispatcher.getRegistry().addSingletonResource(userRootResource);
when(uriInfo.getBaseUri()).thenReturn(URI.create("/")); when(uriInfo.getBaseUri()).thenReturn(URI.create("/"));