From 16c3ef9494803c497bb2d943daf0d81b348f1dbd Mon Sep 17 00:00:00 2001 From: Robert Isele Date: Thu, 29 Jan 2026 16:10:41 +0100 Subject: [PATCH 1/6] First iteration of consolidating configured directories. --- silk-core/src/main/resources/logback.xml | 6 +- silk-core/src/main/resources/reference.conf | 18 +++++- .../org/silkframework/config/Config.scala | 57 +------------------ .../silkframework/config/Directories.scala | 33 +++++++++++ .../app/config/WorkbenchConfig.scala | 21 +++---- .../workspace/WorkspaceController.scala | 2 +- 6 files changed, 62 insertions(+), 75 deletions(-) create mode 100644 silk-core/src/main/scala/org/silkframework/config/Directories.scala diff --git a/silk-core/src/main/resources/logback.xml b/silk-core/src/main/resources/logback.xml index c43a5e2688..b91e64e9d7 100644 --- a/silk-core/src/main/resources/logback.xml +++ b/silk-core/src/main/resources/logback.xml @@ -1,9 +1,9 @@ - + - ${elds.home}/var/log/dataintegration.log + ${cmem.home}/dataintegration.log %d{yyyy-MM-dd'T'HH:mm:ss.SSSX,UTC} %-5level %logger{15} - %message%n%xException @@ -20,7 +20,7 @@ - /tmp/spark.log + ${cmem.home}/spark.log /spark.%d{yyyyMMdd}.log.zip diff --git a/silk-core/src/main/resources/reference.conf b/silk-core/src/main/resources/reference.conf index e495faf1e4..f546635b3a 100644 --- a/silk-core/src/main/resources/reference.conf +++ b/silk-core/src/main/resources/reference.conf @@ -1,6 +1,18 @@ -# Set the elds.home variable. The ELDS_HOME environment variable is used if it has been defined. -elds.home = ${user.home}"/.silk" -elds.home = ${?ELDS_HOME} +# Set the cmem.home variable. The CMEM_HOME environment variable is used if it has been defined. +silk.home = ${user.home}"/.silk" + +directories = { + + # Base directory for all DataIntegration data. + data = ${silk.home}"/data" + + # Base directory for all caches. + cache = ${silk.home}"/caches" + + # Base directory for all logs. + logs = ${silk.home}"/logs" + +} ################################################# # Workspace Provider diff --git a/silk-core/src/main/scala/org/silkframework/config/Config.scala b/silk-core/src/main/scala/org/silkframework/config/Config.scala index 65794104f9..03b8dc287d 100644 --- a/silk-core/src/main/scala/org/silkframework/config/Config.scala +++ b/silk-core/src/main/scala/org/silkframework/config/Config.scala @@ -1,12 +1,9 @@ package org.silkframework.config import com.typesafe.config.{ConfigException, ConfigFactory, Config => TypesafeConfig} -import org.silkframework.config.Config._ import org.silkframework.runtime.validation.ValidationException -import java.io.File import java.time.{Duration, Instant} -import java.util.logging.Logger import javax.inject.Named import scala.language.implicitConversions @@ -24,17 +21,6 @@ trait Config { def timestamp: Instant } -object Config{ - final val ELDS_HOME_ENV: String = "ELDS_HOME" - final val ELDS_HOME_CONF: String = "elds.home" - final val USER_HOME_CONF: String = "user.home" - final val DATAINTEGRATION_PATH: String = "/etc/dataintegration" - final val DATAINTEGRATION_CONFIG_DIR: String = DATAINTEGRATION_PATH + "/conf" - final val DATAINTEGRATION_CONF: String = "/conf/dataintegration.conf" - final val REFERENCE_CONF: String = "/conf/reference.conf" - final val APPLICATION_CONF: String = "/conf/application.conf" -} - @Named("default") class DefaultConfig private() extends Config { // Overwrite default logging pattern for java.util.logging @@ -42,55 +28,14 @@ class DefaultConfig private() extends Config { System.setProperty("java.util.logging.SimpleFormatter.format", "%1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS %1$Tp %3$s%n%4$s: %5$s%6$s%n") } - private lazy val log = Logger.getLogger(this.getClass.getName) - private var config = this.synchronized {init()} private var currentTimestamp = Instant.now() - /** - * Will check and return if ELDS_HOME was defined either as environment variable or in the dataintegration config. - */ - lazy val eldsHomeDir: Option[File] ={ - ConfigFactory.invalidateCaches() - val conf = ConfigFactory.load() - Option(if(conf.hasPath(ELDS_HOME_CONF)) conf.getString(ELDS_HOME_CONF) else System.getenv(ELDS_HOME_ENV)) - .map(p => new File(p)) - } - private def init(): TypesafeConfig = { this.synchronized { ConfigFactory.invalidateCaches() - var fullConfig = ConfigFactory.load() - // Check if we are running as part of the eccenca Linked Data Suite - eldsHomeDir match { - case Some(eldsHome) => - val dataintegrationConfigPath = DATAINTEGRATION_PATH + DATAINTEGRATION_CONF - val configFile = new File(eldsHome, dataintegrationConfigPath) - if (!configFile.exists) { - val msg = new StringBuilder - msg ++= s"Configuration file not found at: ${configFile.getAbsolutePath}.\n" - msg ++= s"Falling back on default reference.conf file.\n" - msg ++= "Possible fix: Map a volume with the config file to this location.\n" - msg ++= "Otherwise set elds.home or $ELDS_HOME to point to the correct location." - log.warning(msg.toString()) - } - fullConfig = ConfigFactory.parseFile(configFile).withFallback(fullConfig) - case None => Logger.getLogger(this.getClass.getName).info( - "Variable $ELDS_HOME is not defined. If this application is not running in the ELDS context " + - "you can ignore this warning. Otherwise please configure $ELDS_HOME or elds.home." - ) - } - - // Check if we are running as part of the Play Framework - val playConfig1 = new File(System.getProperty(USER_HOME_CONF) + REFERENCE_CONF) - val playConfig2 = new File(System.getProperty(USER_HOME_CONF) + APPLICATION_CONF) - if (playConfig1.exists()) { - fullConfig = fullConfig.withFallback(ConfigFactory.parseFile(playConfig1)) - } - if (playConfig2.exists()) { - fullConfig = fullConfig.withFallback(ConfigFactory.parseFile(playConfig2)) - } + val fullConfig = ConfigFactory.load() currentTimestamp = Instant.now() fullConfig.resolve() } diff --git a/silk-core/src/main/scala/org/silkframework/config/Directories.scala b/silk-core/src/main/scala/org/silkframework/config/Directories.scala new file mode 100644 index 0000000000..32c85ca4bf --- /dev/null +++ b/silk-core/src/main/scala/org/silkframework/config/Directories.scala @@ -0,0 +1,33 @@ +package org.silkframework.config + +import java.io.File +import java.nio.file.Path + +/** + * Holds the paths to important directories used by Silk. + * + * @param data The directory where project data is stored. + * @param cache The directory where cache files are stored. + * @param logs The directory where log files are stored. + */ +case class Directories(data: Path, + cache: Path, + logs: Path) + +object Directories { + + private val config: Directories = { + val dirConfig = DefaultConfig.instance().getConfig("directories") + Directories( + data = new File(dirConfig.getString("data")).toPath, + cache = new File(dirConfig.getString("cache")).toPath, + logs = new File(dirConfig.getString("logs")).toPath + ) + } + + /** + * Returns the configured directories. + */ + def apply(): Directories = config + +} diff --git a/silk-workbench/silk-workbench-core/app/config/WorkbenchConfig.scala b/silk-workbench/silk-workbench-core/app/config/WorkbenchConfig.scala index ec462d80cd..2a5efef0ce 100644 --- a/silk-workbench/silk-workbench-core/app/config/WorkbenchConfig.scala +++ b/silk-workbench/silk-workbench-core/app/config/WorkbenchConfig.scala @@ -2,7 +2,7 @@ package config import com.typesafe.config.{Config => TypesafeConfig} import config.WorkbenchConfig.Tabs -import org.silkframework.config.{Config, DefaultConfig} +import org.silkframework.config.{Config, DefaultConfig, Directories} import org.silkframework.runtime.metrics.MeterRegistryProvider import org.silkframework.runtime.metrics.MetricsConfig.prefix import org.silkframework.runtime.resource._ @@ -204,7 +204,7 @@ object WorkbenchConfig { */ lazy val get = { val config = Configuration(DefaultConfig.instance()) - val resourceLoader = getResourceLoader + val resourceLoader = createBrandingResourceLoader WorkbenchConfig( title = config.getOptional[String]("workbench.title").getOrElse("Silk Workbench"), @@ -247,16 +247,13 @@ object WorkbenchConfig { } } - def getResourceLoader: ResourceLoader = { - DefaultConfig.instance.eldsHomeDir match { - case None => - // If no eLDs home directory is set, use the classpath resource loader only. - ClasspathResourceLoader("") - case Some(eldsHome) => - // If an eLDs home directory is set, use the file resource manager for the config directory. - val configDir = new File(eldsHome, Config.DATAINTEGRATION_CONFIG_DIR) - FallbackResourceManager(ReadOnlyResourceManager(ClasspathResourceLoader("")), FileResourceManager(configDir), writeIntoFallbackLoader = false) - } + /** + * The resource loader for branding resources, such as logos and welcome messages. + */ + def createBrandingResourceLoader: ResourceLoader = { + // First search in the branding directory inside the data directory and then in the classpath + val brandingDir = Directories().data.resolve("branding").toFile + FallbackResourceManager(FileResourceManager(brandingDir), ReadOnlyResourceManager(ClasspathResourceLoader("")), writeIntoFallbackLoader = false) } /** diff --git a/silk-workbench/silk-workbench-workspace/app/controllers/workspace/WorkspaceController.scala b/silk-workbench/silk-workbench-workspace/app/controllers/workspace/WorkspaceController.scala index aeb825febb..4ec47da12b 100644 --- a/silk-workbench/silk-workbench-workspace/app/controllers/workspace/WorkspaceController.scala +++ b/silk-workbench/silk-workbench-workspace/app/controllers/workspace/WorkspaceController.scala @@ -70,7 +70,7 @@ class WorkspaceController @Inject() (implicit workspaceReact: WorkspaceReact) ex // Load example and write it to a temporary file val exampleFile = Files.createTempFile("example", ".zip") - val inputStream = WorkbenchConfig.getResourceLoader.get("example.zip").inputStream + val inputStream = WorkbenchConfig.createBrandingResourceLoader.get("example.zip").inputStream try { Files.copy(inputStream, exampleFile, StandardCopyOption.REPLACE_EXISTING) From 39cbf0f3dd18e55d9961f08a6f32641dce3135fe Mon Sep 17 00:00:00 2001 From: Robert Isele Date: Thu, 29 Jan 2026 17:22:49 +0100 Subject: [PATCH 2/6] Further consolidated configured directories. --- silk-core/src/main/resources/logback.xml | 6 ++--- silk-core/src/main/resources/reference.conf | 24 +++++++++++-------- .../rule/RuntimeLinkingConfig.scala | 2 -- .../rule/execution/GenerateLinks.scala | 10 ++++---- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/silk-core/src/main/resources/logback.xml b/silk-core/src/main/resources/logback.xml index b91e64e9d7..5d96b1d77d 100644 --- a/silk-core/src/main/resources/logback.xml +++ b/silk-core/src/main/resources/logback.xml @@ -1,9 +1,9 @@ - + - ${cmem.home}/dataintegration.log + ${logDir}/dataintegration.log %d{yyyy-MM-dd'T'HH:mm:ss.SSSX,UTC} %-5level %logger{15} - %message%n%xException @@ -20,7 +20,7 @@ - ${cmem.home}/spark.log + ${logDir}/spark.log /spark.%d{yyyyMMdd}.log.zip diff --git a/silk-core/src/main/resources/reference.conf b/silk-core/src/main/resources/reference.conf index f546635b3a..60cb4c9959 100644 --- a/silk-core/src/main/resources/reference.conf +++ b/silk-core/src/main/resources/reference.conf @@ -1,16 +1,20 @@ -# Set the cmem.home variable. The CMEM_HOME environment variable is used if it has been defined. -silk.home = ${user.home}"/.silk" +################################################# +# Directories +################################################# directories = { - # Base directory for all DataIntegration data. - data = ${silk.home}"/data" + # Base directory for all Silk related files. + base = ${user.home}"/.silk" + + # Directory for all data. + data = ${directories.base}"/data" - # Base directory for all caches. - cache = ${silk.home}"/caches" + # Directory for all caches. + cache = ${directories.base}"/caches" - # Base directory for all logs. - logs = ${silk.home}"/logs" + # Directory for all logs. + logs = ${directories.base}"/logs" } @@ -22,7 +26,7 @@ directories = { workspace.provider.plugin = fileWorkspaceProvider workspace.provider.fileWorkspaceProvider = { # Directory to hold the workspace - dir = ${elds.home}"/workspace/" + dir = ${directories.data}"/workspace/" } ################################################# @@ -32,7 +36,7 @@ workspace.provider.fileWorkspaceProvider = { # Holds all resources in project specific directories. workspace.repository.plugin = projectFile workspace.repository.projectFile = { - dir = ${elds.home}"/workspace/" + dir = ${directories.data}"/workspace/" } # Setting the default internal dataset. diff --git a/silk-rules/src/main/scala/org/silkframework/rule/RuntimeLinkingConfig.scala b/silk-rules/src/main/scala/org/silkframework/rule/RuntimeLinkingConfig.scala index 77d9c0316f..d206c40719 100644 --- a/silk-rules/src/main/scala/org/silkframework/rule/RuntimeLinkingConfig.scala +++ b/silk-rules/src/main/scala/org/silkframework/rule/RuntimeLinkingConfig.scala @@ -31,7 +31,6 @@ import org.silkframework.rule.execution.ExecutionMethod * @param partitionSize The maximum size of the entity partitions in the cache. * @param numThreads The number of concurrent threads used for matching. * @param generateLinksWithEntities Generate links with the entities they connect. - * @param homeDir The directory used by Silk to store persistent information such as caches. * @param sampleSizeOpt Load all entities if set to None, else only load a random sample of max. the configured size * from each data source to be linked. * @param linkLimit If defined, the execution will stop after the configured number of links is reached and will return @@ -48,7 +47,6 @@ case class RuntimeLinkingConfig(executionMethod: ExecutionMethod = ExecutionMeth partitionSize: Int = 1000, numThreads: Int = Runtime.getRuntime.availableProcessors(), generateLinksWithEntities: Boolean = false, - homeDir: String = System.getProperty("user.home") + "/.silk/", logLevel: Level = Level.INFO, sampleSizeOpt: Option[Int] = None, linkLimit: Option[Int] = None, diff --git a/silk-rules/src/main/scala/org/silkframework/rule/execution/GenerateLinks.scala b/silk-rules/src/main/scala/org/silkframework/rule/execution/GenerateLinks.scala index 02191fccec..c9f0106dba 100644 --- a/silk-rules/src/main/scala/org/silkframework/rule/execution/GenerateLinks.scala +++ b/silk-rules/src/main/scala/org/silkframework/rule/execution/GenerateLinks.scala @@ -15,7 +15,7 @@ package org.silkframework.rule.execution import org.silkframework.cache.{EntityCache, FileEntityCache, MemoryEntityCache} -import org.silkframework.config.{Prefixes, Task} +import org.silkframework.config.{Directories, Prefixes, Task} import org.silkframework.dataset.{DataSource, LinkSink} import org.silkframework.entity.{Entity, EntitySchema, Link} import org.silkframework.execution.ExecutionReport @@ -193,11 +193,11 @@ class GenerateLinks(task: Task[LinkSpec], val sourceSchema = comparisonToRestrictionConverter.extendEntitySchemaWithLinkageRuleRestriction(entityDescs.source, rule, sourceOrTarget = true) val targetSchema = comparisonToRestrictionConverter.extendEntitySchemaWithLinkageRuleRestriction(entityDescs.target, rule, sourceOrTarget = false) if (runtimeConfig.useFileCache) { - val cacheDir = new File(runtimeConfig.homeDir + "/entityCache/" + task.id + UUID.randomUUID().toString) - + val cacheDir = Directories().cache.resolve("linkingCaches") + val fileName = task.id + "_" + UUID.randomUUID().toString DPair( - source = new FileEntityCache(sourceSchema, sourceIndexFunction, cacheDir + "_source/", runtimeConfig), - target = new FileEntityCache(targetSchema, targetIndexFunction, cacheDir + "_target/", runtimeConfig) + source = new FileEntityCache(sourceSchema, sourceIndexFunction, cacheDir.resolve(fileName + "_source").toFile, runtimeConfig), + target = new FileEntityCache(targetSchema, targetIndexFunction, cacheDir.resolve(fileName + "_target").toFile, runtimeConfig) ) } else { DPair( From 3ad9bd6a39926851fa18bf44a89a210c54abdbed Mon Sep 17 00:00:00 2001 From: Robert Isele Date: Fri, 30 Jan 2026 15:06:31 +0100 Subject: [PATCH 3/6] Consolidate configuration directory structure and update related paths --- silk-core/src/main/resources/reference.conf | 3 +++ .../scala/org/silkframework/config/Directories.scala | 5 ++++- .../app/config/WorkbenchConfig.scala | 10 +++++----- .../controllers/workspace/WorkspaceController.scala | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/silk-core/src/main/resources/reference.conf b/silk-core/src/main/resources/reference.conf index 60cb4c9959..23cb5ed23a 100644 --- a/silk-core/src/main/resources/reference.conf +++ b/silk-core/src/main/resources/reference.conf @@ -7,6 +7,9 @@ directories = { # Base directory for all Silk related files. base = ${user.home}"/.silk" + # Directory for all configuration files. + config = ${directories.base}"/config" + # Directory for all data. data = ${directories.base}"/data" diff --git a/silk-core/src/main/scala/org/silkframework/config/Directories.scala b/silk-core/src/main/scala/org/silkframework/config/Directories.scala index 32c85ca4bf..9827c6c951 100644 --- a/silk-core/src/main/scala/org/silkframework/config/Directories.scala +++ b/silk-core/src/main/scala/org/silkframework/config/Directories.scala @@ -6,11 +6,13 @@ import java.nio.file.Path /** * Holds the paths to important directories used by Silk. * + * @param config The directory where configuration files are stored. * @param data The directory where project data is stored. * @param cache The directory where cache files are stored. * @param logs The directory where log files are stored. */ -case class Directories(data: Path, +case class Directories(config: Path, + data: Path, cache: Path, logs: Path) @@ -19,6 +21,7 @@ object Directories { private val config: Directories = { val dirConfig = DefaultConfig.instance().getConfig("directories") Directories( + config = new File(dirConfig.getString("config")).toPath, data = new File(dirConfig.getString("data")).toPath, cache = new File(dirConfig.getString("cache")).toPath, logs = new File(dirConfig.getString("logs")).toPath diff --git a/silk-workbench/silk-workbench-core/app/config/WorkbenchConfig.scala b/silk-workbench/silk-workbench-core/app/config/WorkbenchConfig.scala index 2a5efef0ce..7bc0ce4abd 100644 --- a/silk-workbench/silk-workbench-core/app/config/WorkbenchConfig.scala +++ b/silk-workbench/silk-workbench-core/app/config/WorkbenchConfig.scala @@ -204,7 +204,7 @@ object WorkbenchConfig { */ lazy val get = { val config = Configuration(DefaultConfig.instance()) - val resourceLoader = createBrandingResourceLoader + val resourceLoader = createConfigResourceLoader WorkbenchConfig( title = config.getOptional[String]("workbench.title").getOrElse("Silk Workbench"), @@ -248,12 +248,12 @@ object WorkbenchConfig { } /** - * The resource loader for branding resources, such as logos and welcome messages. + * The resource loader for config resources, inclusing logos and welcome messages. */ - def createBrandingResourceLoader: ResourceLoader = { + def createConfigResourceLoader: ResourceLoader = { // First search in the branding directory inside the data directory and then in the classpath - val brandingDir = Directories().data.resolve("branding").toFile - FallbackResourceManager(FileResourceManager(brandingDir), ReadOnlyResourceManager(ClasspathResourceLoader("")), writeIntoFallbackLoader = false) + val configDir = Directories().config.toFile + FallbackResourceManager(FileResourceManager(configDir), ReadOnlyResourceManager(ClasspathResourceLoader("")), writeIntoFallbackLoader = false) } /** diff --git a/silk-workbench/silk-workbench-workspace/app/controllers/workspace/WorkspaceController.scala b/silk-workbench/silk-workbench-workspace/app/controllers/workspace/WorkspaceController.scala index 4ec47da12b..e455deef7c 100644 --- a/silk-workbench/silk-workbench-workspace/app/controllers/workspace/WorkspaceController.scala +++ b/silk-workbench/silk-workbench-workspace/app/controllers/workspace/WorkspaceController.scala @@ -70,7 +70,7 @@ class WorkspaceController @Inject() (implicit workspaceReact: WorkspaceReact) ex // Load example and write it to a temporary file val exampleFile = Files.createTempFile("example", ".zip") - val inputStream = WorkbenchConfig.createBrandingResourceLoader.get("example.zip").inputStream + val inputStream = WorkbenchConfig.createConfigResourceLoader.get("example.zip").inputStream try { Files.copy(inputStream, exampleFile, StandardCopyOption.REPLACE_EXISTING) From 7ffc9579b163a3401182b011518715debd64bf97 Mon Sep 17 00:00:00 2001 From: Robert Isele Date: Fri, 30 Jan 2026 15:22:08 +0100 Subject: [PATCH 4/6] Refactor EccencaApplicationLoader to utilize Silk's DefaultConfig for configuration loading --- .../org/silkframework/config/Config.scala | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/silk-core/src/main/scala/org/silkframework/config/Config.scala b/silk-core/src/main/scala/org/silkframework/config/Config.scala index 03b8dc287d..75c9ed3291 100644 --- a/silk-core/src/main/scala/org/silkframework/config/Config.scala +++ b/silk-core/src/main/scala/org/silkframework/config/Config.scala @@ -23,6 +23,7 @@ trait Config { @Named("default") class DefaultConfig private() extends Config { + // Overwrite default logging pattern for java.util.logging if (System.getProperty("java.util.logging.SimpleFormatter.format") == null) { System.setProperty("java.util.logging.SimpleFormatter.format", "%1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS %1$Tp %3$s%n%4$s: %5$s%6$s%n") @@ -35,7 +36,28 @@ class DefaultConfig private() extends Config { private def init(): TypesafeConfig = { this.synchronized { ConfigFactory.invalidateCaches() - val fullConfig = ConfigFactory.load() + + // Check for external config file based on environment variables + val configPath = sys.env.get("DATAINTEGRATION_CONFIG") match { + case Some(configDir) => s"$configDir/dataintegration.conf" + case None => sys.env.get("CMEM_HOME") match { + case Some(cmemHome) => s"$cmemHome/dataintegration/config/dataintegration.conf" + case None => sys.props.get("user.home").map(home => s"$home/.cmem/dataintegration/config/dataintegration.conf").getOrElse("") + } + } + + val configFile = new java.io.File(configPath) + val fullConfig = if (configFile.exists()) { + println(s"Loading external config from: $configPath") + // Load with external config having highest priority + val externalConfig = ConfigFactory.parseFile(configFile) + ConfigFactory.systemProperties() + .withFallback(externalConfig) + .withFallback(ConfigFactory.load()) + } else { + ConfigFactory.load() + } + currentTimestamp = Instant.now() fullConfig.resolve() } From 03a2254e209f55fac0acf7ae4a4de63265072ca9 Mon Sep 17 00:00:00 2001 From: Robert Isele Date: Tue, 24 Feb 2026 09:26:04 +0100 Subject: [PATCH 5/6] Update FileUtils to write Java temp files to the configure cache directory. --- .../main/scala/org/silkframework/util/FileUtils.scala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/silk-core/src/main/scala/org/silkframework/util/FileUtils.scala b/silk-core/src/main/scala/org/silkframework/util/FileUtils.scala index c30fecb8ad..af346d124d 100644 --- a/silk-core/src/main/scala/org/silkframework/util/FileUtils.scala +++ b/silk-core/src/main/scala/org/silkframework/util/FileUtils.scala @@ -17,7 +17,7 @@ package org.silkframework.util import org.silkframework.config.DefaultConfig import java.io.{File, IOException} -import java.nio.file.Files +import java.nio.file.{Files, Paths} import scala.language.implicitConversions import scala.util.Try @@ -35,11 +35,16 @@ object FileUtils { val tmpDir = Files.createTempDirectory("silk-tmp-file-dir") tmpDir.toString } - if(cfg.hasPath(tmpDirKey)) { + val dir = if(cfg.hasPath(tmpDirKey)) { Try(cfg.getString(tmpDirKey)).getOrElse(default) } else { default } + // Ensure the directory exists (needed when accessed outside ApplicationValidationModule, e.g. standalone Silk) + Files.createDirectories(Paths.get(dir)) + // Redirect all standard Java temp file creation to the configured directory + System.setProperty("java.io.tmpdir", dir) + dir } } From 88f48c889d1308ecde9e20b188407cea5d5833b7 Mon Sep 17 00:00:00 2001 From: Robert Isele Date: Tue, 24 Feb 2026 12:46:29 +0100 Subject: [PATCH 6/6] config.tempFilesDirectory should always be set to the tmp directory within the configured cache directory --- silk-core/src/main/resources/reference.conf | 3 +++ silk-workbench/conf/application.conf | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/silk-core/src/main/resources/reference.conf b/silk-core/src/main/resources/reference.conf index 23cb5ed23a..ec15015602 100644 --- a/silk-core/src/main/resources/reference.conf +++ b/silk-core/src/main/resources/reference.conf @@ -21,6 +21,9 @@ directories = { } +# Temp file directory used e.g. for storing result files for async requests +config.tempFilesDirectory = ${directories.cache}"/tmp" + ################################################# # Workspace Provider ################################################# diff --git a/silk-workbench/conf/application.conf b/silk-workbench/conf/application.conf index e9192f0592..26196d7926 100644 --- a/silk-workbench/conf/application.conf +++ b/silk-workbench/conf/application.conf @@ -97,7 +97,4 @@ cache-updater { } } -# Temp file directory used e.g. for storing result files for async requests -config.tempFilesDirectory = ${silk.home}"/tmp" - play.modules.enabled += "cacheUpdater.CacheUpdaterModule" \ No newline at end of file