Fix cached entity was updated during inlineImages

This commit is contained in:
ViacheslavKlimov 2024-12-19 18:12:00 +02:00
parent ed65586024
commit ad97199f04
10 changed files with 32 additions and 11 deletions

View File

@ -88,7 +88,7 @@ public class AssetProfileController extends BaseController {
AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId));
var result = checkAssetProfileId(assetProfileId, Operation.READ);
if (inlineImages) {
imageService.inlineImage(result);
result = imageService.inlineImage(result);
}
return result;
}

View File

@ -96,7 +96,7 @@ public class DeviceProfileController extends BaseController {
DeviceProfileId deviceProfileId = new DeviceProfileId(toUUID(strDeviceProfileId));
var result = checkDeviceProfileId(deviceProfileId, Operation.READ);
if (inlineImages) {
imageService.inlineImage(result);
result = imageService.inlineImage(result);
}
return result;
}

View File

@ -90,7 +90,7 @@ public class WidgetsBundleController extends BaseController {
WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId));
var result = checkWidgetsBundleId(widgetsBundleId, Operation.READ);
if (inlineImages) {
imageService.inlineImage(result);
result = imageService.inlineImage(result);
}
return result;
}

View File

@ -34,7 +34,6 @@ public class AssetProfileExportService extends BaseEntityExportService<AssetProf
assetProfile.setDefaultDashboardId(getExternalIdOrElseInternal(ctx, assetProfile.getDefaultDashboardId()));
assetProfile.setDefaultRuleChainId(getExternalIdOrElseInternal(ctx, assetProfile.getDefaultRuleChainId()));
assetProfile.setDefaultEdgeRuleChainId(getExternalIdOrElseInternal(ctx, assetProfile.getDefaultEdgeRuleChainId()));
imageService.inlineImage(assetProfile);
}
@Override

View File

@ -32,7 +32,6 @@ import org.thingsboard.server.common.data.sync.ie.AttributeExportData;
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
import org.thingsboard.server.dao.attributes.AttributesService;
import org.thingsboard.server.dao.relation.RelationDao;
import org.thingsboard.server.dao.resource.ImageService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.ie.exporting.EntityExportService;
import org.thingsboard.server.service.sync.ie.exporting.ExportableEntitiesService;
@ -60,8 +59,6 @@ public class DefaultEntityExportService<I extends EntityId, E extends Exportable
private RelationDao relationDao;
@Autowired
private AttributesService attributesService;
@Autowired
protected ImageService imageService;
@Override
public final D getExportData(EntitiesExportCtx<?> ctx, I entityId) throws ThingsboardException {

View File

@ -34,7 +34,6 @@ public class DeviceProfileExportService extends BaseEntityExportService<DevicePr
deviceProfile.setDefaultDashboardId(getExternalIdOrElseInternal(ctx, deviceProfile.getDefaultDashboardId()));
deviceProfile.setDefaultRuleChainId(getExternalIdOrElseInternal(ctx, deviceProfile.getDefaultRuleChainId()));
deviceProfile.setDefaultEdgeRuleChainId(getExternalIdOrElseInternal(ctx, deviceProfile.getDefaultEdgeRuleChainId()));
imageService.inlineImage(deviceProfile);
}
@Override

View File

@ -40,7 +40,6 @@ public class WidgetsBundleExportService extends BaseEntityExportService<WidgetsB
if (widgetsBundle.getTenantId() == null || widgetsBundle.getTenantId().isNullUid()) {
throw new IllegalArgumentException("Export of system Widget Bundles is not allowed");
}
imageService.inlineImage(widgetsBundle);
List<String> fqns = widgetTypeService.findWidgetFqnsByWidgetsBundleId(ctx.getTenantId(), widgetsBundle.getId());
exportData.setFqns(fqns);

View File

@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.test.context.TestPropertySource;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.ImageDescriptor;
import org.thingsboard.server.common.data.ResourceExportData;
import org.thingsboard.server.common.data.ResourceSubType;
@ -321,6 +322,24 @@ public class ImageControllerTest extends AbstractControllerTest {
assertThat(systemParams.getMaxResourceSize()).isEqualTo(0);
}
@Test
public void testInlineImages() throws Exception {
TbResourceInfo imageInfo = uploadImage(HttpMethod.POST, "/api/image", "my_png_image.png", "image/png", PNG_IMAGE);
DeviceProfile deviceProfile = createDeviceProfile("Test");
deviceProfile.setImage("tb-image;" + imageInfo.getLink());
deviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
DeviceProfile deviceProfileInlined = doGet("/api/deviceProfile/" + deviceProfile.getUuidId() + "?inlineImages=true", DeviceProfile.class);
assertThat(deviceProfileInlined.getImage()).isEqualTo("tb-image:" +
Base64.getEncoder().encodeToString(imageInfo.getResourceKey().getBytes()) + ":"
+ Base64.getEncoder().encodeToString(imageInfo.getName().getBytes()) + ":"
+ Base64.getEncoder().encodeToString(imageInfo.getResourceSubType().name().getBytes()) +
";data:image/png;base64," + Base64.getEncoder().encodeToString(PNG_IMAGE));
deviceProfile = doGet("/api/deviceProfile/" + deviceProfile.getUuidId(), DeviceProfile.class);
assertThat(deviceProfile.getImage()).isEqualTo("tb-image;" + imageInfo.getLink());
}
private TbResourceInfo updateImagePublicStatus(String filename, boolean isPublic) throws Exception {
return doPut("/api/images/tenant/" + filename + "/public/" + isPublic, "", TbResourceInfo.class);
}

View File

@ -64,7 +64,7 @@ public interface ImageService {
boolean updateImagesUsage(WidgetTypeDetails widgetType);
void inlineImage(HasImage entity);
<T extends HasImage> T inlineImage(T entity);
Collection<TbResourceInfo> getUsedImages(Dashboard dashboard);

View File

@ -27,6 +27,7 @@ import org.apache.commons.lang3.tuple.Pair;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cache.CaffeineTbTransactionalCache;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.EntityType;
@ -526,9 +527,16 @@ public class BaseImageService extends BaseResourceService implements ImageServic
}
@Override
public void inlineImage(HasImage entity) {
public <T extends HasImage> T inlineImage(T entity) {
log.trace("Executing inlineImage [{}] [{}] [{}]", entity.getTenantId(), entity.getClass().getSimpleName(), entity.getName());
if (StringUtils.isEmpty(entity.getImage())) {
return entity;
}
if (cache instanceof CaffeineTbTransactionalCache) {
entity = JacksonUtil.clone(entity); // cloning the entity to avoid updating the cached one
}
entity.setImage(inlineImage(entity.getTenantId(), "image", entity.getImage(), true));
return entity;
}
@Override