feat(api): implement POST endpoint for searching entities#63
Conversation
Method was lost when resolving rebase conflict — the --ours strategy on EntityDtoOutMapper.java preserved main's Spotless formatting but dropped the new search-page mapping method added by the branch. Also applies Spotless formatting to all files touched during rebase resolution that still had indentation/whitespace violations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 30005138 | Triggered | Generic Password | 3077707 | src/test/java/com/decathlon/idp_core/AbstractIntegrationTest.java | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
There was a problem hiding this comment.
Pull request overview
Adds a new cross-template POST /api/v1/entities/search API for free-text and structured entity search, backed by new domain parsing/validation services, JPA specifications, persistence support, migration indexes, and integration/unit coverage.
Changes:
- Introduces structured search DTOs, parser/validator, domain models, repository port method, controller endpoint, and exception mapping.
- Adds JPA predicate/specification support for global text search and nested filter criteria.
- Adds PostgreSQL trigram index migration, local/test extension initialization, and broad test coverage for search scenarios.
Reviewed changes
Copilot reviewed 47 out of 47 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
.github/instructions/java.instructions.md |
Adds JavaDoc Markdown guidance. |
docker-compose.yml |
Mounts local PostgreSQL extension init script. |
scripts/init-extensions.sql |
Adds local pg_trgm initialization. |
src/main/resources/db/migration/V3_6__add_search_performance_indexes.sql |
Adds search performance indexes. |
src/test/resources/db/init/init-extensions.sql |
Adds Testcontainers pg_trgm initialization. |
src/main/java/.../EntityController.java |
Adds POST /entities/search endpoint. |
src/main/java/.../SwaggerDescription.java |
Adds Swagger constants for search endpoint. |
src/main/java/.../EntitySearchRequestDtoIn.java |
Adds search request DTO. |
src/main/java/.../FilterNodeDtoIn.java |
Adds polymorphic filter node DTO. |
src/main/java/.../SearchFilterMapper.java |
Maps API filter DTOs to raw domain filter nodes. |
src/main/java/.../EntityDtoOutMapper.java |
Adds multi-template search page DTO mapping. |
src/main/java/.../ApiExceptionHandler.java |
Maps new filter/search exceptions to HTTP 400. |
src/main/java/.../SearchFilterNode.java |
Adds typed search filter tree model. |
src/main/java/.../RawSearchFilterNode.java |
Adds raw search filter tree model. |
src/main/java/.../LogicalConnector.java |
Adds AND/OR connector enum. |
src/main/java/.../SearchOperator.java |
Adds search operator enum. |
src/main/java/.../SearchConstraints.java |
Adds search limits and allowed sort fields. |
src/main/java/.../FilterConstraints.java |
Extracts legacy filter DSL limits. |
src/main/java/.../ValidationMessages.java |
Adds search validation messages. |
src/main/java/.../InvalidSearchQueryException.java |
Adds search validation exception. |
src/main/java/.../InvalidFilterDslException.java |
Adds renamed legacy filter DSL exception. |
src/main/java/.../InvalidQueryDslException.java |
Removes old legacy filter DSL exception. |
src/main/java/.../EntityFilterDslParser.java |
Renames/refactors legacy q= parser. |
src/main/java/.../SearchFilterParser.java |
Parses structured search filter trees. |
src/main/java/.../SearchFilterValidationService.java |
Validates structured search filters and query text. |
src/main/java/.../EntityService.java |
Adds search orchestration, validation, pagination, and sorting. |
src/main/java/.../EntityRepositoryPort.java |
Adds search persistence port method. |
src/main/java/.../PostgresEntityAdapter.java |
Implements search using JPA specifications. |
src/main/java/.../EntityFilterSpecification.java |
Renames legacy specification and shares predicate builder. |
src/main/java/.../EntitySearchSpecification.java |
Adds structured search JPA specification builder. |
src/main/java/.../JpaPredicateBuilder.java |
Adds shared predicate and LIKE escaping utilities. |
src/test/java/.../AbstractIntegrationTest.java |
Initializes test PostgreSQL extension. |
src/test/java/.../EntityControllerTest.java |
Adds integration tests for search endpoint. |
src/test/java/.../EntityServiceTest.java |
Adds service tests for search validation/pagination/sort. |
src/test/java/.../EntityFilterDslParserTest.java |
Updates legacy parser tests after rename. |
src/test/java/.../SearchFilterParserTest.java |
Adds structured parser unit tests. |
src/test/java/.../SearchFilterValidationServiceTest.java |
Adds search validation unit tests. |
src/test/java/.../EntitySearchSpecificationTest.java |
Adds search specification construction tests. |
src/test/java/.../JpaPredicateBuilderTest.java |
Updates LIKE escaping tests for shared builder. |
src/test/resources/integration_test/json/entity/v1/searchEntities_200_byRelationNameContains.json |
Adds expected search fixture. |
src/test/resources/integration_test/json/entity/v1/searchEntities_200_byRelationNameEq.json |
Adds expected search fixture. |
src/test/resources/integration_test/json/entity/v1/searchEntities_200_byRelationsAsTarget.json |
Adds expected search fixture. |
src/test/resources/integration_test/json/entity/v1/searchEntities_200_byRelationsAsTargetPresence.json |
Adds expected search fixture. |
src/test/resources/integration_test/json/entity/v1/searchEntities_200_byTemplateAndProperty.json |
Adds expected search fixture. |
src/test/resources/integration_test/json/entity/v1/searchEntities_200_neq.json |
Adds expected search fixture. |
src/test/resources/integration_test/json/entity/v1/searchEntities_200_orTemplates.json |
Adds expected search fixture. |
src/test/resources/integration_test/json/entity/v1/searchEntities_200_startsWith.json |
Adds expected search fixture. |
|
| pass_filenames: false | ||
| files: \.java$ | ||
| stages: [commit] | ||
| stages: [pre-commit] |
There was a problem hiding this comment.
[WARNING] hook id `spotless-check` uses deprecated stage names (commit) which will be removed in a future version. run: `pre-commit migrate-config` to automatically fix this.
| /// case-insensitive matching, allowing GIN trigram indexes (V3_5) to be leveraged. | ||
| /// SQL wildcards (`%` and `_`) in user-supplied values are escaped to prevent unintended | ||
| /// pattern matching. EQ and NEQ use `LOWER()` with functional btree indexes (V3_4). |
| @@ -0,0 +1,39 @@ | |||
| package com.decathlon.idp_core.domain.model.entity; | |||
There was a problem hiding this comment.
RawSearchFilterNode représente un arbre de filtre brut utilisé pour le parsing et la validation, plutôt qu'une entité métier.
Je me demande si le package domain.model.entity reflète bien sa responsabilité.
Est-ce qu'un package dédié au search/filter (domain.search, domain.filter etc.) ne serait pas plus explicite ?
There was a problem hiding this comment.
Effectivement j'ai déplacé les objets domaines liés au search dans un package dédié domain.search 👍
| return entityRepository.search(filter, query, pageable); | ||
| } | ||
|
|
||
| private Pageable buildPageable(int page, int size, String sort) { |
There was a problem hiding this comment.
On a du Spring Data (Page, Pageable, Sort) directement dans le EntityService, ce qui couple un peu le domaine au framework.
Proposition possible pour alléger ça :
Garder le EntityService centré sur l’orchestration + validation métier uniquement
Remplacer Page/Pageable/Sort par des types neutres (ex: page, size, sort ou PaginationCriteria) dans le domaine
Déplacer la construction du PageRequest + parsing du sort dans l’adapter d’infrastructure (impl EntityRepositoryPort) ->
PaginatedResult search(SearchFilterNode filter, String query, PaginationCriteria paginationCriteria);



PR Description
What this PR Provides
Adds
POST /api/v1/entities/searchan endpoint for advanced paginated entity search/filteridentifier,name,templateIdentifierand all property values simultaneouslyAND/ORgroups and 10 operators:EQ,NEQ,CONTAINS,NOT_CONTAINS,STARTS_WITH,ENDS_WITH,GT,GTE,LT,LTEtemplate,identifier,name), properties (property.{name}), relations (relation.{name},relation.{name}.identifier) and reverse-relations (relations_as_target.{name}.{field})query+filter)EntityQueryParserServicewith a cleaner three-way split:EntityFilterDslParser(existing DSL),SearchFilterParser(filter tree parsing),SearchFilterValidationService(validation)EntitySearchSpecificationandJpaPredicateBuilderfor composable JPA predicate buildingV3_6with GIN trigram and functional btree indexes onentity,property, andrelationtables for ILIKE/EQ search performancepg_trgmPostgreSQL extension, initialized viainit-extensions.sqlReview
The reviewer must double-check these points:
How to test
Free-text search
Should return all entities whose identifier, name, templateIdentifier or any property value contains "checkout" (case-insensitive).
Structured filter on a single template
Should return all microservices entities with language = JAVA.
Combined free-text + filter:
Should return microservices entities that also match "payment" in any text field.
Error case — invalid filter:
Should return 400 Bad Request with a validation error message
Breaking changes
N/A