Can't construct a java object for tag (java.lang.NoSuchMethodException)

5,048 views
Skip to first unread message

Kurtis Mullins

unread,
Mar 11, 2013, 3:43:44 PM3/11/13
to snakeya...@googlegroups.com
Hey,

I'm trying to read through the docs and understand how to use SnakeYAML. My code here is sort of crude; I'm just trying to get it to work but have ran into an exception. I'm not sure of the cause. Can anyone help me out with this?

import java.io.IOException;
import java.net.URL;
import java.util.Map;

import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;

import com.google.common.base.Charsets;
import com.google.common.io.Resources;

public class ConfigurationManager {
public static Object yamlconfig;

public static Object getInstance(String environment) throws IOException {
if (yamlconfig == null) {
Yaml yaml = new Yaml(new Constructor(Config.class));
URL filename = ConfigurationManager.class.getResource("/resources/config.yaml");
String rawConfig = Resources.toString(filename, Charsets.UTF_8);
yamlconfig = yaml.load(rawConfig);
}
return ConfigurationManager.yamlconfig;
}
// Testing purposes...
public static void main(String[] args) {
Object config;
try {
yamlconfig = ConfigurationManager.getInstance("local"); 
System.out.println(yamlconfig);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public class Config {
private Map<String, Environment> environments;
}
public class Environment {
private boolean clustered;
private Map<String, String> mongodb;
private Map<String, String> redis;
private Map<String, String> twitter;
private Map<String, Object> data;
}

}

Exception in thread "main" Can't construct a java object for tag:yaml.org,2002:<HIDDEN>.util.config.ConfigurationManager$Config; exception=java.lang.NoSuchMethodException: org.<HIDDEN>.util.config.ConfigurationManager$Config.<init>()
 in 'string', line 1, column 1:
    environments:
    ^

at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:333)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:182)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:141)
at org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.java:127)
at org.yaml.snakeyaml.Yaml.loadFromReader(Yaml.java:481)
at org.yaml.snakeyaml.Yaml.load(Yaml.java:400)
at org.<HIDDEN>.util.config.ConfigurationManager.getInstance(ConfigurationManager.java:27)
at org.<HIDDEN>.util.config.ConfigurationManager.main(ConfigurationManager.java:38)
Caused by: org.yaml.snakeyaml.error.YAMLException: java.lang.NoSuchMethodException: org.<HIDDEN>.util.config.ConfigurationManager$Config.<init>()
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.createEmptyJavaBean(Constructor.java:219)
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.construct(Constructor.java:189)
at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:331)
... 7 more
Caused by: java.lang.NoSuchMethodException: org.<HIDDEN>.util.config.ConfigurationManager$Config.<init>()
at java.lang.Class.getConstructor0(Class.java:2730)
at java.lang.Class.getDeclaredConstructor(Class.java:2004)
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.createEmptyJavaBean(Constructor.java:215)
... 9 more

Thanks,
- Kurtis

Kurtis Mullins

unread,
Mar 11, 2013, 3:46:58 PM3/11/13
to snakeya...@googlegroups.com
And please ignore that System.out.println statement. I really didn't expect it do anything or even use it; I just needed a good breakpoint so I could try to look into that yamlconfig object.

Jordan Angold

unread,
Mar 12, 2013, 2:29:21 AM3/12/13
to snakeya...@googlegroups.com
I can see why this case would be confusing. If I hadn't hit it repeatedly myself, I would be very confused too.

In your code, you have a ConfigurationManager$Config class and a ConfigurationManager$Environment class. Since you have not marked those classes as 'static', they are implicitly initialized with a hidden reference to their "parent" ConfigurationManager when you create them. However, this means that there is no constructor with zero arguments (which looks like ConfigurationManager$Config.<init>() in the exception).

The Oracle Java tutorials have a good page on this language feature here: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

Since it looks like you intend for ConfigurationManager to implement the "singleton" pattern, I recommend that you mark the Config and Environment classes static. Doing so should make your existing Java code work (though you might have to generate setters/getters or set SnakeYaml's bean access configuration or use lombok.

If you want to have an instance of ConfigurationManager that has nested instance(s) of Config and Environment, then message back. I don't know how to do that offhand, but I would be happy to help if you need it.

/Jordan

hardeep reehal

unread,
Apr 22, 2013, 4:38:52 PM4/22/13
to snakeya...@googlegroups.com
Kurtis: I beleive you are trying to read configuration shown as below:
 
test:
 key: value
 key1: valu1
 
where test is environment. The exception suggests that it is expecting to find 'environments' at the top level which obviously is not defined in the config.yaml.In order to solve this you either have to map the java classes to the exact name put in the configuration yaml. For example you will have to defined class for each environment such as 'test', 'dev' etc and defined these envrionments in the config yaml. the downside of this is that you have to create java class everytime you are introducing new environment. If you want to generalize the environment where environment is represented by environment class and in configuration it could be any of the environment such as 'dev', 'test' etc, then you need to extract the environment from configuration and convert it to string, create yaml instance based on environment class and then cast the obect to environment. I have similar requirements and am able to code and use it.  Following is the generalized code which works for me.


if (data.containsKey(envName)){
  String st = new Yaml().dump(data.get(envName));
  Constructor cnstr = new Constructor(Env.class);
  Yaml yaml = new Yaml(cnstr);
  env = (Env)yaml.load(st); 

Now you can access member variables on the env class.

Hope it helps!

Reply all
Reply to author
Forward
0 new messages