spring-projects/spring-framework · error · IllegalArgumentException
staticField must be a fully qualified class plus static…
Error message
staticField must be a fully qualified class plus static field name: for example, 'example.MyExampleClass.MY_EXAMPLE_FIELD'
What it means
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.
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.
Example fix
<!-- before: bare field name, no class --> <bean id='f' class='o.s.b.f.config.FieldRetrievingFactoryBean'> <property name='staticField' value='MAX'/> </bean> <!-- after: fully qualified class plus field --> <bean id='f' class='o.s.b.f.config.FieldRetrievingFactoryBean'> <property name='staticField' value='com.acme.Const.MAX'/> </bean>
Defensive patterns
Strategy: validation
Validate before calling
String sf = fb.getStaticField();
int dot = (sf == null) ? -1 : sf.lastIndexOf('.');
if (dot <= 0 || dot == sf.length() - 1) {
throw new IllegalArgumentException("staticField must be 'pkg.Cls.FIELD': " + sf);
} Type guard
// True if staticField has a class portion and a non-empty field name
boolean wellFormed(String sf) {
int dot = sf == null ? -1 : sf.lastIndexOf('.');
return dot > 0 && dot < sf.length() - 1;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Specify either targetClass or targetObject, not both
- Specify targetClass or targetObject in combination with…
- Invalid key '
- Neither 'targetObject' nor 'targetBeanName' specified, and…
- Property 'serviceLocatorInterface' is required
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/20b13fa8b8cfdf2b.
Report an issue: GitHub.
Appendix: source
Thrown at spring-beans/src/main/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.java:182
throw new IllegalArgumentException("Specify either targetClass or targetObject, not both");
}
if (this.targetClass == null && this.targetObject == null) {
if (this.targetField != null) {
throw new IllegalArgumentException(
"Specify targetClass or targetObject in combination with targetField");
}
// If no other property specified, consider bean name as static field expression.
if (this.staticField == null) {
this.staticField = this.beanName;
Assert.state(this.staticField != null, "No target field specified");
}
// Try to parse static field into class and field.
int lastDotIndex = this.staticField.lastIndexOf('.');
if (lastDotIndex == -1 || lastDotIndex == this.staticField.length()) {
throw new IllegalArgumentException(
"staticField must be a fully qualified class plus static field name: " +
"for example, 'example.MyExampleClass.MY_EXAMPLE_FIELD'");
}
String className = this.staticField.substring(0, lastDotIndex);
String fieldName = this.staticField.substring(lastDotIndex + 1);
this.targetClass = ClassUtils.forName(className, this.beanClassLoader);
this.targetField = fieldName;
}
else if (this.targetField == null) {
// Either targetClass or targetObject specified.
throw new IllegalArgumentException("targetField is required");
}
// Try to get the exact method first.
Class<?> targetClass = (this.targetObject != null ? this.targetObject.getClass() : this.targetClass);
this.fieldObject = targetClass.getField(this.targetField);
}View on GitHub (pinned to 69bf83ad71)