0

It worth to mention that I am using maven as my build management tool. I have a jar (let's call it dep.jar) which will be included into the final project (final.jar) as dependency. dep.jar has a class with main method. I need to have several entry points (classes with main methods) within my final.jar's top level directory so I can use entry point depending on my need. Including one from dep.jar.

I considered:

  1. Changing META-INF/MANIFEST.MF file within jar. As Oracle stated that is not possible to reference main classes inside jar's dependencies (BOOT-INF/lib directory) -> https://docs.oracle.com/javase/tutorial/deployment/jar/downman.html;
  2. Uber jar - not an option, I am dependent on jar directory structure inside Java code base
  3. Using special class loader like this one http://www.jdotsoft.com/JarClassLoader.php. But it implies changing final.jar's main method which I cannot do due to project restrictions.
  4. Using maven-dependency-plugin but it can unpack inner jar (dep.jar) and copy classes to maven working directory target which during packaging phase will be packed to BOOT-INF/classes directory. Again, I cannot reference main classes from there. If I unpack and copy them somewhere different than target - copied classes will not appear in my final.jar

Is there any other plugin or option how to add classes from final.jar dependant jar dep.jar during JAR build to final.jar's top level?

EDIT: final.jar project looks like this:

final.jar
    |_______BOOT-INF
              |_______lib
              |         |_______dep.jar (contains main class I want to invoke)
              |_______classes
                         |__________dir (directory I want to copy on demand with help of CLI)

NikitoZZZ
  • 33
  • 7
  • Are you talking about a spring boot application? – khmarbaise Apr 03 '20 at 16:42
  • Yes and no. I have two entry points - one launches spring app, another one (```dep.jar```'s one) is not. So I cannot use spring plugins for that If that's what you're asking. – NikitoZZZ Apr 03 '20 at 16:44
  • The important thing here is that your first citizen app is a spring boot app which means the dependencies are located in `BOOT-INF/lib` which means you can't access them in any usual way. What you could do is to make a separate entry point in spring boot (an extra extrypoint) https://dzone.com/articles/configuring-a-main-class-in-spring-boot But a combination of a second entry point where you might start with class loading fuzz...the question is: Why do you need that? – khmarbaise Apr 03 '20 at 17:30
  • I need to create a CLI which is working with files that were created during spring app building. I need to use ```final.jar``` for that so I can access those files. But I don't want to initialise spring context since it's to heavy. So I want to have second entry point without spring. I can access dependencies in ```BOOT-INF/lib``` by the way using ```maven-dependency-plugin```. But I didn't figure out how to place them at ```final.jar```'s top level. – NikitoZZZ Apr 03 '20 at 17:51
  • Now I'm confuses completely. You are generating files during the build but need to consume them via runtime but not for the spring boot app. Why not packaging them as resources and consuming them. And a second entry point without spring I've given you in the link. Can you explain the purpose of those files etc. sounds from my point of view very strange ?... – khmarbaise Apr 03 '20 at 17:53
  • I have a restriction that is initialising of spring context is a heavy operation. And for simple CLI `copy` operations it's not acceptable. CLI I am working on will be executed for each client application after application build was completed. Each client might have tens of our applications in different variations. And CLI will be launched for every one of them. So it's crucial to run CLI without spring. Purpose of these files - definition of services we're providing to clients. – NikitoZZZ Apr 03 '20 at 18:09
  • If you need to execute after the build I would vote a maven plugin to integrate that into your build which could handle that..But where do you need to copy file? Cause after the spring boot app is packaged it's a final jar ..and shouldn't be changed afterwards... – khmarbaise Apr 03 '20 at 18:24
  • I cannot use maven plugin since parameters that are passed to CLI might differ from invocation to invocation. And I am not going to change spring ```final.jar``` afterwards, I just need to copy some files from it's resources to desired destination, that's all. – NikitoZZZ Apr 03 '20 at 18:29
  • You could have several executions of a plugin that's not the issue. Copying some file from it's resources to which location? I'm confused about talking about the `final.jar` copying/but talking about build time? Copying resources can be done with Maven parts...? Could you make a simple example project to show what you mean.... – khmarbaise Apr 03 '20 at 18:47
  • Sorry, I am late, but let me ask you just this: Why not add the main method of `dep.jar` to `final.jar`? Dependencies usually don't have main methods, only executable jars have them. So why not just move the main method to `final.jar`? – J Fabian Meier Apr 03 '20 at 19:09
  • @JFMeier I would gladly do that in automated way but I don't how. That's actually what I meant by the original question. ```final.jar``` is created for each client automatically by ```spring-boot-maven-plugin```. I didn't find how I can configure that plugin to has two entry points (classes with main methods) at the same time if it's even possible. I can't add method from ```dep.jar``` to ```final.jar``` by hands if that what's you're asking. @khmarbaise I edited original question. – NikitoZZZ Apr 03 '20 at 19:18
  • Ok, then why not build separate jars for the different "entry points" that you need, each having one main method? – J Fabian Meier Apr 03 '20 at 19:21
  • It's not advised since our app is handed to clients in form of one executable jar. It would be tedious to provide and teach each one of them to work with brand new jar. Plus I need access to resources that are inside ```final.jar``` but I can copy them somewhere else during build process I guess... But I'll keep your advice in mind if I won't find another solution. Thank you. – NikitoZZZ Apr 03 '20 at 20:12

1 Answers1

0

I found a solution here Spring Boot - How to specify an alternate start-class? (Multiple Entry Points). Ended up using -Dloader.main property when launching jar. Command line looks like these: java -jar -Dloader.main=<main_class> ./final.jar

NikitoZZZ
  • 33
  • 7