Skip to content

Commit 888d8cf

Browse files
committed
feat: readme update and encpasulation of class loading by bootstrap
1 parent 22433ff commit 888d8cf

3 files changed

Lines changed: 30 additions & 59 deletions

File tree

README.md

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,29 +36,25 @@ dependencies {
3636

3737
// Mark dependencies as dynamic
3838
// They will be available at compile time but NOT included in the JAR
39-
dynamic("net.dv8tion:JDA:6.1.2")
40-
dynamic("com.google.guava:guava:32.1.3-jre")
39+
bootstrap("net.dv8tion:JDA:6.1.2")
40+
bootstrap("com.google.guava:guava:32.1.3-jre")
4141
}
4242
```
4343

4444
### 2. Use the simple bootstrap API
4545

4646
**Main.java:**
4747
```java
48-
import fr.traqueur.bootstrap.BootstrapLoader;
4948

5049
public class Main {
5150
public static void main(String[] args) {
52-
DynamicLoader.bootstrap(args, MyApp.class);
51+
BootstrapLoader.bootstrap(args, MyApp.class);
5352
}
5453
}
5554
```
5655

5756
**MyApp.java:**
5857
```java
59-
import fr.traqueur.bootstrap.BootstrapApplication;
60-
import net.dv8tion.jda.api.JDA;
61-
import net.dv8tion.jda.api.JDABuilder;
6258

6359
public class MyApp implements DynamicApplication {
6460
private JDA jda; // You can use dynamic dependency types directly!
@@ -84,14 +80,14 @@ On first run, dependencies will be downloaded to `.dynamic-loader/cache/`.
8480

8581
### Build Time
8682

87-
1. The Gradle plugin creates a `dynamic` configuration extending `compileOnly`
83+
1. The Gradle plugin creates a `boostrap` configuration extending `compileOnly`
8884
2. Dynamic dependencies are available during compilation
89-
3. A manifest file `META-INF/dynamic-dependencies.json` is generated
85+
3. A manifest file `META-INF/bootstrap-dependencies.json` is generated
9086
4. Dynamic dependencies are **excluded** from the JAR
9187

9288
### Runtime
9389

94-
1. `DynamicLoader.bootstrap()` loads the manifest
90+
1. `BootstrapLoader.bootstrap()` loads the manifest
9591
2. Maven Resolver downloads dependencies and their transitive dependencies
9692
3. An **IsolatedClassLoader** (child-first) is created with the dependencies
9793
4. Your application class is loaded and instantiated via the isolated ClassLoader
@@ -113,7 +109,7 @@ This is crucial for allowing your application classes to reference types from dy
113109
For more control over initialization:
114110

115111
```java
116-
DynamicLoader.bootstrap(args, ctx -> {
112+
BootstrapLoader.bootstrap(args, ctx -> {
117113
MyApp app = ctx.create(MyApp.class);
118114

119115
// Access the ClassLoader
@@ -132,10 +128,10 @@ Via system property or environment variable:
132128

133129
```bash
134130
# System property
135-
java -Ddynamicloader.cache.dir=/custom/cache -jar app.jar
131+
java -Dbootstraploader.cache.dir=/custom/cache -jar app.jar
136132

137133
# Environment variable
138-
export DYNAMIC_LOADER_CACHE_DIR=/custom/cache
134+
export BOOTSTRAP_LOADER_CACHE_DIR=/custom/cache
139135
java -jar app.jar
140136
```
141137

@@ -159,9 +155,9 @@ These repositories are included in the generated manifest.
159155
```
160156
Bootstrap/
161157
├── bootstrap-core/ # Runtime library (Java 21)
162-
│ ├── DynamicLoader.java # Main entry point
163-
│ ├── DynamicApplication.java # Simple interface
164-
│ ├── DynamicEntrypoint.java # Callback interface
158+
│ ├── BootstrapLoader.java # Main entry point
159+
│ ├── BootstrapApplication.java # Simple interface
160+
│ ├── BootstrapEntrypoint.java # Callback interface
165161
│ ├── config/
166162
│ │ └── DependencyManifest.java # JSON parser
167163
│ ├── loader/
@@ -172,16 +168,16 @@ Bootstrap/
172168
│ └── SimpleTransferListener.java
173169
174170
├── bootstrap-gradle/ # Gradle plugin (Kotlin)
175-
│ ├── DynamicLoaderPlugin.kt
176-
│ ├── DynamicLoaderExtension.kt
171+
│ ├── BootstrapLoaderPlugin.kt
172+
│ ├── BootstrapLoaderExtension.kt
177173
│ └── GenerateDynamicManifestTask.kt
178174
179175
└── example/ # Discord bot example
180176
```
181177

182178
## Manifest Format
183179

184-
**META-INF/dynamic-dependencies.json:**
180+
**META-INF/bootstrap-dependencies.json:**
185181
```json
186182
{
187183
"dependencies": [
Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,15 @@
11
package fr.traqueur.bootstrap.loader;
22

3+
import fr.traqueur.bootstrap.BootstrapApplication;
34
import fr.traqueur.bootstrap.BootstrapEntrypoint;
45

56
/**
67
* Context object provided to {@link BootstrapEntrypoint} callbacks.
78
* This context provides access to the isolated ClassLoader and utility methods.
9+
* @param classLoader the isolated ClassLoader containing dynamic dependencies
10+
* @param args the command line arguments
811
*/
9-
public class LoaderContext {
10-
11-
private final IsolatedClassLoader classLoader;
12-
private final String[] args;
13-
14-
/**
15-
* Creates a new loader context.
16-
*
17-
* @param classLoader the isolated ClassLoader containing dynamic dependencies
18-
* @param args the command line arguments
19-
*/
20-
public LoaderContext(IsolatedClassLoader classLoader, String[] args) {
21-
this.classLoader = classLoader;
22-
this.args = args;
23-
}
24-
25-
/**
26-
* Gets the isolated ClassLoader.
27-
*
28-
* @return the ClassLoader with dynamic dependencies
29-
*/
30-
public IsolatedClassLoader getClassLoader() {
31-
return classLoader;
32-
}
33-
34-
/**
35-
* Gets the command line arguments.
36-
*
37-
* @return the arguments passed to the application
38-
*/
39-
public String[] args() {
40-
return args;
41-
}
12+
public record LoaderContext(IsolatedClassLoader classLoader, String[] args) {
4213

4314
/**
4415
* Creates an instance of the specified class using the isolated ClassLoader.
@@ -49,17 +20,17 @@ public String[] args() {
4920
* reflection with the no-args constructor.</p>
5021
*
5122
* @param clazz the class to instantiate
52-
* @param <T> the type of the class
23+
* @param <T> the type of the class
5324
* @return a new instance of the class
5425
* @throws RuntimeException if instantiation fails
5526
*/
56-
public <T> T create(Class<T> clazz) {
27+
public <T extends BootstrapApplication> T create(Class<T> clazz) {
5728
try {
5829
// Load class through isolated ClassLoader
59-
Class<?> loadedClass = classLoader.loadClass(clazz.getName());
30+
Class<BootstrapApplication> loadedClass = this.loadClass(clazz.getName());
6031

6132
// Create instance using reflection
62-
Object instance = loadedClass.getDeclaredConstructor().newInstance();
33+
BootstrapApplication instance = loadedClass.getDeclaredConstructor().newInstance();
6334

6435
// Cast to expected type
6536
return clazz.cast(instance);
@@ -75,7 +46,11 @@ public <T> T create(Class<T> clazz) {
7546
* @return the loaded class
7647
* @throws ClassNotFoundException if the class cannot be found
7748
*/
78-
public Class<?> loadClass(String className) throws ClassNotFoundException {
79-
return classLoader.loadClass(className);
49+
@SuppressWarnings("unchecked")
50+
public Class<BootstrapApplication> loadClass(String className) throws ClassNotFoundException {
51+
Class<?> clazz = classLoader.loadClass(className);
52+
if (BootstrapApplication.class.isAssignableFrom(clazz))
53+
return (Class<BootstrapApplication>) clazz;
54+
throw new ClassNotFoundException(className);
8055
}
8156
}

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ org.gradle.jvmargs=-Xmx2g
22
kotlin.code.style=official
33

44
group=fr.traqueur.bootstrap
5-
version=1.0.2
5+
version=1.0.3

0 commit comments

Comments
 (0)