diff --git a/config/src/main/java/com/typesafe/config/ConfigBeanFactory.java b/config/src/main/java/com/typesafe/config/ConfigBeanFactory.java index 53687d6e..acc2aa4f 100644 --- a/config/src/main/java/com/typesafe/config/ConfigBeanFactory.java +++ b/config/src/main/java/com/typesafe/config/ConfigBeanFactory.java @@ -40,6 +40,10 @@ public class ConfigBeanFactory { * @param clazz class to be instantiated * @param the type of the class to be instantiated * @return an instance of the class populated with data from the config + * @throws ConfigException.BadBean + * If something is wrong with the JavaBean + * @throws ConfigException + * Can throw the same exceptions as the getters on Config */ public static T create(Config config, Class clazz) { return createInternal(config, clazz); @@ -57,8 +61,8 @@ public class ConfigBeanFactory { BeanInfo beanInfo = null; try { beanInfo = Introspector.getBeanInfo(clazz); - } catch(IntrospectionException e) { - throw new ConfigException.Generic("Could not get bean information for class " + clazz.getName(), e); + } catch (IntrospectionException e) { + throw new ConfigException.BadBean("Could not get bean information for class " + clazz.getName(), e); } try { @@ -70,8 +74,7 @@ public class ConfigBeanFactory { Method setter = beanProp.getWriteMethod(); Object configValue = configProps.get(beanProp.getName()); if (configValue == null) { - throw new ConfigException.Generic( - "Could not find property '" + beanProp.getName() + "' from class '" + clazz.getName() + "' in config."); + throw new ConfigException.Missing(beanProp.getName()); } if (configValue instanceof Map) { configValue = createInternal(config.getConfig(originalNames.get(beanProp.getDisplayName())), beanProp.getPropertyType()); @@ -84,11 +87,11 @@ public class ConfigBeanFactory { } return bean; } catch (InstantiationException e) { - throw new ConfigException.Generic(clazz + " needs a public no args constructor", e); + throw new ConfigException.BadBean(clazz.getName() + " needs a public no-args constructor to be used as a bean", e); } catch (IllegalAccessException e) { - throw new ConfigException.Generic(clazz + " getters and setters are not accessible", e); + throw new ConfigException.BadBean(clazz.getName() + " getters and setters are not accessible, they must be for use as a bean", e); } catch (InvocationTargetException e) { - throw new ConfigException.Generic("Calling bean method caused exception", e); + throw new ConfigException.BadBean("Calling bean method on " + clazz.getName() + " caused an exception", e); } } diff --git a/config/src/main/java/com/typesafe/config/ConfigException.java b/config/src/main/java/com/typesafe/config/ConfigException.java index df2c7b34..79742b34 100644 --- a/config/src/main/java/com/typesafe/config/ConfigException.java +++ b/config/src/main/java/com/typesafe/config/ConfigException.java @@ -385,6 +385,21 @@ public abstract class ConfigException extends RuntimeException implements Serial } } + /** + * Some problem with a JavaBean we are trying to initialize. + */ + public static class BadBean extends BugOrBroken { + private static final long serialVersionUID = 1L; + + public BadBean(String message, Throwable cause) { + super(message, cause); + } + + public BadBean(String message) { + this(message, null); + } + } + /** * Exception that doesn't fall into any other category. */ diff --git a/config/src/test/scala/com/typesafe/config/impl/ConfigBeanFactoryTest.scala b/config/src/test/scala/com/typesafe/config/impl/ConfigBeanFactoryTest.scala index 0d1c05c2..6eec28b9 100644 --- a/config/src/test/scala/com/typesafe/config/impl/ConfigBeanFactoryTest.scala +++ b/config/src/test/scala/com/typesafe/config/impl/ConfigBeanFactoryTest.scala @@ -40,11 +40,11 @@ class ConfigBeanFactoryTest extends TestUtils { val configIs: InputStream = this.getClass().getClassLoader().getResourceAsStream("beanconfig/beanconfig01.conf") val config: Config = ConfigFactory.parseReader(new InputStreamReader(configIs), ConfigParseOptions.defaults.setSyntax(ConfigSyntax.CONF)).resolve - val expected = intercept[ConfigException.Generic] { + val expected = intercept[ConfigException.Missing] { ConfigBeanFactory.create(config, classOf[NoFoundPropBeanConfig]) } - assertEquals("Could not find property 'propNotListedInConfig' from class 'beanconfig.NoFoundPropBeanConfig' in config.", - expected.getMessage) + // TODO this error message should have the config name not the camelcase name + assertTrue(expected.getMessage.contains("propNotListedInConfig")) } @Test