11package checks .spring ;
22
33import java .util .List ;
4+ import java .util .Map ;
45import org .springframework .beans .factory .annotation .Value ;
56import org .springframework .data .mongodb .repository .Query ;
67import org .springframework .data .repository .query .Param ;
@@ -14,6 +15,7 @@ public class SpelExpressionCheckSample {
1415 private static final String INVALID_PROPERTY_PLACEHOLDER = "${foo.bar[}" ;
1516 private static final String VALID_PROPERTY_PLACEHOLDER = "${foo.bar}" ;
1617
18+
1719 @ Value (UNCLOSED ) // Noncompliant {{Add missing '}' for this property placeholder or SpEL expression.}}
1820// ^^^^^^^^
1921 private String complexArgument1 ;
@@ -100,15 +102,15 @@ public class SpelExpressionCheckSample {
100102 @ Value ("${user.region:#{'D'+'E'}}" ) // Compliant
101103 private String default10 ;
102104
103- @ Value ("${user.region:#{null}:#{null}:foo.bar}" ) // Noncompliant
105+ @ Value ("${user.region:#{null}:#{null}:foo.bar}" ) // Compliant
104106 private String default11 ;
105107
106- @ Value ("${user.region:#{null}:#{4**4}:foo.bar}" ) // Noncompliant {{Correct this malformed property placeholder .}}
107- // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^
108+ @ Value ("${user.region:#{null}:#{4**4}:foo.bar}" ) // Noncompliant {{Correct this malformed SpEL expression .}}
109+ // ^^^^^^^
108110 private String default12 ;
109111
110112 @ Value ("${user.region:#{4**4}:#{null}:foo.bar}" ) // Noncompliant {{Correct this malformed SpEL expression.}}
111- // ^^^^^^^
113+
112114 private String default13 ;
113115
114116 @ Value ("${user.2region:default-region}" ) // Compliant
@@ -441,4 +443,49 @@ public static class RequestController2 { }
441443 private String sonarJava5079DefaultValueContainsColon2 ;
442444
443445 private static final String MOCKED_SOAP_SP_CLIENT_SSL = "classpath:mocked-soap-sp-client-ssl.jks" ;
446+
447+ static class PropertyPlaceHolderInsideSpEL {
448+ // We want to parse correctly the expression below
449+ @ Value ("#{${placeholder}}" ) // Compliant
450+ private Map <String , Integer > placeholderStage1 ;
451+
452+ // However, the problem is that Spring evaluates the expression in two stages
453+ // 1. it parses the property placeholders and substitutes them
454+ // 2. it parses the SpEL expression and executes it
455+
456+ // After evaluating the property placeholder, we have the following expression
457+ @ Value ("#{{key1: '1', key2: '2', key3: '3'}}" ) // Compliant
458+ private Map <String , Integer > SpELStage1 ;
459+
460+ // It is easy to validate that property placeholders are valid, but without the context we cannot validate the spring expression
461+ // A solution is to use clever values to replace the property placeholders for instance replace "${placeholder}" with "#aVar"
462+ @ Value ("#{${placeholder}}" ) // Compliant
463+ private Integer placeholderStage2 ;
464+ @ Value ("#{#aVar}" ) // Compliant
465+ private Integer SpELStage2 ;
466+
467+ // However, it is not possible to find a value that is valid in all the cases.
468+ // "#aVar" does not work in the case below.
469+ @ Value ("#{@${placeholder}}" ) // Compliant
470+ private Integer placeholderStage3 ;
471+ // "@#aVar" is not a valid SpEL expression.
472+ @ Value ("#{@#aVar}" ) // Noncompliant
473+ private Integer SpELStage3 ;
474+
475+ @ Value ("#{@${placeholder}}" ) // Compliant
476+ private Integer placeholderStage4 ;
477+ @ Value ("#{@aBean}" ) // Compliant
478+ private Integer SpELStage4 ;
479+
480+ @ Value ("#{${placeholder:10}}" ) // Compliant
481+ private Integer placeholderStage5 ;
482+ @ Value ("#{10}" ) // Compliant
483+ private Integer SpELStage5 ;
484+
485+
486+ @ Value ("#{@${placeholder:10}}" ) // Compliant
487+ private Integer placeholderStage6 ;
488+ @ Value ("#{@10}" ) // Noncompliant
489+ private Integer SpELStage6 ;
490+ }
444491}
0 commit comments