He estado en esto por horas, pero parece que no puede desenredar esto. Los pertenece error a este segmento de código:
(Código completo en la parte inferior de esta cuestión. Estoy usando capturas de pantalla para mostrar visualmente el tema.)
El error en sí mismo es:
no hay instancia (s) de variable de tipo (s) U existir para que se ajuste a GetUsersForAdAccountResponse CompletionStage
Al principio de la cadena de thenCompose
s, borré el return
y se utiliza IntelliJ de "Introducir variable local ..." función para ver qué tipo de toda la cadena (hasta e incluyendo la línea 1118) regresa:
El resultado fue una
final CompletionStage<U> uCompletionStage = ...
Sin embargo, se puede ver que el tipo de retorno del método es que abarca
public CompletionStage<GetUsersForAdAccountResponse> ...
¿Qué impide que el compilador inferir GetUsersForAdAccountResponse
? (De nuevo, normalmente hay una return
aquí.)
También he intentado introducir una variable local en cada thenCompose
a lo largo del camino, y todos ellos parecen correctos. Cada uno produce una CompletionStage<Foo>
, para las que los próximos thenCompose
suministros lambda esperando Foo
y produce una CompletionStage<Bar>
, y así sucesivamente. (En una reorganización del código vi un anidado CompletionStage<CompletionStage<Foo>>
pero creo que era un artefacto de mi propia reescritura.)
No sé si ayudará, pero aquí es todo el método:
@Override
public CompletionStage<GetUsersForAdAccountResponse> getUsersForAdAccount(
RequestContext context, GetUsersForAdAccountRequest request) {
Uuid adAccountId = request.getAdAccountId();
return verifyAuthorization(context,
PortcullisTemplates.Action.GET_USERS_FOR_AD_ACCOUNT.getName(),
portcullisTemplates.topOrganizationResource())
.thenCompose(auditLogPrincipal -> jdbiExecutor.executeInTransaction(handler -> {
// We purposely safeguard the account lookup as well behind Portcullis.
AdAccountDao adAccountDao = handler.attach(AdAccountDao.class);
if (adAccountDao.getAdAccountById(adAccountId) == null) {
throw new ValidationException(SERVICE_NAME,
"Ad account not found: " + UuidUtils.toString(adAccountId));
}
AdAccountRoleUserMappingDao roleDao = handler.attach(AdAccountRoleUserMappingDao.class);
List<String> roleNames = request.getRoleNamesList();
return roleNames.isEmpty() ?
roleDao.getAdAccountRoleUserMappingsByAdAccount(adAccountId) :
roleDao.getAdAccountRoleUserMappingsByAdAccountAndRoles(adAccountId, roleNames);
})).thenCompose(adAccountRoleUserMappings -> jdbiExecutor.execute(UserDao.class, userDao -> {
return userDao
.getUsersBy]UserIds(
adAccountRoleUserMappings.stream()
.map(AdAccountRoleUserMapping::userId)
.collect(Collectors.toList())
).stream()
.collect(Collectors.toMap(
User::userId,
user -> new EncryptedFieldsBuilder()
.firstName(user.encryptedFirstName())
.lastName(user.encryptedLastName())
.email(user.encryptedEmail())
.build()
));
}).thenCompose(
userEncryptedFields -> padlockService.decryptUserAccounts(userEncryptedFields)
).thenCompose(decryptedUsers -> GetUsersForAdAccountResponse.newBuilder()
.addAllUserWithRole(
adAccountRoleUserMappings.stream()
.filter(mapping -> decryptedUsers.containsKey(mapping.userId()))
.map(mapping -> UserWithRole.newBuilder()
.setAccount(decryptedUsers.get(mapping.userId()))
.setRoleName(mapping.roleName())
.build())
.collect(Collectors.toSet())
).build()
));
}
El último thenCompose
en la cadena debe ser thenApply
. La función que se le pasa está volviendo una GetUsersForAdAccountResponse
que no es CompletionStage
.
thenCompose
es la flatMap
de CompletableFuture
. Se necesita una función que devuelve una CompletionStage
y aplana el resultado.