Skip to content

Commit 54774f4

Browse files
heathduttonalisman
authored andcommitted
Fix 500 error when genomicDataFilters is empty (#11206)
When genomicDataFilters is null or empty, return an empty list instead of throwing IndexOutOfBoundsException.
1 parent 6c28892 commit 54774f4

2 files changed

Lines changed: 159 additions & 0 deletions

File tree

src/main/java/org/cbioportal/application/rest/vcolumnstore/ColumnarStoreStudyViewController.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import jakarta.validation.Valid;
1313
import java.math.BigDecimal;
1414
import java.util.ArrayList;
15+
import java.util.Collections;
1516
import java.util.List;
1617
import java.util.Map;
1718
import java.util.Set;
@@ -424,6 +425,13 @@ public ResponseEntity<List<GenomicDataCountItem>> fetchGenomicDataCounts(
424425
throws StudyNotFoundException {
425426
List<GenomicDataFilter> genomicDataFilters = genomicDataCountFilter.getGenomicDataFilters();
426427
StudyViewFilter studyViewFilter = genomicDataCountFilter.getStudyViewFilter();
428+
429+
// If genomicDataFilters is null or empty, return an empty result list
430+
// This prevents IndexOutOfBoundsException in the MyBatis mapper
431+
if (genomicDataFilters == null || genomicDataFilters.isEmpty()) {
432+
return ResponseEntity.ok(Collections.emptyList());
433+
}
434+
427435
// when there is only one filter, it means study view is doing a single chart filter operation
428436
// remove filter from studyViewFilter to return all data counts
429437
// the reason we do this is to make sure after chart get filtered, user can still see unselected
@@ -499,6 +507,13 @@ public ResponseEntity<List<GenomicDataCountItem>> fetchMutationDataCounts(
499507
GenomicDataCountFilter genomicDataCountFilter) {
500508
List<GenomicDataFilter> genomicDataFilters = genomicDataCountFilter.getGenomicDataFilters();
501509
StudyViewFilter studyViewFilter = genomicDataCountFilter.getStudyViewFilter();
510+
511+
// If genomicDataFilters is null or empty, return an empty result list
512+
// This prevents IndexOutOfBoundsException in the MyBatis mapper
513+
if (genomicDataFilters == null || genomicDataFilters.isEmpty()) {
514+
return ResponseEntity.ok(Collections.emptyList());
515+
}
516+
502517
// when there is only one filter, it means study view is doing a single chart filter operation
503518
// remove filter from studyViewFilter to return all data counts
504519
// the reason we do this is to make sure after chart get filtered, user can still see unselected
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package org.cbioportal.application.rest.vcolumnstore;
2+
3+
import static org.mockito.Mockito.never;
4+
import static org.mockito.Mockito.verify;
5+
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
6+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
7+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
8+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
9+
10+
import com.fasterxml.jackson.databind.ObjectMapper;
11+
import java.util.Arrays;
12+
import java.util.Collections;
13+
import org.cbioportal.domain.studyview.StudyViewService;
14+
import org.cbioportal.legacy.web.parameter.GenomicDataCountFilter;
15+
import org.cbioportal.legacy.web.parameter.StudyViewFilter;
16+
import org.junit.Test;
17+
import org.junit.runner.RunWith;
18+
import org.springframework.beans.factory.annotation.Autowired;
19+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
20+
import org.springframework.boot.test.context.SpringBootTest;
21+
import org.springframework.boot.test.mock.mockito.MockBean;
22+
import org.springframework.http.MediaType;
23+
import org.springframework.security.test.context.support.WithMockUser;
24+
import org.springframework.test.context.junit4.SpringRunner;
25+
import org.springframework.test.web.servlet.MockMvc;
26+
27+
/**
28+
* Unit tests for ColumnarStoreStudyViewController.
29+
*
30+
* When genomicDataFilters is empty or null, the endpoints should return
31+
* an empty list instead of throwing an IndexOutOfBoundsException.
32+
*/
33+
@RunWith(SpringRunner.class)
34+
@SpringBootTest
35+
@AutoConfigureMockMvc
36+
public class ColumnarStoreStudyViewControllerTest {
37+
38+
@Autowired
39+
private MockMvc mockMvc;
40+
41+
@Autowired
42+
private ObjectMapper objectMapper;
43+
44+
@MockBean
45+
private StudyViewService studyViewService;
46+
47+
private static final String TEST_STUDY_ID = "test_study";
48+
49+
@Test
50+
@WithMockUser
51+
public void fetchGenomicDataCountsWithEmptyFiltersReturnsEmptyList() throws Exception {
52+
GenomicDataCountFilter filter = new GenomicDataCountFilter();
53+
filter.setGenomicDataFilters(Collections.emptyList());
54+
55+
StudyViewFilter studyViewFilter = new StudyViewFilter();
56+
studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID));
57+
filter.setStudyViewFilter(studyViewFilter);
58+
59+
mockMvc.perform(post("/api/column-store/genomic-data-counts/fetch")
60+
.with(csrf())
61+
.contentType(MediaType.APPLICATION_JSON)
62+
.content(objectMapper.writeValueAsString(filter)))
63+
.andExpect(status().isOk())
64+
.andExpect(content().json("[]"));
65+
66+
// Verify that the service was never called (early return due to empty filters)
67+
verify(studyViewService, never()).getCNACountsByGeneSpecific(
68+
org.mockito.ArgumentMatchers.any(),
69+
org.mockito.ArgumentMatchers.anyList()
70+
);
71+
}
72+
73+
@Test
74+
@WithMockUser
75+
public void fetchGenomicDataCountsWithNullFiltersReturnsEmptyList() throws Exception {
76+
GenomicDataCountFilter filter = new GenomicDataCountFilter();
77+
filter.setGenomicDataFilters(null);
78+
79+
StudyViewFilter studyViewFilter = new StudyViewFilter();
80+
studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID));
81+
filter.setStudyViewFilter(studyViewFilter);
82+
83+
mockMvc.perform(post("/api/column-store/genomic-data-counts/fetch")
84+
.with(csrf())
85+
.contentType(MediaType.APPLICATION_JSON)
86+
.content(objectMapper.writeValueAsString(filter)))
87+
.andExpect(status().isOk())
88+
.andExpect(content().json("[]"));
89+
90+
// Verify that the service was never called (early return due to null filters)
91+
verify(studyViewService, never()).getCNACountsByGeneSpecific(
92+
org.mockito.ArgumentMatchers.any(),
93+
org.mockito.ArgumentMatchers.anyList()
94+
);
95+
}
96+
97+
@Test
98+
@WithMockUser
99+
public void fetchMutationDataCountsWithEmptyFiltersReturnsEmptyList() throws Exception {
100+
GenomicDataCountFilter filter = new GenomicDataCountFilter();
101+
filter.setGenomicDataFilters(Collections.emptyList());
102+
103+
StudyViewFilter studyViewFilter = new StudyViewFilter();
104+
studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID));
105+
filter.setStudyViewFilter(studyViewFilter);
106+
107+
mockMvc.perform(post("/api/column-store/mutation-data-counts/fetch")
108+
.with(csrf())
109+
.contentType(MediaType.APPLICATION_JSON)
110+
.content(objectMapper.writeValueAsString(filter)))
111+
.andExpect(status().isOk())
112+
.andExpect(content().json("[]"));
113+
114+
// Verify that the service was never called (early return due to empty filters)
115+
verify(studyViewService, never()).getMutationCountsByGeneSpecific(
116+
org.mockito.ArgumentMatchers.any(),
117+
org.mockito.ArgumentMatchers.anyList()
118+
);
119+
}
120+
121+
@Test
122+
@WithMockUser
123+
public void fetchMutationDataCountsWithNullFiltersReturnsEmptyList() throws Exception {
124+
GenomicDataCountFilter filter = new GenomicDataCountFilter();
125+
filter.setGenomicDataFilters(null);
126+
127+
StudyViewFilter studyViewFilter = new StudyViewFilter();
128+
studyViewFilter.setStudyIds(Arrays.asList(TEST_STUDY_ID));
129+
filter.setStudyViewFilter(studyViewFilter);
130+
131+
mockMvc.perform(post("/api/column-store/mutation-data-counts/fetch")
132+
.with(csrf())
133+
.contentType(MediaType.APPLICATION_JSON)
134+
.content(objectMapper.writeValueAsString(filter)))
135+
.andExpect(status().isOk())
136+
.andExpect(content().json("[]"));
137+
138+
// Verify that the service was never called (early return due to null filters)
139+
verify(studyViewService, never()).getMutationCountsByGeneSpecific(
140+
org.mockito.ArgumentMatchers.any(),
141+
org.mockito.ArgumentMatchers.anyList()
142+
);
143+
}
144+
}

0 commit comments

Comments
 (0)