diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/Bean.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/Bean.java
index e9772936392..53a76f094ac 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/Bean.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/Bean.java
@@ -22,10 +22,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import org.springframework.beans.factory.annotation.Autowire;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-
/**
* Annotation to be applied to methods that create beans in a Spring context. The name of
@@ -65,33 +61,39 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
@Documented
public @interface Bean {
- /**
- * Role this bean plays in the overall application configuration.
- *
- * @see BeanDefinition#ROLE_APPLICATION
- * @see BeanDefinition#ROLE_INFRASTRUCTURE
- * @see BeanDefinition#ROLE_SUPPORT
- *
- * @see AbstractBeanDefinition the 'role' field is assigned by default to
- * ROLE_APPLICATION
- */
- int role() default BeanDefinition.ROLE_APPLICATION;
+ // TODO:
+// /**
+// * Role this bean plays in the overall application configuration.
+// *
+// * @see BeanDefinition#ROLE_APPLICATION
+// * @see BeanDefinition#ROLE_INFRASTRUCTURE
+// * @see BeanDefinition#ROLE_SUPPORT
+// *
+// * @see AbstractBeanDefinition the 'role' field is assigned by default to
+// * ROLE_APPLICATION
+// */
+// int role() default BeanDefinition.ROLE_APPLICATION;
+
+ String[] name() default {};
- /**
- * Bean aliases.
- */
- String[] aliases() default {};
+ // TODO: Prune aliases, favor name[]
+// /**
+// * Bean aliases.
+// */
+// String[] aliases() default {};
- /**
- * Scope: whether the bean is a singleton, prototype or custom scope. Default is
- * singleton.
- */
- String scope() default StandardScopes.SINGLETON;
+ // TODO: favor @Scope
+// /**
+// * Scope: whether the bean is a singleton, prototype or custom scope. Default is
+// * singleton.
+// */
+// String scope() default StandardScopes.SINGLETON;
- /**
- * Bean autowire strategy.
- */
- Autowire autowire() default Autowire.INHERITED;
+ // TODO: prune autowiring?
+// /**
+// * Bean autowire strategy.
+// */
+// Autowire autowire() default Autowire.INHERITED;
// /**
// * Bean lazy strategy.
@@ -111,13 +113,14 @@ public @interface Bean {
* Bean init method name. Normally this is not needed, as the initialization (with
* parameterization) can be done directly through java code.
*/
- String initMethodName() default "";
+ String initMethod() default "";
/**
* Bean destroy method name.
*/
- String destroyMethodName() default "";
+ String destroyMethod() default "";
+ // TODO: Prune DependencyCheck
// /**
// * Bean dependency check strategy.
// */
@@ -128,19 +131,23 @@ public @interface Bean {
*/
String[] dependsOn() default {};
+ // TODO: Prune @Meta
// /**
// * Metadata for the current bean.
// */
// Meta[] meta() default { };
- /**
- * Allow the bean to be overridden in another JavaConfig, XML or other non-Java
- * configuration. This is consistent with DefaultListableBeanFactory's
- * allowBeanDefinitionOverriding property, which defaults to true.
- *
- * @return whether overriding of this bean is allowed
- */
- boolean allowOverriding() default true;
+ // TODO: Prune allowOverriding
+// /**
+// * Allow the bean to be overridden in another JavaConfig, XML or other non-Java
+// * configuration. This is consistent with DefaultListableBeanFactory's
+// * allowBeanDefinitionOverriding property, which defaults to true.
+// *
+// * @return whether overriding of this bean is allowed
+// */
+// boolean allowOverriding() default true;
+//
+ //String name() default "";
}
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/BeanMethod.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/BeanMethod.java
index 606ee570351..96077eb48d1 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/BeanMethod.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/BeanMethod.java
@@ -16,16 +16,22 @@
package org.springframework.config.java;
import static java.lang.String.*;
+import static org.springframework.config.java.StandardScopes.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
+import org.springframework.beans.factory.parsing.Location;
+import org.springframework.beans.factory.parsing.Problem;
+import org.springframework.beans.factory.parsing.ProblemReporter;
+import org.springframework.context.annotation.Scope;
+import org.springframework.core.io.FileSystemResource;
import org.springframework.util.Assert;
-public final class BeanMethod implements Validatable {
+public final class BeanMethod {
private final String name;
private final int modifiers;
@@ -65,9 +71,8 @@ public final class BeanMethod implements Validatable {
}
/**
- * Returns the annotation on this method matching annoType or null
- * IllegalStateException} if not present.
- *
+ * @return the annotation on this method matching annoType or
+ * {@literal null} if not present.
* @see #getRequiredAnnotation(Class)
*/
@SuppressWarnings("unchecked")
@@ -80,9 +85,8 @@ public final class BeanMethod implements Validatable {
}
/**
- * Returns the annotation on this method matching annoType or throws
- * {@link IllegalStateException} if not present.
- *
+ * @return the annotation on this method matching annoType
+ * @throws {@link IllegalStateException} if not present
* @see #getAnnotation(Class)
*/
public T getRequiredAnnotation(Class annoType) {
@@ -96,7 +100,7 @@ public final class BeanMethod implements Validatable {
}
/**
- * Sets up bi-directional relationship between this method and its declaring class.
+ * Set up a bi-directional relationship between this method and its declaring class.
*
* @see ConfigurationClass#addMethod(BeanMethod)
*/
@@ -116,22 +120,20 @@ public final class BeanMethod implements Validatable {
return lineNumber;
}
- public void validate(List errors) {
+ public void validate(ProblemReporter problemReporter) {
if (Modifier.isPrivate(getModifiers()))
- errors.add(new PrivateMethodError());
+ problemReporter.error(new PrivateMethodError());
if (Modifier.isFinal(getModifiers()))
- errors.add(new FinalMethodError());
+ problemReporter.error(new FinalMethodError());
if (this.getAnnotation(ScopedProxy.class) == null)
return;
- Bean bean =this.getRequiredAnnotation(Bean.class);
-
- if (bean.scope().equals(StandardScopes.SINGLETON)
- || bean.scope().equals(StandardScopes.PROTOTYPE))
- errors.add(new InvalidScopedProxyDeclarationError(this));
+ Scope scope = this.getAnnotation(Scope.class);
+ if(scope == null || scope.equals(SINGLETON) || scope.equals(PROTOTYPE))
+ problemReporter.error(new InvalidScopedProxyDeclarationError(this));
}
@Override
@@ -181,27 +183,17 @@ public final class BeanMethod implements Validatable {
return true;
}
- /** JavaConfigMethods must be visible (non-private) in order to accommodate CGLIB. */
- public class PrivateMethodError extends UsageError {
+ /** {@link Bean} methods must be non-private in order to accommodate CGLIB. */
+ public class PrivateMethodError extends Problem {
public PrivateMethodError() {
- super(getDeclaringClass(), getLineNumber());
- }
-
- @Override
- public String getDescription() {
- return format("method '%s' may not be private", getName());
+ super(format("method '%s' may not be private", getName()), new Location(new FileSystemResource("/dev/null")));
}
}
- /** JavaConfigMethods must be extensible (non-final) in order to accommodate CGLIB. */
- public class FinalMethodError extends UsageError {
+ /** {@link Bean} methods must be non-final in order to accommodate CGLIB. */
+ public class FinalMethodError extends Problem {
public FinalMethodError() {
- super(getDeclaringClass(), getLineNumber());
- }
-
- @Override
- public String getDescription() {
- return format("method '%s' may not be final - remove the final modifier to continue", getName());
+ super(format("method '%s' may not be final. remove the final modifier to continue", getName()), new Location(new FileSystemResource("/dev/null")));
}
}
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/BeanRegistrar.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/BeanRegistrar.java
index b9852c839df..266123ef05c 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/BeanRegistrar.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/BeanRegistrar.java
@@ -4,6 +4,8 @@ import static java.lang.String.*;
import static org.springframework.util.StringUtils.*;
import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -15,6 +17,7 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.annotation.Scope;
import org.springframework.core.annotation.AnnotationUtils;
@@ -42,20 +45,28 @@ public class BeanRegistrar implements BeanDefinitionRegistrar {
beanDef.setFactoryMethodName(method.getName());
Bean bean = method.getRequiredAnnotation(Bean.class);
-
- Configuration defaults = configClass.getMetadata();
+
+ // TODO: prune defaults
+ //Configuration defaults = configClass.getMetadata();
// consider scoping
- beanDef.setScope(bean.scope());
+ Scope scope = method.getAnnotation(Scope.class);
+ if(scope != null)
+ beanDef.setScope(scope.value());
- // consider autowiring
- if (bean.autowire() != AnnotationUtils.getDefaultValue(Bean.class, "autowire"))
- beanDef.setAutowireMode(bean.autowire().value());
- else if (defaults.defaultAutowire() != AnnotationUtils.getDefaultValue(Configuration.class,
- "defaultAutowire"))
- beanDef.setAutowireMode(defaults.defaultAutowire().value());
+ // TODO: prune autowiring
+// // consider autowiring
+// if (bean.autowire() != AnnotationUtils.getDefaultValue(Bean.class, "autowire"))
+// beanDef.setAutowireMode(bean.autowire().value());
+// else if (defaults.defaultAutowire() != AnnotationUtils.getDefaultValue(Configuration.class,
+// "defaultAutowire"))
+// beanDef.setAutowireMode(defaults.defaultAutowire().value());
- String beanName = method.getName();
+ // consider name and any aliases
+ ArrayList names = new ArrayList(Arrays.asList(bean.name()));
+ String beanName = (names.size() > 0) ? names.remove(0) : method.getName();
+ for (String alias : bean.name())
+ registry.registerAlias(beanName, alias);
// has this already been overriden (i.e.: via XML)?
if (containsBeanDefinitionIncludingAncestry(beanName, registry)) {
@@ -65,11 +76,12 @@ public class BeanRegistrar implements BeanDefinitionRegistrar {
if (!(existingBeanDef instanceof ConfigurationClassBeanDefinition)) {
// no -> then it's an external override, probably XML
- // ensure that overriding is ok
- if (bean.allowOverriding() == false) {
- UsageError error = configClass.new IllegalBeanOverrideError(null, method);
- throw new MalformedConfigurationException(error);
- }
+ // TODO: Prune this
+// // ensure that overriding is ok
+// if (bean.allowOverriding() == false) {
+// UsageError error = configClass.new IllegalBeanOverrideError(null, method);
+// throw new MalformedConfigurationException(error);
+// }
// overriding is legal, return immediately
logger.info(format("Skipping loading bean definition for %s: a definition for bean "
@@ -78,13 +90,6 @@ public class BeanRegistrar implements BeanDefinitionRegistrar {
}
}
- // propagate this bean's 'role' attribute
- beanDef.setRole(bean.role());
-
- // consider aliases
- for (String alias : bean.aliases())
- registry.registerAlias(beanName, alias);
-
// TODO: re-enable for Lazy support
// // is this bean marked as primary for disambiguation?
// if (bean.primary() == Primary.TRUE)
@@ -96,12 +101,12 @@ public class BeanRegistrar implements BeanDefinitionRegistrar {
// beanDef.setLazyInit(true);
// does this bean have a custom init-method specified?
- String initMethodName = bean.initMethodName();
+ String initMethodName = bean.initMethod();
if (hasText(initMethodName))
beanDef.setInitMethodName(initMethodName);
// does this bean have a custom destroy-method specified?
- String destroyMethodName = bean.destroyMethodName();
+ String destroyMethodName = bean.destroyMethod();
if (hasText(destroyMethodName))
beanDef.setDestroyMethodName(destroyMethodName);
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/Configuration.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/Configuration.java
index 1c6756f581b..d07c689d62d 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/Configuration.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/Configuration.java
@@ -22,8 +22,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import org.springframework.beans.factory.annotation.Autowire;
-import org.springframework.beans.factory.annotation.Required;
import org.springframework.stereotype.Component;
@@ -44,9 +42,13 @@ import org.springframework.stereotype.Component;
* fact that this annotation is meta-annotated with {@link Component @Component}.
*
*
+ * May be used in conjunction with {@link Lazy}
+ *
* @author Rod Johnson
* @author Chris Beams
* @since 3.0
+ * @see Lazy
+ * @see Bean
*/
@Component
@Target( { ElementType.TYPE })
@@ -55,22 +57,25 @@ import org.springframework.stereotype.Component;
@Documented
public @interface Configuration {
- /**
- * Configuration name. Allow different variants, such as test, production etc. Default
- * will always match.
- *
- * @return
- */
- String[] names() default "";
+ // TODO: consider pruning @Configuration(name[])
+// /**
+// * Configuration name. Allow different variants, such as test, production etc. Default
+// * will always match.
+// *
+// * @return
+// */
+// String[] name() default "";
- /**
- * Specifies the default autowiring strategy.
- *
- * @see Autowire
- * @return
- */
- Autowire defaultAutowire() default Autowire.INHERITED;
+ // TODO: Prune defaultAutowire
+// /**
+// * Specifies the default autowiring strategy.
+// *
+// * @see Autowire
+// * @return
+// */
+// Autowire defaultAutowire() default Autowire.INHERITED;
+ // TODO: Prune DependencyCheck
// /**
// * Dependency check strategy. By default, the dependency check is
// * unspecified, that is the default Spring option will apply. In most cases,
@@ -81,6 +86,8 @@ public @interface Configuration {
// */
// DependencyCheck defaultDependencyCheck() default DependencyCheck.UNSPECIFIED;
//
+
+ // TODO: Favor @Lazy at the @Configuration class level. Should have @Target(TYPE, METHOD)
// /**
// * Bean instantiation strategy. By default, it is unspecified.
// *
@@ -89,14 +96,16 @@ public @interface Configuration {
// */
// Lazy defaultLazy() default Lazy.UNSPECIFIED;
- /**
- * Do we autowire with aspects from the enclosing factory scope?
- */
- boolean useFactoryAspects() default false;
+ // TODO: prune useFactoryAspects
+// /**
+// * Do we autowire with aspects from the enclosing factory scope?
+// */
+// boolean useFactoryAspects() default false;
- /**
- * Do we check {@link Required @Required} methods to make sure they've been called?
- */
- boolean checkRequired() default false;
+ // TODO: this is the default, and needs to be switched off at annotation-config
+// /**
+// * Do we check {@link Required @Required} methods to make sure they've been called?
+// */
+// boolean checkRequired() default false;
}
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationClass.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationClass.java
index c5a1e1b5115..a73dde096e3 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationClass.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationClass.java
@@ -21,9 +21,12 @@ import static java.lang.String.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
+import org.springframework.beans.factory.parsing.Location;
+import org.springframework.beans.factory.parsing.Problem;
+import org.springframework.beans.factory.parsing.ProblemReporter;
+import org.springframework.core.io.FileSystemResource;
import org.springframework.util.Assert;
import sun.security.x509.Extension;
@@ -47,7 +50,7 @@ import sun.security.x509.Extension;
*/
// TODO: SJC-242 update documentation in light of generalization changes
// consider removing all refs to Bean, ExternalBean, etc.
-public final class ConfigurationClass extends ModelClass implements Validatable {
+public final class ConfigurationClass extends ModelClass {
private String beanName;
@@ -174,18 +177,18 @@ public final class ConfigurationClass extends ModelClass implements Validatable
return this;
}
- public void validate(List errors) {
+ public void validate(ProblemReporter problemReporter) {
// configuration classes must be annotated with @Configuration
if (metadata == null)
- errors.add(new NonAnnotatedConfigurationError());
+ problemReporter.error(new NonAnnotatedConfigurationError());
// a configuration class may not be final (CGLIB limitation)
if (Modifier.isFinal(modifiers))
- errors.add(new FinalConfigurationError());
+ problemReporter.error(new FinalConfigurationError());
for (BeanMethod method : methods)
- method.validate(errors);
+ method.validate(problemReporter);
}
@@ -248,94 +251,27 @@ public final class ConfigurationClass extends ModelClass implements Validatable
/** Configuration classes must be annotated with {@link Configuration @Configuration}. */
- public class NonAnnotatedConfigurationError extends UsageError {
+ public class NonAnnotatedConfigurationError extends Problem {
public NonAnnotatedConfigurationError() {
- super(ConfigurationClass.this, -1);
+ super(
+ format("%s was provided as a Java Configuration class but was not annotated with @%s. "
+ + "Update the class definition to continue.", getSimpleName(), Configuration.class
+ .getSimpleName()),
+ new Location(new FileSystemResource("/dev/null"))
+ );
}
- @Override
- public String getDescription() {
- return format("%s was provided as a Java Configuration class but was not annotated with @%s. "
- + "Update the class definition to continue.", getSimpleName(), Configuration.class
- .getSimpleName());
- }
}
/** Configuration classes must be non-final to accommodate CGLIB subclassing. */
- public class FinalConfigurationError extends UsageError {
+ public class FinalConfigurationError extends Problem {
public FinalConfigurationError() {
- super(ConfigurationClass.this, -1);
+ super(
+ format("@%s class may not be final. Remove the final modifier to continue.",
+ Configuration.class.getSimpleName()),
+ new Location(new FileSystemResource("/dev/null"))
+ );
}
-
- @Override
- public String getDescription() {
- return format("@%s class may not be final. Remove the final modifier to continue.",
- Configuration.class.getSimpleName());
- }
- }
-
-
- public class InvalidPluginException extends UsageError {
-
- private final Annotation invalidPluginAnnotation;
-
- public InvalidPluginException(Annotation invalidPluginAnnotation) {
- super(ConfigurationClass.this, -1);
- this.invalidPluginAnnotation = invalidPluginAnnotation;
- }
-
- @Override
- public String getDescription() {
- return format("Annotation [%s] was not annotated with @Plugin", invalidPluginAnnotation);
- }
-
- }
-
- /**
- * Error raised when a Bean marked as 'allowOverriding=false' is attempted to be
- * overridden by another bean definition.
- *
- * @see Bean#allowOverriding()
- */
- public class IllegalBeanOverrideError extends UsageError {
- private final ConfigurationClass authoritativeClass;
- private final BeanMethod finalMethodInQuestion;
-
- /**
- * Creates a new IllegalBeanOverrideError object.
- *
- * @param violatingClass class attempting an illegal override. null value signifies
- * that the violating class is unknown or that there is no class to speak of
- * (in the case of an XML bean definition doing the illegal overriding)
- * @param finalMethodInQuestion the method that has been marked
- * 'allowOverriding=false'
- */
- public IllegalBeanOverrideError(ConfigurationClass violatingClass, BeanMethod finalMethodInQuestion) {
- super(violatingClass, -1);
- this.authoritativeClass = ConfigurationClass.this;
- this.finalMethodInQuestion = finalMethodInQuestion;
- }
-
- @Override
- public String getDescription() {
- return format("Illegal attempt by '%s' to override bean definition originally "
- + "specified by %s.%s. Consider removing 'allowOverride=false' from original method.",
- finalMethodInQuestion.getName(), authoritativeClass.getSimpleName(),
- finalMethodInQuestion.getName());
- }
- }
-
- public boolean hasMethod(String methodName) {
- return getMethod(methodName) != null;
- }
-
- public BeanMethod getMethod(String methodName) {
-
- for (BeanMethod method : methods)
- if (methodName.equals(method.getName()))
- return method;
-
- return null;
}
}
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationModel.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationModel.java
index 9a8403ff8b6..2fe2db831ae 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationModel.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/ConfigurationModel.java
@@ -18,7 +18,11 @@ package org.springframework.config.java;
import static java.lang.String.*;
import java.util.ArrayList;
-import java.util.List;
+
+import org.springframework.beans.factory.parsing.Location;
+import org.springframework.beans.factory.parsing.Problem;
+import org.springframework.beans.factory.parsing.ProblemReporter;
+import org.springframework.core.io.FileSystemResource;
@@ -39,7 +43,7 @@ import java.util.List;
* @author Chris Beams
* @see org.springframework.config.java.internal.parsing.ConfigurationParser
*/
-public final class ConfigurationModel implements Validatable {
+public final class ConfigurationModel {
/* list is used because order and collection equality matters. */
private final ArrayList configurationClasses = new ArrayList();
@@ -89,35 +93,40 @@ public final class ConfigurationModel implements Validatable {
* Recurses through the model validating each object along the way and aggregating any
* errors.
*
- * @see ConfigurationClass#validate(java.util.List)
- * @see BeanMethod#validate(java.util.List)
- * @see UsageError
+ * @see ConfigurationClass#validate
+ * @see BeanMethod#validate
*/
- public void validate(List errors) {
+ public void validate(ProblemReporter problemReporter) {
// user must specify at least one configuration
if (configurationClasses.isEmpty())
- errors.add(new EmptyModelError());
+ problemReporter.error(new EmptyModelError());
- // check for any illegal @Bean overriding
- ConfigurationClass[] allClasses = getAllConfigurationClasses();
- for (int i = 0; i < allClasses.length; i++) {
- for (BeanMethod method : allClasses[i].getMethods()) {
- Bean bean = method.getAnnotation(Bean.class);
-
- if (bean == null || bean.allowOverriding())
- continue;
-
- for (int j = i + 1; j < allClasses.length; j++)
- if (allClasses[j].hasMethod(method.getName()))
- errors.add(allClasses[i].new IllegalBeanOverrideError(allClasses[j], method));
- }
- }
+ // TODO: prune this
+// // check for any illegal @Bean overriding
+// ConfigurationClass[] allClasses = getAllConfigurationClasses();
+// for (int i = 0; i < allClasses.length; i++) {
+// for (BeanMethod method : allClasses[i].getMethods()) {
+// Bean bean = method.getAnnotation(Bean.class);
+//
+// if (bean == null || bean.allowOverriding())
+// continue;
+//
+// for (int j = i + 1; j < allClasses.length; j++)
+// if (allClasses[j].hasMethod(method.getName()))
+// problemReporter.error(
+// new Problem(
+// allClasses[i].new IllegalBeanOverrideError(allClasses[j], method).getDescription(),
+// new Location(new ClassPathResource(allClasses[i].getName().replace('.', '/').concat(".class")))
+// )
+// );
+// }
+// }
// each individual configuration class must be well-formed
// note that each configClass detects usage errors on its imports recursively
// note that each configClass will recursively process its respective methods
for (ConfigurationClass configClass : configurationClasses)
- configClass.validate(errors);
+ configClass.validate(problemReporter);
}
@Override
@@ -151,15 +160,13 @@ public final class ConfigurationModel implements Validatable {
}
- public class EmptyModelError extends UsageError {
+ public class EmptyModelError extends Problem {
public EmptyModelError() {
- super(null, 0);
- }
-
- @Override
- public String getDescription() {
- return format("Configuration model was empty. Make sure at least one "
- + "@%s class has been specified.", Configuration.class.getSimpleName());
+ super(
+ format("Configuration model was empty. Make sure at least one "
+ + "@%s class has been specified.", Configuration.class.getSimpleName()),
+ new Location(new FileSystemResource("/dev/null"))
+ );
}
}
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/InvalidScopedProxyDeclarationError.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/InvalidScopedProxyDeclarationError.java
index 4fc9dbe2e3d..78894e33c05 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/InvalidScopedProxyDeclarationError.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/InvalidScopedProxyDeclarationError.java
@@ -15,19 +15,19 @@
*/
package org.springframework.config.java;
+import org.springframework.beans.factory.parsing.Location;
+import org.springframework.beans.factory.parsing.Problem;
+import org.springframework.core.io.FileSystemResource;
-public class InvalidScopedProxyDeclarationError extends UsageError {
- private final BeanMethod method;
+public class InvalidScopedProxyDeclarationError extends Problem {
public InvalidScopedProxyDeclarationError(BeanMethod method) {
- super(method.getDeclaringClass(), method.getLineNumber());
- this.method = method;
+ super(
+ String.format("method %s contains an invalid annotation declaration: @%s "
+ + "cannot be used on a singleton/prototype bean", method.getName(), ScopedProxy.class
+ .getSimpleName()),
+ new Location(new FileSystemResource("/dev/null"))
+ );
}
- @Override
- public String getDescription() {
- return String.format("method %s contains an invalid annotation declaration: @%s "
- + "cannot be used on a singleton/prototype bean", method.getName(), ScopedProxy.class
- .getSimpleName());
- }
}
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/MalformedConfigurationException.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/MalformedConfigurationException.java
deleted file mode 100644
index 4fda73f97b8..00000000000
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/MalformedConfigurationException.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2002-2008 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.config.java;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-
-/**
- * TODO: rename to UsageException / move outside .internal?
- *
- * @author Chris Beams
- */
-@SuppressWarnings("serial")
-public class MalformedConfigurationException extends RuntimeException {
-
- private final List extends UsageError> errors;
-
- public MalformedConfigurationException(String message) {
- super(message);
- this.errors = new ArrayList();
- }
-
- public MalformedConfigurationException(UsageError... errors) {
- super(toString(errors));
- this.errors = Arrays.asList(errors);
- }
-
- public boolean containsError(Class extends UsageError> errorType) {
- for (UsageError error : errors)
- if (error.getClass().isAssignableFrom(errorType))
- return true;
-
- return false;
- }
-
- /**
- * Render a list of syntax errors as output suitable for diagnosis via System.err.
- */
- private static String toString(UsageError... errors) {
- StringBuilder sb = new StringBuilder();
-
- sb.append("\n");
-
- if (errors.length == 1)
- sb.append("A usage error has ");
- else
- sb.append(errors.length + " usage errors have ");
-
- sb.append("been detected:\n");
-
- for (int i = 0; i < errors.length; i++) {
- sb.append(errors[i].toString());
- if ((i + 1) < errors.length)
- sb.append('\n');
- }
-
- return sb.toString();
- }
-
-}
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/UsageError.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/UsageError.java
deleted file mode 100644
index d7d9122d1a0..00000000000
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/UsageError.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2002-2008 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.config.java;
-
-
-/**
- * Represents an invalid usage of JavaConfig constructs, e.g. a {@link Configuration} that
- * declares no {@link Bean @Bean} methods, or declaring both {@link Bean @Bean} and
- * {@link ExternalBean @ExternalBean} on a single method. Explore the type hierarchy to
- * discover all possible usage errors.
- *
- * @author Chris Beams
- * @see MalformedConfigurationException
- */
-public abstract class UsageError {
-
- private final ModelClass clazz;
- private final int lineNumber;
-
- /**
- * Create a new usage error, providing information about where the error was detected.
- *
- * @param modelClass class in which this error was detected. Null value indicates that
- * the error was not local to a single class.
- * @param lineNumber line number on which this error was detected (useful for tooling
- * integration)
- *
- * @see ModelClass#getSource()
- */
- public UsageError(ModelClass modelClass, int lineNumber) {
- this.clazz = modelClass;
- this.lineNumber = lineNumber;
- }
-
- /**
- * Human-readable description of this error suitable for console output or IDE tooling.
- */
- public abstract String getDescription();
-
- /**
- * Same as {@link #getDescription()} but attributed with class and line number
- * information. If modelClass constructor parameter was null, class and line number
- * information will be omitted.
- */
- public final String getAttributedDescription() {
- if (clazz == null)
- return getDescription();
-
- return String.format("%s:%d: %s", clazz.getSource(), lineNumber, getDescription());
- }
-
- /**
- * Delegates directly to {@link #getAttributedDescription()}.
- */
- @Override
- public String toString() {
- return getAttributedDescription();
- }
-
-}
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/Validatable.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/Validatable.java
deleted file mode 100644
index b2260baadea..00000000000
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/Validatable.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.springframework.config.java;
-
-import java.util.List;
-
-
-/**
- * Indicates a type is able to be validated for errors.
- *
- * @author Chris Beams
- */
-interface Validatable {
-
- /**
- * Validates this object, adding any errors to the supplied list of errors.
- */
- public void validate(List errors);
-
-}
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/ConfigurationEnhancer.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/ConfigurationEnhancer.java
index b2221d47022..77f16a50182 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/ConfigurationEnhancer.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/internal/enhancement/ConfigurationEnhancer.java
@@ -174,6 +174,7 @@ public class ConfigurationEnhancer {
* @return original subclass instance unless superclass is annnotated with @Aspect, in
* which case a subclass of the subclass is returned
*/
+ // TODO: try to implement with modifications to AbstractAspectJAdvisorFactory#isAspect
private Class> nestOneClassDeeperIfAspect(Class> superclass, Class> origSubclass) {
boolean superclassIsAnAspect = false;
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/AbstractConfigurationClassProcessor.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/AbstractConfigurationClassProcessor.java
index 9d18b8cd266..141d86de60b 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/AbstractConfigurationClassProcessor.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/AbstractConfigurationClassProcessor.java
@@ -16,11 +16,13 @@
package org.springframework.config.java.support;
import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
+import org.springframework.beans.factory.parsing.FailFastProblemReporter;
+import org.springframework.beans.factory.parsing.ProblemReporter;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.config.java.Bean;
import org.springframework.config.java.Configuration;
import org.springframework.config.java.ConfigurationModel;
-import org.springframework.config.java.MalformedConfigurationException;
import org.springframework.config.java.internal.parsing.ConfigurationParser;
@@ -44,6 +46,14 @@ import org.springframework.config.java.internal.parsing.ConfigurationParser;
*/
public abstract class AbstractConfigurationClassProcessor {
+ /**
+ * Used to register any problems detected with {@link Configuration} or {@link Bean}
+ * declarations. For instance, a Bean method marked as {@literal final} is illegal
+ * and would be reported as a problem. Defaults to {@link FailFastProblemReporter},
+ * but is overridable with {@link #setProblemReporter}
+ */
+ private ProblemReporter problemReporter = new FailFastProblemReporter();
+
/**
* Populate and return a registry containing all {@link Configuration} bean definitions
* to be processed.
@@ -65,12 +75,27 @@ public abstract class AbstractConfigurationClassProcessor {
/**
* Validate the given model and handle any errors. Implementations may choose to throw
- * {@link MalformedConfigurationException}, or in the case of tooling register problems
+ * {@link BeanDefinitionParsingException}, or in the case of tooling register problems
* with the UI.
* @param configModel {@link ConfigurationModel} to validate
*/
protected abstract void validateModel(ConfigurationModel configModel);
+ /**
+ * Override the default {@link ProblemReporter}.
+ * @param problemReporter custom problem reporter
+ */
+ protected final void setProblemReporter(ProblemReporter problemReporter) {
+ this.problemReporter = problemReporter;
+ }
+
+ /**
+ * Get the currently registered {@link ProblemReporter}.
+ */
+ protected final ProblemReporter getProblemReporter() {
+ return problemReporter;
+ }
+
/**
* Build and validate a {@link ConfigurationModel} based on the registry of
* {@link Configuration} classes provided by {@link #getConfigurationBeanDefinitions},
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationClassPostProcessor.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationClassPostProcessor.java
index 267562fcdac..d045a4c19db 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationClassPostProcessor.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationClassPostProcessor.java
@@ -18,7 +18,6 @@ package org.springframework.config.java.support;
import static java.lang.String.*;
import java.io.IOException;
-import java.util.ArrayList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -31,8 +30,6 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.config.java.Bean;
import org.springframework.config.java.Configuration;
import org.springframework.config.java.ConfigurationModel;
-import org.springframework.config.java.MalformedConfigurationException;
-import org.springframework.config.java.UsageError;
import org.springframework.config.java.internal.enhancement.ConfigurationEnhancer;
import org.springframework.config.java.internal.parsing.ConfigurationParser;
import org.springframework.core.Ordered;
@@ -136,15 +133,12 @@ public class ConfigurationClassPostProcessor extends AbstractConfigurationClassP
}
/**
- * Validates the given model.
- * @throws MalformedConfigurationException if any errors are detected
+ * Validates the given model. Any problems found are delegated
+ * to {@link #getProblemReporter()}.
*/
@Override
protected void validateModel(ConfigurationModel model) {
- ArrayList errors = new ArrayList();
- model.validate(errors);
- if (errors.size() > 0)
- throw new MalformedConfigurationException(errors.toArray(new UsageError[] {}));
+ model.validate(this.getProblemReporter());
}
/**
diff --git a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationModelBeanDefinitionReader.java b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationModelBeanDefinitionReader.java
index 0fe4e339475..07c4bad512d 100644
--- a/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationModelBeanDefinitionReader.java
+++ b/org.springframework.config.java/src/main/java/org/springframework/config/java/support/ConfigurationModelBeanDefinitionReader.java
@@ -19,12 +19,10 @@ import static java.lang.String.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
-import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
import org.springframework.config.java.Bean;
import org.springframework.config.java.BeanMethod;
@@ -96,18 +94,18 @@ class ConfigurationModelBeanDefinitionReader {
* @param beanDefs
*/
private void doLoadBeanDefinitionForConfigurationClass(ConfigurationClass configClass) {
- Configuration metadata = configClass.getMetadata();
- // TODO: think about implications with annotation-config
- if (metadata.checkRequired() == true) {
- RootBeanDefinition requiredAnnotationPostProcessor = new RootBeanDefinition();
- Class> beanClass = RequiredAnnotationBeanPostProcessor.class;
- String beanName = beanClass.getName() + "#0";
- requiredAnnotationPostProcessor.setBeanClass(beanClass);
- requiredAnnotationPostProcessor
- .setResourceDescription("ensures @Required methods have been invoked");
- registry.registerBeanDefinition(beanName, requiredAnnotationPostProcessor);
- }
+ // TODO: prune support for @Required
+// Configuration metadata = configClass.getMetadata();
+// if (metadata.checkRequired() == true) {
+// RootBeanDefinition requiredAnnotationPostProcessor = new RootBeanDefinition();
+// Class> beanClass = RequiredAnnotationBeanPostProcessor.class;
+// String beanName = beanClass.getName() + "#0";
+// requiredAnnotationPostProcessor.setBeanClass(beanClass);
+// requiredAnnotationPostProcessor
+// .setResourceDescription("ensures @Required methods have been invoked");
+// registry.registerBeanDefinition(beanName, requiredAnnotationPostProcessor);
+// }
GenericBeanDefinition configBeanDef = new GenericBeanDefinition();
configBeanDef.setBeanClassName(configClass.getName());
diff --git a/org.springframework.config.java/src/test/java/test/basic/BasicTests.java b/org.springframework.config.java/src/test/java/test/basic/BasicTests.java
index 479f05230c8..ed6729c0ad6 100644
--- a/org.springframework.config.java/src/test/java/test/basic/BasicTests.java
+++ b/org.springframework.config.java/src/test/java/test/basic/BasicTests.java
@@ -11,9 +11,9 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.config.java.Bean;
import org.springframework.config.java.Configuration;
-import org.springframework.config.java.MalformedConfigurationException;
import org.springframework.config.java.StandardScopes;
import org.springframework.config.java.support.ConfigurationClassPostProcessor;
+import org.springframework.context.annotation.Scope;
import test.beans.ITestBean;
import test.beans.TestBean;
@@ -96,68 +96,10 @@ public class BasicTests {
return bar;
}
- @Bean(scope = StandardScopes.PROTOTYPE)
+ @Bean @Scope(StandardScopes.PROTOTYPE)
public TestBean baz() {
return new TestBean("bar");
}
}
-
- @Test
- public void legalBeanOverriding() {
- {
- BeanFactory factory = initBeanFactory(ConfigWithBeanThatAllowsOverriding.class, ConfigWithBeanOverride.class);
-
- TestBean testBean = factory.getBean("testBean", TestBean.class);
-
- assertThat(testBean.getName(), equalTo("overridden"));
- }
-
- // now try it the other way around - order matters!
-
- {
- BeanFactory factory = initBeanFactory(ConfigWithBeanOverride.class, ConfigWithBeanThatAllowsOverriding.class);
-
- TestBean testBean = factory.getBean("testBean", TestBean.class);
-
- assertThat(testBean.getName(), equalTo("original"));
- }
-
- }
-
- @Test(expected=MalformedConfigurationException.class)
- public void illegalBeanOverriding() {
- initBeanFactory(ConfigWithBeanThatDisallowsOverriding.class, ConfigWithBeanOverride.class);
- }
-
- @Test
- public void illegalBeanOverriding2() {
- // should be okay when the class that disallows overriding is the one doing the overriding
- initBeanFactory(ConfigWithBeanOverride.class, ConfigWithBeanThatDisallowsOverriding.class);
- }
-
- @Configuration
- static class ConfigWithBeanThatAllowsOverriding {
- @Bean
- public TestBean testBean() {
- return new TestBean("original");
- }
- }
-
- @Configuration
- static class ConfigWithBeanThatDisallowsOverriding {
- @Bean(allowOverriding = false)
- public TestBean testBean() {
- return new TestBean("original");
- }
- }
-
- @Configuration
- static class ConfigWithBeanOverride {
- @Bean
- public TestBean testBean() {
- return new TestBean("overridden");
- }
- }
-
}
diff --git a/org.springframework.config.java/src/test/java/test/feature/lifecycle/scoping/ScopingTests.java b/org.springframework.config.java/src/test/java/test/feature/lifecycle/scoping/ScopingTests.java
index a5e0eb40bd3..99f21a4e90d 100644
--- a/org.springframework.config.java/src/test/java/test/feature/lifecycle/scoping/ScopingTests.java
+++ b/org.springframework.config.java/src/test/java/test/feature/lifecycle/scoping/ScopingTests.java
@@ -24,11 +24,10 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.aop.scope.ScopedObject;
import org.springframework.beans.factory.config.Scope;
+import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.config.java.Bean;
import org.springframework.config.java.Configuration;
-import org.springframework.config.java.InvalidScopedProxyDeclarationError;
-import org.springframework.config.java.MalformedConfigurationException;
import org.springframework.config.java.ScopedProxy;
import org.springframework.config.java.StandardScopes;
import org.springframework.config.java.support.ConfigurationClassPostProcessor;
@@ -118,8 +117,8 @@ public class ScopingTests {
try {
createContext(null, InvalidProxyOnPredefinedScopesConfiguration.class);
fail("exception expected");
- } catch (MalformedConfigurationException ex) {
- assertTrue(ex.containsError(InvalidScopedProxyDeclarationError.class));
+ } catch (BeanDefinitionParsingException ex) {
+ assertTrue(ex.getMessage().contains("cannot be used on a singleton/prototype bean"));
}
}
@@ -241,7 +240,8 @@ public class ScopingTests {
@Configuration
static class ScopeTestConfiguration {
- @Bean(scope = StandardScopes.SESSION)
+ @Bean
+ @org.springframework.context.annotation.Scope(StandardScopes.SESSION)
@ScopedProxy
public Foo foo() {
return new Foo();
@@ -326,21 +326,24 @@ public class ScopingTests {
@Configuration
public static class ScopedConfigurationClass {
- @Bean(scope = SCOPE)
+ @Bean
+ @org.springframework.context.annotation.Scope(SCOPE)
public TestBean scopedClass() {
TestBean tb = new TestBean();
tb.setName(flag);
return tb;
}
- @Bean(scope = SCOPE)
+ @Bean
+ @org.springframework.context.annotation.Scope(SCOPE)
public ITestBean scopedInterface() {
TestBean tb = new TestBean();
tb.setName(flag);
return tb;
}
- @Bean(scope = SCOPE)
+ @Bean
+ @org.springframework.context.annotation.Scope(SCOPE)
@ScopedProxy(proxyTargetClass = false)
public ITestBean scopedProxyInterface() {
TestBean tb = new TestBean();
@@ -349,7 +352,8 @@ public class ScopingTests {
}
@ScopedProxy
- @Bean(scope = SCOPE)
+ @Bean
+ @org.springframework.context.annotation.Scope(SCOPE)
public TestBean scopedProxyClass() {
TestBean tb = new TestBean();
tb.setName(flag);