use of eu.bcvsolutions.idm.core.api.domain.TransactionContext in project CzechIdMng by bcvsolutions.
the class DefaultEntityEventManager method executeEvent.
@Override
@Transactional
public void executeEvent(IdmEntityEventDto event) {
Assert.notNull(event, "Event is reqired to be event executed.");
Assert.notNull(event.getOwnerId(), "Event owner identifier is reqired to be event executed.");
if (!eventConfiguration.isAsynchronous()) {
// synchronous processing
// we don't persist events and their states
process(new CoreEvent<>(EntityEventType.EXECUTE, event));
return;
}
if (event.getPriority() == PriorityType.IMMEDIATE) {
// synchronous processing
// we don't persist events and their states
// TODO: what about running event with the same owner? And events in queue for the same owner => no locking now, last wins
process(new CoreEvent<>(EntityEventType.EXECUTE, event));
return;
}
//
if (runningOwnerEvents.putIfAbsent(event.getOwnerId(), event.getId()) != null) {
LOG.debug("Previous event [{}] for owner with id [{}] is currently processed.", runningOwnerEvents.get(event.getOwnerId()), event.getOwnerId());
// event will be processed in another scheduling
return;
}
// check super owner is not processed
UUID superOwnerId = event.getSuperOwnerId();
if (superOwnerId != null && !superOwnerId.equals(event.getOwnerId())) {
if (runningOwnerEvents.putIfAbsent(superOwnerId, event.getId()) != null) {
LOG.debug("Previous event [{}] for super owner with id [{}] is currently processed.", runningOwnerEvents.get(superOwnerId), superOwnerId);
runningOwnerEvents.remove(event.getOwnerId());
// event will be processed in another scheduling
return;
}
}
// execute event in new thread asynchronously
try {
eventConfiguration.getExecutor().execute(new Runnable() {
@Override
@SuppressWarnings("unchecked")
public void run() {
// run as event creator
securityService.setAuthentication(new IdmJwtAuthentication(new IdmIdentityDto(event.getCreatorId(), event.getCreator()), new IdmIdentityDto(event.getOriginalCreatorId(), event.getOriginalCreator()), null, ZonedDateTime.now(), Lists.newArrayList(IdmAuthorityUtils.getAdminAuthority()), null));
// run under original transaction id - asynchronous processing continue the "user" transaction
TransactionContextHolder.setContext(new TransactionContext(event.getTransactionId()));
//
LOG.debug("Executing event under user [{}] (admin authorities) and transaction [{}]", securityService.getUsername(), TransactionContextHolder.getContext().getTransactionId());
//
try {
process(new CoreEvent<>(EntityEventType.EXECUTE, event));
} catch (Exception ex) {
// all processor should persist their own entity state (see AbstractEntityEventProcessor)
// event result is persisted here
OperationState resultState = OperationState.EXCEPTION;
ResultModel resultModel;
if (ex instanceof ResultCodeException) {
ResultCodeException resultCodeException = (ResultCodeException) ex;
resultModel = resultCodeException.getError().getError();
if (resultCodeException.getStatus() == HttpStatus.ACCEPTED) {
// => concrete information is preserved in model to know, what happen
resultState = OperationState.EXECUTED;
}
} else {
resultModel = new DefaultResultModel(CoreResultCode.EVENT_EXECUTE_FAILED, ImmutableMap.of("eventId", event.getId(), "eventType", String.valueOf(event.getEventType()), "ownerId", String.valueOf(event.getOwnerId()), "instanceId", String.valueOf(event.getInstanceId())));
}
saveResult(event.getId(), new OperationResultDto.Builder(resultState).setCause(ex).setModel(resultModel).build());
//
ExceptionUtils.log(LOG, resultModel, ex);
// We check if owner service supports this feature (implements ExceptionProcessable).
try {
Class<?> ownerClass = Class.forName(event.getOwnerType());
ReadDtoService<?, ?> dtoService = lookupService.getDtoService((Class<? extends Identifiable>) ownerClass);
if (dtoService instanceof ExceptionProcessable) {
ExceptionProcessable<?> exceptionProcessable = (ExceptionProcessable<?>) dtoService;
// Propagate the exception
exceptionProcessable.processException(event.getOwnerId(), ex);
}
} catch (ClassNotFoundException e) {
// Only to the log
LOG.error(e.getLocalizedMessage(), e);
}
} finally {
LOG.trace("Event [{}] ends for owner with id [{}].", event.getId(), event.getOwnerId());
removeRunningEvent(event);
}
}
});
//
LOG.trace("Running event [{}] for owner with id [{}].", event.getId(), event.getOwnerId());
} catch (RejectedExecutionException ex) {
// thread pool queue is full - wait for another try
removeRunningEvent(event);
}
}
use of eu.bcvsolutions.idm.core.api.domain.TransactionContext in project CzechIdMng by bcvsolutions.
the class DelegatingTransactionContextRunnable method run.
@Override
public void run() {
TransactionContext originalTransactionContext = TransactionContextHolder.getContext();
try {
TransactionContextHolder.setContext(delegateTransactionContext);
delegate.run();
} finally {
// TODO: Here is uses same logic as in original DelegatingSecurityContextRunnable
// class (restoring of original context), but this maybe cause problem with using same instance of context.
TransactionContext emptyContext = TransactionContextHolder.createEmptyContext();
if (emptyContext.equals(originalTransactionContext)) {
TransactionContextHolder.clearContext();
} else {
TransactionContextHolder.setContext(originalTransactionContext);
}
}
}
use of eu.bcvsolutions.idm.core.api.domain.TransactionContext in project CzechIdMng by bcvsolutions.
the class AbstractLongRunningTaskExecutor method start.
/**
* Starts given task
* - persists task properties
*
* @return
*/
protected boolean start() {
Assert.notNull(longRunningTaskId, "LRT has to be persisted before task starts.");
IdmLongRunningTaskDto task = longRunningTaskService.get(longRunningTaskId);
Map<String, Object> taskProperties = task.getTaskProperties();
//
// set user transaction context for current thread
TransactionContext context = (TransactionContext) taskProperties.get(LongRunningTaskExecutor.PARAMETER_TRANSACTION_CONTEXT);
if (context != null) {
TransactionContextHolder.setContext(context);
}
//
validate(task);
//
Thread currentThread = Thread.currentThread();
task.setThreadId(currentThread.getId());
task.setThreadName(currentThread.getName());
//
setStateProperties(task);
//
task.setRunning(true);
task.setTaskStarted(ZonedDateTime.now());
task.setResult(new OperationResult.Builder(OperationState.RUNNING).build());
task.setStateful(isStateful());
taskProperties.put(LongRunningTaskExecutor.PARAMETER_INSTANCE_ID, task.getInstanceId());
taskProperties.putAll(getProperties());
task.setTaskProperties(taskProperties);
task.setStateful(isStateful());
//
longRunningTaskService.save(task);
//
return true;
}
use of eu.bcvsolutions.idm.core.api.domain.TransactionContext in project CzechIdMng by bcvsolutions.
the class StartUserTransactionFilter method doFilterInternal.
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
TransactionContext context = TransactionContextHolder.createEmptyContext();
TransactionContextHolder.setContext(context);
//
LOG.trace("Starting new user transaction [{}]", context.getTransactionId());
//
chain.doFilter(request, response);
}
Aggregations