(Spring Boot) Stuffing fat jars & run-time route startup

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

(Spring Boot) Stuffing fat jars & run-time route startup

Ron Cecchini
Hi, gang. I hope you’re all doing well.  Two questions if I could.

TL;DR: (so you can decide now if you want to hit <delete> since this is long...)

 1. How to add a resource file from a Maven parent to a child’s fat (Spring Boot) JAR?
 2. How to parse command line args and have the main() call SpringApplication.run() so that it starts one route or another based on the args?

.....

1. The first question is actually more Maven + Spring Boot related than Camel, per se, but I know someone here knows the answer.

My Maven project contains a bunch of sub-modules, each of which is a standalone Spring Boot + Camel app.

Each module’s POM is fairly bare bones since it inherits almost everything from the parent POM, including a generic spring-boot-maven-plugin:repackage for packaging everything into a fat JAR.

Each sub-module has its own application.properties *and* pulls in a project.properties from the parent.

So, each module's camel-context.xml has a <propertyPlaceholder> that looks something like:

  [...]
  <propertiesLocation resolver="file"      path="resources/project.properties" optional="false">
  <propertiesLocation resolver="classpath" path="application.properties"       optional="false">
  [...]

This works perfectly in IntelliJ.  The module really is seeing everything in that parent project.properties file.

But doing a 'java -jar submodule.jar' at the command line throws a FileNotFoundException because it now *can't* find 'resources/project.properties'.

Since I need these JARs to be truly "fat" (standalone) I don't even want to bother figuring out how to make the call from a different directory, or with a -cp <classpath>, etc.

So -

Do I need to move the <build><plugins><plugin> down into each sub-module's POM?

And if so, how do I tell it to include the parent's 'resources/project.properties'?

.....

2. This one is a little tricky, I think...

A very simplified version of my pipeline looks something like:

1. 'initialize' route
2. 'polling' route
3. 'processing' route

The 'polling' route does *not* start automatically.  The 'initialize' route does a bunch of stuff, and then it uses "controlbus" to start the 'polling' route - and off we go, polling & processing.

But now I want to do something weird based on how we call this submodule.jar:

1. if no args are passed to the jar, then start 'initialize' and let it run as usual.
2. if some args are passed, create an Exchange body, and call the 'processing' route.  I.e. don't start any polling; it's just a "one and done".

So basically the question boils down to:

In MyApp's main(), after doing SpringApplication.run(MyApp.class, args) to start everything up, how do I:

Get the CamelContext and then either *start* the 'initialize' route or call the 'processing' route.

Actually, if I can get the CamelContext, I know how to get a ProducerTemplate to call the 'processing' route.

But I really don't know how to *start* a route.

.....

Ok, that's it.

Thank you if you've read this far!

Stay safe!
Reply | Threaded
Open this post in threaded view
|

Re: (Spring Boot) Stuffing fat jars & run-time route startup

Claussnitzer, Ralf
Hi Ron,

you could start the route right away together with the context
(autostart). Or you simply obtain the context and call
startRoute("processing").

But why all this deferred starting? Why not just start the route and
send Exchanges whenever you want to process? If you need to control a
routes lifecycle in detail (suspending, resuming) have a look at what
route policies can do.

Regards,
Ralf

On 4/29/20 12:28 AM, Ron Cecchini wrote:
> But I really don't know how to*start*  a route.
Reply | Threaded
Open this post in threaded view
|

Re: (Spring Boot) Stuffing fat jars & run-time route startup

Ron Cecchini
In reply to this post by Ron Cecchini
Never mind.  I got it.  Sorry about that...

The first required adding a couple of <build><resources><resource><includes> in the parent POM and tweaking each submodule's camel-context.xml.

The second required discovering (after a dozen Spring Boot + Camel apps) that SpringApplication.run() actually returns a ConfigurableApplicationContext from which I could get the CamelContext.  (who knew!  heh  I know, you all did... whereas I've been assuming for over a year that it returned a void.)

And then depending on whether or not any command line args were passed in:

1. 0 args: call context.getRouteController().startRoute("initialize") and start up polling & processing
   [ ServiceHelper.startService(context.getRoute("initialize").getConsumer()) also works ]

2. >0 args: call context.createProducerTemplate().sendBody("direct:processing", body) with the passed in args,
   and then gracefully shutdown and exit.

If you're wondering why I'm bothering with all this it's because the need suddenly came up to use my pipeline as a command line tool.  The processing it does is pretty involved... and I didn't want to strip it down for parts and create a new standalone tool from scratch.  I was like, "If I can just get the user's params to *that* part of the pipeline, it will all work out nicely..."  And now it does.  Yay.  Thank you, Spring & Camel.

> On April 28, 2020 at 6:28 PM Ron Cecchini <[hidden email]> wrote:
>
>
> Hi, gang. I hope you’re all doing well.  Two questions if I could.
>
> TL;DR: (so you can decide now if you want to hit <delete> since this is long...)
>
>  1. How to add a resource file from a Maven parent to a child’s fat (Spring Boot) JAR?
>  2. How to parse command line args and have the main() call SpringApplication.run() so that it starts one route or another based on the args?
>
> .....
>
> 1. The first question is actually more Maven + Spring Boot related than Camel, per se, but I know someone here knows the answer.
>
> My Maven project contains a bunch of sub-modules, each of which is a standalone Spring Boot + Camel app.
>
> Each module’s POM is fairly bare bones since it inherits almost everything from the parent POM, including a generic spring-boot-maven-plugin:repackage for packaging everything into a fat JAR.
>
> Each sub-module has its own application.properties *and* pulls in a project.properties from the parent.
>
> So, each module's camel-context.xml has a <propertyPlaceholder> that looks something like:
>
>   [...]
>   <propertiesLocation resolver="file"      path="resources/project.properties" optional="false">
>   <propertiesLocation resolver="classpath" path="application.properties"       optional="false">
>   [...]
>
> This works perfectly in IntelliJ.  The module really is seeing everything in that parent project.properties file.
>
> But doing a 'java -jar submodule.jar' at the command line throws a FileNotFoundException because it now *can't* find 'resources/project.properties'.
>
> Since I need these JARs to be truly "fat" (standalone) I don't even want to bother figuring out how to make the call from a different directory, or with a -cp <classpath>, etc.
>
> So -
>
> Do I need to move the <build><plugins><plugin> down into each sub-module's POM?
>
> And if so, how do I tell it to include the parent's 'resources/project.properties'?
>
> .....
>
> 2. This one is a little tricky, I think...
>
> A very simplified version of my pipeline looks something like:
>
> 1. 'initialize' route
> 2. 'polling' route
> 3. 'processing' route
>
> The 'polling' route does *not* start automatically.  The 'initialize' route does a bunch of stuff, and then it uses "controlbus" to start the 'polling' route - and off we go, polling & processing.
>
> But now I want to do something weird based on how we call this submodule.jar:
>
> 1. if no args are passed to the jar, then start 'initialize' and let it run as usual.
> 2. if some args are passed, create an Exchange body, and call the 'processing' route.  I.e. don't start any polling; it's just a "one and done".
>
> So basically the question boils down to:
>
> In MyApp's main(), after doing SpringApplication.run(MyApp.class, args) to start everything up, how do I:
>
> Get the CamelContext and then either *start* the 'initialize' route or call the 'processing' route.
>
> Actually, if I can get the CamelContext, I know how to get a ProducerTemplate to call the 'processing' route.
>
> But I really don't know how to *start* a route.
>
> .....
>
> Ok, that's it.
>
> Thank you if you've read this far!
>
> Stay safe!