I'm working on a project which involves maven, java and clojure. The problem I'm facing is this, I have some UTF-8 chars in my clojure source files because of which my source code is not interpreted correctly by the java compiler, I kinda got it working by setting the environment variable JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8, but what I want is to pass this property through MAVEN.
I have already tried setting MAVEN_OPTS=-Dfile.encoding but this doesn't seem to work.
I have also tried setting configuration for the compiler plugin of maven... something like this:
<configuration>
<compilerArgument>-Dfile.encoding=UTF8</compilerArgument>
</configuration>
This doesn't work either.
I'm I doing something wrong, or is there another way.
thanks,
RD
Ok, Here's some more detail.
This is my parent pom,
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
<encoding>UTF-8</encoding> <! also tried <encoding>UTF8</encoding>
</configuration>
</plugin>
Nothing interesting in the child's pom except...
<resources>
<resource>
<directory>src/main/clojure</directory>
</resource>
</resources>
;; clojure code snippet which causes problems
(let [char "대"]
(not (empty? (filter #(s/contains? % char) <some-list>)))
;; The list is always empty because I never find a match if I do not set the env. variable
Did you try passing compiler options? [-encoding UTF-8]
Update: Based on your comments, this is a runtime, not a compile issue. As a workaround, you could try escaping the character as unicode.
i.e. change the character to '\uXXXX' in the clojure file, where XXXX is the Unicode point in hexadecimal.
If your problem is happening in your unit tests. You can configure the surefire plugin by setting the argLine property. This allows you to set arbitrary JVM options on the command line.
Did you set the parameter through Compiler Plugin like this?
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgument>-Dfile.encoding=UTF8</compilerArgument>
</configuration>
</plugin>
</plugins>
Given the fact that Clojure actually hardcodes the expected encoding of input files to UTF8 (see src/jvm/clojure/lang/Compiler.java, loadFile-method), I'm surprised that using file.encoding does have any effect at all.
Try adding this property to your pom
UTF-8
For me, this code works without problem in cider REPL in Emacs.
;; returns sequence ("대")
(filter #(= % "대") ["대" "한" "민" "국"])
Can you provide code which emits error?
Related
I have a project with complicated build setup (parent POM's with parent POM's) and so it happens that my compiler plugin executes with maven.compiler.release=8.
This prevents me from setting source/target to Java 11 and I can't set release to 11 since I need to specify some --add-exports.
Is there a way to remove a system property in a profile so that it will not appear and my source/target switches would work? The best I could think of is setting maven.compiler.release to empty value but it won't work with compiler plugin.
How do I clear the system property in a profile? Alternatively, is there a way to trace who actually set it in the first place?
I had similar problem. Here is how to delete release property from parent POM and use --add-exports.
Use the combine.self="override" attribute like this
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release combine.self="override"/>
<compilerArgs>
<arg>--add-exports</arg>
<arg>jdk.compiler/com.sun.tools.javac.api=ALL-NNAMED</arg>
</compilerArgs>
...
et, voila!
The project I am working on needs to use Google Protobuf for serialization, therefore a number of stub has to be generated before my code is built.
The command line arguments I use is:
protoc -I=src/proto --java_out=src/main/java src/proto/*.proto
This works fine in the console.
I now wants to use Maven exec plugin so that this manual process becomes part of the Maven build. The pom section I used is:
<build>
<plugins>
<plugin>
<artifactId>exec-maven-plugin</artifactId>
<groupId>org.codehaus.mojo</groupId>
<version>1.3.2</version>
<executions>
<execution>
<id>Google Protobuf Stub Generation</id>
<phase>generate-sources</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>protoc</executable>
<commandlineArgs>-I=src/proto --java_out=src/main/java src/proto/*.proto</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
An error is given to complain there is no file called: src/proto/*.proto
However, it works fine if I remove the wildcard and specify a specific file, e.g.
<commandlineArgs>-I=src/proto --java_out=src/main/java src/proto/model.proto</commandlineArgs>
I think it is the wildcard * that cause the problem as Maven might have a different way to handle it.
My question is that how can I specify "All files with .proto extension in that folder" in Maven?
If you have bash, you can cheat and use 'bash' as your executable, '-c' as the first argument, and your full command as the second argument.
Essentially, the second argument will be ran in the shell, so wildcard(*) characters work and you generally get the same functionality as using the command line directly.
If you are calling the protoc command on a shell, the wildcard-operator is replaced by the shell with all matching files. protoc command itself is not able to handle the wildcard.
For example:
By calling "ls *.txt" on your shell, the ls command is not called with the argument "*.txt". The shell translates the command-call to "ls file1.txt file2.txt ..."
Solution: Create a command out of find xargs and protoc.
I'm on creating a maven based java project, which contains the PMD maven plugin. I use my own rule set XML and it works like a charm, except two rule sets: the emptycode and the unnecessary: when I run the build, maven says: "can't find resource". The role definitions look like:
<role ref="rulesets/emptycode" />
and
<role ref="rulesets/unnecessary" />
In every other cases, this kind of definition works. What I found out is that: there is a rule set with the name "unnecessary" under ecmasrcipt category, so maybe this definition needs some suggestion to use java version. I tried multiple thinks, like set language attribute to the ruleset xml node ("JAVA", based on PMD JavaDoc), and some pre-postfix in ref, but it doesn't work and I found no working solution over the web. Does someone has an idea, what I forgot to set, or what I fail? Thanks for any help!
PMD seems to be a fiddly beastie to use from Maven. I've just figured this out with version 3.0 of the plugin - there are two solutions:
The quick-and-dirty solution: put rulesets in your project:
download the PMD jar (http://sourceforge.net/projects/pmd/files/latest/download)
extract lib/pmd-x.x.x.jar
extract from that PMD jar file the rulesets/<type>/<ruleset>.xml files you want to use
place them in a folder under your project - something like ${basedir}/pmd/...
reference them as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<configuration>
<rulesets>
<ruleset>${basedir}/pmd/<ruleset>.xml</ruleset>
</rulesets>
</configuration>
</plugin>
The advantage is this is easy, the disadvantage is if you update the PMD version in future you'll need to remember to update these files.
The nice solution: reference rulesets in pmd-x.x.x.jar.
create a custom ruleset such as: ${basedir}/pmd/custom.xml (see http://pmd.sourceforge.net/pmd-5.0.2/howtomakearuleset.html)
reference the PMD rulesets in the following way: <rule ref="rulesets/java/imports.xml"/>
NB: the path is the path inside pmd-x.x.x.jar (see quick-and-dirty above) with no leading slash
reference your custom ruleset as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<configuration>
<rulesets>
<ruleset>${basedir}/pmd/custom.xml</ruleset>
</rulesets>
</configuration>
</plugin>
The advantage is this will always reference the current PMD rulesets from the PMD jar, the disadvantage is it's a bit fiddly to get right.
To experiment with this until it was working (maven-pmd-plugin version 3.0) I kept running mvn pmd:pmd (<linkXref>false</linkXref> in pom.xml) and tweaked the paths until I stopped getting errors.
In my unit tests I want to create a tmp directory inside the ${project.build.directory}. How can I access the value of ${project.build.directory} inside my unit test?
One way, which I could think of, is to provide a filtered properties file in the test resources, which holdes that value. (I haven't tried yet, but I think that should work.)
Is there a direct way to access/ pass this property value?
I've used something like this with some success before. The unit test will still run even if not using Maven, the target directory will still get created two dirs up relative to the cwd of wherever the tests are run.
public File targetDir(){
String relPath = getClass().getProtectionDomain().getCodeSource().getLocation().getFile();
File targetDir = new File(relPath+"../../target");
if(!targetDir.exists()) {
targetDir.mkdir();
}
return targetDir;
}
I think using system properties is quite straightforward if you configure the surefire-plugin as explained here http://maven.apache.org/plugins/maven-surefire-plugin/examples/system-properties.html . Even the example there is answering your question directly:
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
<configuration>
<systemPropertyVariables>
<propertyName>propertyValue</propertyName>
<buildDirectory>${project.build.directory}</buildDirectory>
[...]
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
[...]
</project>
Remember, that your unit tests don't have to be executed from Maven surefire plugin, so ${project.build.directory} property might not be available. To make your tests more portable I would rather recommend using File.createTempFile().
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.