Details
-
Type:
Bug
-
Status: Resolved
-
Priority:
Minor
-
Resolution: Works as Designed
-
Affects Version/s: 2.2.4 (Moore SR4)
-
Fix Version/s: None
-
Component/s: Mapping / Conversion, Repository
-
Environment:Windows 10 Enterprise 64-bit
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Pom parent: spring-boot-starter-parent-2.2.4.RELEASE
Description
I am getting a StackOverflowError when calling a method of my MongoDB repository interface:
public interface TermRepository extends MongoRepository<Term, String>, QuerydslPredicateExecutor<Term> { // [...] @Query("{$or:[{'apis' : {$in : ?0 } }, {$text:{$search:?1}}]}") Page<Term> globalSearch(List<DBRef> apis, String searchKeyword, Pageable pageable); }
- apis is a list with just one DBRef: new DBRef("api", new ObjectId("5e3ad9faaafa595898b6a682"))
- searchKeyword equals "accounts"
- pageable is {{Page request [number: 0, size 37, sort: UNSORTED]}}. If size is 36, it doesn't throw the StackOverflowError!
- The query gets translated into
{ $or: [{ 'apis': { $in: [{ '$ref': 'api', '$id': ObjectId('5e3ad9faaafa595898b6a682') }] } }, { $text: { $search: 'account' } }] }
- If I execute the query directly in mongo, it returns 55 elements.
- I've tried to increase thread stack to -Xss1G (it's a lot, I know), and it just keeps filling the stack slowly and won't return. If I rerun the test with a page size of 36, it returns immediately.
Does anyone have a clue what's happening?
The Term:
public class Term { @Id private String id; @NotBlank @TextIndexed @JsonProperty private String name; @NotBlank @TextIndexed @JsonProperty private String objectType; @Transient @JsonProperty private String snakeCase; @NotEmpty @JsonProperty private List<String> functionalCategories; @NotNull @JsonProperty private TermTypeEnum termType; @NotEmpty @JsonProperty private Map<String, String> description; @Setter @NotNull @JsonProperty private TermStateEnum state; @NotBlank @TextIndexed @JsonProperty private String example; @DBRef @NotNull @Indexed @JsonProperty private List<Api> apis; @DBRef @NotNull @JsonProperty private User contributor; @NotBlank @TextIndexed @JsonProperty private String version; @DBRef @JsonProperty private Map<String, Term> attributes; }
The stacktrace: https://pastebin.com/y0XYt7p6
Although there might be a circular reference because Term has an attribute Map<String, Term>, I think it's not a circular reference what is producing the stack overflow.
Doing some debug, I saw that the stack overflow occurs because in the end, spring-data keeps instantiating this Term only (not others, so I don't see the circular reference):
Term(id=5e3ad9faaafa595898b6a7ea, name=debitCurrency, objectType=string, snakeCase=debit_currency, functionalCategories=null, termType=BODY, description={"english"=Debit Currency.}, state=PROPOSED, example=null, apis=[Api(id=5e3ad9faaafa595898b6a67f, name=Payments-1.0.1, description=null, responsible=null)], contributor=null, version=null, attributes=null)
Which in turn does not reference other terms.
Here is another Term, just for comparison:
Term(id=5e3ad9faaafa595898b6a6c8, name=displayCardNumber, objectType=string, snakeCase=display_card_number, functionalCategories=null, termType=BODY, description={"english"=Related card number to the account.}, state=PROPOSED, example=null, apis=[Api(id=5e3ad9faaafa595898b6a682, name=Accounts-1.0.2, description=null, responsible=null)], contributor=null, version=null, attributes=null)
I see no difference, but debitCurrency produces the stack overflow and displayCardNumber doesn't.