Skip to content

[BI-3082] Implement generalized list item search endpoint, targeting DeltaBreed germplasm use case - #33

Merged
jloux-brapi merged 19 commits into
epic/BI-2862from
feature/BI-3082
Oct 23, 2026
Merged

jloux-brapi merged 19 commits into
epic/BI-2862from
feature/BI-3082

Conversation

@jloux-brapi

@jloux-brapi jloux-brapi commented Oct 19, 2026 •

Copy link
Copy Markdown

Description

Story: BI-3082

Supporting changes:

New Lists API endpoint /search/lists/{listDbId}/items added to allow list type entity search requests. In particular, this search request will be used by bi-api to support the requirement of sorting, filtering, and paginating germplasm data that belongs in lists. Previously issues were found with the cache-removal implementation of germplasm lists, and this body should work should address all of these issues. To support a generalized approach to this endpoint, the following features were implemented:

  • Generalized interface ListItemSearchRequestHandler for all ListTypeSearchRequests to implement. Only Germplasm implements this right now, if BrAPI wants to support all list types we (or them) can implement the rest at that time
  • Models to support ListItemWithFullItem<T> responses added. In particular, this new model object provides ListItem information, as well as the full BrAPI model object that is represented by . In the case of DeltaBreed, this is germplasm, but if other list types are implemented, this generalized approach will allow for different models to use this object.
  • Validation of generalized search requests that come in for a particular list type. If requests come in with attributes/properties not found in the expected search request type, a 400 error is thrown with a descriptive message of what happened.
  • Renamed EntityColumnNameAndType to SortAndFilterEntityColumnInfo after new support requirements caused more attributes to be added to this model. These new attributes, supplied on creation, tell the SearchQueryBuilder about special use cases that were previously being overwritten or ignored with existing features. These new attributes make this more explicit.
  • BrAPIRepositry/Impl support to search on multiple entities which is required for this new endpoint's use case. This code has been generalized to support any such use case.
  • SearchQueryBuilder support for multiple entity search requests
  • Changes to BrAPIGermplasmService.buildGermplasmSearchQuery() to prevent fetching the synonyms collection in the initial query. This was seen as a problem for using on the list query in general because it would have required the usage of BrAPIRespository.findAllBySearchPaginatingWithFetches(), which utilizes a difficult to edit subquery. It was found through these changes in fact that this method can likely be removed in favor of simply not fetching the first collection, then iterating through all the collections you need to fetch to populate before conversion. It's the subject of this new ticket

Dependencies

  • bi-api feature/BI-3082
  • brapi feature/BI-3082

Testing

Testing for this bi-api PR is sufficient for the testing of this ticket.

Supplemental testing can be done on the new /search/lists/{listDbId}/items endpoint as well to test corner cases as well, but not required.

Checklist:

@jloux-brapi
jloux-brapi marked this pull request as ready for review October 19, 2026 21:58
List<GermplasmEntity> synonyms = germplasmRepository.findAllBySearch(searchQuery);

Map<String, List<ExternalReferenceEntity>> synonymsByEntity = new HashMap<>();
synonyms.forEach(entity -> synonymsByEntity.put(entity.getId().toString(), entity.getExternalReferences()));

@humsika humsika Oct 22, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The synonyms block reads getExternalReferences() and calls setExternalReferences(), so synonyms are never set in findGermplasmEntitiesWithoutPaging.
I think it should be getSynonyms() / setSynonyms(), with the map typed Map<String, List<GermplasmSynonymEntity>>.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

"synonyms");
// Because the join was overwritten above, the original synonym join was removed with the replace. This extra join restores it so
// queries with join in the where clause can continue to work.
searchQuery.join("synonyms", "synonyms");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

join("synonyms", "synonyms") adds an INNER JOIN, and it stays in place for the xref, attribute, donor, and later queries. Germplasm without synonyms drop out of those results and come back with null external references, attributes, and so on. bi-api depends on those external references.
Can we add this join only when a synonyms filter is present, or use a LEFT JOIN?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opted for a check on the filter instead of a left join, less code.

I also noticed the where clause was wrong for instituteCodes, so fixed that as well.


if (entityColumnNameAndType.getEntityColumnName().startsWith("*")) {
joinCollectionColumn(entityColumnNameAndType.getEntityColumnName());
if (sortAndFilterEntityColumnInfo.isCollectionOnEntity() && !sortAndFilterEntityColumnInfo.isJoinOnUnrelatedEntity()) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This used to check startsWith("*"), and it now checks isCollectionOnEntity(). But the * columns in StudySearchRequest (externalReferenceId, externalReferenceSource, germplasmDbId, observationVariableDbId, seasonDbId) and TrialSearchRequest (locationDbId) still use the 2-arg constructor, so the flag is false for them.
joinCollectionColumn is skipped, and the WHERE clause refers to an alias that was never joined, so the query fails with a 500.
bi-api’s StudyQuery filters on externalReferenceId, so this affects a path bi-api actually uses. Sorting on these columns also no longer returns a 400. Those entries need the 4-arg constructor with isCollectionOnEntity = true.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@humsika humsika left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good to me.

Comment thread src/main/java/io/swagger/api/core/ListsApi.java Outdated
@jloux-brapi
jloux-brapi merged commit 0c67028 into epic/BI-2862 Oct 23, 2026
@jloux-brapi
jloux-brapi deleted the feature/BI-3082 branch October 23, 2026 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants