Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SnakeYaml "Unable to find property error"

Here is part of my config.yml:

#Authenctication
AuthenticationConfig:
  AuthencticationType: LDAP
  LDAPConfig:
     LDAPUrl: ldap://localhost:389
     ConnectionType: simple
     LDAPSecurityConfig:
        RootDN: cn=manager,dc=maxcrc,dc=com
        RootPassword: secret
        UserSearchDN: ou=People,dc=maxcrc,dc=com
        GroupdSearchDB: ou=Groups,dc=maxcrc,dc=com

I have a class used for parsing:

public class YamlConfiguraiton {
    private AuthenticationConfiguration AuthenticationConfig;

    public void setAuthenticationConfig(AuthenticationConfiguration AuthenticationConfig) {
        this.AuthenticationConfig = AuthenticationConfig;
    }

    public AuthenticationConfiguration getAuthenticationConfig() {
        return this.AuthenticationConfig;
    }
}

However, when I run

try(InputStream in = new FileInputStream(new File(ymalPath))) {
            yamlConfig = yaml.loadAs(in, YamlConfiguraiton.class);
        } catch (IOException e) {
            e.printStackTrace();
        }

the following error happens:

Exception in thread "main" Cannot create property=AuthenticationConfig for JavaBean=com.ibm.entity.matching.common.bootstrap.YamlConfiguraiton@e7860081
 in 'reader', line 2, column 1:
    AuthenticationConfig:
    ^
Unable to find property 'AuthenticationConfig' on class: com.ibm.entity.matching.common.bootstrap.YamlConfiguraiton
 in 'reader', line 3, column 4:
       AuthencticationType: LDAP
       ^

    at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2ndStep(Constructor.java:270)
    at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.construct(Constructor.java:149)
    at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:309)
    at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:204)
    at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:193)
    at org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:159)
    at org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.java:146)
    at org.yaml.snakeyaml.Yaml.loadFromReader(Yaml.java:524)
    at org.yaml.snakeyaml.Yaml.loadAs(Yaml.java:518)
    at com.ibm.entity.matching.bootstrap.EntityMatching.boot(EntityMatching.java:55)
    at com.ibm.entity.matching.bootstrap.EntityMatching.main(EntityMatching.java:35)
Caused by: org.yaml.snakeyaml.error.YAMLException: Unable to find property 'AuthenticationConfig' on class: com.ibm.entity.matching.common.bootstrap.YamlConfiguraiton
    at org.yaml.snakeyaml.introspector.PropertyUtils.getProperty(PropertyUtils.java:159)
    at org.yaml.snakeyaml.introspector.PropertyUtils.getProperty(PropertyUtils.java:148)
    at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.getProperty(Constructor.java:287)
    at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2ndStep(Constructor.java:208)
    ... 10 more

Why it complains about cannot finding property AuthenticationConfig while AuthenticationConfig is just the name of the instance variable?

UPDATE After I changed the instance variables from "private" to "public", they were recognized by SnakeYaml, but this is not what we expect for sure. The classes are not recognized as JavaBean.

UPDATE I found the root cause. It is the naming convention. If you want SnakeYaml to parse your yaml file, camelCase has to be complied with. The name of setter and getter method is also important. Say there is a private instance variable called ldapConfig, then its getter and setter's name has to be getLdapConfig and setLdapConfig, even getLDAPConfig and setLDAPConfig won't work.

like image 284
zero_yu Avatar asked Oct 03 '18 03:10

zero_yu


1 Answers

The main reason for the error is that you need to define all the attributes present in Yaml file in POJO class (i.e. YamlConfiguraiton).

You can use the below code to skip the undefined properties.

Representer representer = new Representer();
            representer.getPropertyUtils().setSkipMissingProperties(true);
            Yaml yaml = new Yaml(new Constructor(YamlConfiguraiton.class), representer);

Firstly, rename the attribute names to camelCase in Yaml file.

Refer the below code:-

Code:-

public class YamlReadCustom {

    private static String yamlPath = "/authentication.yaml";

    public static void main(String[] args) {
        Representer representer = new Representer();
        representer.getPropertyUtils().setSkipMissingProperties(true);
        Yaml yaml = new Yaml(new Constructor(Authentication.class), representer);
        try(InputStream in = YamlReadCustom.class.getResourceAsStream (yamlPath)) {
            Authentication authentication = yaml.loadAs(in, Authentication.class);
            System.out.println(authentication.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Authentication:-

public class Authentication {
    private String authenticationConfig;
    private String authencticationType;
    private LdapConfig ldapConfig;

    //getters and setters
}

LdapConfig:-

public class LdapConfig {
    private String ldapUrl;
    private String connectionType;
    private Map<String, Object> ldapSecurityConfig;
    //getters and setters
}

authentication.yaml

authenticationConfig:
authencticationType: LDAP
ldapConfig:
  ldapUrl: ldap://localhost:389
  connectionType: simple
  ldapSecurityConfig:
    rootDn: cn=manager,dc=maxcrc,dc=com
    rootPassword: secret
    userSearchDn: ou=People,dc=maxcrc,dc=com
    groupdSearchDb: ou=Groups,dc=maxcrc,dc=com
like image 65
notionquest Avatar answered Sep 18 '22 11:09

notionquest