1.14.4 Loading ConfigurationSection from external configuration yml not found

Discussion in 'Spigot Plugin Development' started by Big_Bad_E, Jan 17, 2020.

  1. Sorry the title is a mouthful, but I am currently trying to load a yml from inside my plugin’s data folder. The yml loads/saves correctly, but for some reason one configurationsection loads incorrectly.
    Here’s my yml:
    enchants:
    testenchant:
    ...
    price:
    ...
    Now for some reason, the enchants and testenchant section load correctly, but I cannot load price. I checked my location of the section I’m getting it from and it is right, getKeys() shows the data in other sections but not the section.

    My code is on github.com/BigBadE/EnchantmentTokens, it’s set at https://github.com/BigBadE/Enchantm...bade/enchantmenttokens/EnchantmentTokens.java line 487 (loadConfigForField), line 510 is where I print the current path (which is correct), line 511 I get the ConfigurationSection using “location” (Which I have printed and is set to “price”), and newSection is null for some reason.
     
  2. gotta see the yml to help you with a yml issue
     
  3. Ok could you pls post your config yml inside a "code" segment here? I would like to see if your formatting is correct.

    Also some tips that might help with debugging and readability:
    Split your code into more classes.
    For IO stuff its not bad to have a FileManager or IOManager.
    Your packet stuff should also probably be in its own class.
    The whole repetetive try-> something something reflection -> catch seems DRY (meaning you repeat yourself too often)
    Create a reflection utils class. It can be static if you want. Just make a method that exposes Fields and fetches them.
    The onEnable method is just a entry point and should generally not be packed to the limit.

    Try to create a "chain of responsibility". Create Objects that get passed around between manager classes with specific tasks.
    Also many here swear on dependency injection over singleton designs but in your case either one would be an improvement.

    Dependency injection means:
    If you have for example your main class and need the instance of your class (of which only one should exist) in another
    one. You could either create a static getter for your main class (which would be [kind of] a singleton design) or you can just
    pass the instance in the constructor of the class that needs your main instance.
     
  4. I put my hierarchy but the formatting messed it up.

    I use dependency injection, and I know I have to refactor my main class, the project just got a lot bigger than I meant real quick.

    I’ll do a quick refactor and update the git, then repost it.

    I do appreciate the code review though. The project is an old one I’ve picked up again recently and I’ve been trying to detangle the mess.
     
  5. @7smile7 I refactored it some, I’d gladly take any more suggested changes.

    In my new code https://github.com/BigBadE/Enchantm...antmenttokens/utils/ConfigurationManager.java Line 52
    Code (Text):
        public static void loadConfigForField(Field field, ConfigurationSection section, Object target) {
            if (field.isAnnotationPresent(ConfigurationField.class)) {
                String location = field.getAnnotation(ConfigurationField.class).value();
                ConfigurationSection current = section;
                if (location.contains(".")) {
                    String[] next = location.split("\\.");
                    for (String nextLoc : next) {
                        try {
                            ConfigurationSection newSection = Objects.requireNonNull(current).getConfigurationSection(nextLoc);
                            if (newSection == null)
                                current = current.createSection(nextLoc);
                            else
                                current = newSection;
                        } catch (NullPointerException ignored) {
                            assert current != null;
                            current = current.createSection(nextLoc);
                        }
                    }
                }
                location = field.getName();
                if (field.getType().equals(ConfigurationSection.class)) {
                    ConfigurationSection newSection = current.getConfigurationSection(location);
                    if (newSection == null)
                        newSection = current.createSection(location);
                    ReflectionManager.setValue(field, newSection, target);
                } else {
                    Object value = Objects.requireNonNull(current).get(location);
                    if (value != null)
                        ReflectionManager.setValue(field, value, target);
                    else
                        current.set(location, ReflectionManager.getValue(field, target));
                }
            }
        }
    is where I load configuration sections, My structure is:

    enchants:
    enchants.testenchants:
    enchants.testenchants.price:
    enchants.testenchants.price.1: 10

    I load the configurationsection using getConfigurationSection at line 73.
    I printed the path and the value of location.
    Path: enchants.testenchants
    location: price
    Yet newSection is still null.
    The weird thing is if I use getKeys and print them (setting deep to true), I don’t find any values from in price, but I find other values in testenchants.
     
    #5 Big_Bad_E, Jan 17, 2020
    Last edited: Jan 17, 2020