Search in sources :

Example 1 with TransactionContext

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);
    }
}
Also used : DefaultResultModel(eu.bcvsolutions.idm.core.api.dto.DefaultResultModel) ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) DefaultResultModel(eu.bcvsolutions.idm.core.api.dto.DefaultResultModel) ResultModel(eu.bcvsolutions.idm.core.api.dto.ResultModel) EventContentDeletedException(eu.bcvsolutions.idm.core.api.exception.EventContentDeletedException) ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) CoreEvent(eu.bcvsolutions.idm.core.api.event.CoreEvent) TransactionContext(eu.bcvsolutions.idm.core.api.domain.TransactionContext) IdmJwtAuthentication(eu.bcvsolutions.idm.core.security.api.domain.IdmJwtAuthentication) UUID(java.util.UUID) IdmIdentityDto(eu.bcvsolutions.idm.core.api.dto.IdmIdentityDto) ExceptionProcessable(eu.bcvsolutions.idm.core.security.api.service.ExceptionProcessable) OperationState(eu.bcvsolutions.idm.core.api.domain.OperationState) Transactional(org.springframework.transaction.annotation.Transactional)

Example 2 with TransactionContext

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);
        }
    }
}
Also used : TransactionContext(eu.bcvsolutions.idm.core.api.domain.TransactionContext)

Example 3 with TransactionContext

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;
}
Also used : IdmLongRunningTaskDto(eu.bcvsolutions.idm.core.scheduler.api.dto.IdmLongRunningTaskDto) TransactionContext(eu.bcvsolutions.idm.core.api.domain.TransactionContext)

Example 4 with TransactionContext

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);
}
Also used : TransactionContext(eu.bcvsolutions.idm.core.api.domain.TransactionContext)

Aggregations

TransactionContext (eu.bcvsolutions.idm.core.api.domain.TransactionContext)4 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)1 OperationState (eu.bcvsolutions.idm.core.api.domain.OperationState)1 DefaultResultModel (eu.bcvsolutions.idm.core.api.dto.DefaultResultModel)1 IdmIdentityDto (eu.bcvsolutions.idm.core.api.dto.IdmIdentityDto)1 ResultModel (eu.bcvsolutions.idm.core.api.dto.ResultModel)1 CoreEvent (eu.bcvsolutions.idm.core.api.event.CoreEvent)1 EventContentDeletedException (eu.bcvsolutions.idm.core.api.exception.EventContentDeletedException)1 ResultCodeException (eu.bcvsolutions.idm.core.api.exception.ResultCodeException)1 IdmLongRunningTaskDto (eu.bcvsolutions.idm.core.scheduler.api.dto.IdmLongRunningTaskDto)1 IdmJwtAuthentication (eu.bcvsolutions.idm.core.security.api.domain.IdmJwtAuthentication)1 ExceptionProcessable (eu.bcvsolutions.idm.core.security.api.service.ExceptionProcessable)1 UUID (java.util.UUID)1 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)1 Transactional (org.springframework.transaction.annotation.Transactional)1