Getting application version from pom - java

I have a rest endpoint used to return information about application (so far only app version)
But so far this info is hardcoded, and it's pretty easy to forget to change it.
I will be better to retrieve app version from pom or manifest file. Is there any project that brings such functionality?

Spring Boot can refer to the project version defined in pom.xml and expose it via REST using Actuator:
# application.properties
endpoints.info.enabled=true
info.app.version=#project.version#
Then accessing the /info URL (e.g. http://localhost:8080/info) will return:
{"app": {"version": "<major.minor.incremental>"}}
See also: spring boot/spring web app embedded version number

You better use build-in manifest.
new Manifest(Application.class.getResourceAsStream("/META-INF/manifest.mf"))
For the concrete impl-version:
new Manifest(Application.class.getResourceAsStream("/META-INF/manifest.mf"))
.getMainAttributes()
.get(Attributes.Name.IMPLEMENTATION_VERSION)
Using maven do not forget to create the manifest using:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

There is amazing project named Appinfo, please use it and enjoy! (It has an ugly page, I know - but it works :)
AppInfo allows to automatically feed your application with a current version number, build date or build number.
Also excellent Spring Boot Actuator provides feature named Info Endpoint which can publish version information to web or REST.
By default the Actuator adds an /info endpoint to the main server. It contains the commit and timestamp information from git.properties (if that file exists) and also any properties it finds in the environment with prefix "info".

You could use the resource filtering of maven or something like the maven-substitute-plugin.

Related

Maven resource plugin doesn't filter out customized delimiters nested in ${}

I have a properties file:
property.a=$[value]
I am using maven-resources-plugin with filtering on this property file enabled in order to substitute build variables in there:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimiter>$[*]</delimiter>
</delimiters>
</configuration>
</plugin>
Everything works flawlessly, until $[*] token is not nested into ${*} one, like below:
property.a=${VALUE:$[value]}
Assuming value=XXX in Maven properties, I expected to get:
property.a=${VALUE:XXX}
However, Maven resources plugin doesn't substitute $[value] in there, leaving filtered contecnts as-is. I tried enabling supportMultiLineFiltering but it changed nothing. It feels like despite <delimiters> option is set explicitly, plugin treats ${*} as a valid delimiter either, and tries to filter it, without success.
How should I configure maven resources plugin so that it filters the property file contents as expected?
I just realized I missed a configuration option in maven resource plugin, designed specially for controlling default delimiters - useDefaultDelimiters, which is true by default. The configuration below solved the issue:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimiter>$[*]</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>

Share Classloader between multiple in Jetty Maven Plugin

I'm try to configure maven jetty plugin to start my war application, but it has some complications like as follow descriptions:
1º - It has dependencies with a ejb jar;
2º - It has dependencies with war (tag jstl:import context="nscl");
3º - The classloader between wars must be shareded.
So, I need some help to resolve the third problem. Looks my jetty plugin configuration in pom.xml:
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.1.v20170120</version>
<configuration>
<useProvidedScope>true</useProvidedScope>
<useTestScope>true</useTestScope>
<webApp>
<contextPath>/nscl/cntr</contextPath>
</webApp>
<contextHandlers>
<contextHandler implementation="org.eclipse.jetty.maven.plugin.JettyWebAppContext">
<war>${contexto.war.path}</war>
<contextPath>/nscl</contextPath>
</contextHandler>
</contextHandlers>
<systemProperties>
<systemProperty>
<name>spring.profiles.active</name>
<value>test</value>
</systemProperty>
</systemProperties>
</configuration>
</plugin>
The problem is, when jetty is starting the second war (context-path = nscl), I receive problems saying the classes used to start first war not exist to second, a sample is classes of spring framework.
Thanks !!!!
You are hitting Standard Servlet Spec behavior.
Your WebApp's cannot share the same ClassLoader.
That is a fundamental part of being a Servlet Spec WebApp, the ClassLoader isolation.
Attempting to force it will just create mysterious problems with the ClassLoader hierarchy (InvalidClassChange errors, memory leaks, GC failures, etc)
Perhaps you can detail why you think you need this.
As there's likely already a standard way to accomplish it using the features of the Servlet spec (and not fighting it).

How to run a main after embedded tomcat is run

There is a java webapp with an embedded tomcat 7 that is built with this instructions (Using tomcat7-maven-plugin).
this webapp is launching with a jar file like this: java -jar webapp.jar
Question: How to run a main class after launching this embedded tomcat?
What you need is to setup your application's entry point. For this you need to configure your main class inside the jar's Manifest file.
Something like
Manifest-Version: 1.0.1
Created-By: <jdk_version>
Main-Class: fully.qalified.class.name.with.main.method
For more details on Manifest, take a look into this link here
For making this step part of your maven build cycle, you need to make some changes in the mave.jar.plugin. Something like
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<mainClass>fully.qalified.class.name.with.main.method</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
The final jar that is created will have your main method as the applications entry point
If I understood your question correctly. In Eclipse, Right click the project and pick "Run on Server."

appengine-maven-plugin configuration options like jvm flags

Since version 1.7.4. of Google App Engine the official appengine-maven-plugin is released by Google.
It has a task appengine:devserver to start the local development server.
This plugin seems not to have any Maven configuration options.
I wonder how I can
a) provider jvm flags
b) to disable new version check (when working offline)
Note that until now I was using the unofficial net.kindleit maven-gae-plugin like:
<plugin>
<groupId>net.kindleit</groupId>
<artifactId>maven-gae-plugin</artifactId>
<version>0.9.4</version>
<configuration>
<disableUpdateCheck>true</disableUpdateCheck>
<javaAgent>${env.REBEL_HOME}/jrebel.jar</javaAgent>
<jvmFlags>
<jvmFlag>-noverify</jvmFlag>
<jvmFlag>-Ddatastore.backing_store=${project.basedir}/local_db.bin</jvmFlag>
<jvmFlag>-Ddatastore.default_high_rep_job_policy_unapplied_job_pct=20</jvmFlag>
<jvmFlag>-Drebel.spring_data_plugin=true</jvmFlag>
</jvmFlags>
<wait>true</wait>
</configuration>
<dependencies>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-tools-sdk</artifactId>
<version>${com.google.appengine.version}</version>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-1.0-sdk</artifactId>
<version>${com.google.appengine.version}</version>
</dependency>
</dependencies>
</plugin>
I wrote the plugin, so I guess this is my fault. The configuration is well supported for appcfg operations (like update/rollback/etc.), but I need to fix a few things obviously for the development server. I'll get onto that and there should be an update soon.
UPDATE : I've pushed a snapshot build that supports configuration for the devserver target. It's in 1.7.5-SNAPSHOT.
YOU WILL NEED TO READ THIS TO USE SNAPSHOT BUILDS : http://code.google.com/p/appengine-maven-plugin/
It looks like 1.7.5 of both the SDK and Maven plugin are now available from the normal Maven repository thus it should be sufficient to simply update those dependencies to the 1.7.5 version and omit the declaration of the SNAPSHOT repository. The 1.7.5 maven-appserver-plugin does seem to support jvmFlags like the following:
<configuration>
<jvmFlags>
<jvmFlag>-Ddatastore.default_high_rep_job_policy_unapplied_job_pct=20</jvmFlag>
</jvmFlags>
</configuration>
Yea!
Thank you to MattStep and the Google team!
Having exactly that issue myself. Checking the actual sources for the plugin, the DevAppServerRunner has zero support for passing extra arguments of any kind to the dev server. It looks like the best way to do it at the moment is to use the unofficial plugin.
source for DevAppServerRunner.java

Injecting Maven project information into Swing Application Framework resources?

I have a Maven project using the Swing Application Framework and would like to inject project information from the pom.xml into my application's global resources to avoid duplication.
The base application (provided via netbeans) uses Application.title, Application.version, Application.vendor, Application.description resources etc for Window titles and about box configuration but I can't find a way to set these values programatically at run time and I'm not a maven maven so don't have the skills to inject them at build time.
Anyone have any recommendations on how best to achieve the desired result?
You could try using filtered resources. If you create a property file, say src/main/resources/com/myapp/app.properties that looks like this:
version=${project.version}
name=${project.name}
id=${project.artifactId}
Them you need to enable filtering in your pom.xml:
<build>
<resources>
<resource>src/main/resources</resource>
<filtering>true</filtering>
</resources>
</build>
Now when maven builds your project, it'll expand the property file, and place it on the classpath. Then you can just call getResourceAsStream("/com/myapp/app.properties") to read it into your app.
Whist maven does automatically create a file /META-INF/maven/$groupId/$artifactId/pom.properties, this may not have all the information you need.
You can keep those in separte property file and read it from both pom.xml and your application.
Another option is to read pom.xml file from classpath (mvn will put it in META-INF folder) and parse it from there as plain xml file.
I would go with first option.
I would try using the maven-antrun-plugin. Pass the necessary maven properties to ant and create an ant build script which modifies an application properties file or the spring context configuration directly.
Another way would be to generate a separate properties file with the properties-maven-plugin and then add this properties file to the application bundle names:
For the pom.xml to write application.properties file:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>write-project-properties</goal>
</goals>
</execution>
</executions>
<configuration>
<outputFile>${project.build.outputDirectory}/application.properties</outputFile>
</configuration>
</plugin>
...
</plugins>
...
</build>
For including the application.properties into your application:
public class MyApplication extends SingleFrameApplication
public MyApplication() {
super();
addGeneratedApplicationProperties();
}
private void addGeneratedApplicationProperties() {
ResourceManager resourceManager = getContext().getResourceManager();
getContext().setApplicationClass(MyApplication.class);
List<String> bundleNames = new LinkedList<String>(resourceManager.getApplicationBundleNames());
bundleNames.add(0, "application");
resourceManager.setApplicationBundleNames(bundleNames);
}
...
}
However, I find the maven-filter-solution way more elegant.

Categories

Resources