3535import com .fasterxml .jackson .databind .ObjectMapper ;
3636import jakarta .servlet .http .HttpServletRequest ;
3737import jakarta .servlet .http .HttpServletResponse ;
38+ import java .io .IOException ;
3839import java .util .ArrayList ;
3940import java .util .Arrays ;
4041import java .util .Collection ;
4344import java .util .List ;
4445import java .util .Set ;
4546import java .util .stream .Collectors ;
47+ import org .cbioportal .application .rest .error .ErrorResponse ;
4648import org .cbioportal .legacy .model .AlterationFilter ;
4749import org .cbioportal .legacy .model .MolecularProfile ;
4850import org .cbioportal .legacy .model .MolecularProfileCaseIdentifier ;
@@ -165,24 +167,29 @@ public class InvolvedCancerStudyExtractorInterceptor implements HandlerIntercept
165167 * @param message the error message to include in the response body
166168 */
167169 private void sendBadRequestResponse (HttpServletResponse response , String message ) {
168- try {
169- response . setStatus ( HttpServletResponse . SC_BAD_REQUEST );
170- response . setContentType ( "application/json" ) ;
171- response . setCharacterEncoding ( "UTF-8" );
170+ if ( response . isCommitted ()) {
171+ LOG . warn ( "Cannot send error response - response already committed" );
172+ return ;
173+ }
172174
175+ try {
173176 // Truncate message before Jackson source location info if present
174- String truncatedMessage = message ;
177+ String cleanMessage = message ;
175178 int sourceIndex = message .indexOf (" at [Source:" );
176179 if (sourceIndex != -1 ) {
177- truncatedMessage = message .substring (0 , sourceIndex );
180+ cleanMessage = message .substring (0 , sourceIndex );
178181 }
179182
180- String jsonError =
181- String .format ("{\" message\" :\" %s\" }" , truncatedMessage .replace ("\" " , "\\ \" " ));
182- response .getWriter ().write (jsonError );
183+ response .setStatus (HttpServletResponse .SC_BAD_REQUEST );
184+ response .setContentType ("application/json" );
185+ response .setCharacterEncoding ("UTF-8" );
186+
187+ // Use ObjectMapper for proper JSON escaping (matches GlobalExceptionHandler pattern)
188+ ErrorResponse errorResponse = new ErrorResponse ("Invalid request body: " + cleanMessage );
189+ response .getWriter ().write (objectMapper .writeValueAsString (errorResponse ));
183190 response .getWriter ().flush ();
184- } catch (Exception ex ) {
185- LOG .error ("Failed to send error response: {}" , ex .getMessage ());
191+ } catch (IOException ex ) {
192+ LOG .error ("Failed to write error response: {}" , ex .getMessage ());
186193 }
187194 }
188195
@@ -297,7 +304,7 @@ private boolean extractAttributesFromPatientFilter(
297304 }
298305 } catch (Exception e ) {
299306 LOG .error ("exception thrown during extraction of patientFilter: {}" , e .getMessage ());
300- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
307+ sendBadRequestResponse (response , e .getMessage ());
301308 return false ;
302309 }
303310 return true ;
@@ -333,7 +340,7 @@ private boolean extractAttributesFromSampleFilter(
333340 }
334341 } catch (Exception e ) {
335342 LOG .error ("exception thrown during extraction of sampleFilter: {}" , e .getMessage ());
336- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
343+ sendBadRequestResponse (response , e .getMessage ());
337344 return false ;
338345 }
339346 return true ;
@@ -369,7 +376,7 @@ private boolean extractAttributesFromMolecularProfileFilter(
369376 }
370377 } catch (Exception e ) {
371378 LOG .error ("exception thrown during extraction of molecularProfileFilter: {}" , e .getMessage ());
372- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
379+ sendBadRequestResponse (response , e .getMessage ());
373380 return false ;
374381 }
375382 return true ;
@@ -407,7 +414,7 @@ private boolean extractAttributesFromClinicalAttributeCountFilter(
407414 } catch (Exception e ) {
408415 LOG .error (
409416 "exception thrown during extraction of clinicalAttributeCountFilter: {}" , e .getMessage ());
410- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
417+ sendBadRequestResponse (response , e .getMessage ());
411418 return false ;
412419 }
413420 return true ;
@@ -448,7 +455,7 @@ private boolean extractAttributesFromNamespaceAttributeCountFilter(
448455 LOG .error (
449456 "exception thrown during extraction of namespaceAttributeCountFilter: {}" ,
450457 e .getMessage ());
451- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
458+ sendBadRequestResponse (response , e .getMessage ());
452459 return false ;
453460 }
454461 return true ;
@@ -482,7 +489,7 @@ private boolean extractAttributesFromClinicalDataMultiStudyFilter(
482489 } catch (Exception e ) {
483490 LOG .error (
484491 "exception thrown during extraction of clinicalDataMultiStudyFilter: {}" , e .getMessage ());
485- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
492+ sendBadRequestResponse (response , e .getMessage ());
486493 return false ;
487494 }
488495 return true ;
@@ -522,7 +529,7 @@ private boolean extractAttributesFromGenePanelDataMultipleStudyFilter(
522529 LOG .error (
523530 "exception thrown during extraction of genePanelSampleMolecularIdentifiers: {}" ,
524531 e .getMessage ());
525- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
532+ sendBadRequestResponse (response , e .getMessage ());
526533 return false ;
527534 }
528535 return true ;
@@ -563,7 +570,7 @@ private boolean extractAttributesFromMolecularDataMultipleStudyFilter(
563570 LOG .error (
564571 "exception thrown during extraction of molecularDataMultipleStudyFilter: {}" ,
565572 e .getMessage ());
566- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
573+ sendBadRequestResponse (response , e .getMessage ());
567574 return false ;
568575 }
569576 return true ;
@@ -606,7 +613,7 @@ private boolean extractAttributesFromGenericAssayDataMultipleStudyFilter(
606613 LOG .error (
607614 "exception thrown during extraction of genericAssayDataMultipleStudyFilter: {}" ,
608615 e .getMessage ());
609- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
616+ sendBadRequestResponse (response , e .getMessage ());
610617 return false ;
611618 }
612619 return true ;
@@ -643,7 +650,7 @@ private boolean extractAttributesFromMutationMultipleStudyFilter(
643650 } catch (Exception e ) {
644651 LOG .error (
645652 "exception thrown during extraction of mutationMultipleStudyFilter: {}" , e .getMessage ());
646- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
653+ sendBadRequestResponse (response , e .getMessage ());
647654 return false ;
648655 }
649656 return true ;
@@ -678,7 +685,7 @@ private boolean extractAttributesFromSampleIdentifiers(
678685 }
679686 } catch (Exception e ) {
680687 LOG .error ("exception thrown during extraction of sampleIdentifiers: {}" , e .getMessage ());
681- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
688+ sendBadRequestResponse (response , e .getMessage ());
682689 return false ;
683690 }
684691 return true ;
@@ -701,7 +708,7 @@ private boolean extractAttributesFromClinicalDataBinCountFilter(
701708 } catch (Exception e ) {
702709 LOG .error (
703710 "exception thrown during extraction of clinicalDataBinCountFilter: {}" , e .getMessage ());
704- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
711+ sendBadRequestResponse (response , e .getMessage ());
705712 return false ;
706713 }
707714 return true ;
@@ -724,7 +731,7 @@ private boolean extractAttributesFromGenomicDataBinCountFilter(
724731 } catch (Exception e ) {
725732 LOG .error (
726733 "exception thrown during extraction of genomicDataBinCountFilter: {}" , e .getMessage ());
727- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
734+ sendBadRequestResponse (response , e .getMessage ());
728735 return false ;
729736 }
730737 return true ;
@@ -746,7 +753,7 @@ private boolean extractAttributesFromGenomicDataCountFilter(
746753 }
747754 } catch (Exception e ) {
748755 LOG .error ("exception thrown during extraction of genomicDataCountFilter: {}" , e .getMessage ());
749- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
756+ sendBadRequestResponse (response , e .getMessage ());
750757 return false ;
751758 }
752759 return true ;
@@ -773,7 +780,7 @@ private boolean extractAttributesFromGenericAssayDataBinCountFilter(
773780 LOG .error (
774781 "exception thrown during extraction of genericAssayDataBinCountFilter: {}" ,
775782 e .getMessage ());
776- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
783+ sendBadRequestResponse (response , e .getMessage ());
777784 return false ;
778785 }
779786 return true ;
@@ -797,7 +804,7 @@ private boolean extractAttributesFromGenericAssayDataCountFilter(
797804 } catch (Exception e ) {
798805 LOG .error (
799806 "exception thrown during extraction of genericAssayDataCountFilter: {}" , e .getMessage ());
800- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
807+ sendBadRequestResponse (response , e .getMessage ());
801808 return false ;
802809 }
803810 return true ;
@@ -808,7 +815,7 @@ private boolean extractAttributesFromClinicalDataCountFilter(
808815 try {
809816 ClinicalDataCountFilter clinicalDataCountFilter =
810817 objectMapper .readValue (request .getInputStream (), ClinicalDataCountFilter .class );
811- LOG .debug ("extracted clinicalDataBinCountFilter : {}" , clinicalDataCountFilter );
818+ LOG .debug ("extracted clinicalDataCountFilter : {}" , clinicalDataCountFilter );
812819 LOG .debug ("setting interceptedClinicalDataCountFilter to {}" , clinicalDataCountFilter );
813820 request .setAttribute ("interceptedClinicalDataCountFilter" , clinicalDataCountFilter );
814821 if (cacheMapUtil .hasCacheEnabled ()) {
@@ -819,8 +826,8 @@ private boolean extractAttributesFromClinicalDataCountFilter(
819826 }
820827 } catch (Exception e ) {
821828 LOG .error (
822- "exception thrown during extraction of clinicalDataBinCountFilter : {}" , e .getMessage ());
823- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
829+ "exception thrown during extraction of clinicalDataCountFilter : {}" , e .getMessage ());
830+ sendBadRequestResponse (response , e .getMessage ());
824831 return false ;
825832 }
826833 return true ;
@@ -843,7 +850,7 @@ private boolean extractAttributesFromNamespaceDataCountFilter(
843850 } catch (Exception e ) {
844851 LOG .error (
845852 "exception thrown during extraction of namespaceDataCountFilter: {}" , e .getMessage ());
846- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
853+ sendBadRequestResponse (response , e .getMessage ());
847854 return false ;
848855 }
849856 return true ;
@@ -868,7 +875,7 @@ private boolean extractAttributesFromGroupFilter(
868875 }
869876 } catch (Exception e ) {
870877 LOG .error ("exception thrown during extraction of groupFilter: {}" , e .getMessage ());
871- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
878+ sendBadRequestResponse (response , e .getMessage ());
872879 return false ;
873880 }
874881 return true ;
@@ -900,7 +907,7 @@ private boolean extractAttributesFromStudyViewFilter(
900907 }
901908 } catch (Exception e ) {
902909 LOG .error ("exception thrown during extraction of studyViewFilter: {}" , e .getMessage ());
903- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
910+ sendBadRequestResponse (response , e .getMessage ());
904911 return false ;
905912 }
906913 return true ;
@@ -930,7 +937,7 @@ private boolean extractAttributesFromMolecularProfileCasesGroups(
930937 LOG .error (
931938 "exception thrown during extraction of molecularProfileCasesGroupFilters: {}" ,
932939 e .getMessage ());
933- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
940+ sendBadRequestResponse (response , e .getMessage ());
934941 return false ;
935942 }
936943 return true ;
@@ -970,7 +977,7 @@ private boolean extractAttributesFromMolecularProfileCasesGroupsAndAlterationTyp
970977 LOG .error (
971978 "exception thrown during extraction of molecularProfileCasesGroupFilters: {}" ,
972979 e .getMessage ());
973- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
980+ sendBadRequestResponse (response , e .getMessage ());
974981 return false ;
975982 }
976983 return true ;
@@ -998,7 +1005,7 @@ private boolean extractAttributesFromStructuralVariantFilter(
9981005 } catch (Exception e ) {
9991006 LOG .error (
10001007 "exception thrown during extraction of structuralVariantFilter: {}" , e .getMessage ());
1001- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
1008+ sendBadRequestResponse (response , e .getMessage ());
10021009 return false ;
10031010 }
10041011 return true ;
@@ -1170,7 +1177,7 @@ private boolean extractCancerStudyIdsFromSurvivalRequest(
11701177 }
11711178 } catch (Exception e ) {
11721179 LOG .error ("exception thrown during extraction of survivalRequest: {}" , e .getMessage ());
1173- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
1180+ sendBadRequestResponse (response , e .getMessage ());
11741181 return false ;
11751182 }
11761183 return true ;
@@ -1198,7 +1205,7 @@ private boolean extractCancerStudyIdsFromClinicalEventAttributeRequest(
11981205 LOG .error (
11991206 "exception thrown during extraction of clinicalEventAttributeRequest: {}" ,
12001207 e .getMessage ());
1201- sendBadRequestResponse (response , "Invalid request body: " + e .getMessage ());
1208+ sendBadRequestResponse (response , e .getMessage ());
12021209 return false ;
12031210 }
12041211 return true ;
0 commit comments