Skip to content

Commit ce049fd

Browse files
committed
Fix code related to making command objects validateble. Fixes #10091
1 parent 69fca8c commit ce049fd

File tree

5 files changed

+94
-24
lines changed

5 files changed

+94
-24
lines changed

grails-core/src/main/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformation.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,16 @@ protected Class getAnnotationTypeClass() {
157157
}
158158

159159
public void performInjectionOnArtefactType(SourceUnit sourceUnit, ClassNode cNode, String artefactType) {
160-
doPerformInjectionOnArtefactType(sourceUnit, cNode, artefactType);
160+
List<ClassInjector> injectors = findInjectors(artefactType, GrailsAwareInjectionOperation.getClassInjectors());
161+
for (ClassInjector injector : injectors) {
162+
if(injector instanceof CompilationUnitAware) {
163+
((CompilationUnitAware) injector).setCompilationUnit(this.compilationUnit);
164+
}
165+
}
166+
performInjection(sourceUnit, cNode, injectors);
161167
}
162168

169+
@Deprecated
163170
public static void doPerformInjectionOnArtefactType(SourceUnit sourceUnit, ClassNode cNode, String artefactType) {
164171
List<ClassInjector> injectors = findInjectors(artefactType, GrailsAwareInjectionOperation.getClassInjectors());
165172
performInjection(sourceUnit, cNode, injectors);

grails-plugin-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -736,18 +736,23 @@ protected void initializeAndValidateCommandObjectParameter(final BlockStatement
736736
javax.persistence.Entity.class) ||
737737
commandObjectNode.implementsInterface(ClassHelper.make(Validateable.class));
738738

739-
if (!argumentIsValidateable) {
739+
if (!argumentIsValidateable && commandObjectNode.isPrimaryClassNode()) {
740740
final ModuleNode commandObjectModule = commandObjectNode.getModule();
741-
if (commandObjectModule != null) {
741+
if (commandObjectModule != null && this.compilationUnit != null) {
742742
if (commandObjectModule == controllerNode.getModule() ||
743743
doesModulePathIncludeSubstring(commandObjectModule,
744744
"grails-app" + File.separator + "controllers" + File.separator)) {
745745

746746
TraitInjectionUtils.injectTrait(compilationUnit, source, commandObjectNode, Validateable.class);
747747

748-
/* ConstructorNode constructorNode = commandObjectNode.getDeclaredConstructors().get(0);
749-
ClassNode helper = Traits.findHelper(ClassHelper.make(Validateable.class));
750-
((BlockStatement)constructorNode.getCode()).addStatement(new ExpressionStatement(new StaticMethodCallExpression(helper, "$init$", VariableExpression.THIS_EXPRESSION)));*/
748+
List<ConstructorNode> declaredConstructors = commandObjectNode.getDeclaredConstructors();
749+
if(declaredConstructors.isEmpty()) {
750+
BlockStatement constructorLogic = new BlockStatement();
751+
ConstructorNode constructorNode = new ConstructorNode(Modifier.PUBLIC, constructorLogic);
752+
ClassNode helper = Traits.findHelper(ClassHelper.make(Validateable.class));
753+
commandObjectNode.addConstructor(constructorNode);
754+
constructorLogic.addStatement(new ExpressionStatement(new StaticMethodCallExpression(helper, "$init$", VariableExpression.THIS_EXPRESSION)));
755+
}
751756
argumentIsValidateable = true;
752757
} else if (doesModulePathIncludeSubstring(commandObjectModule,
753758
"grails-app" + File.separator + "domain" + File.separator)) {

grails-plugin-validation/src/main/groovy/grails/validation/Validateable.groovy

Lines changed: 69 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,26 +38,32 @@ trait Validateable {
3838
private static Map<String, ConstrainedProperty> constraintsMapInternal
3939
Errors errors
4040

41+
/**
42+
* @return The errors
43+
*/
4144
Errors getErrors() {
4245
initErrors()
4346
errors
4447
}
4548

49+
/**
50+
* @return Whether the object has errors
51+
*/
4652
Boolean hasErrors() {
4753
initErrors()
4854
errors.hasErrors()
4955
}
5056

57+
/**
58+
* Clear the errors
59+
*/
5160
void clearErrors() {
5261
errors = null
5362
}
5463

55-
private void initErrors() {
56-
if (errors == null) {
57-
errors = new ValidationErrors(this, this.getClass().getName())
58-
}
59-
}
60-
64+
/**
65+
* @return The map of applied constraints
66+
*/
6167
static Map<String, ConstrainedProperty> getConstraintsMap() {
6268
if (constraintsMapInternal == null) {
6369
ConstraintsEvaluator evaluator = findConstraintsEvaluator()
@@ -67,45 +73,74 @@ trait Validateable {
6773
constraintsMapInternal
6874
}
6975

70-
@CompileStatic
71-
private static ConstraintsEvaluator findConstraintsEvaluator() {
72-
try {
73-
BeanFactory ctx = Holders.applicationContext
74-
ConstraintsEvaluator evaluator = ctx.getBean(ConstraintsEvaluator.BEAN_NAME, ConstraintsEvaluator)
75-
return evaluator
76-
} catch (Throwable e) {
77-
return new DefaultConstraintEvaluator()
78-
}
79-
}
80-
76+
/**
77+
* Validate the object
78+
*
79+
* @return True if it is valid
80+
*/
8181
boolean validate() {
8282
validate null, null, null
8383
}
8484

85+
/**
86+
* Validate the object with the given adhoc constraints
87+
*
88+
* @return True if it is valid
89+
*/
8590
boolean validate(Closure<?>... adHocConstraintsClosures) {
8691
validate(null, null, adHocConstraintsClosures)
8792
}
8893

94+
/**
95+
* Validate the object with the given parameters
96+
*
97+
* @return True if it is valid
98+
*/
8999
boolean validate(Map<String, Object> params) {
90100
validate params, null
91101
}
92102

103+
/**
104+
* Validate the object with the given parameters and adhoc constraints
105+
*
106+
* @return True if it is valid
107+
*/
93108
boolean validate(Map<String, Object> params, Closure<?>... adHocConstraintsClosures) {
94109
validate(null, params, adHocConstraintsClosures)
95110
}
96111

112+
/**
113+
* Validate the object for the given list of fields
114+
*
115+
* @return True if it is valid
116+
*/
97117
boolean validate(List fieldsToValidate) {
98118
validate fieldsToValidate, null, null
99119
}
100120

121+
/**
122+
* Validate the object for the given list of fields and adhoc constraints
123+
*
124+
* @return True if it is valid
125+
*/
101126
boolean validate(List fieldsToValidate, Closure<?>... adHocConstraintsClosures) {
102127
validate(fieldsToValidate, null, adHocConstraintsClosures)
103128
}
104129

130+
/**
131+
* Validate the object for the given list of fields and parameters
132+
*
133+
* @return True if it is valid
134+
*/
105135
boolean validate(List fieldsToValidate, Map<String, Object> params) {
106136
validate fieldsToValidate, params, null
107137
}
108138

139+
/**
140+
* Validate the object for the given list of fields, parameters and adhoc constraints
141+
*
142+
* @return True if it is valid
143+
*/
109144
boolean validate(List fieldsToValidate, Map<String, Object> params, Closure<?>... adHocConstraintsClosures) {
110145
beforeValidateHelper.invokeBeforeValidate(this, fieldsToValidate)
111146

@@ -157,6 +192,17 @@ trait Validateable {
157192
this.getProperty(prop.propertyName)
158193
}
159194

195+
@CompileStatic
196+
private static ConstraintsEvaluator findConstraintsEvaluator() {
197+
try {
198+
BeanFactory ctx = Holders.applicationContext
199+
ConstraintsEvaluator evaluator = ctx.getBean(ConstraintsEvaluator.BEAN_NAME, ConstraintsEvaluator)
200+
return evaluator
201+
} catch (Throwable e) {
202+
return new DefaultConstraintEvaluator()
203+
}
204+
}
205+
160206
private MessageSource findMessageSource() {
161207
try {
162208
ApplicationContext ctx = Holders.applicationContext
@@ -167,6 +213,12 @@ trait Validateable {
167213
}
168214
}
169215

216+
private void initErrors() {
217+
if (errors == null) {
218+
errors = new ValidationErrors(this, this.getClass().getName())
219+
}
220+
}
221+
170222
static boolean defaultNullable() {
171223
false
172224
}

grails-test-suite-web/src/test/groovy/org/grails/web/commandobjects/CommandObjectsSpec.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class CommandObjectsSpec extends Specification {
191191
when:
192192
def model = controller.methodAction()
193193
def person = model.person
194-
def constrainedProperties = person.constraints
194+
def constrainedProperties = person.constraintsMap
195195
def nameConstrainedProperty = constrainedProperties.name
196196
def matchesProperty = nameConstrainedProperty.matches
197197

grails-test-suite-web/src/test/groovy/org/grails/web/taglib/CoreTagsTests.groovy

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.grails.web.taglib
22

3+
import grails.util.Environment
34
import org.grails.taglib.GrailsTagException
45

56
/**
@@ -10,6 +11,11 @@ import org.grails.taglib.GrailsTagException
1011
*/
1112
class CoreTagsTests extends AbstractGrailsTagTests {
1213

14+
@Override
15+
protected void onSetUp() {
16+
System.setProperty(Environment.KEY, "")
17+
}
18+
1319
void testUnlessWithTestCondition() {
1420
def template = '<g:unless test="${cond}">body text</g:unless>'
1521
assertOutputEquals 'body text', template, [cond: false], {it.toString().trim()}

0 commit comments

Comments
 (0)