I have added a node in my pom.xml:
<properties>
<getdownload-webapp.version>1.5</getdownload-webapp.version>
</properties>
how could I get this 1.5 value in code?
String version = System.getProperty("getdownload-webapp.version"); // output version = null
This code gave me null while running(
ps: there is no settings.xml in this project
So you have a property like this.
<properties>
<getdownload-webapp.version>1.5</getdownload-webapp.version>
</properties>
Create a file as follows in your Maven project.
src/main/resources/project.properties
Or as follows if it is for tests only.
src/test/resources/project.properties
Add this line inside the new file. Please note that you should not prefix with "properties" (e.g. don't write "properties.getdownload-webapp.version").
version=${getdownload-webapp.version}
Note that you can also add flags like this to the file.
debug=false
If not already done, you have to enable Maven filtering for your project. It is the feature that will look for placeholders inside the files of your project to be replaced by values from the pom. In order to proceed, you need add these lines inside the <build> tag of your pom.xml file. This is how to do with src/main:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
And here is how to do for src/test:
<build>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
...
Finally, in your source code (MyClassName.java), add a block like
Properties props = new Properties();
props.load(MyClassName.class.getClassLoader().getResourceAsStream("project.properties"));
String version = props.getProperty("version");
You can add as many variables as you want to the project.properties file and load each one using this method.
The mechanism chiefly in charge to transfer Maven properties to Java application is provided by the Maven Resource Plugin
The plugin is part of the Maven Super Pom and executed during the process-resources phase of the Jar Default Lifecyle. The only thing you have to do is to active filtering.
This will replace any placeholders, e.g. ${my.property} in any of the files in src/main/resources with the corresponding property from your pom, e.g. <property><my.property>test</my.property></property>
How you make this property then available to your Java application is up to you - reading it from the classpath would work.
I assume you want to get it in the code to check something right? You can use filtering from maven that will inject the value in the source code, similar to the filtering option
http://mojo.codehaus.org/templating-maven-plugin/
String version = project.getProperties().getProperty("getdownload-webapp.version");
Where project is of type MavenProject
Related
TL; DR
Maven's Resources plugin doesn't seem to respect excludes elements in the resource configuration.
Setting
I have a large Java/Dart project where I need to deploy a WAR file that has both my UI and my backend in separate JARs. I want to cut down on the size of the deployed file, and I want to drop certain folders from the WAR. Based on the plugin documentation, I thought I could simply set excludes in my plugin configuration, and it won't copy over the unnecessary folders. However, it seems the Resources plugin is outright ignoring these, despite, the Maven model package including a setExcludes function.
Current Attempts
So far, I've tried two main approaches. My configuration is as follows:
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}</outputDirectory>
<resources>
<resource>
<directory>src/main/webapp</directory>
<excludes>
<exclude>web.xml</exclude>
<exclude>appengine-web.xml</exclude>
<exclude>**/web/_el/*</exclude>
<exclude>WEB-INF/pages/frontend/**</exclude>
<exclude>**/_el/js/frontend/**</exclude>
<exclude>**/_el/dart/app/dashboard/lib/**</exclude>
<exclude>**/_el/dart/app/dashboard/.dart_tool/**</exclude>
</excludes>
</resource>
</resources>
</configuration>
I tried to use this config inside the execution element, as well as outside from directly under the plugin element, but both times it was ignored, and everything in the webapp directory was copied over mindlessly.
On a hunch, I did try setting filtering to true, but that just ate up all the memory in my computer, and it didn't even work - what it did process was copied over.
I also tried using the Shade plugin, but gave up on that pretty quickly, as the DontIncludeResourceTransformer only permits suffix-filtering, which is not adequate for my use case.
Question
So what am I doing wrong? Based on the docs, I believe the plugin should respect my excludes list and skip the vast majority of files, but it's evidently not doing that.
You need to use apache **maven war plugin**.
The WAR Plugin is responsible for collecting all artifact dependencies, classes and resources of the web application and packaging them into a web application archive.
It is possible to include or exclude certain files from the WAR file, by using the and configuration parameters. They each take a comma-separated list of Ant file set patterns. You can use wildcards such as ** to indicate multiple directories and * to indicate an optional part of a file or directory name.
Here is an example where we exclude all JAR files from WEB-INF/lib:
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
https://maven.apache.org/plugins/maven-war-plugin/examples/including-excluding-files-from-war.html
I am starting to get deeper into Gradle by migrating one project I have From Maven 3.6.3 to Gradle 6.5.1.
I'm arriving at the stage where I have to build a War file in the impl module that is slightly customized: I rename the Jars in the lib folder, and include via an overlay (from a Jar built in the api module from the same project) some resources.
The current Maven configuration is the following:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<outputFileNameMapping>#{groupId}#-#{artifactId}#-#{version}#.#{extension}#</outputFileNameMapping>
<webResources>
<resource>
<directory>src/main/webapp</directory>
</resource>
</webResources>
<overlays>
<!-- Include the OpenAPI spec -->
<overlay>
<groupId>com.project.rest</groupId>
<artifactId>api</artifactId>
<type>jar</type>
<includes>
<include>specs/</include>
</includes>
</overlay>
</overlays>
</configuration>
</plugin>
So I'm trying to come up with something similar for Gradle regarding the libraries renaming.
I saw in the documentation of the plugin that there is a rename method in the plugin:
Renames a source file. The closure will be called with a single parameter, the name of the file. The closure should return a String object with a new target name. The closure may return null, in which case the original name will be used.
The issue is that is takes the name of file in parameter, whereas I would need (in order to mimic the outputFileNameMapping option) to get the dependency so I could extract its metadata.
So I assume this is not the right option. Is there a way to achieve this with Gradle?
Thanks
The gradle war plugin has a number of configuration options, including archiveFileName (or archiveName on older versions of gradle). archiveFileName by default is set to: [archiveBaseName]-[archiveAppendix]-[archiveVersion]-[archiveClassifier].[archiveExtension]
This can be declared in the war {} block in your build.gradle. You should be able to do something like this:
war {
archiveFileName = "${project.group}-${project.name}-$archiveVersion.$archiveExtension"
}
For more on the available configuration options, see the War documentation
This will rename the war file itself.
If you want to rename contents of the war file instead, you can use the war.rootSpec.rename(), like so:
// make a copy of the implementation configuration that can be resolved so we can loop over it.
configurations {
implementationList {
extendsFrom implementation
canBeResolved true
}
}
war {
rootSpec.rename({ fileInWar ->
def returnValue = fileInWar
project.configurations.implementationList.resolvedConfiguration.resolvedArtifacts.each {
if (it.file.name == fileInWar) {
def depInfo = it.moduleVersion.id
print "$returnValue -> "
returnValue = "${depInfo.group}.${depInfo.name}-${depInfo.version}.${it.extension}"
println "$returnValue"
}
}
return returnValue
})
}
However, note that this will not resolve conflicts if you have duplicate dependencies.
My pom.xml has <systemPropertyVariables> and <profiles>. Right now if I want to run it as a maven build i am using -DXXX for system property variables and -PXXX for profiles in the goal.
Now I would like to run this as JUnit test in eclipse. I found that system property variables can be given in VMArguments.
Now the problem is how to access this profile. Here is how my profile looks like
<profile>
<id>devqa</id>
<build>
<resources>
<resource>
<directory>src/main/resources/devqa</directory>
</resource>
</resources>
</build>
</profile>
I have a file in the resource location and im accessing it in my test
File testfile = new File(this.getClass().getResource("/config.properties").toURI());
I tried to give this in Active Maven Profiles but it didn't work. How to make this work
Add the resource path src/main/resources/devqa to junit run configuration class path using add projects widget. It may work.
I have environment variables in my application.properties like this spring.mail.username=${username}
The ${username} is declare in eclipse environment variable. When I build maven package and install, then deploy it to tcServer. The TC Server does not know ${username}. Another word, the environment variables do not include in the war file during build.
How do I get the environment variable in eclipse to include in war file for deployment?
Using Maven filtering as described in alexbt's answer, is the right approach for including values defined elsewhere. His example touches on including an operating system environment variable. You can extend this to Maven properties also. For example,
<project ...>
<properties>
<spring.mailuser>bob#mycompany.com</spring.mailuser>
</properties>
...
<build>
...
</build>
</project>
defines a Maven properties whose value is retrieved by ${spring.mailuser} and can be used as part
of other Maven configurations or injected as content via Maven filtering. Given this, changing
applicable.properties as follows
spring.mail.username=${spring.mailuser}
will inject the value of the property at build time.
If you wish to have a build-time variable replaced, I would suggest you to use maven filtering:
Have an environment variable (not an eclipse one):
export username=user3184890
Then, in your pom.xml, activate maven filtering on resources (assuming your application.properties is in src/main/resources:
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
Also, change your application.properties to this:
spring.mail.username=${env.username}
or
spring.mail.username=#env.username#
According to the Spring boot documentation, it's possible to define additional command when using a remote shell based on Crash.
Default locations for these commands are classpath*:/commands/,classpath*:/crash/commands/
A property can be used to override the default locations but in the provided example, the custom command is located in resources.
In my opinion, custom commands (at least java commands) shouldn't be located in resources but in src/main/java.
It works fine when defining a custom path in resources but how can I define a custom path in src/main/java? Didn't find a way to do it for now!
If they're under src/main/java, they'll be compiled automatically which is not what you need. My solution was to simulate that directory as a resources folder, which in short translates to:
configure the compiler plugin to ignore that particular folder
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<excludes>
<exclude>crash/commands/*</exclude>
</excludes>
</configuration>
</plugin>
copy the files just like any regular resources in the target directory
<resource>
<directory>src/main/java/crash/commands</directory>
<targetPath>crash/commands</targetPath>
<filtering>false</filtering>
</resource>
Minor update & disclaimer:
As you may already know, there are a couple of closures which are executed on login/logout. At least with v1.3.1, which is what I'm blindly inheriting from spring-boot, it will pick the first login.groovy it finds in the classpath. My project's artifact is packaged in an RPM along with all the other dependencies. Since its name begins with r, it comes after crash.shell-1.3.1.jar which is where the defaults reside, so I had to do the following small hack to make it pick up my own scripts instead of the default ones:
<!-- hack to make CRaSH pick up login.groovy from our jar instead of the default one -->
<finalName>0_${project.artifactId}-${project.version}</finalName>
You can try to put your command at src/main/resources/commands/