Skip to content

Commit

Permalink
Allow DynamicUpdate making the (erreneous) updatePartial method and P…
Browse files Browse the repository at this point in the history
…ATCH interface redundant
  • Loading branch information
dnlkoch committed May 13, 2022
1 parent 8f0b581 commit ea2d923
Show file tree
Hide file tree
Showing 14 changed files with 57 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

import java.time.OffsetDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

Expand Down Expand Up @@ -597,80 +596,6 @@ public S update(@RequestBody S entity, @PathVariable("id") Long entityId) {
}
}

@PatchMapping("/{id}")
@ResponseStatus(HttpStatus.OK)
public S updatePartial(@RequestBody Map<String, Object> values, @PathVariable("id") Long entityId) {
log.trace("Requested to partially update entity of type {} with ID {} ({})", getGenericClassName(), entityId, values);

try {
Object idFromValues = values.get("id");
if (idFromValues == null) {
log.error("Field 'id' (entity {})is missing in the passed values: {}.", entityId, values);
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
}
Long id = Long.valueOf((Integer) idFromValues);
if (!entityId.equals(id)) {
log.error("IDs of update candidate (ID: {}) and update data ({}) don't match.", entityId, values);
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
}

S persistedEntity = service.findOne(entityId).orElseThrow();
if (persistedEntity != null) {
S updatedEntity = service.updatePartial(entityId, persistedEntity, values);

log.trace("Successfully updated values for entity of type {} with ID {}",
getGenericClassName(), entityId);

return updatedEntity;
} else {
log.error("Could not find entity of type {} with ID {}",
getGenericClassName(), entityId);

throw new ResponseStatusException(
HttpStatus.NOT_FOUND,
messageSource.getMessage(
"BaseController.NOT_FOUND",
null,
LocaleContextHolder.getLocale()
)
);
}
} catch (AccessDeniedException ade) {
log.warn("Updating values of type {} with ID {} is denied",
getGenericClassName(), entityId);

throw new ResponseStatusException(
HttpStatus.NOT_FOUND,
messageSource.getMessage(
"BaseController.NOT_FOUND",
null,
LocaleContextHolder.getLocale()
),
ade
);
} catch (NumberFormatException nfe) {
log.error("Can't parse 'id' field ({}) from values ({}). It has to be an Integer.: {}",
values, entityId, nfe.getMessage());
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
} catch (ResponseStatusException rse) {
throw rse;
} catch (Exception e) {
log.error("Error while updating values for entity of type {} with ID {}: \n {}",
getGenericClassName(), entityId, e.getMessage());
log.trace("Full stack trace: ", e);

throw new ResponseStatusException(
HttpStatus.INTERNAL_SERVER_ERROR,
messageSource.getMessage(
"BaseController.INTERNAL_SERVER_ERROR",
null,
LocaleContextHolder.getLocale()
),
e
);
}
}

@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void delete(@PathVariable("id") Long entityId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import lombok.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.Type;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.Audited;
Expand All @@ -33,6 +34,7 @@

@Entity(name = "applications")
@Table(schema = "shogun")
@DynamicUpdate
@Audited
@AuditTable(value = "applications_rev", schema = "shogun_rev")
@Cacheable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
import lombok.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.util.UUID;

@Entity(name = "files")
@Table(schema = "shogun")
@DynamicUpdate
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "files")
@AllArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
import lombok.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.Audited;

import javax.persistence.*;

@Entity(name = "groups")
@Table(schema = "shogun")
@DynamicUpdate
@Audited
@AuditTable(value = "groups_rev", schema = "shogun_rev")
@Cacheable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,18 @@
package de.terrestris.shogun.lib.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Entity(name = "imagefiles")
@Table(schema = "shogun")
@DynamicUpdate
@Cacheable
@Data
@AllArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.geojson.GeoJsonObject;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.Type;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.Audited;
Expand All @@ -32,6 +33,7 @@

@Entity(name = "layers")
@Table(schema = "shogun")
@DynamicUpdate
@Audited
@AuditTable(value = "layers_rev", schema = "shogun_rev")
@Cacheable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import lombok.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.Type;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.Audited;
Expand All @@ -30,6 +31,7 @@

@Entity(name = "users")
@Table(schema = "shogun")
@DynamicUpdate
@Audited
@AuditTable(value = "users_rev", schema = "shogun_rev")
@Cacheable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,21 @@
package de.terrestris.shogun.lib.model.security.permission;

import de.terrestris.shogun.lib.model.Group;
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.Audited;

import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity(name = "groupclasspermissions")
@Table(schema = "shogun")
@DynamicUpdate
@Audited
@AuditTable(value = "groupclasspermissions_rev", schema = "shogun_rev")
@Cacheable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,21 @@
package de.terrestris.shogun.lib.model.security.permission;

import de.terrestris.shogun.lib.model.Group;
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.Audited;

import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity(name = "groupinstancepermissions")
@Table(schema = "shogun")
@DynamicUpdate
@Audited
@AuditTable(value = "groupinstancepermissions_rev", schema = "shogun_rev")
@Cacheable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,22 @@
import de.terrestris.shogun.lib.enumeration.PermissionCollectionType;
import de.terrestris.shogun.lib.enumeration.PermissionType;
import de.terrestris.shogun.lib.model.BaseEntity;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Cacheable;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Set;

@Entity(name = "permissions")
@Table(schema = "shogun")
@DynamicUpdate
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "permissions")
@Data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,21 @@
package de.terrestris.shogun.lib.model.security.permission;

import de.terrestris.shogun.lib.model.User;
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.Audited;

import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity(name = "userclasspermissions")
@Table(schema = "shogun")
@DynamicUpdate
@Audited
@AuditTable(value = "userclasspermissions_rev", schema = "shogun_rev")
@Cacheable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,21 @@
package de.terrestris.shogun.lib.model.security.permission;

import de.terrestris.shogun.lib.model.User;
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.Audited;

import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity(name = "userinstancepermissions")
@Table(schema = "shogun")
@DynamicUpdate
@Audited
@AuditTable(value = "userinstancepermissions_rev", schema = "shogun_rev")
@Cacheable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,28 +140,11 @@ public S create(S entity) {
public S update(Long id, S entity) throws IOException {
Optional<S> persistedEntityOpt = repository.findById(id);

ObjectNode jsonObject = objectMapper.valueToTree(entity);

// Ensure the created timestamp will not be overridden.
S persistedEntity = persistedEntityOpt.orElseThrow();
OffsetDateTime createdTimestamp = persistedEntity.getCreated();
String serialized = createdTimestamp != null ? createdTimestamp.toInstant().toString() : null;
jsonObject.put("created", serialized);

S updatedEntity = objectMapper.readerForUpdating(persistedEntity).readValue(jsonObject);

return repository.save(updatedEntity);
}
entity.setCreated(persistedEntity.getCreated());

@PreAuthorize("hasRole('ROLE_ADMIN') or hasPermission(#entity, 'UPDATE')")
@Transactional(isolation = Isolation.SERIALIZABLE)
public S updatePartial(Long entityId, S entity, Map<String, Object> values) throws IOException {
if (ObjectUtils.notEqual(entityId, entity.getId())) {
throw new IOException("ID's of passed entity and parameter do not match. No partial update possible");
}
JsonNode jsonObject = objectMapper.valueToTree(values);
S updatedEntity = objectMapper.readerForUpdating(entity).readValue(jsonObject);
return repository.save(updatedEntity);
return repository.save(entity);
}

@PreAuthorize("hasRole('ROLE_ADMIN') or hasPermission(#entity, 'DELETE')")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,6 @@ public void update_ShouldCallCorrectRepositoryMethodAndShouldReturnTheCreatedEnt
when(baseCrudRepositoryMock.findById(1909L)).thenReturn(Optional.of(mockEntity));
when(baseCrudRepositoryMock.save(mockEntity)).thenReturn(mockEntity);

when(objectMapperMock.valueToTree(mockEntity)).thenReturn(returnNode);
when(objectMapperMock.readerForUpdating(mockEntity)).thenReturn(objectReaderMock);
when(objectReaderMock.readValue(returnNode)).thenReturn(mockEntity);

S returnValue = (S) service.update(1909L, mockEntity);

verify(baseCrudRepositoryMock, times(1)).findById(1909L);
Expand Down

0 comments on commit ea2d923

Please sign in to comment.