{"record":{"id":"20b13fa8b8cfdf2b","repo":"spring-projects/spring-framework","slug":"staticfield-must-be-a-fully-qualified-class-plus-s","errorCode":null,"errorMessage":"staticField must be a fully qualified class plus static field name: for example, 'example.MyExampleClass.MY_EXAMPLE_FIELD'","messagePattern":"staticField must be a fully qualified class plus static field name: for example, 'example\\.MyExampleClass\\.MY_EXAMPLE_FIELD'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.java","lineNumber":182,"sourceCode":"\t\t\tthrow new IllegalArgumentException(\"Specify either targetClass or targetObject, not both\");\n\t\t}\n\n\t\tif (this.targetClass == null && this.targetObject == null) {\n\t\t\tif (this.targetField != null) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"Specify targetClass or targetObject in combination with targetField\");\n\t\t\t}\n\n\t\t\t// If no other property specified, consider bean name as static field expression.\n\t\t\tif (this.staticField == null) {\n\t\t\t\tthis.staticField = this.beanName;\n\t\t\t\tAssert.state(this.staticField != null, \"No target field specified\");\n\t\t\t}\n\n\t\t\t// Try to parse static field into class and field.\n\t\t\tint lastDotIndex = this.staticField.lastIndexOf('.');\n\t\t\tif (lastDotIndex == -1 || lastDotIndex == this.staticField.length()) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"staticField must be a fully qualified class plus static field name: \" +\n\t\t\t\t\t\t\"for example, 'example.MyExampleClass.MY_EXAMPLE_FIELD'\");\n\t\t\t}\n\t\t\tString className = this.staticField.substring(0, lastDotIndex);\n\t\t\tString fieldName = this.staticField.substring(lastDotIndex + 1);\n\t\t\tthis.targetClass = ClassUtils.forName(className, this.beanClassLoader);\n\t\t\tthis.targetField = fieldName;\n\t\t}\n\n\t\telse if (this.targetField == null) {\n\t\t\t// Either targetClass or targetObject specified.\n\t\t\tthrow new IllegalArgumentException(\"targetField is required\");\n\t\t}\n\n\t\t// Try to get the exact method first.\n\t\tClass<?> targetClass = (this.targetObject != null ? this.targetObject.getClass() : this.targetClass);\n\t\tthis.fieldObject = targetClass.getField(this.targetField);\n\t}","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-beans/src/main/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.java#L164-L200","documentation":"Thrown as an IllegalArgumentException by FieldRetrievingFactoryBean.afterPropertiesSet when staticField does not contain a '.' separating the class name from the field name, or the dot is the last character. The factory parses staticField as 'fullyQualifiedClassName.fieldName' via lastIndexOf('.'); if there is no dot or no name after it, the split is impossible and the configuration is rejected with an explicit example.","triggerScenarios":"Setting staticField to a value with no '.' (e.g. just 'MAX' or a bare bean name without package), or ending with '.' (e.g. 'com.acme.Const.'). The factory enters the parse branch (no targetClass/targetObject, no targetField) and the lastIndexOf('.') check fails.","commonSituations":"Passing a short bean id like 'MAX' as staticField assuming it resolves; typo dropping the package portion; trailing dot from concatenation bugs; copy-paste that included only the field name; misconfigured PropertyPlaceholder producing an empty package portion.","solutions":["Set staticField to the full 'package.Class.FIELD' form, e.g. 'com.acme.Const.MAX'.","If the bean id itself is the full expression, ensure it contains the package, class, and field separated by dots.","If you only have a field name, also set targetClass (or targetObject) and targetField instead of staticField.","Log/inspect the actual staticField value at runtime to catch placeholder or whitespace corruption."],"exampleFix":"<!-- before: bare field name, no class -->\n<bean id='f' class='o.s.b.f.config.FieldRetrievingFactoryBean'>\n  <property name='staticField' value='MAX'/>\n</bean>\n\n<!-- after: fully qualified class plus field -->\n<bean id='f' class='o.s.b.f.config.FieldRetrievingFactoryBean'>\n  <property name='staticField' value='com.acme.Const.MAX'/>\n</bean>","handlingStrategy":"validation","validationCode":"String sf = fb.getStaticField();\nint dot = (sf == null) ? -1 : sf.lastIndexOf('.');\nif (dot <= 0 || dot == sf.length() - 1) {\n    throw new IllegalArgumentException(\"staticField must be 'pkg.Cls.FIELD': \" + sf);\n}","typeGuard":"// True if staticField has a class portion and a non-empty field name\nboolean wellFormed(String sf) {\n    int dot = sf == null ? -1 : sf.lastIndexOf('.');\n    return dot > 0 && dot < sf.length() - 1;\n}","tryCatchPattern":null,"preventionTips":["Always write staticField as fully-qualified 'package.Class.FIELD'.","If only the field name is known, set targetClass + targetField instead.","Log the runtime staticField value to catch placeholder corruption.","Lint static-field strings in XML/annotations during CI."],"tags":["spring","factory-bean","configuration","static-field","validation"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}