From db4db1741d46eb66505552230399175daa7c987d Mon Sep 17 00:00:00 2001 From: luklpz Date: Fri, 15 May 2026 08:14:21 +0200 Subject: [PATCH] fix: handle Dolibarr/PS 404 on empty filter results MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both APIs return 404 (not 200+empty) when a filter finds no results. Catch DolibarrApiException(404) in getOrCreateThirdparty and getProductByRef; catch PrestashopApiException(404) in getProductByReference — treat as empty/not-found instead of error. Co-Authored-By: Claude Sonnet 4.6 --- .../integration/dolibarr/DolibarrClient.java | 45 ++++++++++++------- .../prestashop/PrestashopClient.java | 31 ++++++++----- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/dolibarr/DolibarrClient.java b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/dolibarr/DolibarrClient.java index 01268a6..1d55fc4 100644 --- a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/dolibarr/DolibarrClient.java +++ b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/dolibarr/DolibarrClient.java @@ -1,6 +1,7 @@ package com.teterialosjuanjos.tfg.sync_service.integration.dolibarr; import com.teterialosjuanjos.tfg.sync_service.integration.dolibarr.dto.*; +import com.teterialosjuanjos.tfg.sync_service.integration.dolibarr.exception.DolibarrApiException; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.core.ParameterizedTypeReference; @@ -50,15 +51,19 @@ public class DolibarrClient { */ public DolibarrProductDto getProductByRef(String ref) { String filter = "(t.ref:=:'%s')".formatted(ref); - List results = restClient.get() - .uri(u -> u.path("/products") - .queryParam("sqlfilters", filter) - .queryParam("limit", 1) - .build()) - .retrieve() - .body(new ParameterizedTypeReference>() {}); - - return (results != null && !results.isEmpty()) ? results.get(0) : null; + try { + List results = restClient.get() + .uri(u -> u.path("/products") + .queryParam("sqlfilters", filter) + .queryParam("limit", 1) + .build()) + .retrieve() + .body(new ParameterizedTypeReference>() {}); + return (results != null && !results.isEmpty()) ? results.get(0) : null; + } catch (DolibarrApiException e) { + if (e.getStatusCode().value() == 404) return null; + throw e; + } } /** @@ -119,13 +124,21 @@ public class DolibarrClient { */ public DolibarrThirdpartyDto getOrCreateThirdparty(String email, String name) { log.debug("Looking up Dolibarr thirdparty email={}", email); - List matches = restClient.get() - .uri(u -> u.path("/thirdparties") - .queryParam("sqlfilters", "(t.email:=:'%s')".formatted(email)) - .queryParam("limit", 1) - .build()) - .retrieve() - .body(new ParameterizedTypeReference>() {}); + List matches = null; + try { + matches = restClient.get() + .uri(u -> u.path("/thirdparties") + .queryParam("sqlfilters", "(t.email:=:'%s')".formatted(email)) + .queryParam("limit", 1) + .build()) + .retrieve() + .body(new ParameterizedTypeReference>() {}); + } catch (DolibarrApiException e) { + // Dolibarr returns 404 (not 200 + empty array) when filter finds no results + if (e.getStatusCode().value() != 404) { + throw e; + } + } if (matches != null && !matches.isEmpty()) { return matches.get(0); diff --git a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/prestashop/PrestashopClient.java b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/prestashop/PrestashopClient.java index 465fcb5..b5fbd64 100644 --- a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/prestashop/PrestashopClient.java +++ b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/prestashop/PrestashopClient.java @@ -2,6 +2,7 @@ package com.teterialosjuanjos.tfg.sync_service.integration.prestashop; import com.teterialosjuanjos.tfg.sync_service.config.IntegrationProperties; import com.teterialosjuanjos.tfg.sync_service.integration.prestashop.dto.*; +import com.teterialosjuanjos.tfg.sync_service.integration.prestashop.exception.PrestashopApiException; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.MediaType; @@ -66,20 +67,26 @@ public class PrestashopClient { public Optional getProductByReference(String reference) { // PS WebService requires [value] brackets for exact-match filtering String exactRef = "[" + reference + "]"; - PrestashopProductDto.ListResponse response = restClient.get() - .uri(u -> u.path("/products") - .queryParam("ws_key", wsKey) - .queryParam("output_format", "JSON") - .queryParam("display", "full") - .queryParam("filter[reference]", exactRef) - .build()) - .retrieve() - .body(PrestashopProductDto.ListResponse.class); + try { + PrestashopProductDto.ListResponse response = restClient.get() + .uri(u -> u.path("/products") + .queryParam("ws_key", wsKey) + .queryParam("output_format", "JSON") + .queryParam("display", "full") + .queryParam("filter[reference]", exactRef) + .build()) + .retrieve() + .body(PrestashopProductDto.ListResponse.class); - if (response == null || response.products() == null || response.products().isEmpty()) { - return Optional.empty(); + if (response == null || response.products() == null || response.products().isEmpty()) { + return Optional.empty(); + } + return Optional.of(response.products().get(0)); + } catch (PrestashopApiException e) { + // PS may return 404 instead of 200+empty when filter finds no results + if (e.getStatusCode() != null && e.getStatusCode().value() == 404) return Optional.empty(); + throw e; } - return Optional.of(response.products().get(0)); } /**