Reputation: 321
I'm tryng to use SnakeYaml library to configure my project using a YAML file. I have already read this example: Here
I follow that structure and I have these files:
config/statisticsConfig.yml
:
statisticsTopologyParams:
tickTupleFrequency: 60
hourlyStatistics:
windowLength: 3600
emitFrequency: 60
dailyStatistics:
windowLength: 86400
emitFrequency: 3600
Configuration.java
:
public class Configuration {
Map<String, ServiceConfig> statisticsTopologyParams;
public Configuration() {
}
@Override
public String toString() {
return "YamlConfig{" +
"statistics=" + statisticsTopologyParams +
'}';
}
public Map<String, ServiceConfig> getStatisticsTopologyParams() {
return statisticsTopologyParams;
}
public void setStatisticsTopologyParams(Map<String, ServiceConfig> statisticsTopologyParams) {
this.statisticsTopologyParams = statisticsTopologyParams;
}
}
ServiceConfig.java
:
public class ServiceConfig {
private Integer tickTupleFrequency;
private Map<String, Integer> hourlyStatistics;
private Map<String, Integer> dailyStatistics;
public ServiceConfig() {
}
public Integer getTickTupleFrequency() {
return tickTupleFrequency;
}
public void setTickTupleFrequency(Integer tickTupleFrequency) {
this.tickTupleFrequency = tickTupleFrequency;
}
public Map<String, Integer> getHourlyStatistics() {
return hourlyStatistics;
}
public void setHourlyStatistics(Map<String, Integer> hourlyStatistics) {
this.hourlyStatistics = hourlyStatistics;
}
public Map<String, Integer> getDailyStatistics() {
return dailyStatistics;
}
public void setDailyStatistics(Map<String, Integer> dailyStatistics) {
this.dailyStatistics = dailyStatistics;
}
}
YamlConfigRunner.java
:
public class YamlConfigRunner {
public Configuration getConfiguration(String filePath) throws IOException {
Constructor constructor = new Constructor(Configuration.class);
Yaml yaml = new Yaml(constructor);
try (InputStream in = Files.newInputStream(Paths.get(filePath))) {
Configuration config = yaml.loadAs(in, Configuration.class);
System.out.println(config.toString());
return config;
}
}
}
However I obtain the exception:
null; Can't construct a java object for tag:yaml.org,2002:org.uniroma2.sdcc.Utils.Configuration; exception=Cannot create property=statisticsTopologyParams for JavaBean=YamlConfig{statistics=null}; No single argument constructor found for class org.uniroma2.sdcc.Utils.ServiceConfig; in 'reader', line 1, column 1:
statisticsTopologyParams:
Caused by: org.yaml.snakeyaml.error.YAMLException: No single argument constructor found for class org.uniroma2.sdcc.Utils.ServiceConfig
Upvotes: 3
Views: 8127
Reputation: 39688
The problem is that you are telling SnakeYaml to convert a number (60
) into a ServiceConfig
object. Since ServiceConfig
does not have a constructor which takes exactly one argument, SnakeYaml does not know how to do that.
To go into more detail, this is the failing line:
tickTupleFrequency: 60
tickTupleFrequency
here is the key of a Map<String, ServiceConfig>
. It is no problem to load it as String, so SnakeYaml does that. Now, there is a value 60
. This must be converted into a ServiceConfig
object to fit into the Map. How is SnakeYaml supposed to do that? It doesn't know, and therefore, yield the error.
You seem to have simply forgotten to add the Map level to your YAML, since both tickTupleFrequency
and the following keys are all fields of a ServiceConfig
object. So maybe this is what you actually want to have:
statisticsTopologyParams:
My fancy ServiceConfig:
tickTupleFrequency: 60
hourlyStatistics:
windowLength: 3600
emitFrequency: 60
dailyStatistics:
windowLength: 86400
emitFrequency: 3600
Now, My fancy ServiceConfig
will be the key in the Map<String, ServiceConfig>
and the containing map will be loaded as ServiceConfig
object.
Upvotes: 3