Merge branch 'master' into feature_boot_13_sec_41

This commit is contained in:
kaizimmerm
2016-08-26 09:17:39 +02:00
125 changed files with 2069 additions and 2352 deletions

View File

@@ -299,8 +299,6 @@ public class JpaControllerManagement implements ControllerManagement {
case CANCELED:
case WARNING:
case RUNNING:
handleIntermediateFeedback(mergedAction, mergedTarget);
break;
default:
break;
}
@@ -312,16 +310,6 @@ public class JpaControllerManagement implements ControllerManagement {
return actionRepository.save(mergedAction);
}
private void handleIntermediateFeedback(final JpaAction mergedAction, final JpaTarget mergedTarget) {
// we change the target state only if the action is still running
// otherwise this is considered as late feedback that does not have
// an impact on the state anymore.
if (mergedAction.isActive()) {
DeploymentHelper.updateTargetInfo(mergedTarget, TargetUpdateStatus.PENDING, false, targetInfoRepository,
entityManager);
}
}
private void handleErrorOnAction(final JpaAction mergedAction, final JpaTarget mergedTarget) {
mergedAction.setActive(false);
mergedAction.setStatus(Status.ERROR);
@@ -349,15 +337,17 @@ public class JpaControllerManagement implements ControllerManagement {
action.setStatus(Status.FINISHED);
final JpaTargetInfo targetInfo = (JpaTargetInfo) target.getTargetInfo();
final JpaDistributionSet ds = (JpaDistributionSet) entityManager.merge(action.getDistributionSet());
targetInfo.setInstalledDistributionSet(ds);
if (target.getAssignedDistributionSet() != null && targetInfo.getInstalledDistributionSet() != null && target
.getAssignedDistributionSet().getId().equals(targetInfo.getInstalledDistributionSet().getId())) {
targetInfo.setInstallationDate(System.currentTimeMillis());
// check if the assigned set is equal to the installed set (not
// necessarily the case as another update might be pending already).
if (target.getAssignedDistributionSet() != null && target.getAssignedDistributionSet().getId()
.equals(targetInfo.getInstalledDistributionSet().getId())) {
targetInfo.setUpdateStatus(TargetUpdateStatus.IN_SYNC);
targetInfo.setInstallationDate(System.currentTimeMillis());
} else {
targetInfo.setUpdateStatus(TargetUpdateStatus.PENDING);
targetInfo.setInstallationDate(System.currentTimeMillis());
}
targetInfoRepository.save(targetInfo);
entityManager.detach(ds);
}

View File

@@ -82,7 +82,6 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
@@ -599,11 +598,16 @@ public class JpaDeploymentManagement implements DeploymentManagement {
@Override
public Page<Action> findActionsByTarget(final String rsqlParam, final Target target, final Pageable pageable) {
final Specification<JpaAction> specification = RSQLUtility.parse(rsqlParam, ActionFields.class);
return convertAcPage(actionRepository.findAll((Specification<JpaAction>) (root, query, cb) -> cb
.and(specification.toPredicate(root, query, cb), cb.equal(root.get(JpaAction_.target), target)),
pageable), pageable);
final Specification<JpaAction> byTargetSpec = createSpecificationFor(target, rsqlParam);
final Page<JpaAction> actions = actionRepository.findAll(byTargetSpec, pageable);
return convertAcPage(actions, pageable);
}
private Specification<JpaAction> createSpecificationFor(final Target target, final String rsqlParam) {
final Specification<JpaAction> spec = RSQLUtility.parse(rsqlParam, ActionFields.class);
return (root, query, cb) -> cb.and(spec.toPredicate(root, query, cb),
cb.equal(root.get(JpaAction_.target), target));
}
private static Page<Action> convertAcPage(final Page<JpaAction> findAll, final Pageable pageable) {
@@ -642,10 +646,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
@Override
public Long countActionsByTarget(final String rsqlParam, final Target target) {
final Specification<JpaAction> spec = RSQLUtility.parse(rsqlParam, ActionFields.class);
return actionRepository.count((root, query, cb) -> cb.and(spec.toPredicate(root, query, cb),
cb.equal(root.get(JpaAction_.target), target)));
return actionRepository.count(createSpecificationFor(target, rsqlParam));
}
@Override

View File

@@ -483,7 +483,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
if (distributionSetMetadataRepository.exists(metadata.getId())) {
throwMetadataKeyAlreadyExists(metadata.getId().getKey());
}
touch(metadata.getDistributionSet());
return distributionSetMetadataRepository.save(metadata);
}
@@ -515,7 +515,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
findOne(metadata.getDistributionSet(), metadata.getKey());
// touch it to update the lock revision because we are modifying the
// DS indirectly
touch(metadata.getDistributionSet());;
touch(metadata.getDistributionSet());
return distributionSetMetadataRepository.save(metadata);
}
@@ -528,8 +528,11 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
}
/**
* Method to get the latest distribution set based on ds ID after the metadata changes for that distribution set.
* @param distributionSet Distribution set
* Method to get the latest distribution set based on ds ID after the
* metadata changes for that distribution set.
*
* @param distributionSet
* Distribution set
*/
private void touch(final DistributionSet distributionSet) {
final DistributionSet latestDistributionSet = findDistributionSetById(distributionSet.getId());
@@ -552,7 +555,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Override
public List<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId) {
return new ArrayList<DistributionSetMetadata>(distributionSetMetadataRepository
return new ArrayList<>(distributionSetMetadataRepository
.findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.equal(
root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id),
distributionSetId)));

View File

@@ -599,7 +599,7 @@ public class JpaRolloutManagement implements RolloutManagement {
/**
* Get count of targets in different status in rollout.
*
* @param page
* @param pageable
* the page request to sort and limit the result
* @return a list of rollouts with details of targets count for different
* statuses

View File

@@ -26,7 +26,6 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.domain.Specifications;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

View File

@@ -46,6 +46,7 @@ import org.springframework.transaction.TransactionSystemException;
*/
@Aspect
public class ExceptionMappingAspectHandler implements Ordered {
private static final Logger LOG = LoggerFactory.getLogger(ExceptionMappingAspectHandler.class);
private static final Map<String, String> EXCEPTION_MAPPING = new HashMap<>();
@@ -63,6 +64,7 @@ public class ExceptionMappingAspectHandler implements Ordered {
private final SQLStateSQLExceptionTranslator sqlStateExceptionTranslator = new SQLStateSQLExceptionTranslator();
static {
MAPPED_EXCEPTION_ORDER.add(DuplicateKeyException.class);
MAPPED_EXCEPTION_ORDER.add(DataIntegrityViolationException.class);
MAPPED_EXCEPTION_ORDER.add(ConcurrencyFailureException.class);
@@ -90,9 +92,11 @@ public class ExceptionMappingAspectHandler implements Ordered {
+ " || execution( * org.eclipse.hawkbit.controller.*.*(..)) "
+ " || execution( * org.eclipse.hawkbit.rest.resource.*.*(..)) "
+ " || execution( * org.eclipse.hawkbit.service.*.*(..)) )", throwing = "ex")
// Exception squid:S00112 - Is aspectJ proxy
@SuppressWarnings({ "squid:S00112" })
// Exception for squid:S00112, squid:S1162
// It is a AspectJ proxy which deals with exceptions.
@SuppressWarnings({ "squid:S00112", "squid:S1162" })
public void catchAndWrapJpaExceptionsService(final Exception ex) throws Throwable {
LOG.trace("exception occured", ex);
Exception translatedAccessException = translateEclipseLinkExceptionIfPossible(ex);
@@ -122,6 +126,7 @@ public class ExceptionMappingAspectHandler implements Ordered {
break;
}
}
LOG.trace("mapped exception {} to {}", translatedAccessException.getClass(), mappingException.getClass());
throw mappingException;
}
@@ -138,7 +143,7 @@ public class ExceptionMappingAspectHandler implements Ordered {
* translate the exception by the sql error code. Luckily, there we can use
* {@link SQLStateSQLExceptionTranslator} if we can get a
* {@link SQLException}.
*
*
* @param accessException
* the base access exception from jpa
* @return the translated accessException

View File

@@ -43,11 +43,11 @@ public class EntityPropertyChangeListener extends DescriptorEventAdapter {
}
}
private boolean isEventAwareEntity(final Object object) {
private static boolean isEventAwareEntity(final Object object) {
return object instanceof EventAwareEntity;
}
private void doNotifiy(final Runnable runnable) {
private static void doNotifiy(final Runnable runnable) {
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(runnable);
}

View File

@@ -98,8 +98,8 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements
* the status for this action status
* @param occurredAt
* the occurred timestamp
* @param messages
* the messages which should be added to this action status
* @param message
* the message which should be added to this action status
*/
public JpaActionStatus(final JpaAction action, final Status status, final Long occurredAt, final String message) {
this.action = action;

View File

@@ -34,7 +34,7 @@ import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent;
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent.PropertyChange;
import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent;
@@ -299,8 +299,8 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
@Override
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
final Map<String, AbstractPropertyChangeEvent<JpaDistributionSet>.Values> changeSet = EntityPropertyChangeHelper
.getChangeSet(JpaDistributionSet.class, descriptorEvent);
final Map<String, PropertyChange> changeSet = EntityPropertyChangeHelper.getChangeSet(JpaDistributionSet.class,
descriptorEvent);
EventBusHolder.getInstance().getEventBus().post(new DistributionSetUpdateEvent(this));
if (changeSet.containsKey(DELETED_PROPERTY)) {

View File

@@ -70,6 +70,7 @@ import org.springframework.data.domain.Persistable;
// sub entities
@SuppressWarnings("squid:S2160")
public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Long>, Target, EventAwareEntity {
private static final long serialVersionUID = 1L;
@Column(name = "controller_id", length = 64)
@@ -185,7 +186,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Lon
}
/**
* @param isNew
* @param entityNew
* the isNew to set
*/
public void setNew(final boolean entityNew) {

View File

@@ -122,7 +122,7 @@ public class JpaTargetInfo implements Persistable<Long>, TargetInfo, EventAwareE
private boolean requestControllerAttributes = true;
/**
* Constructor for {@link TargetStatus}.
* Constructor for {@link JpaTargetInfo}.
*
* @param target
* related to this status.
@@ -149,7 +149,7 @@ public class JpaTargetInfo implements Persistable<Long>, TargetInfo, EventAwareE
}
/**
* @param isNew
* @param entityNew
* the isNew to set
*/
public void setNew(final boolean entityNew) {

View File

@@ -11,7 +11,7 @@ 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.eventbus.event.AbstractPropertyChangeEvent.PropertyChange;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
@@ -32,15 +32,14 @@ public class EntityPropertyChangeHelper<T extends TenantAwareBaseEntity> {
* @param event
* @return the map of the changeSet
*/
public static <T extends TenantAwareBaseEntity> Map<String, AbstractPropertyChangeEvent<T>.Values> getChangeSet(
final Class<T> clazz, final DescriptorEvent event) {
public static <T extends TenantAwareBaseEntity> Map<String, PropertyChange> 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())));
record -> new PropertyChange(record.getOldValue(), record.getNewValue())));
}
}

View File

@@ -8,6 +8,8 @@
*/
package org.eclipse.hawkbit.repository.jpa.rsql;
import static org.eclipse.hawkbit.repository.FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -15,7 +17,6 @@ import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
@@ -49,7 +50,7 @@ import cz.jirutka.rsql.parser.ast.RSQLVisitor;
* A utility class which is able to parse RSQL strings into an spring data
* {@link Specification} which then can be enhanced sql queries to filter
* entities. RSQL parser library: https://github.com/jirutka/rsql-parser
*
*
* <ul>
* <li>Equal to : ==</li>
* <li>Not equal to : !=</li>
@@ -83,14 +84,12 @@ public final class RSQLUtility {
/**
* parses an RSQL valid string into an JPA {@link Specification} which then
* can be used to filter for JPA entities with the given RSQL query.
*
*
* @param rsql
* the rsql query
* @param fieldNameProvider
* the enum class type which implements the
* {@link FieldNameProvider}
* @param entityManager
* {@link EntityManager}
* @return an specification which can be used with JPA
* @throws RSQLParameterUnsupportedFieldException
* if a field in the RSQL string is used but not provided by the
@@ -105,10 +104,10 @@ public final class RSQLUtility {
/**
* Validate the given rsql string regarding existence and correct syntax.
*
*
* @param rsql
* the rsql string to get validated
*
*
*/
public static void isValid(final String rsql) {
parseRsql(rsql);
@@ -156,7 +155,7 @@ public final class RSQLUtility {
/**
* An implementation of the {@link RSQLVisitor} to visit the parsed tokens
* and build jpa where clauses.
*
*
*
*
* @param <A>
@@ -205,7 +204,7 @@ public final class RSQLUtility {
}
private String getAndValidatePropertyFieldName(final A propertyEnum, final ComparisonNode node) {
String finalProperty = propertyEnum.getFieldName();
final String[] graph = node.getSelector().split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR);
validateMapParamter(propertyEnum, node, graph);
@@ -215,9 +214,12 @@ public final class RSQLUtility {
throw createRSQLParameterUnsupportedException(node);
}
final StringBuilder fieldNameBuilder = new StringBuilder(propertyEnum.getFieldName());
for (int i = 1; i < graph.length; i++) {
final String propertyField = graph[i];
finalProperty += FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR + propertyField;
fieldNameBuilder.append(SUB_ATTRIBUTE_SEPERATOR).append(propertyField);
// the key of map is not in the graph
if (propertyEnum.isMap() && graph.length == (i + 1)) {
@@ -229,7 +231,7 @@ public final class RSQLUtility {
}
}
return finalProperty;
return fieldNameBuilder.toString();
}
private void validateMapParamter(final A propertyEnum, final ComparisonNode node, final String[] graph) {

View File

@@ -16,6 +16,7 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.hawkbit.repository.DistributionSetAssignmentResult;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
@@ -197,7 +198,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
}
@Test
@Description("Verfies that a DS is of default type if not specified explicitly at creation time.")
@Description("Verifies that a DS is of default type if not specified explicitly at creation time.")
public void createDistributionSetWithImplicitType() {
final DistributionSet set = distributionSetManagement
.createDistributionSet(new JpaDistributionSet("newtypesoft", "1", "", null, null));
@@ -208,7 +209,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
}
@Test
@Description("Verfies that multiple DS are of default type if not specified explicitly at creation time.")
@Description("Verifies that multiple DS are of default type if not specified explicitly at creation time.")
public void createMultipleDistributionSetsWithImplicitType() {
List<DistributionSet> sets = new ArrayList<>();
@@ -228,7 +229,7 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
}
@Test
@Description("Verfies that a DS entity cannot be used for creation.")
@Description("Verifies that a DS entity cannot be used for creation.")
public void createDistributionSetFailsOnExistingEntity() {
final DistributionSet set = distributionSetManagement
.createDistributionSet(new JpaDistributionSet("newtypesoft", "1", "", null, null));
@@ -818,6 +819,27 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
.isEqualTo(2);
}
@Test
@Description("Verify that the DistributionSetAssignmentResult not contains already assigned targets.")
public void verifyDistributionSetAssignmentResultNotContainsAlreadyAssignedTargets() {
DistributionSet dsToTargetAssigned = testdataFactory.createDistributionSet("ds-3");
// create assigned DS
dsToTargetAssigned = distributionSetManagement.findDistributionSetByNameAndVersion(dsToTargetAssigned.getName(),
dsToTargetAssigned.getVersion());
final Target target = new JpaTarget("4712");
final Target savedTarget = targetManagement.createTarget(target);
final List<Target> toAssign = Lists.newArrayList(savedTarget);
DistributionSetAssignmentResult assignmentResult = deploymentManagement
.assignDistributionSet(dsToTargetAssigned, toAssign);
assertThat(assignmentResult.getAssignedEntity()).hasSize(1);
assignmentResult = deploymentManagement.assignDistributionSet(dsToTargetAssigned, toAssign);
assertThat(assignmentResult.getAssignedEntity()).hasSize(0);
assertThat(distributionSetRepository.findAll()).hasSize(1);
}
private Rollout createRolloutByVariables(final String rolloutName, final String rolloutDescription,
final int groupSize, final String filterQuery, final DistributionSet distributionSet,
final String successCondition, final String errorCondition) {