Skip to content

Conditional Registration ​

Since v6.2.0

The @ConditionalOnConfig annotation is available starting from UltiTools-API v6.2.0.

UltiTools allows you to conditionally register components based on YAML configuration values. This lets server admins enable or disable features without requiring code changes.

Basic Usage ​

Add @ConditionalOnConfig to any component class (@Service, @CmdExecutor, @EventListener):

java
package com.ultikits.docs.conditional;

import com.ultikits.ultitools.abstracts.command.BaseCommandExecutor;
import com.ultikits.ultitools.annotations.ConditionalOnConfig;
import com.ultikits.ultitools.annotations.command.CmdExecutor;
import org.bukkit.command.CommandSender;

@CmdExecutor(alias = {"warp"}, permission = "myplugin.command.warp")
@ConditionalOnConfig(value = "config/config.yml", path = "enableWarp")
public class WarpCommands extends BaseCommandExecutor {
    // Only registered if enableWarp: true in config.yml

    @Override
    protected void handleHelp(CommandSender sender) {
        sender.sendMessage("/warp");
    }
}

The corresponding YAML:

yaml
# config/config.yml
enableWarp: true

If enableWarp is false or missing, the WarpCommands class is not registered at all — no command, no memory usage, no side effects.

The condition is skipped on the connector path

@ConditionalOnConfig is read only in ComponentScanner.shouldRegister, which sits on the container scan path, while a plugin registered through PluginManager.register(...) reaches its command executors and listeners through a package scan that instantiates them reflectively, so the annotation is never consulted and the class is not skipped as this page describes. Ship the code as a standard UltiTools module with @UltiToolsModule, as every example on this page does; if you have to use a connector, read the config in registerSelf() and decide there whether to register. Making the connector path honour the condition is tracked in issue #334.

Annotation Attributes ​

AttributeTypeDefaultDescription
valueString(required)Config file path relative to the plugin data folder
pathString(required)Dot-separated or slash-separated YAML key path
negatebooleanfalseIf true, register when config value is false (inverted logic)

Examples ​

Conditional Service ​

java
package com.ultikits.docs.conditional;

import com.ultikits.ultitools.annotations.ConditionalOnConfig;
import com.ultikits.ultitools.annotations.Scheduled;
import com.ultikits.ultitools.annotations.Service;

@Service
@ConditionalOnConfig(value = "config/config.yml", path = "economy.enabled")
public class EconomyService {

    @Scheduled(period = 36000, async = true)
    public void distributeTax() {
        // Only runs if economy.enabled: true
    }
}

Conditional Event Listener ​

java
package com.ultikits.docs.conditional;

import com.ultikits.ultitools.annotations.ConditionalOnConfig;
import com.ultikits.ultitools.annotations.EventListener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;

@EventListener
@ConditionalOnConfig(value = "config/config.yml", path = "welcomeMessage.enabled")
public class WelcomeListener implements Listener {

    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        event.getPlayer().sendMessage("Welcome to the server!");
    }
}

Nested Config Keys ​

Use dots or slashes for nested keys:

yaml
# config/config.yml
features:
  teleport:
    enabled: true
  pvp:
    enabled: false
java
package com.ultikits.docs.conditional;

import com.ultikits.ultitools.abstracts.command.BaseCommandExecutor;
import com.ultikits.ultitools.annotations.ConditionalOnConfig;
import com.ultikits.ultitools.annotations.command.CmdExecutor;
import org.bukkit.command.CommandSender;

@CmdExecutor(alias = {"tp"}, permission = "myplugin.teleport")
@ConditionalOnConfig(value = "config/config.yml", path = "features.teleport.enabled")
public class TeleportCommands extends BaseCommandExecutor {

    @Override
    protected void handleHelp(CommandSender sender) {
        sender.sendMessage("/tp");
    }
}

Inverted Logic with negate ​

Use negate = true to register a component when the config value is false:

java
package com.ultikits.docs.conditional;

import com.ultikits.ultitools.annotations.ConditionalOnConfig;
import com.ultikits.ultitools.annotations.Service;

@Service
@ConditionalOnConfig(value = "config/config.yml", path = "maintenance", negate = true)
public class NormalModeService {
    // Only active when maintenance: false (or missing)
}

Complete Example ​

A plugin with optional features controlled by config:

yaml
# config/config.yml
features:
  home: true
  warp: true
  economy: false
  welcome: true
java
package com.ultikits.docs.conditional;

import com.ultikits.ultitools.abstracts.UltiToolsPlugin;
import com.ultikits.ultitools.annotations.UltiToolsModule;

@UltiToolsModule(scanBasePackages = {"com.ultikits.docs.conditional"})
public class MyPlugin extends UltiToolsPlugin {
    @Override
    public boolean registerSelf() { return true; }

    @Override
    public void unregisterSelf() { }
}
java
@CmdExecutor(alias = {"home"}, permission = "myplugin.home")
@ConditionalOnConfig(value = "config/config.yml", path = "features.home")
public class HomeCommands extends BaseCommandExecutor {
    // Registered (features.home = true)

    @Override
    protected void handleHelp(CommandSender sender) { }
}

@CmdExecutor(alias = {"warp"}, permission = "myplugin.warp")
@ConditionalOnConfig(value = "config/config.yml", path = "features.warp")
public class WarpCommands extends BaseCommandExecutor {
    // Registered (features.warp = true)

    @Override
    protected void handleHelp(CommandSender sender) { }
}

@Service
@ConditionalOnConfig(value = "config/config.yml", path = "features.economy")
public class EconomyService {
    // NOT registered (features.economy = false)
}

@EventListener
@ConditionalOnConfig(value = "config/config.yml", path = "features.welcome")
public class WelcomeListener implements Listener {
    // Registered (features.welcome = true)
}

Before v6.2.0

Without @ConditionalOnConfig, developers had to manually check config values in registerSelf() and conditionally register components with if statements. The annotation approach is cleaner and eliminates boilerplate.

Contributors

Released under the MIT License.