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):
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:
# config/config.yml
enableWarp: trueIf enableWarp is false or missing, the WarpCommands class is not registered at all — no command, no memory usage, no side effects.
Only the connector entry point still skips the condition
The standard @UltiToolsModule path resolves command classes as container beans, so a class whose condition is false was never constructed as a bean, and this already worked before v6.3.0. As of v6.3.0 the listener package-scan path evaluates the condition too, closing the one gap that was real. Only the connector entry point (PluginManager.register(UltiToolsPlugin)) performs no component scan at all, so nothing there evaluates the condition yet -- tracked in issue #334.
Annotation Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
value | String | (required) | Config file path relative to the plugin data folder |
path | String | (required) | Dot-separated or slash-separated YAML key path |
negate | boolean | false | If true, register when config value is false (inverted logic) |
Examples
Conditional Service
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
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:
# config/config.yml
features:
teleport:
enabled: true
pvp:
enabled: falsepackage 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:
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:
# config/config.yml
features:
home: true
warp: true
economy: false
welcome: truepackage 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() { }
}@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.