use of com.evolveum.midpoint.provisioning.ucf.api.UcfAsyncUpdateChange in project midpoint by Evolveum.
the class TransformationalAsyncUpdateMessageListener method onMessage.
@Override
public void onMessage(AsyncUpdateMessageType message, AcknowledgementSink acknowledgementSink) {
int messageNumber = messagesSeen.getAndIncrement();
LOGGER.trace("Got message number {}: {}", messageNumber, message);
SecurityContextManager securityContextManager = connectorInstance.getSecurityContextManager();
Authentication oldAuthentication = securityContextManager.getAuthentication();
try {
securityContextManager.setupPreAuthenticatedSecurityContext(authentication);
Task task = connectorInstance.getTaskManager().createTaskInstance(OP_ON_MESSAGE_PREPARATION);
task.setChannel(CHANNEL_ASYNC_UPDATE_URI);
if (authentication != null && authentication.getPrincipal() instanceof MidPointPrincipal) {
task.setOwner(((MidPointPrincipal) authentication.getPrincipal()).getFocus().asPrismObject().clone());
}
Tracer tracer = connectorInstance.getTracer();
OperationResult result = task.getResult();
OperationResultBuilder resultBuilder = OperationResult.createFor(OP_ON_MESSAGE);
try {
ActivityTracingDefinitionType tracing = connectorInstance.getConfiguration().getProcessTracingConfiguration();
if (tracing != null) {
int interval = defaultIfNull(tracing.getInterval(), 1);
boolean matches = interval > 0 && messageNumber % interval == 0;
if (matches) {
task.setTracingProfile(tracing.getTracingProfile());
if (tracing.getTracingPoint().isEmpty()) {
task.addTracingRequest(TracingRootType.ASYNCHRONOUS_MESSAGE_PROCESSING);
} else {
tracing.getTracingPoint().forEach(task::addTracingRequest);
}
}
}
if (task.getTracingRequestedFor().contains(TracingRootType.ASYNCHRONOUS_MESSAGE_PROCESSING)) {
TracingProfileType profile = task.getTracingProfile() != null ? task.getTracingProfile() : tracer.getDefaultProfile();
resultBuilder.tracingProfile(tracer.compileProfile(profile, task.getResult()));
}
// replace task result with the newly-built one
result = resultBuilder.build();
task.setResult(result);
VariablesMap variables = new VariablesMap();
variables.put(VAR_MESSAGE, message, AsyncUpdateMessageType.class);
List<UcfChangeType> changeBeans;
try {
ExpressionType transformExpression = connectorInstance.getTransformExpression();
if (transformExpression != null) {
changeBeans = connectorInstance.getUcfExpressionEvaluator().evaluate(transformExpression, variables, SchemaConstantsGenerated.C_UCF_CHANGE, "computing UCF change from async update", task, result);
} else {
changeBeans = unwrapMessage(message);
}
} catch (RuntimeException | SchemaException | ObjectNotFoundException | SecurityViolationException | CommunicationException | ConfigurationException | ExpressionEvaluationException e) {
throw new SystemException("Couldn't evaluate message transformation expression: " + e.getMessage(), e);
}
if (changeBeans.isEmpty()) {
acknowledgementSink.acknowledge(true, result);
} else {
AcknowledgementSink aggregatedSink = createAggregatingAcknowledgeSink(acknowledgementSink, changeBeans.size());
for (UcfChangeType changeBean : changeBeans) {
// For this to work reliably, we have to run in a single thread. But that's ok.
// If we receive messages in multiple threads, there is no message ordering.
int changeSequentialNumber = changesProduced.incrementAndGet();
// intentionally in this order - to process changes even after failure
// (if listener wants to fail fast, it can throw an exception)
UcfAsyncUpdateChange change = createChange(changeBean, result, changeSequentialNumber, aggregatedSink);
changeListener.onChange(change, task, result);
}
}
} catch (Exception e) {
LoggingUtils.logUnexpectedException(LOGGER, "Got exception while processing asynchronous message in {}", e, task);
result.recordFatalError(e.getMessage(), e);
int changeSequentialNumber = changesProduced.incrementAndGet();
UcfAsyncUpdateChange change = new UcfAsyncUpdateChange(changeSequentialNumber, UcfErrorState.error(e), acknowledgementSink);
changeListener.onChange(change, task, result);
} finally {
result.computeStatusIfUnknown();
// (Otherwise it captures only the pre-processing activities.)
if (result.isTraced()) {
tracer.storeTrace(task, result, null);
}
}
} finally {
securityContextManager.setupPreAuthenticatedSecurityContext(oldAuthentication);
}
}
use of com.evolveum.midpoint.provisioning.ucf.api.UcfAsyncUpdateChange in project midpoint by Evolveum.
the class TransformationalAsyncUpdateMessageListener method createChange.
@NotNull
private UcfAsyncUpdateChange createChange(UcfChangeType changeBean, OperationResult result, int changeSequentialNumber, AcknowledgementSink acknowledgeSink) throws SchemaException {
QName objectClassName = changeBean.getObjectClass();
if (objectClassName == null) {
throw new SchemaException("Object class name is null in " + changeBean);
}
ResourceSchema resourceSchema = getResourceSchema(result);
ResourceObjectDefinition objectClassDef = resourceSchema.findDefinitionForObjectClass(objectClassName);
if (objectClassDef == null) {
throw new SchemaException("Object class " + objectClassName + " not found in " + resourceSchema);
}
ObjectDelta<ShadowType> delta;
ObjectDeltaType deltaBean = changeBean.getObjectDelta();
if (deltaBean != null) {
setFromDefaults((ShadowType) deltaBean.getObjectToAdd(), objectClassName);
if (deltaBean.getObjectType() == null) {
deltaBean.setObjectType(ShadowType.COMPLEX_TYPE);
}
delta = DeltaConvertor.createObjectDelta(deltaBean, getPrismContext());
} else {
delta = null;
}
setFromDefaults(changeBean.getObject(), objectClassName);
Holder<Object> primaryIdentifierRealValueHolder = new Holder<>();
Collection<ResourceAttribute<?>> identifiers = getIdentifiers(changeBean, objectClassDef, primaryIdentifierRealValueHolder);
if (identifiers.isEmpty()) {
throw new SchemaException("No identifiers in async update change bean " + changeBean);
}
boolean notificationOnly = changeBean.getObject() == null && delta == null;
return new UcfAsyncUpdateChange(changeSequentialNumber, primaryIdentifierRealValueHolder.getValue(), objectClassDef.getObjectClassDefinition(), identifiers, delta, asPrismObject(changeBean.getObject()), notificationOnly, acknowledgeSink);
}
Aggregations