appassembler-maven-plugin add custom entry to classpath - java

I'm writing a Java-Application which is using some libaries from anonther thirdparty-Application which is running on my server. At the moment im building my App with the appassembler-maven-plugin. This plugin copy my jars (app and dependencies) into the lib folder an generates a shellscript in the bin dir.
The classpath is generated in this shellscirpt. This solution works but i dublicate the dependency-jars (on time in my app and in the thirdparty-Application write the app for). The classpath of my thirdparty-application is set in a systemvariable like $THIRDPARTYAPP_CLASSPATH.
I want to set the dependencies in my pom.xml to provided, so that the appassembler don't add them to lib and classpath and want to add the systemvar $THIRDPARTYAPP_CLASSPATH in my shellscript, so that my app uses the jars from the installed thirdparty-application.
At the moment i'm doing this manually (editing the shellscript after the build) and it works. Is there any method in the appassembler-maven-plugin to add thid systemvar to the classpath automatically?
I couldn't find anything in the documentation and other questions here regarding a similar problem are not well answerd.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.8.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>assemble</goal>
</goals>
</execution>
</executions>
<configuration>
<assembleDirectory>${project.build.directory}/appassembler</assembleDirectory>
<extraJvmArguments>-Xms512m -Xmx1024m</extraJvmArguments>
<generateRepository>true</generateRepository>
<repositoryName>lib</repositoryName>
<repositoryLayout>flat</repositoryLayout>
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
<platforms>
<platform>unix</platform>
</platforms>
<programs>
<program>
<mainClass>${mainClass}</mainClass>
<id>app</id>
</program>
</programs>
</configuration>
</plugin>

You can configure to create an <environmentSetupFileName>setup-env</environmentSetupFileName> which can define a new classpath part via CLASSPATH_PREFIX which should solve your problem.

Related

Maven and java: how to generate code from protobuf files in test directory?

My question is very similar to this question but for maven and java.
I am testing grpc, and want to put to a simple helloworld.proto in the test/proto folder.
However the file doesn't generate a java file (unlike the proto file in /src/main/proto).
So my question is how to generate code for proto in the test folder?
First, follow the documentation to use the org.xolstice.maven.plugins protobuf-maven-plugin.
Alternatively, you can copy the example pom.xml (this is pinned to the v1.19.0 release; consider using whatever the latest tag is). This pom is used by the helloworld example, among others.
Then add the test-compile and test-compile-custom goals for the protobuf-maven-plugin. This will cause files in src/test/proto to be generated.
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
<goal>test-compile</goal>
<goal>test-compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>

Read Manifest file in Spring boot application

We are using Spring-boot to build micro-services. In my project set-up we have a common maven module named platform-boot with main class with annotation SpringBootApplication
If we want to create a new micro-service (say Service-1), we simply add a dependency of platform-boot module and provide the main-class path in pom.xml and we are good to go.
Problem is when I try to read Manifest.MF file of Service-1 by writing code in my 'main-class' in dependent module. It reads the Manifest.MF file of platform-boot.
Below is the code snippet of how I am reading Manifest.MF file in my main class.
MyMain.class.getProtectionDomain().getCodeSource().getLocation().getPath();
//Returns the path of MyMain.class which is nested jar
Please suggest a way to read the Manifest.MF file of Service-1.
PS: I want to read the Maifest.MF file to get Implementation-Version. Please suggest if any other way of getting it as well.
I found two ways to solve this problem:
We can use maven-dependency-plugin to unpack the child jar while
executing the phase prepare-package. This plug in will extract the
class file from my platform-boot jar to my Service-1.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>unpack</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>my.platform</groupId>
<artifactId>platform-boot</artifactId>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<includes>**/*.class,**/*.xml,**/*.text</includes>
<excludes>**/*test.class</excludes>
</artifactItem>
</artifactItems>
<includes>**/*.java, **/*.text</includes>
<excludes>**/*.properties</excludes>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
Second approach is much simpler, in spring-boot-maven-plugin add a goal
build-info. This will write a file build-info.properties in your META-INF folder and is accessible in code as below.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
In your main method you can get this information using the BuildProperties
bean already registered in ApplicationContext.
ApplicationContext ctx = SpringApplication.run(Application.class, args);
BuildProperties properties = ctx.getBean(BuildProperties.class);
In fact, Spring-actuator also uses this BuildProperties to get the build
information which is helpful in monitoring.
Hi could you please elaborate the need of reading your service-1manifest.mf ?
If you just want the service1 as a dependeny in your parent common module and should not conflict with your service1 bootable application , you can do generate two jars through the exec configuration in spring-boot-maven-plugin .

Use Maven Replace Plugin to replace a phrase on a generated Java file inside Target/generated-sources

I spent hours on this problem, searching several Google and SO entries, I have some ideas but not getting the result.
I have a maven file that does something like this:
grab a jar containing JSON schemas, and unpack them.
Using the Maven Replacer plugin (v 1.5.3), replace a line in a schema file called “MySchema.json” as such:
”Hello” :
”HelloWorld” :
then Maven would use another plugin to compile a class called “converter.java” and runs this class to output a Java file based on “MySchema.json”. let’s call the generated Java file “MyPojo.java”.
Now, I want Maven to replace a line in “MyPojo.java”, but no matter what I do I cannot achieve this.
I tried:
include a separate replace plugin entry for step 4 after the plugin that converts schemas to Java, but ofcourse this caused Maven to complain about existing replace plugin with same artifact/group id from step 2.
Tried adding a separate execution id to the goal “replace” for second plugin, this is invalid for this plugin.
There is a parent project to my current project folder, I tried putting another replacer plugin in the parent POM and make the phase to be any of the “package”, “generate-resources”, “compile”, etc. did not work. Note: the phase for replacements inside “MySchema.json” (in my current project POM) is generate-sources.
give absolute path to the Java, it kept complaining that path does not exist. But I copied and pasted the path to the Java inside windows explorer address bar after it was generated and could read it from Windows explorer. Note that the generated Java file “MyPojo.java”, went under “target/generated-sources” which is sourced by a parent POM above this project using a Maven Helper plugin in parent POM, so this folder should be visible as a source for further compilation. That Maven Helper plugin has phase generate-sources.
Use with same result as above
In my current project (non-parent one) this is the POM code:
<build>
<!—execute a plugin grab schemas jar and unpack schemas-->
...
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>${project.basedir}/target/schemas/MySchema.json</include>
</includes>
<replacements>
<replacement>
<token>"Hello":</token>
<value>"Hello World":</value>
</replacement>
</replacements>
</configuration>
</plugin>
<!-- execute a Plugin for converting shcemas to POJO -->
. . .
</plugins>
</build>
</project>
You should be able to declare the plugin only once and run two replace execution at different Maven Build Lifecycle phases:
Before the Json -> POJO conversion
After the Json -> POJO conversion
So, translating that into could would result in something like:
<plugin>
<!-- (unique) plugin declaration -->
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>maven-replacer-plugin</artifactId>
<version>1.3.5</version>
<executions>
<!-- first execution: replace on json file -->
<execution>
<id>replace-for-json</id>
<phase>some-phase-before-conversion</phase>
<goals>
<goal>replace</goal>
</goals>
<configuration>
<filesToInclude>${project.basedir}/target/schemas/MySchema.json</filesToInclude>
<preserveDir>true</preserveDir>
<outputDir>target</outputDir>
<replacements>
<replacement>
<token>"Hello":</token>
<value>"Hello World (Json)":</value>
</replacement>
</replacements>
</configuration>
</execution>
<!-- second execution: replace on java file -->
<execution>
<id>replace-for-pojo</id>
<phase>some-phase-after-conversion</phase>
<goals>
<goal>replace</goal>
</goals>
<configuration>
<filesToInclude>${project.basedir}/target/generated-sources/MyPojo.java</filesToInclude>
<preserveDir>true</preserveDir>
<outputDir>target</outputDir>
<replacements>
<replacement>
<token>"Hello":</token>
<value>"Hello World (Java)":</value>
</replacement>
</replacements>
</configuration>
</execution>
</executions>
</plugin>
Source: Configuration for the maven-replacer-plugin on two separate executions

Clean jar conflicts

In our project I want to remove all the potential jar conflicts that might arise during runtime. Our stack is so big, we have same jar brought in by different dependencies. Here is the problem, each dependency is bringing in different version of the same jar and causing issues, after fresh deployment.
Where do I start from ? Are there any maven plugins to resolve this ?
Any help or pointers on this is much appricieated.
You can use the maven-enforcer-plugin as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.3.1</version>
<configuration>
<fail>true</fail>
<rules>
<dependencyConvergence/>
</rules>
</configuration>
<executions>
<execution>
<id>enforce-dependencies</id>
<goals>
<goal>enforce</goal>
</goals>
</execution>
</executions>
</plugin>
This will stop the build when there are conflicting dependencies.
A handy tool: JHades. In a nutshell, it is a tool that helps with Jar dependency Hell. In itself, it is a Jar with no dependencies, except for the JDK. It can be used to spot easy conflicts and to debug more severe issues. Example:
new JHades()
.printClassLoaders()
.printClasspath()
.overlappingJarsReport()
.multipleClassVersionsReport()
.findClassByName("org.jhades.SomeServiceImpl")
Prints the class loader chain, jars, duplicate classes, ...

minify frontend with minify-maven-plugin

I'm using the maven plugin minify-maven-plugin in order to minify my frontend project. This works fine when I go over dos box to the frontend project and execute mvn clean install but when I execute mvn clean install in the main pom in my reactor project then I get the following exception:
Failed to execute goal com.samaxes.maven:minify-maven-plugin:1.7.4:minify (default-minify) on project my.project-frontend: Execution default-minify of goal com.samaxes.maven:minify-maven-plugin:1.7.4:minify failed: basedir ./src/main/resources/public/app/. does not exis
Does anyone know what to do in order to make this work?
Below the concerned plugin configuration:
<!-- minify plugin -->
<plugin>
<groupId>com.samaxes.maven</groupId>
<artifactId>minify-maven-plugin</artifactId>
<version>1.7.4</version>
<executions>
<execution>
<id>default-minify</id>
<phase>prepare-package</phase><!-- When omitted defaults to 'process-resources' -->
<configuration>
<charset>UTF-8</charset>
<skipMerge>true</skipMerge>
<nosuffix>true</nosuffix>
<closureCompilationLevel>WHITESPACE_ONLY</closureCompilationLevel>
<webappSourceDir>src/main/resources/public/app</webappSourceDir>
<webappTargetDir>${project.build.outputDirectory}/public/app</webappTargetDir>
<cssSourceDir>./</cssSourceDir>
<cssSourceIncludes>
<cssSourceInclude>**/*.css</cssSourceInclude>
</cssSourceIncludes>
<jsSourceDir>./</jsSourceDir>
<jsSourceIncludes>
<jsSourceInclude>**/*.js</jsSourceInclude>
</jsSourceIncludes>
<jsEngine>CLOSURE</jsEngine>
</configuration>
<goals>
<goal>minify</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- minify plugin end -->
I was able to reproduce your issue and fix it by changing the configuration entry below
<webappSourceDir>src/main/resources/public/app</webappSourceDir>
to
<webappSourceDir>${project.basedir}/src/main/resources/public/app</webappSourceDir>
That is, adding the standard ${project.basedir} property as a prefix.
With that, the build was successful from the module itself but also from the parent one (the reactor/aggregator build).
Thanks to this prefix, the reactor build will properly resolve the path, pointing at the current base directory (the one of the concerned module) during the build.
From official Maven Builder model documentation
{project.basedir} the directory containing the pom.xml file
Hence, the reactor build will replace this property for each module, pointing at the directory containing the module pom.xml file (hence, the directory of the module). It will also work properly when executing the build from the module directly, obviously pointing at the current directory.
Also note: ${basedir} would also work but it is deprecated in favor of project.basedir, hence better to use the latter.
You cam minify as:
<plugin>
<groupId>com.samaxes.maven</groupId>
<artifactId>minify-maven-plugin</artifactId>
<version>1.7.4</version>
<executions>
<execution>
<id>minify-css</id>
<configuration>
<charset>utf-8</charset>
<skipMerge>true</skipMerge>
<statistics>true</statistics>
<cssSourceDir>css</cssSourceDir>
<cssTargetDir>css/min</cssTargetDir>
<cssSourceIncludes>
<cssSourceInclude>*.css</cssSourceInclude>
</cssSourceIncludes>
</configuration>
<goals>
<goal>minify</goal>
</goals>
</execution>
<execution>
<id>minify-js-cfl</id>
<configuration>
<charset>utf-8</charset>
<skipMerge>true</skipMerge>
<statistics>true</statistics>
<jsSourceDir>js/xyz/modules/cfl</jsSourceDir>
<jsTargetDir>js/xyz/modules/cfl/min</jsTargetDir>
<jsSourceIncludes>
<jsSourceInclude>*.js</jsSourceInclude>
</jsSourceIncludes>
</configuration>
<goals>
<goal>minify</goal>
</goals>
</execution>
<execution>

Categories