From 165387d6eec2bd006bf484cd2c0e4d72eca5ee2e Mon Sep 17 00:00:00 2001 From: Michael Jacoby Date: Wed, 29 Jan 2025 11:30:41 +0100 Subject: [PATCH] Fix bug that auxiliary files were not loaded when starting from code with an initial model file (#1022) * fix bug that auxiliary files were not loaded when starting from code with an initial model file * add unit test * improve code quality --- .../iosb/ilt/faaast/service/Service.java | 16 +++- docs/source/other/release-notes.md | 2 + .../iosb/ilt/faaast/service/starter/App.java | 17 +--- .../ilt/faaast/service/test/ServiceIT.java | 77 +++++++++++++++++++ 4 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 test/src/test/java/de/fraunhofer/iosb/ilt/faaast/service/test/ServiceIT.java diff --git a/core/src/main/java/de/fraunhofer/iosb/ilt/faaast/service/Service.java b/core/src/main/java/de/fraunhofer/iosb/ilt/faaast/service/Service.java index 26297543c..3487f8ea3 100644 --- a/core/src/main/java/de/fraunhofer/iosb/ilt/faaast/service/Service.java +++ b/core/src/main/java/de/fraunhofer/iosb/ilt/faaast/service/Service.java @@ -35,6 +35,7 @@ import de.fraunhofer.iosb.ilt.faaast.service.model.api.paging.PagingInfo; import de.fraunhofer.iosb.ilt.faaast.service.model.exception.PersistenceException; import de.fraunhofer.iosb.ilt.faaast.service.model.exception.ResourceNotFoundException; +import de.fraunhofer.iosb.ilt.faaast.service.model.serialization.DataFormat; import de.fraunhofer.iosb.ilt.faaast.service.persistence.AssetAdministrationShellSearchCriteria; import de.fraunhofer.iosb.ilt.faaast.service.persistence.ConceptDescriptionSearchCriteria; import de.fraunhofer.iosb.ilt.faaast.service.persistence.Persistence; @@ -46,6 +47,7 @@ import de.fraunhofer.iosb.ilt.faaast.service.typing.TypeExtractor; import de.fraunhofer.iosb.ilt.faaast.service.typing.TypeInfo; import de.fraunhofer.iosb.ilt.faaast.service.util.Ensure; +import de.fraunhofer.iosb.ilt.faaast.service.util.FileHelper; import de.fraunhofer.iosb.ilt.faaast.service.util.ReferenceHelper; import java.util.ArrayList; import java.util.List; @@ -292,10 +294,11 @@ public void stop() { private void init() throws ConfigurationException { Ensure.requireNonNull(config.getPersistence(), new InvalidConfigurationException("config.persistence must be non-null")); - persistence = (Persistence) config.getPersistence().newInstance(config.getCore(), this); Ensure.requireNonNull(config.getFileStorage(), new InvalidConfigurationException("config.filestorage must be non-null")); - fileStorage = (FileStorage) config.getFileStorage().newInstance(config.getCore(), this); Ensure.requireNonNull(config.getMessageBus(), new InvalidConfigurationException("config.messagebus must be non-null")); + ensureInitialModelFilesAreLoaded(); + persistence = (Persistence) config.getPersistence().newInstance(config.getCore(), this); + fileStorage = (FileStorage) config.getFileStorage().newInstance(config.getCore(), this); messageBus = (MessageBus) config.getMessageBus().newInstance(config.getCore(), this); if (config.getAssetConnections() != null) { List assetConnections = new ArrayList<>(); @@ -318,4 +321,13 @@ private void init() throws ConfigurationException { this.requestExecutionContext = new DynamicRequestExecutionContext(this); this.registrySynchronization = new RegistrySynchronization(config.getCore(), persistence, messageBus, endpoints); } + + + private void ensureInitialModelFilesAreLoaded() { + if (Objects.nonNull(config.getPersistence().getInitialModelFile()) + && DataFormat.forFileExtension(FileHelper.getFileExtensionWithoutSeparator(config.getPersistence().getInitialModelFile())).stream() + .anyMatch(DataFormat::getCanStoreFiles)) { + config.getFileStorage().setInitialModelFile(config.getPersistence().getInitialModelFile()); + } + } } diff --git a/docs/source/other/release-notes.md b/docs/source/other/release-notes.md index 1a6058513..565ebc642 100644 --- a/docs/source/other/release-notes.md +++ b/docs/source/other/release-notes.md @@ -3,6 +3,8 @@ ## 1.3.0-SNAPSHOT (current development version) **Internal changes & bugfixes** +- General + - Fix bug that auxiliary files were not loaded when starting from code with an initial model file - Endpoint - HTTP - URL query parameters are now correctly URL-decoded diff --git a/starter/src/main/java/de/fraunhofer/iosb/ilt/faaast/service/starter/App.java b/starter/src/main/java/de/fraunhofer/iosb/ilt/faaast/service/starter/App.java index cf32f7c03..2fec0b005 100644 --- a/starter/src/main/java/de/fraunhofer/iosb/ilt/faaast/service/starter/App.java +++ b/starter/src/main/java/de/fraunhofer/iosb/ilt/faaast/service/starter/App.java @@ -462,7 +462,7 @@ protected static String envPathWithAlternativeSeparator(String key) { } - private void withModelFromCommandLine(ServiceConfig config, String fileExtension) { + private void withModelFromCommandLine(ServiceConfig config) { try { LOGGER.info("Model: {} (CLI)", modelFile.getCanonicalFile()); if (config.getPersistence().getInitialModelFile() != null) { @@ -475,13 +475,10 @@ private void withModelFromCommandLine(ServiceConfig config, String fileExtension LOGGER.info("Retrieving path of model file failed with {}", e.getMessage()); } config.getPersistence().setInitialModelFile(modelFile); - if (DataFormat.AASX.getFileExtensions().contains(fileExtension)) { - config.getFileStorage().setInitialModelFile(modelFile); - } } - private void withModelFromEnvironmentVariable(ServiceConfig config, String fileExtension) { + private void withModelFromEnvironmentVariable(ServiceConfig config) { LOGGER.info("Model: {} (ENV)", getEnvValue(ENV_PATH_MODEL_FILE)); if (config.getPersistence().getInitialModelFile() != null) { LOGGER.info("Overriding model path {} set in Config File with {}", @@ -489,20 +486,17 @@ private void withModelFromEnvironmentVariable(ServiceConfig config, String fileE getEnvValue(ENV_PATH_MODEL_FILE)); } config.getPersistence().setInitialModelFile(new File(getEnvValue(ENV_PATH_MODEL_FILE))); - if (DataFormat.AASX.getFileExtensions().contains(fileExtension)) { - config.getFileStorage().setInitialModelFile(new File(getEnvValue(ENV_PATH_MODEL_FILE))); - } modelFile = new File(getEnvValue(ENV_PATH_MODEL_FILE)); } private ServiceConfig withModel(ServiceConfig config) { if (spec.commandLine().getParseResult().hasMatchedOption(COMMAND_MODEL)) { - withModelFromCommandLine(config, FileHelper.getFileExtensionWithoutSeparator(modelFile)); + withModelFromCommandLine(config); return config; } if (getEnvValue(ENV_PATH_MODEL_FILE) != null && !getEnvValue(ENV_PATH_MODEL_FILE).isBlank()) { - withModelFromEnvironmentVariable(config, FileHelper.getFileExtensionWithoutSeparator(getEnvValue(ENV_PATH_MODEL_FILE))); + withModelFromEnvironmentVariable(config); return config; } if (config.getPersistence().getInitialModelFile() != null) { @@ -514,9 +508,6 @@ private ServiceConfig withModel(ServiceConfig config) { if (defaultModel.isPresent()) { LOGGER.info("Model: {} (default location)", defaultModel.get().getAbsoluteFile()); config.getPersistence().setInitialModelFile(defaultModel.get()); - if (DataFormat.AASX.getFileExtensions().contains(FileHelper.getFileExtensionWithoutSeparator(defaultModel.get()))) { - config.getFileStorage().setInitialModelFile(defaultModel.get()); - } modelFile = new File(defaultModel.get().getAbsolutePath()); return config; } diff --git a/test/src/test/java/de/fraunhofer/iosb/ilt/faaast/service/test/ServiceIT.java b/test/src/test/java/de/fraunhofer/iosb/ilt/faaast/service/test/ServiceIT.java new file mode 100644 index 000000000..b0055b186 --- /dev/null +++ b/test/src/test/java/de/fraunhofer/iosb/ilt/faaast/service/test/ServiceIT.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021 Fraunhofer IOSB, eine rechtlich nicht selbstaendige + * Einrichtung der Fraunhofer-Gesellschaft zur Foerderung der angewandten + * Forschung e.V. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.fraunhofer.iosb.ilt.faaast.service.test; + +import de.fraunhofer.iosb.ilt.faaast.service.Service; +import de.fraunhofer.iosb.ilt.faaast.service.assetconnection.AssetConnectionException; +import de.fraunhofer.iosb.ilt.faaast.service.config.ServiceConfig; +import de.fraunhofer.iosb.ilt.faaast.service.dataformat.EnvironmentSerializationManager; +import de.fraunhofer.iosb.ilt.faaast.service.dataformat.SerializationException; +import de.fraunhofer.iosb.ilt.faaast.service.exception.ConfigurationException; +import de.fraunhofer.iosb.ilt.faaast.service.filestorage.memory.FileStorageInMemoryConfig; +import de.fraunhofer.iosb.ilt.faaast.service.messagebus.internal.MessageBusInternalConfig; +import de.fraunhofer.iosb.ilt.faaast.service.model.EnvironmentContext; +import de.fraunhofer.iosb.ilt.faaast.service.model.exception.PersistenceException; +import de.fraunhofer.iosb.ilt.faaast.service.model.exception.ResourceNotFoundException; +import de.fraunhofer.iosb.ilt.faaast.service.model.serialization.DataFormat; +import de.fraunhofer.iosb.ilt.faaast.service.persistence.memory.PersistenceInMemoryConfig; +import java.io.File; +import java.io.IOException; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultEnvironment; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultFile; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodel; +import org.junit.Assert; +import org.junit.Test; + + +public class ServiceIT { + + @Test + public void testLoadingAuxiliaryFilesFromInitialModel() + throws ConfigurationException, AssetConnectionException, IOException, SerializationException, ResourceNotFoundException, PersistenceException { + final String submodelId = "http://example.com/submodel/1"; + final String submodelIdShort = "submodel1"; + final String fileIdShort = "file1"; + final String filePath = "/foo/bar/file1.xyz"; + final byte[] fileContent = "hello world".getBytes(); + File aasxFile = File.createTempFile("model", ".aasx"); + aasxFile.deleteOnExit(); + EnvironmentContext model = EnvironmentContext.builder() + .environment(new DefaultEnvironment.Builder() + .submodels(new DefaultSubmodel.Builder() + .id(submodelId) + .idShort(submodelIdShort) + .submodelElements(new DefaultFile.Builder() + .idShort(fileIdShort) + .contentType("application/octet-stream") + .value(filePath) + .build()) + .build()) + .build()) + .file(fileContent, filePath) + .build(); + EnvironmentSerializationManager.serializerFor(DataFormat.AASX).write(aasxFile, model); + ServiceConfig config = ServiceConfig.builder() + .persistence(PersistenceInMemoryConfig.builder() + .initialModelFile(aasxFile) + .build()) + .fileStorage(FileStorageInMemoryConfig.builder().build()) + .messageBus(MessageBusInternalConfig.builder().build()) + .build(); + Service service = new Service(config); + byte[] actual = service.getFileStorage().get(filePath); + Assert.assertArrayEquals(fileContent, actual); + } +}