ModifyFeaturePropertiesStrategy extends AbstractThingCommandStrategy<ModifyFeatureProperties> { @Override protected Result<ThingEvent> doApply(final Context<ThingId> context, @Nullable final Thing thing, final long nextRevision, final ModifyFeatureProperties command, @Nullable final Metadata metadata) { final String featureId = command.getFeatureId(); final Thing nonNullThing = getEntityOrThrow(thing); final JsonObject thingWithoutProperties = nonNullThing.removeFeatureProperties(featureId).toJson(); final JsonObject propertiesJsonObject = command.getProperties().toJson(); ThingCommandSizeValidator.getInstance().ensureValidSize( () -> { final long lengthWithOutProperties = thingWithoutProperties.getUpperBoundForStringSize(); final long propertiesLength = propertiesJsonObject.getUpperBoundForStringSize() + "properties".length() + featureId.length() + 5L; return lengthWithOutProperties + propertiesLength; }, () -> { final long lengthWithOutProperties = thingWithoutProperties.toString().length(); final long propertiesLength = propertiesJsonObject.toString().length() + "properties".length() + featureId.length() + 5L; return lengthWithOutProperties + propertiesLength; }, command::getDittoHeaders); return extractFeature(command, nonNullThing) .map(feature -> getModifyOrCreateResult(feature, context, nextRevision, command, thing, metadata)) .orElseGet(() -> ResultFactory.newErrorResult( ExceptionFactory.featureNotFound(context.getState(), featureId, command.getDittoHeaders()), command)); } ModifyFeaturePropertiesStrategy(); @Override Optional<EntityTag> previousEntityTag(final ModifyFeatureProperties command,
            @Nullable final Thing previousEntity); @Override Optional<EntityTag> nextEntityTag(final ModifyFeatureProperties command, @Nullable final Thing newEntity);  }
@Test public void modifyFeaturePropertiesSoThatThingGetsTooLarge() { final CommandStrategy.Context<ThingId> context = getDefaultContext(); final Feature feature = Feature.newBuilder() .properties(JsonObject.newBuilder().set("foo", false).set("bar", 42).build()) .withId("myFeature") .build(); final long staticOverhead = 80; final StringBuilder sb = new StringBuilder(); for (int i = 0; i < THING_SIZE_LIMIT_BYTES - staticOverhead; i++) { sb.append('a'); } final JsonObject largeAttributes = JsonObject.newBuilder() .set("a", sb.toString()) .build(); final ThingId thingId = ThingId.of("foo","bar"); final Thing thing = Thing.newBuilder() .setId(thingId) .setAttributes(largeAttributes) .build(); CreateThing.of(thing, null, DittoHeaders.empty()); final ModifyFeatureProperties command = ModifyFeatureProperties.of(thingId, feature.getId(), feature.getProperties().get(), DittoHeaders.empty()); assertThatThrownBy(() -> underTest.doApply(context, thing, NEXT_REVISION, command, null)) .isInstanceOf(ThingTooLargeException.class); }