This is an automated email from the ASF dual-hosted git repository. jsinovassin pushed a commit to branch UNOMI-986-oneshot-import-tenant-dir in repository https://gitbox.apache.org/repos/asf/unomi.git
commit 59a98f19ec73f815864dcc0852f3548ee1e7017f Author: jsinovassin <[email protected]> AuthorDate: Wed Sep 16 18:25:45 2026 +0200 UNOMI-986: Write a one-shot import CSV to the directory of its tenant The endpoint that receives a one-shot CSV import and the Camel route that consumes it disagreed on the path. The endpoint wrote the file to the root of the upload directory. The route reads the tenant from the name of the directory holding the file, and the root directory is not a tenant. Every one-shot import uploaded through the endpoint was therefore dropped. The caller saw no failure. The upload answered 200, and the only trace was one warning: WARN ImportConfigByFileNameProcessor - Invalid or missing tenant ID in path: /opt/unomi/data/tmp/unomi_oneshot_import_configs/19d061b5-....csv The endpoint now resolves the current tenant, creates the directory named after it, and writes the file there. The route already reads sub-directories, because ProfileImportOneShotRouteBuilder declares recursive=true, so the per-tenant directory is what it expected all along. Measured on Apache Unomi 3.1.0-SNAPSHOT. The upload writes <uploadDir>/default/<importConfigId>.csv, the route reads it, and the profiles of the CSV are imported. An end to end test that drives the import through the user interface went from failing to passing. ExportConfigurationServiceEndPoint carries a /oneshot path as well. This commit does not cover the export side, which is worth checking for the same disagreement. --- .../rest/ImportConfigurationServiceEndPoint.java | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/extensions/router/router-rest/src/main/java/org/apache/unomi/router/rest/ImportConfigurationServiceEndPoint.java b/extensions/router/router-rest/src/main/java/org/apache/unomi/router/rest/ImportConfigurationServiceEndPoint.java index e8d639df1..3dc1cb4d8 100644 --- a/extensions/router/router-rest/src/main/java/org/apache/unomi/router/rest/ImportConfigurationServiceEndPoint.java +++ b/extensions/router/router-rest/src/main/java/org/apache/unomi/router/rest/ImportConfigurationServiceEndPoint.java @@ -20,6 +20,7 @@ import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.ext.multipart.Multipart; import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing; import org.apache.unomi.api.services.ConfigSharingService; +import org.apache.unomi.api.services.ExecutionContextManager; import org.apache.unomi.router.api.ImportConfiguration; import org.apache.unomi.router.api.RouterConstants; import org.apache.unomi.router.api.services.ImportExportConfigurationService; @@ -62,10 +63,17 @@ public class ImportConfigurationServiceEndPoint extends AbstractConfigurationSer @Reference protected ConfigSharingService configSharingService; + @Reference + protected ExecutionContextManager executionContextManager; + public void setConfigSharingService(ConfigSharingService configSharingService) { this.configSharingService = configSharingService; } + public void setExecutionContextManager(ExecutionContextManager executionContextManager) { + this.executionContextManager = executionContextManager; + } + public ImportConfigurationServiceEndPoint() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { LOGGER.info("Initializing import configuration service endpoint..."); } @@ -131,8 +139,9 @@ public class ImportConfigurationServiceEndPoint extends AbstractConfigurationSer /** * Uploads a one-shot CSV file for an existing import configuration. * <p> - * The file is stored under the configured one-shot upload directory as {@code {importConfigId}.csv} - * for subsequent Camel processing. + * The file is stored under the configured one-shot upload directory, in a sub-directory named + * after the current tenant, as {@code {tenantId}/{importConfigId}.csv}. The Camel route reads the + * tenant from that directory name. * * @param importConfigId the import configuration id (multipart field) * @param file the CSV file upload (multipart field) @@ -148,7 +157,13 @@ public class ImportConfigurationServiceEndPoint extends AbstractConfigurationSer public Response processOneshotImportConfigurationCSV(@Multipart(value = "importConfigId") @NotNull @Pattern(regexp = "^[a-zA-Z0-9_.\\-]{1,255}$") String importConfigId, @Multipart(value = "file") Attachment file) { try { - java.nio.file.Path path = Paths.get(configSharingService.getProperty(RouterConstants.IMPORT_ONESHOT_UPLOAD_DIR) + importConfigId + ".csv"); + // The Camel route reads the tenant from the directory holding the file, so the upload + // writes it there. Without that directory ImportConfigByFileNameProcessor answers + // "Invalid or missing tenant ID in path" and drops the file, and the import never runs. + String tenantId = executionContextManager.getCurrentContext().getTenantId(); + java.nio.file.Path tenantDir = Paths.get(String.valueOf(configSharingService.getProperty(RouterConstants.IMPORT_ONESHOT_UPLOAD_DIR)), tenantId); + Files.createDirectories(tenantDir); + java.nio.file.Path path = tenantDir.resolve(importConfigId + ".csv"); Files.deleteIfExists(path); InputStream in = file.getObject(InputStream.class);
