Spring-Boot app is not honoring -Dloader.path - java

My Spring boot app (v2.1.1.RELEASE) is packaged using below plugin and layout :
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<finalName>my-service-${project.version}</finalName>
<mainClass>com.my.app.MainClass</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
I am using below launch script :
java -Dloader.path=/path/to/config/dir/ -jar my-service-1.0.jar
In one of dependencies which my app has, below code is used to read the external xml config files (e.g. hbase-site.xml) :
URL url = ClassLoader.getSystemResource(filename);
which is why I am trying to make those files available using loader.path but the app still doesn't read the files present on the provided dir. Am I missing anything else?
Already referred : Spring Boot: Is it possible to use external application.properties files in arbitrary directories with a fat jar?
Spring Boot Executable Jar with Classpath

I think it should be the problem of getSystemResource, try to use getClassLoader().getResourceAsStream(path)

Related

Ways to make annotation processors read src/main/resources files on Maven Update

I am trying to make annotation processor read a file from src/main/resources package. The code I am using to read the file is:
resource = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", fileName);
The annotation processor is executed by maven-processor-plugin:
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>3.3.3</version>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>compile</phase>
<configuration>
<outputDirectory>target/generated</outputDirectory>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
...
</dependency
</dependencies>
</plugin>
However, when triggering the processor by Maven update command (via Eclipse IDE), the processor throws an IO exception saying that the resource file does not exist.
I have to trigger each java file separately for the processor to find the resource files.
I believe this issue is due to the processor, be default, running in "generate-sources" phase, while the resources are not detected until "process-resources". Please note: https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Plugins
I have tried changing the phase in the pom file but to no avail. There is a similar post but there has not provided with defined solution: Need file from src/main/resources in generate-sources phase for annotation processor config Strangely, when I run other maven commands like compile or install, the processors can read the resource files (just not through Maven Update). Are there any solutions to how this can be achieved on Maven Update command? Thank you.
You can use below configuration with maven-compiler-plugin.
<generatedSourcesDirectory>
${project.basedir}/src/main/java
</generatedSourcesDirectory>
Check below link for complete implementation.
https://www.thetechnojournals.com/2019/12/annotation-processor-to-generate-dto.html

How to deploy angular 6 project and spring boot project as a single deployment unit

I have two projects one is Angular Project(Front End Application ) and another one is Spring boot (Rest Api's).
When I run both the projects individually everything works fine. But now I want to generate a single runnable jar file for both these projects in such a way that when i run the jar in the localhost:8081 it should up both the Angular module as well as spring boot module.
I've added the following plugin to my pom.xml file
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${build.directory}/classes/static/</outputDirectory >
<resources>
<resource>
<directory>../angular6-MyProject/dist</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Quick answer
You need to copy static files to ${build.directory}/classes/META-INF/resources folder for the servlet container serve them as static files from inside a war/jar file (that's how https://www.webjars.org work).
Handling HTML directly from jar
In the Static Content section of Spring Boot documentation you can find
By default, Spring Boot serves static content from a directory called /static (or /public or /resources or /META-INF/resources) in the classpath or from the root of the ServletContext
The /META-INF/resources is the "standard" way (though not most intuitive) and it comes directly from the Java Servlet Specification 3.0 (from JavaEE version 6)
A Web application exists as a structured hierarchy of directories. The root of this hierarchy serves as the document root for files that are part of the application. For example, for a Web application with the context path
/catalog in a Web container, the index.html file at the base of the Web application hierarchy or in a JAR file inside WEB-INF/lib that includes the
index.html under META-INF/resources directory can be served to satisfy a request from /catalog/index.html.
Therefore, setting an appropriate path should do the job.
Treating Angular application as a dependency
The quoted JavaEE spec is also what webjars utilize. Webjars are client-side dependencies packaged into JAR archive files. The primary reason for webjars to exist is to avoid adding and managing client-side dependencies (like Angular, jQuery), which often results in hard to maintain codebases.
But if the Angular can be a webjar, your frontend can be as well. What I tend to do is to pack the Angular application as a jar file and treat it as a dependency.
Frontend application
Driven npm from Maven + create Jar file
<project>
<groupId>com.examplegroupId>
<artifactId>myapp-ui</artifactId>
<packaging>jar</packaging>
<build>
<plugins>
<!-- run the frontend (npm / bower stack) and update dependencies -->
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<configuration>
<installDirectory>target</installDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<nodeVersion>v8.9.1</nodeVersion>
<npmVersion>5.5.1</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>npm build</id>
<goals>
<goal>npm</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
<!-- copy everything as a webjar -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/META-INF/resources</outputDirectory>
<resources>
<resource>
<directory>dist/</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Backend application
Use the dependency directly
<dependencies>
<dependency>
<groupId>com.example<groupId>
<artifactId>myapp-ui</artifactId>
</dependency>
</dependencies>
Notices
Some issues and observations I've seen with webjars:
I've seen some problems with webjars and web fonts (fonts not being load by the browser when served from inside the jar file)
There are ways to build webjars using npm tools and all packages I've seen require and use java underneath anyway. I haven't seen any native JS solution
Webjars themselves don't impact the performance of an application, however serving static content from Servlet container is always significantly less performant (regarding possible throughput) than serving it from say nginx
I followed this tutorial
and it's somehow similar to what Jakub mentioned in his answer. I usually run the mvn spring-boot:run command to launch it in one go. The key to setting up the project is in the pom.xml. Make sure that you are telling the build to copy the Angular dist/ files into the right place. In this case, it needs to copy the compiled JS from Angular's dist/ folder to the server/target/classes/resources so it can host the static content.
The entire build (mvn clean install) can take forever. So during development I just go to the src/main/web directory and run ng-serve from there so I can see my UI changes quickly.
Hope this helps.
The back-end server uses Spring Boot with Spring Web MVC for REST Controller and Spring Data JPA for interacting with MySQL database. Front-end side is made with Angular 11, HTTP Client & Router.
– Spring Boot exports REST APIs using Spring Web MVC & interacts with MySQL Database using Spring Data JPA.
– Angular Client sends HTTP Requests and retrieve HTTP Responses using axioms, shows data on the components. We also use Angular Router for navigating to pages.
Steps to follow to set up Angular 11 with Spring Boot Application.
Create Angular 11 Application to run and build successfully.
Create build according to environment like QA, PROD, LOCAL.
from dist. folder collect compiled files through node-js.
Angular runs on node server by using typescript. once you compile code and build angular project in dist. folder you will get .js files. java script files.
We can you as it is js files from dist folder to run any UI application.
Create Spring boot application and write REST apis and compile and build successfully.
create static folder in resource folder.
put static folder path inside application.properties like classpath:"resource/static/".
put all compiled js file in to static folder from dist folder.
create webConfig.java file in spring boot project to routing URL for index.html.
Create build nd compile successfully spring boot project.
if you run the project you will get UI from spring boot project.
Create jar from spring boot project.
Deploy on Azure and run the project successfully.
thank you you can visit my blog for in details.
https://draft.blogger.com/blog/post/edit/preview/8320325077779788397/7601438449518293236

Having application as standalone as well as dependency in Spring Boot 1.5

I have a spring boot application (application A) which I deploy as a standalone fat jar. But I also have another spring boot application (application B) which depends on app A. Now, when I try to import some classes from app A into app B, I get a package not found exception. However, IDEs such as Intellij / Eclipse are able to find the package properly. This used to work earlier when I was using Spring Boot 1.3.x. However, after upgrading to 1.5.x, it started failing.
On inspecting the actual jar files, I realized that with Spring Boot 1.3.3, all the classes were under the main package. However, with Spring Boot 1.5.x, they are under BOOT-INF folder. And in the META-INF/Manifest.MF file, we have properties which point to the BOOT-INF folder. And because of this, when I try to import the classes, it is not able to find the packages, because they are under BOOT-INF.
So how else can I have a project standalone application as well as have it as a dependency for another project?
Seems to be a known issue with Spring Boot 1.4.x (https://github.com/spring-projects/spring-boot/issues/6792#issuecomment-243564648). Updating my pom file in application A to have the following fixed it:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

How to create an additional JAR for a specific folder with maven

I have a maven project, I need to generate three separate jars
one for the main application (default)
one for the source code (maven-source-plugin)
and one for my app documentation which reside in target/docs
Question: How can I create a jar containing only the target/docs folder?
You could add the following to your maven pom.xml file, build/plugins section:
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<configuration>
<classifier>docs</classifier>
<classesDirectory>${project.build.directory}/docs</classesDirectory>
<includes>**/*</includes>
</configuration>
<id>pack-docs</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
Which is basically:
Using the maven-jar-plugin, jar goal to pack a new artefact for the project
Adding (or attaching) it as a classifier (docs suffix appended to the normal convention for project artefacts, e.g. artifactId-version.jar)
Setting the target\docs as source of files, using the standard ${project.build.directory} property instead of target (which is its value by default)
Running
mvn clean package
You would then have as part of the output
The jar file normally created, e.g. sample-project-1.0.0-SNAPSHOT.jar
The new docs file, e.g. sample-project-1.0.0-SNAPSHOT-docs.jar

Issue setting the class path in Maven exec plugin when running a Main Class

I have embedded Jetty in my application. In order to automatically execute my integration tests on my build server I'd like Maven to start my application in the pre-integration-test phase. The integration tests are in another project than the application te be tested, because the tests are of a quite complex nature and should be seperated from production code.
I have tried to set up my application using the Maven exec plugin, but keep running into ClassNotFoundErrors. I use the maven-dependency-plugin to copy all dependencies to target/lib/. Until now, I haven't been able to figure out how to tell the exec plugin to add that lib folder to the class path.
This is my current exec plugin configuration:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>default-cli</id>
<phase>pre-integration-test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.zertificon.managementCenter.adminUi.server.WebApp</mainClass>
<!-- this does not work: -->
<classpath>${project.build.directory}/${libFolder}/</classpath>
</configuration>
</execution>
</executions>
</plugin>
The WebApp class I am trying to run originates from another Project and is installed in the local repository. I would highly apreciate any help.
Found the error: I have been using Jetty together with a Selenium Library that itself bundles Jetty, too. This lead to a wrong Jetty Version being loaded wich gave me class not found errors. Go figure.

Categories

Resources