use of eu.bcvsolutions.idm.core.config.DelegatingTransactionContextRunnable in project CzechIdMng by bcvsolutions.
the class DefaultProvisioningExecutor method executeInternal.
/**
* We need to wait to transaction commit, when provisioning is executed - all accounts have to be prepared.
* Next processing is executed outside a transaction
* => operation states has to be saved in new transactions
* => rollback on the target system is not possible anyway
*
* @param provisioningOperation
* @return
*/
@TransactionalEventListener
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public SysProvisioningOperationDto executeInternal(SysProvisioningOperationDto provisioningOperation) {
Assert.notNull(provisioningOperation, "Provisioning operation is required.");
Assert.notNull(provisioningOperation.getSystemEntity(), "System entity is required.");
Assert.notNull(provisioningOperation.getProvisioningContext(), "Provisioning context is required.");
//
try {
boolean checkNotExecuted = provisioningOperation.isSynchronousProvisioning();
if (provisioningOperationService.isNew(provisioningOperation)) {
provisioningOperation = persistOperation(provisioningOperation);
checkNotExecuted = true;
}
if (checkNotExecuted && provisioningOperation.getResult() != null && OperationState.NOT_EXECUTED == provisioningOperation.getResult().getState()) {
return provisioningOperation;
}
//
CoreEvent<SysProvisioningOperationDto> event = new CoreEvent<SysProvisioningOperationDto>(provisioningOperation.getOperationType(), provisioningOperation);
try {
// set a global provisioning timeout even for synchronous call
FutureTask<EventContext<SysProvisioningOperationDto>> futureTask = new FutureTask<EventContext<SysProvisioningOperationDto>>(new Callable<EventContext<SysProvisioningOperationDto>>() {
@Override
public EventContext<SysProvisioningOperationDto> call() {
return entityEventManager.process(event);
}
});
// thread pool is not used here
Thread thread = new Thread(new DelegatingSecurityContextRunnable(new DelegatingTransactionContextRunnable(futureTask)));
thread.start();
//
// global timeout by configuration
long timeout = provisioningConfiguration.getTimeout();
try {
// TODO: non blocking wait if possible (refactoring is needed + java 9 helps)
EventContext<SysProvisioningOperationDto> context = futureTask.get(timeout, TimeUnit.MILLISECONDS);
//
return context.getContent();
} catch (InterruptedException ex) {
futureTask.cancel(true);
// propagate exception to upper catch
throw ex;
} catch (TimeoutException ex) {
futureTask.cancel(true);
// put thread into queue and wait => timeout too => retry mecchanism will work
throw new ResultCodeException(AccResultCode.PROVISIONING_TIMEOUT, ImmutableMap.of("name", provisioningOperation.getSystemEntityUid(), "system", provisioningOperation.getSystem(), "operationType", provisioningOperation.getOperationType(), "objectClass", provisioningOperation.getProvisioningContext().getConnectorObject().getObjectClass(), "timeout", String.valueOf(timeout)), ex);
}
} catch (Exception ex) {
return provisioningOperationService.handleFailed(provisioningOperation, ex);
} finally {
try {
UUID roleRequestId = provisioningOperation.getRoleRequestId();
if (roleRequestId != null) {
// Check of the state for whole request
// Create mock request -> we don't wont load request from DB -> optimization
IdmRoleRequestDto mockRequest = new IdmRoleRequestDto();
mockRequest.setId(roleRequestId);
mockRequest.setState(RoleRequestState.EXECUTED);
IdmRoleRequestDto returnedReqeust = roleRequestService.refreshSystemState(mockRequest);
OperationResultDto systemState = returnedReqeust.getSystemState();
if (systemState == null) {
// State on system of request was not changed (may be not all provisioning operations are
// resolved)
} else {
// We have final state on systems
IdmRoleRequestDto requestDto = roleRequestService.get(roleRequestId);
if (requestDto != null) {
requestDto.setSystemState(systemState);
roleRequestService.save(requestDto);
} else {
LOG.info(MessageFormat.format("Refresh role-request system state: Role-request with ID [{0}] was not found (maybe was deleted).", roleRequestId));
}
}
}
} catch (Exception ex) {
return provisioningOperationService.handleFailed(provisioningOperation, ex);
}
}
} finally {
UUID eventId = provisioningOperation.getManualEventId();
if (eventId != null) {
IdmEntityEventDto startEvent = entityEventManager.getEvent(eventId);
if (startEvent != null) {
// Complete a manual event (for ensure end of the sync).
entityEventManager.completeManualEvent(startEvent);
}
}
}
}
Aggregations