Passing an enviornment variable to executed process in Maven - java

I've been banging my head against a wall for about an hour on this: I'm trying to pass a simple property (java.library.path) to exec-maven-plugin. The goal is to have it integrate with Netbeans Right Click file > Run File procedure.
So I set my POM like this:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1.1</version>
<configuration>
<environmentVariables>
<java.library.path>native/win32-x86</java.library.path>
</environmentVariables>
</configuration>
</plugin>
</plugins>
</build>
(I use an old version so I can see the execution args, but its fully reproducible with 1.2)
Then I right click my file and click "Run File". Netbeans starts this process:
W:\programming\apache-maven-2.2.1\bin\mvn.bat -Dexec.classpathScope=runtime -Dexec.args=-classpath %classpath org.quackedcube.camera.CameraDemo -Dexec.executable=C:\Program Files\Java\jdk1.6.0_21\bin\java.exe -Dnetbeans.execution=true -Dmaven.repo.local=W:\programming\maven-repo process-classes exec:exec
(The original full classpath execution was changed to exec:exec so hopefully my configuration applied)
But my environment variable is apparently ignored, as the resulting executed program is:
Result of cmd.exe /X /C ""C:\Program Files\Java\jdk1.6.0_21\bin\java.exe" -classpath *snip* org.quackedcube.camera.CameraDemo" execution is: '1'.
I've tried
Using separate Key and Value tags inside an enviornmentVariable tag
Use a key and value tag directly inside an enviornmentVariables tag (worth a try)
binding to a phase
passing as a maven arg and using exec:java instead
Passing -Djava.library.path=native/win32-x86 as a Run argument and VM option in Project Configuration page
and all have failed. I'm really at a loss here.
I guess this is the disadvantage of using JNI in maven: You have to pass as an argument to your tests, your runtime, your module run POM, and your parent POM.
So my question: How can I pass a java.library.path property to an executed file? It would be nice if it integrated with Netbeans Run File functionality (therefor I don't have to change the class name in a POM, build, then run)

Didn't know this, but apparently when doing this you need to put this property first. I didn't think it was necessary since the classpath isn't immediately executed, but apparently it does make a difference.
To fix it, I simply changed this in Project Properties > Actions > Run File via Main
exec.classpathScope=${classPathScope}
exec.args=-Djava.library.path="native/win32-x86" -classpath %classpath ${packageClassName}
exec.executable=java
The reason you can't specifcy it in the POM is that NB passes the classpath and what its execution via command line exec.args, which overrides whats in your POM.
While this might be ugly and platform dependant, its what happens when you mix JNI and Maven. There isn't really another way that I can see.

Not sure if you tried this but as long as you need to set property on a level of JVM it should be done with -Djava.library.path=/some/path
So in order to specify it for exec-maven-plugin you could write something like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<configuration>
<executable>java</executable>
<arguments>
<argument>-Djava.library.path=${java.library.path}</argument>
</arguments>
</configuration>
</plugin>
You need, of course, to update the executable and maybe add another attributes.

Related

How do I reference my lambda from code in AWS Cloud Development Kit?

import software.amazon.awscdk.services.lambda.Function;
Function helloLambda = new Function(helloStack, "hellocdkworld123", FunctionProps.builder()
.functionName("HelloLambda")
.code(Code.fromAsset("target/cdkhello-0.1.jar")) // <- x ?
.runtime(Runtime.JAVA_8)
.handler("com.myorg.functions.HelloLambda::sayHello") <- y?
.build());
There is also a possibility to reference it by S3 bucket. But when I run cdk bootstrap I get a generated bucket with generated name of the jar file. How should I be able to reference that before hand from code? Of course now I could write the exact bucket + file but then purpose of defining it from code is lost right?
First of all, assuming that the method that you want to execute when the Lambda is invoked is sayHello, from the com.myorg.functions.HelloLambda class, then that part of your solution is correct. The more difficult part is actually accessing the JAR with your Lambda code in it.
NOTE: I've updated my original answer with what I think is a better way to accomplish this. In order to avoid confusion and making this answer too wordy, I've removed the original answer, though much of it is common with this one. I credit this answer for helping to improve this answer.
Pass the path to the dependent resource's JAR to CDK
TL;DR
Create a new property for the full path to your Lambda JAR.
Associate dependency and execution related goals into the package phase of the build.
Update cdk.json to point to the the package phase.
Pass the full path via a system property to your CDK code.
Use the System property to pass to Code.asset(...).
Preparation
I've separated out the Lambda and the CDK infrastructure code into separate Maven modules. The intention being that once the Lambda code is compiled, packaged up into an uber JAR (its code plus all of its dependencies' code), the infrastructure module can refer to it as a dependency, passing the full path to the Lambda JAR to the App/Stack class to that it can use it as an asset.
Create a new property for the full path to your Lambda JAR.
In the properties section of your pom.xml, create a new property to refer to your Lambda JAR. Something like this:
<properties>
...
<lambda.jar>${GROUP_ID:ARTIFACT_ID:jar}</lambda.jar>
...
</properties>
Populate a property with the full path to your Lambda dependency's JAR, using the dependency plugin.
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<goals>
<goal>properties</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
...
<plugins>
</build>
This associates the properties goal with the process-resources phase. Whenever that phase of the build occurs, the property you've created previously will be populated with the full path to the JAR in your local repository.
Associate dependency and execution related goals into a single phase of the build.
When you create a new CDK Java project, it outputs a file called cdk.json, which points by default to the Maven exec:java goal. In order for your new lambda.jar property to be populated correctly, you need to associate the exec:java goal with the same phase as above.
<build>
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<mainClass>com.myorg.TestingApp</mainClass>
</configuration>
</plugin>
...
</plugins>
</build>
In order for your code to get access to the JAR file that you've generated, you need to create a System property (I couldn't get environment variables to work) to your App class. Your pom.xml started with something like this:
Pass the full path via a system property to your CDK code.
In the configuration section (after mainClass), add a system property for your assets directory, something like this:
<systemProperties>
<systemProperty>
<key>lambda.jar</key>
<value>${lambda.jar}</value>
</systemProperty>
</systemProperties>
Update cdk.json to point to the the common phase you've used.
Your cdk.json of your CDK project should be changed to point to the process-resources phase. Once done it will look like this:
{
"app": "mvn package"
}
It will cause both the goals to be run in succession, and upon execution the path to your Lambda's JAR will be passed as a system property.
Access the property from your App/Stack code.
Finally, now that the system property is created, you can access it from your code by calling System.getProperty("lambda.jar"). Something like this:
final Code code = Code.fromAsset(System.getProperty("lambda.jar"));
You can then use the code reference wherever needed when defining your Lambda functions.

How to create .bat files using Maven Appassembler that runs a JAR?

I'm trying to create a .bat file to run my generated executable JAR file. I found this method of creating .bat files for running a project. So, I read up on the plugin here and added the following to my pom.xml.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>assemble</goal>
</goals>
</execution>
</executions>
<configuration>
<assembleDirectory>${assembleDir}</assembleDirectory>
<generateRepository>false</generateRepository>
<repositoryName>lib</repositoryName>
<configurationDirectory>conf</configurationDirectory>
<copyConfigurationDirectory>false</copyConfigurationDirectory>
<programs>
<program>
<mainClass>com.companyname.tests.TestRunner</mainClass>
<id>AutoConfigTest</id>
</program>
</programs>
</configuration>
</plugin>
And, yes, as the name suggests, this JAR contains JUnit test cases.
I prevented the plugin from unpacking JARs and creating the repo folder and set that to my already generated lib folder, which contains all the JARs(executables and the dependencies). The .bat file is being generated but, when running it, I'm getting the following error.
Error: Could not find or load main class com.companyname.tests.TestRunner
Also, I want the command prompt to stay after execution. In this case it is closing immediately. Maybe its because I'm getting an error. I'm not sure.
So, got into searching again and found this. But as the accepted answer suggests, my pom.xml already contains -
<packaging>jar</packaging>
The assembled directory is -
AutoConfigTest
|
|--bin
| `- contains the .bat file
|--conf
| `- contains the property files and other configuration files
|--lib
`- contains all the JARs
What am I doing wrong here?
Maybe it's related to (from the README.md)
All dependencies and the artifact of the project itself are placed in a generated Maven repository in a defined assemble directory. All artifacts (dependencies + the artifact from the project) are added to the classpath in the generated bin scripts.
In your pom.xml you prevent the generation of that repository. So you need to ensure that the artifact from the project is copied at the expected place.
Assuming following project settings
<groupId>com.companyname</groupId>
<artifactId>Maven-AppAssembler</artifactId>
<version>0.0.1-SNAPSHOT</version>
the artifact is expected to be at (the CLASSPATH setting in the scripts bin/AutoConfigTest)
"$REPO"/com/companyname/Maven-AppAssembler/0.0.1-SNAPSHOT/Maven-AppAssembler-0.0.1-SNAPSHOT.jar
where $REPO resolve to target/appassembler/lib.
I found the issue. #SubOptimal was correct in pointing out that the main class isn't visible to the batch file.
For some reason, the test JAR file (which contains the main class) isn't being added to the classpath variable of the batch file. As a result, whenever I ran the batch file, I was getting the error mentioned in the question.
I went back to the documentation and found this.
Sometimes it happens that you have many dependencies which means having a very long classpath, and becomes too long (in particular on Windows based platforms). This option can help in such situation. If you activate this option, your classpath contains only a classpath wildcard (REPO/*). But be aware that this works only in combination with Java 1.6 and above and with repositoryLayout flat.
So, instead of adding individual JAR files into the path, I added the whole lib directory to the classpath by adding the following to the pom.xml.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.10</version>
...
<configuration>
...
<repositoryLayout>flat</repositoryLayout>
<useWildcardClassPath>true</useWildcardClassPath>
...
</configuration>
...
</plugin>
I could do this because the repository layout of lib was already flat. There were no hierarchies. No other change was required. The batch file now behaves as expected.

Specify pom properties via a properties file?

Due to the way my build system is designed (RTC Build Engine), I would like to provide maven with property values via a properties file, instead of specifying -Dkey=value for every property.
I found a couple of questions on S.O. (How to set build properties from a file in Maven POM? and How to read an external properties file in Maven) that relate precisely to this question, but they are relatively old, and both require custom plugins to work (in alpha state).
I realize that passing parameters to Maven like this is probably not the best solution, but the other option is specifying everything on the command line via -D settings which is not ideal either.
Furthermore, given that this properties file is only really used by the build engine (and not by the individual developer), I don't truly believe it belongs in the pom. But I cannot find any other mechanism that would allow me to specify a plugin to use - settings.xml does not permit specifying plugins.
Is my only choice in this case to use a plugin and specify it in the project pom?
in the pom you can place...
<properties>
<core-version>1234</core-version>
<lib-version>1234</lib-version>
<build-version>9999</lib-version>
<build-date>20150101</build-date>
</properties>
with all the properties you require.
Or you can use...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>dev.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
and the file dev.properties will contain the properties
core-version=1234
lib-version=1234
build-version=9999
build-date=20150101
...
Or... you can inject the properties using a settings.xml file as shown here
You may also find the Maven build number plugin useful... here
The best in such cases is to upgrade to at least Maven 3.2.1 which supports defining such properties on the command line like the following:
mvn -Drevision=1234 -Dchangelist=WhatEver -Dsha1=XXXX clean package
But you can only use the above names.
Excerpt from release notes:
A simple change to prevent Maven from emitting warnings about versions
with property expressions. Allowed property expressions in versions
include ${revision}, ${changelist}, and ${sha1}. These properties can
be set externally, but eventually a mechanism will be created in Maven
where these properties can be injected in a standard way. For example
you may want to glean the current Git revision and inject that value
into ${sha1}. This is by no means a complete solution for continuous
delivery but is a step in the right direction.

When I use the maven-release-plugin to release a branch, why does it try to create the branch from revision 0?

I'm using the maven-release-plugin. I'm trying to release a branch and it's failing when it tries to execute this command:
cmd.exe /X /C "svn --non-interactive copy --file C:\Users\USER~1\AppData\Local\Temp\maven-scm-711744598.commit --parents --revision 0 https://domain/svn/app/branches/2.4.8.x https://domain/svn/app/tags/App-2.4.8.1"
It gives this error:
svn: E195012: Unable to find repository location for 'https://domain/svn/app/branches/2.4.8.x' in revision 0
I think this is happening in the prepare goal because when it fails it says:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.5:prepare
I asked a svn expert about this, and he said:
wait, why is it trying to copy something from r0? By definition there is nothing in r0. r0 is always an empty repository, the first objects are added in r1. That's why it fails. the question is why maven tried it. If you supply a revision argument to 'svn copy' then the branch / tag you create is based on the source from the revision you specify so the source has to exist in that revision (if you don't specify, you get HEAD, i.e., the newest revision) ...and as for that, I know nothing about maven or its plugins
So why is maven trying to copy from revision 0? This is the maven command I ran:
mvn --batch-mode release:prepare release:perform
And my root pom has the maven-release-plugin defined like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5</version>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<developmentVersion>2.4.8.2-SNAPSHOT</developmentVersion>
<releaseVersion>2.4.8.1</releaseVersion>
<branchBase>https://domain/svn/app/branches</branchBase>
<tagBase>https://domain/svn/app/tags</tagBase>
</configuration>
</plugin>
Also, my scm tag looks like this:
<scm>
<connection>scm:svn:https://domain/svn/app/branches/2.4.8.x</connection>
</scm>
My svn version is 1.8.5 (r1542147)
Just wanted to add this late answer for if anyone has the same problem and the solution in the comment doesn't work.
We had the same problem in a multi module application, only our parent POM had the SCM tag (which worked perfectly in our other applications). We got the same error but could solve it by adding the corresponding SCM tag to each child POM. We never found out why this was...
As I said as a comment above:
I cleaned up EVERYTHING and ran just release:prepare by itself and it succeeded without issue. Perhaps this is a bug where running release:prepare and release:perform together will cause this
I have not run into this issue since running these commands separately.
I also had this problem. In the affected project I had a custom search and replace of some files during the validate phase and I wanted to check in the changes to Svn before tagging so I added a custom check-in action like this:
<plugin>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<preparationGoals>clean verify scm:checkin -Dmessage="perform release"</preparationGoals>
</configuration>
</plugin>
This had the consequences that when the release plugin tried to check in the changes in the pom file, there were no changes since they were already committed by the custom action. Thus causing this error.
I added a "includes" file list to my custom scm:checkin which only included the files that I had been tampering with and this fixed the problem for me.
The resulting configuration looked like this:
<plugin>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<preparationGoals>clean verify scm:checkin -Dmessage="perform release" -Dincludes="TwogWebUtilsGrailsPlugin.groovy,plugin.xml" -DconnectionType="connection"</preparationGoals>
</configuration>
</plugin>
The reason for my custom replace action is because the project is a Grails plugin and I was following the guidelines in this blog post.
LATE EDIT: After upgrading to maven 3.2, this solution seems to break. I am back to where I started.

How can I pass Hudson's env.EXECUTOR_NUMBER to log4j properties and Java's System.getProperty

My Hudson job calls a single XML database collection and a single log file. E.g.
/db/project
${user.home}/logs/logging.log
I'd like to inject Hudson's env.EXECUTOR_NUMBER in both paths to avoid concurrent execution clashes. E.g.
/db/project {$EXECUTOR_NUMBER}
{$user.home}/logs {$EXECUTOR_NUMBER}/logging.log
I've found out the following:
Hudson site states that I need to pass Hudson's EXECUTOR_NUMBER to Maven as part of the build goal.
Log4J can only use system variables not environment variables (as these are a platform specific concept)
Now that I've got Hudson's EXECUTOR_NUMBER variable specified in the build goal, how can I use this as a system property for use by Log4J and Java's System.getProperties() class?
You can pass System Properties to any Java process using the -D syntax.
mvn clean install -DEXECUTOR_NUMBER={$EXECUTOR_NUMBER}
For a test class in a forked run, you will additionally have to configure the surefire plugin to pass the system property to the forked vm:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
<configuration>
<systemPropertyVariables>
<EXECUTOR_NUMBER>${EXECUTOR_NUMBER}</EXECUTOR_NUMBER>
</systemPropertyVariables>
</configuration>
</plugin>

Categories

Resources