Removed the extra level of abstraction and modified the code
accordingly.
This commit is contained in:
@@ -1,189 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
* which accompanies this distribution, and is available at
|
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
*/
|
|
||||||
package org.eclipse.hawkbit.repository.jpa.model;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.ActionCreatedEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.ActionPropertyChangeEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupPropertyChangeEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutPropertyChangeEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.DescriptorEventDetails.ActionType;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
|
||||||
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
|
||||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
|
||||||
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
|
|
||||||
import org.eclipse.persistence.queries.UpdateObjectQuery;
|
|
||||||
import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of @link{AbstractDescriptorEventVisitor} .Publishes the
|
|
||||||
* appropriate event after any action on entity like create/update.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class AbstractDescriptorEventVisitorImpl implements
|
|
||||||
AbstractDescriptorEventVisitor {
|
|
||||||
|
|
||||||
private static final String COMPLETE = "complete";
|
|
||||||
private static final Logger LOG = LoggerFactory
|
|
||||||
.getLogger(AbstractDescriptorEventVisitorImpl.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void publishEventPostAction(final DescriptorEventDetails event) {
|
|
||||||
Method method = null;
|
|
||||||
DescriptorEvent descriptorEvent = event.getDescriptorEvent();
|
|
||||||
ActionType actiontype = event.getActiontype();
|
|
||||||
try {
|
|
||||||
method = getMethod(descriptorEvent, actiontype);
|
|
||||||
if (method != null) {
|
|
||||||
method.invoke(this, descriptorEvent.getObject(),
|
|
||||||
descriptorEvent);
|
|
||||||
}
|
|
||||||
} catch (NoSuchMethodException | SecurityException
|
|
||||||
| IllegalAccessException | IllegalArgumentException
|
|
||||||
| InvocationTargetException e) {
|
|
||||||
LOG.info(
|
|
||||||
"Exception when invoking approriate method to publis event {}",
|
|
||||||
e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Method getMethod(DescriptorEvent descriptorEvent,
|
|
||||||
ActionType actiontype) throws NoSuchMethodException {
|
|
||||||
if (actiontype == ActionType.UPDATE) {
|
|
||||||
return this.getClass().getMethod("publishEventAfterUpdate",
|
|
||||||
descriptorEvent.getObject().getClass(),
|
|
||||||
DescriptorEvent.class);
|
|
||||||
} else if (actiontype == ActionType.CREATE) {
|
|
||||||
return this.getClass().getMethod("publishEventAfterCreate",
|
|
||||||
descriptorEvent.getObject().getClass(),
|
|
||||||
DescriptorEvent.class);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publishEventAfterCreate(JpaAction action, DescriptorEvent event) {
|
|
||||||
if (action.getRollout() != null) {
|
|
||||||
getAfterTransactionCommmitExecutor().afterCommit(
|
|
||||||
() -> getEventBus().post(new ActionCreatedEvent(action)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publishEventAfterCreate(JpaTarget target, DescriptorEvent event) {
|
|
||||||
getAfterTransactionCommmitExecutor().afterCommit(
|
|
||||||
() -> getEventBus().post(new TargetCreatedEvent(target)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publishEventAfterCreate(JpaDistributionSet ds,
|
|
||||||
DescriptorEvent event) {
|
|
||||||
getAfterTransactionCommmitExecutor().afterCommit(
|
|
||||||
() -> getEventBus().post(new DistributionCreatedEvent(ds)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publishEventAfterUpdate(JpaAction action, DescriptorEvent event) {
|
|
||||||
getAfterTransactionCommmitExecutor().afterCommit(
|
|
||||||
() -> getEventBus().post(
|
|
||||||
new ActionPropertyChangeEvent(action, getChangeSet(
|
|
||||||
Action.class, event))));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publishEventAfterUpdate(JpaTarget target, DescriptorEvent event) {
|
|
||||||
getAfterTransactionCommmitExecutor().afterCommit(
|
|
||||||
() -> getEventBus().post(new TargetUpdatedEvent(target)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publishEventAfterUpdate(JpaTargetInfo targetInfo,
|
|
||||||
DescriptorEvent event) {
|
|
||||||
getAfterTransactionCommmitExecutor()
|
|
||||||
.afterCommit(
|
|
||||||
() -> getEventBus().post(
|
|
||||||
new TargetInfoUpdateEvent(targetInfo)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publishEventAfterUpdate(JpaRollout entity, DescriptorEvent event) {
|
|
||||||
getAfterTransactionCommmitExecutor().afterCommit(
|
|
||||||
() -> getEventBus().post(
|
|
||||||
new RolloutPropertyChangeEvent(entity, getChangeSet(
|
|
||||||
Rollout.class, event))));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publishEventAfterUpdate(JpaRolloutGroup entity,
|
|
||||||
DescriptorEvent event) {
|
|
||||||
getAfterTransactionCommmitExecutor().afterCommit(
|
|
||||||
() -> getEventBus().post(
|
|
||||||
new RolloutGroupPropertyChangeEvent(entity,
|
|
||||||
getChangeSet(RolloutGroup.class, event))));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publishEventAfterUpdate(JpaDistributionSet entity,
|
|
||||||
DescriptorEvent event) {
|
|
||||||
Map<String, AbstractPropertyChangeEvent<JpaDistributionSet>.Values> changeSet = getChangeSet(
|
|
||||||
JpaDistributionSet.class, event);
|
|
||||||
if (changeSet.containsKey(COMPLETE)
|
|
||||||
&& changeSet.get(COMPLETE).getOldValue().equals(false)
|
|
||||||
&& changeSet.get(COMPLETE).getNewValue().equals(true)) {
|
|
||||||
getAfterTransactionCommmitExecutor().afterCommit(
|
|
||||||
() -> getEventBus().post(
|
|
||||||
new DistributionCreatedEvent(entity)));
|
|
||||||
}
|
|
||||||
|
|
||||||
getAfterTransactionCommmitExecutor().afterCommit(
|
|
||||||
() -> getEventBus()
|
|
||||||
.post(new DistributionSetUpdateEvent(entity)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T extends TenantAwareBaseEntity> Map<String, AbstractPropertyChangeEvent<T>.Values> getChangeSet(
|
|
||||||
final Class<T> clazz, final DescriptorEvent event) {
|
|
||||||
final T rolloutGroup = clazz.cast(event.getObject());
|
|
||||||
final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery())
|
|
||||||
.getObjectChangeSet();
|
|
||||||
return changeSet
|
|
||||||
.getChanges()
|
|
||||||
.stream()
|
|
||||||
.filter(record -> record instanceof DirectToFieldChangeRecord)
|
|
||||||
.map(record -> (DirectToFieldChangeRecord) record)
|
|
||||||
.collect(
|
|
||||||
Collectors.toMap(
|
|
||||||
record -> record.getAttribute(),
|
|
||||||
record -> new AbstractPropertyChangeEvent<T>(
|
|
||||||
rolloutGroup, null).new Values(record
|
|
||||||
.getOldValue(), record.getNewValue())));
|
|
||||||
}
|
|
||||||
|
|
||||||
private AfterTransactionCommitExecutor getAfterTransactionCommmitExecutor() {
|
|
||||||
return AfterTransactionCommitExecutorHolder.getInstance()
|
|
||||||
.getAfterCommit();
|
|
||||||
}
|
|
||||||
|
|
||||||
private EventBus getEventBus() {
|
|
||||||
return EventBusHolder.getInstance().getEventBus();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -32,7 +32,7 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
|||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
@Access(AccessType.FIELD)
|
@Access(AccessType.FIELD)
|
||||||
@EntityListeners({ AuditingEntityListener.class, CacheFieldEntityListener.class, EntityPropertyChangeListener.class })
|
@EntityListeners({ AuditingEntityListener.class, CacheFieldEntityListener.class, EntityPropertyChangeListener.class })
|
||||||
public abstract class AbstractJpaBaseEntity implements BaseEntity,AcceptVisitor {
|
public abstract class AbstractJpaBaseEntity implements BaseEntity {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@@ -179,8 +179,4 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity,AcceptVisitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postActionOnEntity(AbstractDescriptorEventVisitor visitor, DescriptorEventDetails eventDetails){
|
|
||||||
visitor.publishEventPostAction(eventDetails);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
|
||||||
*
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
* which accompanies this distribution, and is available at
|
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
*/
|
|
||||||
package org.eclipse.hawkbit.repository.jpa.model;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface to accept visitor @link{AbstractDescriptorEventVisitor}.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public interface AcceptVisitor {
|
|
||||||
public void postActionOnEntity(AbstractDescriptorEventVisitor visitor,
|
|
||||||
DescriptorEventDetails eventDetails);
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.model;
|
package org.eclipse.hawkbit.repository.jpa.model;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.DescriptorEventDetails.ActionType;
|
|
||||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
|
import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
|
||||||
|
|
||||||
@@ -18,19 +17,23 @@ import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
|
|||||||
*/
|
*/
|
||||||
public class EntityPropertyChangeListener extends DescriptorEventAdapter {
|
public class EntityPropertyChangeListener extends DescriptorEventAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postInsert(final DescriptorEvent event) {
|
public void postInsert(final DescriptorEvent event) {
|
||||||
AbstractDescriptorEventVisitor visitor = new AbstractDescriptorEventVisitorImpl();
|
|
||||||
((AbstractJpaBaseEntity) event.getObject()).postActionOnEntity(visitor,
|
|
||||||
new DescriptorEventDetails(ActionType.CREATE, event));
|
|
||||||
|
|
||||||
}
|
final Object object = event.getObject();
|
||||||
|
if (object instanceof EventAwareEntity) {
|
||||||
|
((EventAwareEntity) object).fireCreateEvent(object,event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postUpdate(final DescriptorEvent event) {
|
||||||
|
|
||||||
|
final Object object = event.getObject();
|
||||||
|
if (object instanceof EventAwareEntity) {
|
||||||
|
((EventAwareEntity) object).fireUpdateEvent(object,event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postUpdate(final DescriptorEvent event) {
|
|
||||||
AbstractDescriptorEventVisitor visitor = new AbstractDescriptorEventVisitorImpl();
|
|
||||||
((AbstractJpaBaseEntity) event.getObject()).postActionOnEntity(visitor,
|
|
||||||
new DescriptorEventDetails(ActionType.UPDATE, event));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.model;
|
package org.eclipse.hawkbit.repository.jpa.model;
|
||||||
|
|
||||||
/**
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
*
|
|
||||||
* Interface defining the action to be performed after entity is
|
public interface EventAwareEntity<T> {
|
||||||
* created/updated.
|
|
||||||
*
|
public void fireCreateEvent(T t,DescriptorEvent descriptorEvent);
|
||||||
*/
|
|
||||||
public interface AbstractDescriptorEventVisitor {
|
public void fireUpdateEvent(T t,DescriptorEvent descriptorEvent);
|
||||||
void publishEventPostAction(DescriptorEventDetails eventDetails);
|
|
||||||
|
public void fireDeleteEvent(T t,DescriptorEvent descriptorEvent);
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,11 @@ import javax.persistence.NamedSubgraph;
|
|||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.ActionCreatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.ActionPropertyChangeEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
@@ -35,6 +40,7 @@ import org.eclipse.hawkbit.repository.model.Rollout;
|
|||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPA implementation of {@link Action}.
|
* JPA implementation of {@link Action}.
|
||||||
@@ -49,7 +55,7 @@ import org.eclipse.persistence.annotations.CascadeOnDelete;
|
|||||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||||
// sub entities
|
// sub entities
|
||||||
@SuppressWarnings("squid:S2160")
|
@SuppressWarnings("squid:S2160")
|
||||||
public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action {
|
public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action,EventAwareEntity<JpaAction> {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@@ -171,4 +177,23 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
|
|||||||
return "Action [distributionSet=" + distributionSet + ", getId()=" + getId() + "]";
|
return "Action [distributionSet=" + distributionSet + ", getId()=" + getId() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCreateEvent(final JpaAction jpaAction, final DescriptorEvent descriptorEvent) {
|
||||||
|
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () ->EventBusHolder.getInstance().getEventBus().post(new ActionCreatedEvent(jpaAction)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireUpdateEvent(final JpaAction jpaAction, final DescriptorEvent descriptorEvent) {
|
||||||
|
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () ->EventBusHolder.getInstance().getEventBus().
|
||||||
|
post(new ActionPropertyChangeEvent(jpaAction, EntityPropertyChangeHelper.getChangeSet(Action.class, descriptorEvent))));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireDeleteEvent(final JpaAction jpaAction, final DescriptorEvent descriptorEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -33,8 +34,14 @@ import javax.persistence.OneToMany;
|
|||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.persistence.UniqueConstraint;
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent;
|
||||||
import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException;
|
import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException;
|
||||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||||
@@ -45,6 +52,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
|||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Jpa implementation of {@link DistributionSet}.
|
* Jpa implementation of {@link DistributionSet}.
|
||||||
@@ -61,9 +69,11 @@ import org.eclipse.persistence.annotations.CascadeOnDelete;
|
|||||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||||
// sub entities
|
// sub entities
|
||||||
@SuppressWarnings("squid:S2160")
|
@SuppressWarnings("squid:S2160")
|
||||||
public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet {
|
public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet,EventAwareEntity<JpaDistributionSet> {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final String COMPLETE = "complete";
|
||||||
|
|
||||||
@Column(name = "required_migration_step")
|
@Column(name = "required_migration_step")
|
||||||
private boolean requiredMigrationStep;
|
private boolean requiredMigrationStep;
|
||||||
|
|
||||||
@@ -279,4 +289,32 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
|||||||
return complete;
|
return complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCreateEvent(final JpaDistributionSet jpaDistributionSet, final DescriptorEvent descriptorEvent) {
|
||||||
|
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () -> EventBusHolder.getInstance().getEventBus().post(new DistributionCreatedEvent(jpaDistributionSet)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireUpdateEvent(final JpaDistributionSet jpaDistributionSet, final DescriptorEvent descriptorEvent) {
|
||||||
|
final Map<String, AbstractPropertyChangeEvent<JpaDistributionSet>.Values> changeSet = EntityPropertyChangeHelper.getChangeSet(
|
||||||
|
JpaDistributionSet.class, descriptorEvent);
|
||||||
|
if (changeSet.containsKey(COMPLETE)
|
||||||
|
&& changeSet.get(COMPLETE).getOldValue().equals(false)
|
||||||
|
&& changeSet.get(COMPLETE).getNewValue().equals(true)) {
|
||||||
|
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(
|
||||||
|
() -> EventBusHolder.getInstance().getEventBus().post(
|
||||||
|
new DistributionCreatedEvent(jpaDistributionSet)));
|
||||||
|
}
|
||||||
|
|
||||||
|
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(
|
||||||
|
() -> EventBusHolder.getInstance().getEventBus().post(new DistributionSetUpdateEvent(jpaDistributionSet)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireDeleteEvent(final JpaDistributionSet jpaDistributionSet, final DescriptorEvent descriptorEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,13 +25,18 @@ import javax.persistence.Table;
|
|||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
import javax.persistence.UniqueConstraint;
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.RolloutPropertyChangeEvent;
|
||||||
import org.eclipse.hawkbit.repository.jpa.cache.CacheField;
|
import org.eclipse.hawkbit.repository.jpa.cache.CacheField;
|
||||||
import org.eclipse.hawkbit.repository.jpa.cache.CacheKeys;
|
import org.eclipse.hawkbit.repository.jpa.cache.CacheKeys;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPA implementation of a {@link Rollout}.
|
* JPA implementation of a {@link Rollout}.
|
||||||
@@ -44,7 +49,7 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
|||||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||||
// sub entities
|
// sub entities
|
||||||
@SuppressWarnings("squid:S2160")
|
@SuppressWarnings("squid:S2160")
|
||||||
public class JpaRollout extends AbstractJpaNamedEntity implements Rollout {
|
public class JpaRollout extends AbstractJpaNamedEntity implements Rollout,EventAwareEntity<JpaRollout> {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@@ -197,4 +202,22 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout {
|
|||||||
+ ", getName()=" + getName() + ", getId()=" + getId() + "]";
|
+ ", getName()=" + getName() + ", getId()=" + getId() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCreateEvent(final JpaRollout jpaRollout, final DescriptorEvent descriptorEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireUpdateEvent(final JpaRollout jpaRollout, final DescriptorEvent descriptorEvent) {
|
||||||
|
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() -> EventBusHolder.getInstance().getEventBus().
|
||||||
|
post(new RolloutPropertyChangeEvent(jpaRollout, EntityPropertyChangeHelper.getChangeSet(
|
||||||
|
Rollout.class, descriptorEvent))));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireDeleteEvent(final JpaRollout jpaRollout, final DescriptorEvent descriptorEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,14 @@ import javax.persistence.Table;
|
|||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
import javax.persistence.UniqueConstraint;
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupPropertyChangeEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPA entity definition of persisting a group of an rollout.
|
* JPA entity definition of persisting a group of an rollout.
|
||||||
@@ -40,7 +45,7 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
|||||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||||
// sub entities
|
// sub entities
|
||||||
@SuppressWarnings("squid:S2160")
|
@SuppressWarnings("squid:S2160")
|
||||||
public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup {
|
public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup,EventAwareEntity<JpaRolloutGroup> {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@@ -236,4 +241,21 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr
|
|||||||
+ ", getId()=" + getId() + "]";
|
+ ", getId()=" + getId() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCreateEvent(final JpaRolloutGroup jpaRolloutGroup, final DescriptorEvent descriptorEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireUpdateEvent(final JpaRolloutGroup jpaRolloutGroup, final DescriptorEvent descriptorEvent) {
|
||||||
|
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(() -> EventBusHolder.getInstance().getEventBus().
|
||||||
|
post(new RolloutGroupPropertyChangeEvent(jpaRolloutGroup,
|
||||||
|
EntityPropertyChangeHelper.getChangeSet(RolloutGroup.class, descriptorEvent))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireDeleteEvent(final JpaRolloutGroup jpaRolloutGroup, final DescriptorEvent descriptorEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ import javax.validation.constraints.NotNull;
|
|||||||
import javax.validation.constraints.Size;
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityChecker;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityChecker;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
||||||
@@ -45,6 +49,7 @@ import org.eclipse.hawkbit.repository.model.Target;
|
|||||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
import org.springframework.data.domain.Persistable;
|
import org.springframework.data.domain.Persistable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,7 +69,7 @@ import org.springframework.data.domain.Persistable;
|
|||||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||||
// sub entities
|
// sub entities
|
||||||
@SuppressWarnings("squid:S2160")
|
@SuppressWarnings("squid:S2160")
|
||||||
public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Long>, Target {
|
public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Long>, Target, EventAwareEntity<JpaTarget> {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Column(name = "controller_id", length = 64)
|
@Column(name = "controller_id", length = 64)
|
||||||
@@ -222,6 +227,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Lon
|
|||||||
* @param securityToken
|
* @param securityToken
|
||||||
* the securityToken to set
|
* the securityToken to set
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void setSecurityToken(final String securityToken) {
|
public void setSecurityToken(final String securityToken) {
|
||||||
this.securityToken = securityToken;
|
this.securityToken = securityToken;
|
||||||
}
|
}
|
||||||
@@ -231,4 +237,21 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Lon
|
|||||||
return "Target [controllerId=" + controllerId + ", getId()=" + getId() + "]";
|
return "Target [controllerId=" + controllerId + ", getId()=" + getId() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCreateEvent(final JpaTarget jpaTarget, final DescriptorEvent descriptorEvent) {
|
||||||
|
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () ->EventBusHolder.getInstance().getEventBus().post(new TargetCreatedEvent(jpaTarget)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireUpdateEvent(final JpaTarget jpaTarget,final DescriptorEvent descriptorEvent) {
|
||||||
|
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () -> EventBusHolder.getInstance().getEventBus().post(new TargetUpdatedEvent(jpaTarget)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireDeleteEvent(final JpaTarget jpaTarget, final DescriptorEvent descriptorEvent) {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import javax.persistence.Column;
|
|||||||
import javax.persistence.ConstraintMode;
|
import javax.persistence.ConstraintMode;
|
||||||
import javax.persistence.ElementCollection;
|
import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EntityListeners;
|
||||||
import javax.persistence.EnumType;
|
import javax.persistence.EnumType;
|
||||||
import javax.persistence.Enumerated;
|
import javax.persistence.Enumerated;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
@@ -37,7 +38,10 @@ import javax.persistence.OneToOne;
|
|||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
||||||
import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
|
import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
@@ -48,6 +52,7 @@ import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
|||||||
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
|
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.data.domain.Persistable;
|
import org.springframework.data.domain.Persistable;
|
||||||
@@ -64,7 +69,8 @@ import org.springframework.data.domain.Persistable;
|
|||||||
@Table(name = "sp_target_info", indexes = {
|
@Table(name = "sp_target_info", indexes = {
|
||||||
@Index(name = "sp_idx_target_info_02", columnList = "target_id,update_status") })
|
@Index(name = "sp_idx_target_info_02", columnList = "target_id,update_status") })
|
||||||
@Entity
|
@Entity
|
||||||
public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
|
@EntityListeners(EntityPropertyChangeListener.class)
|
||||||
|
public class JpaTargetInfo implements Persistable<Long>, TargetInfo, EventAwareEntity<JpaTargetInfo> {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(TargetInfo.class);
|
private static final Logger LOG = LoggerFactory.getLogger(TargetInfo.class);
|
||||||
@@ -321,4 +327,18 @@ public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCreateEvent(final JpaTargetInfo jpaTargetInfo,final DescriptorEvent descriptorEvent) {
|
||||||
|
// there is no target info created event
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireUpdateEvent(final JpaTargetInfo jpaTargetInfo, final DescriptorEvent descriptorEvent) {
|
||||||
|
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit( () -> EventBusHolder.getInstance().getEventBus().post(new TargetInfoUpdateEvent(jpaTargetInfo)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireDeleteEvent(final JpaTargetInfo jpaTargetInfo, final DescriptorEvent descriptorEvent) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||||
|
*
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.repository.jpa.model.helper;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
|
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
|
||||||
|
import org.eclipse.persistence.queries.UpdateObjectQuery;
|
||||||
|
import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord;
|
||||||
|
|
||||||
|
public class EntityPropertyChangeHelper<T extends TenantAwareBaseEntity> {
|
||||||
|
|
||||||
|
|
||||||
|
public static <T extends TenantAwareBaseEntity> Map<String, AbstractPropertyChangeEvent<T>.Values> getChangeSet(
|
||||||
|
final Class<T> clazz, final DescriptorEvent event) {
|
||||||
|
final T rolloutGroup = clazz.cast(event.getObject());
|
||||||
|
final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery())
|
||||||
|
.getObjectChangeSet();
|
||||||
|
return changeSet
|
||||||
|
.getChanges()
|
||||||
|
.stream()
|
||||||
|
.filter(record -> record instanceof DirectToFieldChangeRecord)
|
||||||
|
.map(record -> (DirectToFieldChangeRecord) record)
|
||||||
|
.collect(
|
||||||
|
Collectors.toMap(
|
||||||
|
record -> record.getAttribute(),
|
||||||
|
record -> new AbstractPropertyChangeEvent<T>(
|
||||||
|
rolloutGroup, null).new Values(record
|
||||||
|
.getOldValue(), record.getNewValue())));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user