Search in sources :

Example 21 with CoreEvent

use of eu.bcvsolutions.idm.core.api.event.CoreEvent in project CzechIdMng by bcvsolutions.

the class DefaultEntityEventManagerIntergationTest method testBaseDtoProcessing.

@Test
public void testBaseDtoProcessing() {
    MockDto mockDto = new MockDto();
    ObserveDtoProcessor.listenContent(mockDto.getId());
    CoreEvent<BaseDto> event = new CoreEvent<BaseDto>(CoreEventType.NOTIFY, mockDto);
    EventContext<BaseDto> processed = manager.process(event);
    Assert.assertNotNull(processed.getLastResult());
    Boolean observed = (Boolean) processed.getLastResult().getEvent().getProperties().get(ObserveDtoProcessor.PROPERTY_OBSERVED);
    // 
    Assert.assertNotNull(observed);
    Assert.assertTrue(observed);
}
Also used : CoreEvent(eu.bcvsolutions.idm.core.api.event.CoreEvent) BaseDto(eu.bcvsolutions.idm.core.api.dto.BaseDto) MockDto(eu.bcvsolutions.idm.core.event.domain.MockDto) AbstractIntegrationTest(eu.bcvsolutions.idm.test.api.AbstractIntegrationTest) Test(org.junit.Test)

Example 22 with CoreEvent

use of eu.bcvsolutions.idm.core.api.event.CoreEvent in project CzechIdMng by bcvsolutions.

the class DefaultFormService method saveFormInstance.

/**
 * {@inheritDoc}
 *
 * Only given form attributes by the given values will be saved. Other attributes will be left untouched.
 *
 * TODO: validations by given form definition? I don't think, it will not be
 * useful in synchronization etc. - only FE validations will be enough ...
 */
@Override
@Transactional
public IdmFormInstanceDto saveFormInstance(Identifiable owner, IdmFormDefinitionDto formDefinition, List<IdmFormValueDto> newValues, boolean validate, BasePermission... permission) {
    FormableEntity ownerEntity = getOwnerEntity(owner);
    Assert.notNull(ownerEntity, "Form values owner is required.");
    formDefinition = checkDefaultDefinition(ownerEntity.getClass(), formDefinition);
    IdmFormInstanceDto formInstance = new IdmFormInstanceDto(ownerEntity, formDefinition, newValues);
    // 
    CoreEvent<IdmFormInstanceDto> event = new CoreEvent<>(CoreEventType.UPDATE, formInstance);
    // check permissions - check access to filled form values
    event.setPermission(permission);
    // Skip of validation.
    event.getProperties().put(SKIP_EAV_VALIDATION, !validate);
    // publish event for save form instance - see {@link #saveFormInstance(EntityEvent<IdmFormInstanceDto>)}
    return entityEventManager.process(event).getContent();
}
Also used : IdmFormInstanceDto(eu.bcvsolutions.idm.core.eav.api.dto.IdmFormInstanceDto) CoreEvent(eu.bcvsolutions.idm.core.api.event.CoreEvent) FormableEntity(eu.bcvsolutions.idm.core.eav.api.entity.FormableEntity) Transactional(org.springframework.transaction.annotation.Transactional)

Example 23 with CoreEvent

use of eu.bcvsolutions.idm.core.api.event.CoreEvent in project CzechIdMng by bcvsolutions.

the class IdmFormDefinitionController method saveFormValues.

/**
 * Saves owner's form values.
 *
 * @param owner
 * @param formDefinition
 * @param formValues
 * @param permission base permissions to evaluate (AND)
 * @return
 * @throws ForbiddenEntityException if authorization policies doesn't met
 */
public Resource<?> saveFormValues(Identifiable owner, IdmFormDefinitionDto formDefinition, List<IdmFormValueDto> formValues, BasePermission... permission) {
    formDefinition = getDefinition(owner.getClass(), formDefinition);
    // construct form instance with given values
    IdmFormInstanceDto formInstance = new IdmFormInstanceDto(owner, formDefinition, formValues);
    // prepare event envelope
    CoreEvent<IdmFormInstanceDto> event = new CoreEvent<>(CoreEventType.UPDATE, formInstance);
    // FE - high event priority
    event.setPriority(PriorityType.HIGH);
    // publish event for save form instance
    return new Resource<>(formService.publish(event, permission).getContent());
}
Also used : IdmFormInstanceDto(eu.bcvsolutions.idm.core.eav.api.dto.IdmFormInstanceDto) CoreEvent(eu.bcvsolutions.idm.core.api.event.CoreEvent) InputStreamResource(org.springframework.core.io.InputStreamResource) Resource(org.springframework.hateoas.Resource)

Example 24 with CoreEvent

use of eu.bcvsolutions.idm.core.api.event.CoreEvent in project CzechIdMng by bcvsolutions.

the class DefaultEntityEventManager method process.

@Override
@Transactional
@SuppressWarnings("unchecked")
public <E extends Serializable> EventContext<E> process(EntityEvent<E> event, EntityEvent<?> parentEvent) {
    Assert.notNull(event, "Event is required for processing.");
    Serializable content = event.getContent();
    // 
    LOG.info("Publishing event [{}]", event);
    // 
    // continue suspended event
    event.getContext().setSuspended(false);
    // 
    if (parentEvent != null) {
        event.setParentId(parentEvent.getId());
        event.setRootId(parentEvent.getRootId() == null ? parentEvent.getId() : parentEvent.getRootId());
        if (parentEvent.getPriority() != null && (event.getPriority() == null || event.getPriority().getPriority() < parentEvent.getPriority().getPriority())) {
            // parent has higher priority ... execute with the same priority as parent
            event.setPriority(parentEvent.getPriority());
        }
        // parent event type can be preset manually
        if (StringUtils.isEmpty(event.getParentType())) {
            event.setParentType(parentEvent.getType().name());
        }
        // propagate properties from parent to child event.
        // properties need for internal event processing are ignored (see {@link EntityEvent} properties)
        propagateProperties(event, parentEvent);
    }
    // read previous (original) dto source - usable in "check modification" processors
    if (event.getOriginalSource() == null && (content instanceof AbstractDto)) {
        // original source could be set externally
        AbstractDto contentDto = (AbstractDto) content;
        // works only for dto modification
        if (contentDto.getId() != null && lookupService.getDtoLookup(contentDto.getClass()) != null) {
            event.setOriginalSource((E) lookupService.lookupDto(contentDto.getClass(), contentDto.getId()));
        }
    }
    // event is persisted automatically, when parent event is persisted
    try {
        if (content instanceof BaseDto && event.getId() == null && event.getParentId() != null && lookupService.getEntityClass(((BaseDto) content).getClass()) != null) {
            // entity event can be persisted into queue only
            BaseDto dto = (BaseDto) content;
            if (dto.getId() == null) {
                // prepare id for new content - event is persisted before entity is persisted.
                dto.setId(UUID.randomUUID());
            }
            // 
            IdmEntityEventDto preparedEvent = toDto(dto, (EntityEvent<AbstractDto>) event);
            // RUNNING => prevent to start by async task
            preparedEvent.setResult(new OperationResultDto.Builder(OperationState.RUNNING).build());
            preparedEvent.setRootId(event.getRootId() == null ? event.getParentId() : event.getRootId());
            preparedEvent = entityEventService.save(preparedEvent);
            event.setId(preparedEvent.getId());
            // 
            // prepared event is be executed
            CoreEvent<IdmEntityEventDto> executeEvent = new CoreEvent<>(EntityEventType.EXECUTE, preparedEvent);
            publisher.publishEvent(executeEvent);
            // 
            // fill original event result
            E processedContent = (E) preparedEvent.getContent();
            if (processedContent != null) {
                event.setContent(processedContent);
            }
            event.getContext().addResult(new DefaultEventResult<E>(event, new EmptyEntityEventProcessor<E>()));
            // 
            return completeEvent(event);
        } else {
            publisher.publishEvent(event);
            // 
            return completeEvent(event);
        }
    } catch (Exception ex) {
        completeEvent(event);
        // 
        throw ex;
    }
}
Also used : Serializable(java.io.Serializable) CoreEvent(eu.bcvsolutions.idm.core.api.event.CoreEvent) AbstractDto(eu.bcvsolutions.idm.core.api.dto.AbstractDto) EmptyEntityEventProcessor(eu.bcvsolutions.idm.core.api.event.EmptyEntityEventProcessor) BaseDto(eu.bcvsolutions.idm.core.api.dto.BaseDto) 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) IdmEntityEventDto(eu.bcvsolutions.idm.core.api.dto.IdmEntityEventDto) Transactional(org.springframework.transaction.annotation.Transactional)

Example 25 with CoreEvent

use of eu.bcvsolutions.idm.core.api.event.CoreEvent 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)

Aggregations

CoreEvent (eu.bcvsolutions.idm.core.api.event.CoreEvent)46 Test (org.junit.Test)27 AbstractIntegrationTest (eu.bcvsolutions.idm.test.api.AbstractIntegrationTest)17 IdmIdentityDto (eu.bcvsolutions.idm.core.api.dto.IdmIdentityDto)11 IdmRoleDto (eu.bcvsolutions.idm.core.api.dto.IdmRoleDto)10 ResultCodeException (eu.bcvsolutions.idm.core.api.exception.ResultCodeException)9 UUID (java.util.UUID)9 Transactional (org.springframework.transaction.annotation.Transactional)8 BaseDto (eu.bcvsolutions.idm.core.api.dto.BaseDto)7 IdmEntityEventDto (eu.bcvsolutions.idm.core.api.dto.IdmEntityEventDto)7 CoreEventType (eu.bcvsolutions.idm.core.api.event.CoreEvent.CoreEventType)7 IdmFormInstanceDto (eu.bcvsolutions.idm.core.eav.api.dto.IdmFormInstanceDto)7 AbstractUnitTest (eu.bcvsolutions.idm.test.api.AbstractUnitTest)7 Serializable (java.io.Serializable)7 RoleCodeEnvironmentProcessor (eu.bcvsolutions.idm.core.model.event.processor.role.RoleCodeEnvironmentProcessor)6 GuardedString (eu.bcvsolutions.idm.core.security.api.domain.GuardedString)6 IdmFormDefinitionDto (eu.bcvsolutions.idm.core.eav.api.dto.IdmFormDefinitionDto)5 TestContent (eu.bcvsolutions.idm.core.event.TestContent)5 ArrayList (java.util.ArrayList)5 IdmEntityEventFilter (eu.bcvsolutions.idm.core.api.dto.filter.IdmEntityEventFilter)4