Running a Spring Boot application with multiple main classes - maven

I am using Spring Boot with a multi module maven project, the structure looks like this
project
- project-rest-controller
- project-file-adapter
- project-library
Where project-rest-controller module contains the #RestController and has a main Spring Boot class to start the embedded tomcat, the controller will receive a POST and create a request and pass it to the project-library module.
Also, project-file-adapter module contains a Spring-Integration file adapter to pull for a file in a directory, read the file and create a request and pass it to the project-library module.
When I run the application using mvn spring-boot:run from within the parent directory, I get an exception with main class should be specified.
It seems that Spring boot allows to specify the main class in the following way
mvn spring-boot:run -Dstart-class=com.blah.App
but I have two main classes.
Should I start two apps?
one from project-rest-controller
one from project-file-adapter
This will start two JVMs and that's now what I am trying to do?

Related

Spring Boot properties file between develop phase and 'production' phase

I have developed a simple Spring Boot application (not a web but a standalone one).
Inside my app I use a custom 'user.properties' file which properties like:
smtp.host=<development.somesmtp.host>
The ejecutable jar file that contains the packaged application includes that 'user.properties' file.
BUT, if the user of my application whants to change that property, he cant's because the properties file is inside the jar.
smtp.host=<production.somesmtp.host>
What is the correct way to approach this issue?
For me the solution was:
Use this annotations:
#Component
#PropertySource({"file:C:/PRONOM/user.properties", "classpath:user.properties"})
public class UserProperties {
Launch the app with the next command:
java -jar C:/PRONOM/pronom-0.0.1.jar --spring.config.location=file:C:/PRONOM/user.properties

How can I tell Spring Boot to place some of the classes at the root of the jar instead of BOOT-INF?

I'm trying to set a custom log Handler in my Spring Boot (version 2.6.3) application. The result is a ClassNotFound as described in this other question
Can't override java.util.logging.LogManager in a Spring Boot web application: Getting java.lang.ClassNotFoundException on already loaded class
Based on the answer to that question, it seems I need my Handler and all its dependencies to be placed into the root of the executable jar.
Is there a direct way to accomplish this during the Maven build, i.e. not by extracting and repackaging the jar myself post-build?
This issue is a result of BOOT-INF fat jar structure introduced by Spring Boot 1.4.
There is currently no straightforward solution, and it appears some of the Spring Boot maintainers do not agree there is a problem, so it could be a long time before the situation changes:
Issue #6626: Make it easier to package certain content in the root of a fat jar
Issue #12659: Starting executable war with -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager produces a ClassNotFoundException
WORKAROUND #1
I had to do two things to get my application working again with a custom log handler. 1) use Maven Shade to package up the log handler with all its dependencies, and 2) launch the app with using the PropertiesLauncher class in the command line instead of using java -jar:
java -cp executable.jar:logger-shaded.jar -Dloader.main=mypackage.myapp org.springframework.boot.loader.PropertiesLauncher
The executable.jar, logger-shaded.jar, and mypackage.myapp are placeholders specific to my project, so adjust accordingly.
WORKAROUND #2
If the handler is loaded from code in a config class or from main() instead of being specified in the file loaded via java.util.logging.config.file, as discussed in the comments to the answer in this other question, then everything works as expected. I actually prefer this over Workaround #1 as it results in a smaller deployment, but it does require writing a few more lines of code.

Use External properties file

Am looking to pass variables at run time once war file is deployed on tomcat ..
How can i use application.properties whcih is in classplath along with another properties file ex. abcd.properties located at particular directory..Am basically looking to set additional classpath and read value from properties file in that path along with default classpath location for war deployment.
Am using Spring boot .One of the way is to pass all properties to database end , but am looking for a file based i.e properties based workout.
(Having multiple applications on same tomcat instance.)
Spring Boot App --> run as --> run configurations. Now here in VM arguments add Dproperties.location="Path of the properties".
Now, in your Spring Boot application use the annotation #PropertySource("file:${properties.location}/propertiesfileName.properties") just above the class declaration.
Autowire Environment in your class. use env.getProperty("propertyname").
You can access the values from application.properties as usual using #Value annotation. Hope this helps.

Facing issue while integrating CustomSpringUtilityJar in SpringBootApplication

I am having two spring applications and the details as follows:
1). Application One: This is a utility jar and its purpose is for CRUD operations on a specific table. We are using spring data jpa and hibernate for achieving the same. Since it is an utility this will not run alone
and it will be incuded as dependency to other applications. In this case we are using Application2 for that.
2) Application Two: This is a web service application made of Spring boot using yml configuration and also using Application One for CRUD operations on that table.
Issue: While running application Two(i.e. Spring Boot Application) , I am getting the error message related to the the components, repositories and entities of Application one,
as the bean is not registered in the configuration. Following are the approaches I used to solve thes:
Approach 1: In application 2, along with #SpringBootApplication annotation:
added Component Scan, Enity Scan and Enable JPA repositories and in these three annotations we have to include the package of both Application1 and Application2.
This scenario is working fine.
Note: I am not using Approach 1 as I have to make these three changes in every service applications which is going to use this utility jar. So decided to proceed with Approach2
Approach 2: Created an custom annotation like #UtilJar annotation and configuration class in Application1 and in that configuration class, added the three
annotations along with the configuration annotation.
In this case, while adding the custom annotation(created from Application1) in Application2, all the components and repositories registered in Application1 is registered and error is
showing related to the repositories registered in Application 2 . The only way I can solve on this is to give EnableJPARepository in Application2 which again similar to
Approach1.
So the root cause what I understood is because of #EnableJPARepository annotation given in the Application1 prompted for this error in Application2. Can anyone suggest me how to proceed on this.

How to ignore a java file when maven install

I have a #Service class where i'm caching some table data. I don't want those queries to run while building mvn install. Is there a way to ignore the file while building and it only execute when i start the server ?
It's a spring-boot application.
Here is background of my issue. I have initialized the spring boot app from http://start.spring.io/ site, which actually adds dummy application test file with SpringBootTest annotation and default contextLoads() with Test annotation, with an intention to initialize and execute all test cases, which needs to initialize and execute all code base. In my opinion this is not required, as we can have respective Test classes per controller/manager, which will give more controlled environment to hook up your Test setups and executions.
I have removed the default application Test file and included respective test classes for code coverage and quality. This way my beans are not executed at server startup time rather build time.

Resources