-
Notifications
You must be signed in to change notification settings - Fork 1
Framework Builder
The framework builder is your applications entry point, and configuration area. Even with all the options present though, only 2 are required. The main, and pckg (package).
This is an instance of your main class, and optionally a class to reference it by. If a pure object is provided, a binding will be created with the @Main annotation, to the Object class.
@Inject @Main private Object main;
If a class is provided aswell, it'll look like this:
@Inject private YourClass main;
Additionally, an instance of MainBinding is also configured, which contains any metadata used by RPF todo with your main class/instance.
@Inject private MainBinding main;
If supplying your own class to bind to, it's convention to follow the Liskov Subtitution Principle, assuming your class is an extension of something. For example, if you're developing against another API, which uses your main class for other operations, you should declare the interface of that class in the main method, not the class itself. If this isn't the case for you, I'd recommend just providing the raw object, as you should never need to inject the instance yourself anyway.
Strange naming is due to the fact that package
is a keyword in java, and therefore cannot be used as a method/variable name
The pckg is simply your project's root package, which should be scanned. For example, a project with this structure:
`-- src
`-- main
`-- java
`-- me
`-- piggypiglet
`-- project
|-- Project.java
|-- commands
| |-- AddPersonCommand.java
| `-- RemovePersonCommand.java
|-- data
| `-- Person.java
|-- managers
| `-- PeopleManager
`-- routes
`-- PeopleRoute.java
Where Project.java is your main class, you'd provide me.piggypiglet.project
as the pckg.
`-- src
`-- main
`-- java
`-- me
`-- piggypiglet
`-- project
|-- bootstrap
| `-- Project.java
|-- commands
| |-- AddPersonCommand.java
| `-- RemovePersonCommand.java
|-- data
| `-- Person.java
|-- managers
| `-- PeopleManager
`-- routes
`-- PeopleRoute.java
In this tree, as you can see Project.java has moved into the bootstrap package, but you'd still provide me.piggypiglet.project
as the package.
The pckg method also allows for exclusions, if you wish for a class not to be loaded at startup. Keep in mind, classes annotated with @Disabled are still loaded, they're just skipped over in the scanner methods. Classes in exclusion packages won't be loaded at all.
e.g. for the above tree(s), excluding the commands package
Framework.builder()
.pckg("me.piggypiglet.project", "me.piggypiglet.project.commands")
In the event you're developing against another API which already provides your runtime with an injector, you're able to provide that injector, which RPF will then base the initial module around, instead of creating a brand new injector. You can get your API's injector, by simply injecting com.google.inject.Injector. Do not do this with RPF injectors however, instead inject the wrapper class.
@Inject private Injector injector;
private void start() {
Framework.builder()
.injector(injector)
}
This is where you supply your startup process, i.e. startup registerables. This method accepts a varags of RegisterableDatas, which are just wrapper objects containing your registerable class, and optionally it's boot priority. Due to the nature of how registerables work in RPF, the instances have to be grabbed JIT, especially if custom bindings are made in previous registerables.
This functions roughly the same as the startup process, except considerably more basic. For starters, no new bindings can be made, obviously, and there's no priority (except the order of which you input the classes).
The command prefix, is the string that commands will be checked to start with. If you don't provide a command prefix, the command system will not be enabled.
The file methods are where you can register your files & configs. These methods are chainable, meaning you can put multiple of them in the same FrameworkBuilder.
Config: Whether this file is a config or not Name: The name this file will be internally referenced by. It's unlikely you'll ever use this, but name it something user friendly just in case. Internal Path: This is the internal path of the file, i.e. it's embedded path in the jar. This can either be hard coded, or it can be dynamically fetched from another config, by supplying a ConfigPathReference instead of a String. External Path: The hard coded path the file will be placed at. The fileDir, will be appended before this value. This can be set to null, if the file shouldn't be exported outside the jar. Annotation: This, either a class or an annotation instance, is the annotation your file/config will be binded to.
Examples:
.file(true, "config", "/config.json", "config.json", Config.class)
// ----
@Inject @Config private FileConfiguration config;
.file(true, "config", "/config.json", "config.json", Config.class)
.file(true, "lang", new ConfigPathReference("config", "language", "en"), "lang.json", Lang.class)
// ----
@Inject @Lang private FileConfiguration lang;
.file(false, "sql", "/schema.sql", null, SQL.class)
// ----
@Inject @SQL private FileWrapper sql;
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD)
public @interface Lang {
String value();
}
// ----
@AutoAnnotation
public static Lang lang(String value) {
return new AutoAnnotation_LangUtils_lang(value);
}
// ----
.file(true, "en", "/lang_en.json", null, LangUtils.lang("en"))
.file(true, "fr", "/lang_fr.json", null, LangUtils.lang("fr"))
// ----
@Inject @Lang("en") private FileConfiguration en;
@Inject @Land("fr") private FileConfiguration fr;
Simply the number of threads that should be available in the default task manager's pool.
Sometimes addons use configs for values, for example the HTTP addon uses a config for it's port, ip, default authentication system, ssl, etc. You may not want the end user to interact with that specific file though, so you're able to map the locations of addons' configs, to another config. This method is also chainable.
The method accepts three parameters, the addon class, the config name, and the locations map. The addon class is usually Addon.class, e.g. HTTPAddon.class
. The config is your config, the string you set in the second parameter of the #file
method(s). The final parameter, the map, is literally a map of the original paths, to the new paths in your custom config. If you don't know the original paths, look in the addon class as they'll be listed, or in the addon's config(s) themselves.
This method allows you to configure a custom file directory which will be appended to external paths in your file methods. This is useful in the event your application is in a shared environment, and configurations/files should be placed in their own folder, not in the root of the parent application.
This boolean option simply dictates whether debug messages should be sent or not.
This method allows you to declare whether you'll be overriding the default hardcoded values with your own.
If the above is set to true, here's where you provide your own config with mappings. Mapping being og paths to your own paths.
This isn't related to overriding default values, and is instead where you can simply provide your custom language configuration that will be handled by the lang system in RPF. This method accepts your config identifier, and an array of LangEnum values. You should declare an enum implementing LangEnum, with the path of each message stored in the constructor of your enum values. For example:
{
"person": {
"add": "Successfully added %s to the database.",
"remove": "Successfully removed %s from the database."
}
}
public enum Lang implements LangEnum {
ADD_PERSON("person.add"),
REMOVE_PERSON("person.remove");
private final String path;
Lang(String path) {
this.path = path;
}
@Override
public String getPath() {
return path;
}
}
// ----
.customLang("lang", Lang.values())