Spring Boot Maven Plugin. LayoutFactory new feature. Available since 1.5.0.M1.
I am having problems when I define a custom launcher in the Custom Layout:
@Override public String getLauncherClassName() { return "com.mycompany.CustomLauncher"; }
If I include my custom launcher in the boot application sources, it gets repackaged to BOOT-INF/classes, and when I try to run the JAR it fails with a ClassNotFound exception.
I have been reading the Repackager code but I cannot find any hook that allows to selectively exclude a given class from the repackaging sequence. If I override the getRepackagedClassesLocation method in my layout then the boot main class is loaded by a different classloader and it fails on SpringBoot ClassNotFound.
Is there any way that I can force the launcher out of the BOOT-INF/classes repackaging?
UPDATE 1
@Override
public void writeLoadedClasses(LoaderClassesWriter writer) throws IOException
{
String name = PropertiesLauncherInternal.class.getName().replaceAll("\\.", "\\\\") + ".class";
InputStream inputStream = PropertiesLauncherInternal.class.getResourceAsStream(PropertiesLauncherInternal.class.getSimpleName() + ".class");
writer.writeEntry(name, inputStream);
writer.writeLoaderClasses();
}
In order to see that the code is accessible I have added this test:
JarInputStream is = new JarInputStream(new FileInputStream(new File("c:/git/dev/framework/boot/target/boot-current-SNAPSHOT.jar")), true);
JarEntry entry = null;
while (null != (entry = is.getNextJarEntry()))
{
System.out.println(entry.getName() + "-" + entry.getCrc());
}
URL url = new File("c:/git/dev/framework/boot/target/boot-current-SNAPSHOT.jar").toURL();
URL[] urls = new URL[] { url };
ClassLoader cl = new URLClassLoader(urls);
Class cls = cl.loadClass("com.test.Boot");
Class cls = cl.loadClass("com.launcher.PropertiesLauncherInternal");
For the first loop I get the following log:
BOOT-INF/--1
BOOT-INF/classes/--1
BOOT-INF/classes/com/-0
BOOT-INF/classes/com/test/-0
BOOT-INF/classes/com/test/Boot.class-2405822989
...
com\launcher\PropertiesLauncherInternal.class--1
The number next to the class names are the CRC. I am not sure whether is relevant, but the CRC-32 is unknown.
When using the classloader, I am able to load com.test.Boot but it fails on ClassNotFoundException for the PropertiesLauncherInternal.class
Rather than having it alongside your application code, your launcher code should be in a separate module that's declared as a dependency of Spring Boot's Maven plugin. This separate module should use Maven's standard jar packaging and shouldn't be repackaged using Spring Boot's Maven plugin.
There's a sample that shows how to set things up.