Now that maven-3 did drop support for the <uniqueVersion>false</uniqueVersion> for snapshot artefacts it seems that you really need to use timestamped SNAPSHOTS. Especially m2eclipse, which does use maven 3 internally seems to be affected with it, update-snapshots does not work when the SNAPSHOTS are not unique.
It seemed best practice before to set all snapshots to uniqueVersion=false
Now, it seems no big problem to switch to the timestamped version, after all they are managed by a central nexus repository, which is able to delete old snapshots in regular intervalls.
The problem are the local developer workstations. Their local repository quickly does grow very large with unique snapshots.
How to deal with this problem ?
Right now i see the folowing possible solutions:
Ask the developers to purge the repository in regular intervals (which leads to lots of fustration, as it takes long time to delete and even longer to download everything needed)
Set up some script which does delete all SNAPSHOT directories from the local repository and ask developers to run that script from time to time (better than the first, but still takes quite some time to run and download current snapshots)
use the dependency:purge-local-repository plugin (Does have problems when run from eclipse, due to open files, needs to be run from each project)
set up nexus on every workstation and set up a job to clean old snapshots (best result, but I don't want to maintain 50+ nexus servers, plus memory is always tight on developer workstations)
stop using SNAPSHOTS at all
What is the best way to keep your local repository from filling up your hard drive space ?
Update:
To verify the beaviour and to give more info i setup a small nexus server, build two projects (a and b) and try:
a:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.glauche</groupId>
<artifactId>a</artifactId>
<version>0.0.1-SNAPSHOT</version>
<distributionManagement>
<snapshotRepository>
<id>nexus</id>
<name>nexus</name>
<url>http://server:8081/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
</project>
b:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.glauche</groupId>
<artifactId>b</artifactId>
<version>0.0.1-SNAPSHOT</version>
<distributionManagement>
<snapshotRepository>
<id>nexus</id>
<name>nexus</name>
<url>http://server:8081/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
<repositories>
<repository>
<id>nexus</id>
<name>nexus</name>
<snapshots>
<enabled>true</enabled>
</snapshots>
<url>http://server:8081/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>de.glauche</groupId>
<artifactId>a</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
Now, when i use maven and run "deploy" on "a", i'll have
a-0.0.1-SNAPSHOT.jar
a-0.0.1-20101204.150527-6.jar
a-0.0.1-SNAPSHOT.pom
a-0.0.1-20101204.150527-6.pom
in the local repository. With a new timestamp version each time i run the deploy target. The same happens when i try to update Snapshots from the nexus server (close "a" Project, delete it from local repository, build "b")
In an environment where lots of snapshots get build (think hudson server ...), the local reposioty fills up with old versions fast
Update 2:
To test how and why this is failing i did some more tests. Each test is run against clean everything (de/glauche gets delete from both machines and nexus)
mvn deploy with maven 2.2.1 :
local repository on machine A does contain snapshot.jar + snapshot-timestamp.jar
BUT: only one timestamped jar in nexus, metadata reads:
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>de.glauche</groupId>
<artifactId>a</artifactId>
<version>0.0.1-SNAPSHOT</version>
<versioning>
<snapshot>
<timestamp>20101206.200039</timestamp>
<buildNumber>1</buildNumber>
</snapshot>
<lastUpdated>20101206200039</lastUpdated>
</versioning>
</metadata>
run update dependencies (on machine B) in m2eclipse (embedded m3 final) -> local repository has snapshot.jar + snapshot-timestamp.jar :(
run package goal with external maven 2.2.1 -> local repository has snapshot.jar + snapshot-timestamp.jar :(
Ok, next try with maven 3.0.1 (after removing all traces of project a)
local repository on machine A looks better, only one one non-timestamped jar
only one timestamped jar in nexus, metadata reads:
de.glauche
a
0.0.1-SNAPSHOT
<snapshot>
<timestamp>20101206.201808</timestamp>
<buildNumber>3</buildNumber>
</snapshot>
<lastUpdated>20101206201808</lastUpdated>
<snapshotVersions>
<snapshotVersion>
<extension>jar</extension>
<value>0.0.1-20101206.201808-3</value>
<updated>20101206201808</updated>
</snapshotVersion>
<snapshotVersion>
<extension>pom</extension>
<value>0.0.1-20101206.201808-3</value>
<updated>20101206201808</updated>
</snapshotVersion>
</snapshotVersions>
run update dependencies (on machine B) in m2eclipse (embedded m3 final) -> local repository has snapshot.jar + snapshot-timestamp.jar :(
run package goal with external maven 2.2.1 -> local repository has snapshot.jar + snapshot-timestamp.jar :(
So, to recap: The "deploy" goal in maven3 works better than in 2.2.1, the local repository on the creating machine looks fine.
But, the receiver always ends up with lots of timestamed versions ...
What am i doing wrong ?
Update 3
I also did test various other configurations, first replace nexus with artifactory -> same behaviour. Then use linux maven 3 clients to download the snapshots from the repository manager -> local repository still has timestamped snapshots :(
The <uniqueVersion> configuration applied to artifacts that were deployed (via mvn deploy) to a Maven repository such as Nexus.
To remove these from Nexus, you can easily create an automated job to purge the SNAPSHOT repository every day. It can be configured to retain a certain number of shapshots or keep them for a certain period of time. Its super easy and works great.
Artifacts in the local repository on a developer machine get there from the "install" goal and do not use these timestamps...they just keep replacing the one and only SNAPSHOT version unless you are also incrementing the revision number (e.g. 1.0.0-SNAPSHOT to 1.0.1-SNAPSHOT).
This plugin removes project's artifacts from local repository. Useful to keep only one copy of large local snapshot.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>remove-old-artifacts</id>
<phase>package</phase>
<goals>
<goal>remove-project-artifact</goal>
</goals>
<configuration>
<removeAll>true</removeAll><!-- When true, remove all built artifacts including all versions. When false, remove all built artifacts of this project version -->
</configuration>
</execution>
</executions>
</plugin>
Well I didn't like any of proposed solutions. Deleting maven cache often significantly increases network traffic and slows down build process. build-helper-maven-plugin helps only with one artifact, I wanted solution that can purge all outdated timestamped snapshot artifacts from local cache in one simple command. After few days of searching, I gave up and decided to write small program. The final program seems to be working quite well in our environment. So I decided to share it with others who may need such tool. Sources can be pulled from github: https://github.com/nadestin/tools/tree/master/MavenCacheCleanup
As far as the remote repository piece of this, I think the previous answers that discuss a purging of SNAPSHOTs on a regular interval will work. But no one has addressed the local-developer workstation synchronization part of your question.
We have not started using Maven3 yet, so we've yet to see SNAPSHOTs starting to build up on local machines.
But we have had different problems with m2eclipse. When we have "Workspace Resolution" enabled and the project exists within our workspace, source updates usually keep us on the bleeding edge. But we've found it's very difficult to get m2eclipse to update itself with recently published artifacts in Nexus. We're experiencing similar problems within our team and it's particularly problematic because we have a very large project graph... there are a lot of dependencies that won't be in your workspace but will be getting SNAPSHOTs published frequently.
I'm pretty sure this boils back to an issue in m2eclipse where it doesn't handle SNAPSHOTs exactly as it should. You can see in the Maven console within eclipse where m2eclipse tells you it's skipping the update of a recently published SNAPSHOT because it's got a cached version. If you do a -U from a run configuration or from the command line, Maven will pick up the metadata change. But an "Update Snapshots..." selection should tell m2eclipse to have Maven expire this cache. It doesn't appear to be getting passed along. There appears to be a bug out there that is filed for this if you're interested in voting for it:
https://issues.sonatype.org/browse/MNGECLIPSE-2608
You made mention of this in a comment somewhere.
The best workaround for this problem seems to be having developers purge their local workstations when things start to break down from within m2eclipse. Similar solution to a different problem... Others have reported problems with Maven 2.2.1 and 3 backing m2eclipse, and I've seen the same.
I would hope if you're using Maven3 you can configure it to only pull the latest SNAPSHOT, and cache that for the amount of time the repository says (or until you expire it by hand). Hopefully then you won't need to have a bunch of SNAPSHOTs sitting in your local repository.
That is unless you're talking about a build server that is manually doing a mvn install on them. As far as how to prevent SNAPSHOTs from building up on an environment like a build server, we've kind of dodged that bullet by having each build use its own workspace and local repository (though, in Maven 2.2.1, certain things such as POMs seem to always come out of the ~/.m2/repository) The extra SNAPSHOTs really only stick around for a single build and then they get dropped (and downloaded again from scratch). So we've seen this approach does end up eating up more space to begin with, but it tends to remain more stable than having everything resolved out of a single repository. This option (on Hudson) is called "Use private Maven repository" and is under the Advanced button of the Build section on project configurations when you've selected to build with Maven. Here is the help description for that option:
Normally, Hudson uses the local Maven
repository as determined by Maven —
the exact process seems to be
undocumented, but it's
~/.m2/repository and can be overridden
by in
~/.m2/settings.xml (see the reference
for more details.) This normally means
that all the jobs that are executed on
the same node shares a single Maven
repository. The upside of this is that
you can save the disk space, but the
downside of this is that sometimes
those builds could interfere with each
other. For example, you might end up
having builds incorrectly succeed,
just because your have all the
dependencies in your local repository,
despite that fact that none of the
repositories in POM might have them.
There are also some reported problems
regarding having concurrent Maven
processes trying to use the same local
repository.
When this option is checked, Hudson
will tell Maven to use
$WORKSPACE/.repository as the local
Maven repository. This means each job
will get its own isolated Maven
repository just for itself. It fixes
the above problems, at the expense of
additional disk space consumption.
When using this option, consider
setting up a Maven artifact manager so
that you don't have to hit remote
Maven repositories too often.
If you'd prefer to activate this mode
in all the Maven jobs executed on
Hudson, refer to the technique
described here.
Hope this helps - if it doesn't address your problem please let me know where I missed.
In groovy, deleting timestamped files like artifact-0.0.1-20101204.150527-6.jar can be very simple:
root = 'path to your repository'
new File(root).eachFileRecurse {
if (it.name.matches(/.*\-\d{8}\.\d{6}\-\d+\.[\w\.]+$/)) {
println 'Deleting ' + it.name
it.delete()
}
}
Install Groovy, save the script into a file and schedule the execution at each week, start, logon, whatever suits you.
Or, you can even wire the execution into maven build, using gmavenplus-plugin. Notice, how is the repository location set by maven into the property settings.localRepository and then binded through configuration into variable repository:
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>execute</goal>
</goals>
</execution>
</executions>
<configuration>
<properties>
<property>
<name>repository</name>
<value>${settings.localRepository}</value>
</property>
</properties>
<scripts>
<script><![CDATA[
new File(repository).eachFileRecurse {
if (it.name.matches(/.*\-\d{8}\.\d{6}\-\d+\.[\w\.]+$/)) {
println 'Deleting snapshot ' + it.getAbsolutePath()
it.delete()
}
}
]]></script>
</scripts>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.3.7</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</plugin>
Add following parameter into your POM file
POM
<configuration>
<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>
</configuration>
https://maven.apache.org/plugins/maven-dependency-plugin/copy-mojo.html
POM example
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
<destFileName>optional-new-name.jar</destFileName>
</artifactItem>
</artifactItems>
**<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>**
<outputDirectory>${project.build.directory}/wars</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Configure in Jenkins:
// copy artifact
copyMavenArtifact(artifact: "commons-collections:commons-collections:3.2.2:jar", outputAbsoluteArtifactFilename: "${pwd()}/target/my-folder/commons-collections.jar")
Related
I have added the most updated Selenium dependency in my pom.xml
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.7.1</version>
</dependency>
I ran
mvn clean install
inside the directory with my pom.xml and I have also imported the correct classes in my app class as per the Selenium documentation
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
However when i try and run my main method, I get the following error
Exception in thread "main" java.lang.NoClassDefFoundError:
org/openqa/selenium/WebDriver
I look in my ~/.m2/repository folder and I don't see an openqa folder but instead I see a seleniumhq folder.
Why didn't maven install the openqa folder, and why does the documentation say to import from org.openqa... when that never exist in my jar repository. I'm very confused, I just want to be able to import selenium Webdriver successfully while having it in my local repository.
Firstly, check properly if you have all important dependencies for your program.
Secondly, I had similar error while running maven project:
Caused by: java.lang.NoClassDefFoundError: org/openqa/selenium/JavascriptExecutor
And this problem was because of inappropriate plugin, because I tested different versions of Selenium and it didn't help me.
So when I changed maven-jar-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>your_main_class</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
to maven-shade-plugin plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>your_main_class</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
The issue was gone.
The difference between plugins you can find here.
In addition, sometimes we upgrade our libraries even with same method name. Due this different in version, we get NoClassDefFoundError or NoSuchMethodError at runtime when one library was not compatible with such an upgrade.
Java build tools and IDEs can also produce dependency reports that tell you which libraries depend on that JAR. Mostly, identifying and upgrading the library that depends on the older JAR resolve the issue.
To summarize:
try to change versions of Selenium, if it contains all dependencies;
try to add necessary dependencies if you don't have it;
try to check folder of maven if it has or not what says specific error;
try to play with plugins if nothing helps above.
NoClassDefFoundError
NoClassDefFoundError in Java occurs when Java Virtual Machine is not able to find a particular class at runtime which was available at compile time. For example, if we have resolved a method call from a class or accessing any static member of a Class and that Class is not available during run-time then JVM will throw NoClassDefFoundError.
The error you are seeing is :
Exception in thread "main" java.lang.NoClassDefFoundError:
org/openqa/selenium/WebDriver
This clearly indicates that Selenium is trying to resolve the particular class at runtime from org/openqa/selenium/WebDriver which is no more available.
As you mentioned of looking into ~/.m2/repository folder, the maven folder structure for Selenium v3.7.1 (on Windows) is as follows :
C:\Users\<user_name>\.m2\repository\org\seleniumhq\selenium\selenium-java\3.7.1
So when you see a seleniumhq folder, it is pretty much expected.
What went wrong :
From all the above mentioned points it's clear that the related Class or Methods were resolved from one source Compile Time which was not available during Run Time.
This situation occurs if there are presence of multiple sources to resolve the Classes and Methods through JDK / Maven / Gradle.
Solution :
Here are a few steps to solve NoClassDefFoundError :
While using a Build Tool e.g. Maven or Gradle, remove all the External JARs from the Java Build Path. Maven or Gradle will download and resolve all the required dependencies.
If using Selenium JARs within a Java Project add only required External JARs within the Java Build Path and remove the unused one.
While using Maven, either use <artifactId>selenium-java</artifactId> or <artifactId>selenium-server</artifactId>. Avoid using both at the same time.
Remove the unwanted other <dependency> from pom.xml
Clean you Project Workspac within your IDE periodically only to build your project with required dependencies.
Use CCleane tool to wipe away the OS chores periodically.
While you execute a Maven Project always do maven clean, maven install and then maven test.
Encountered this error in Eclipse IDE. In Eclipse go to Project properties and in Java Build Path just add selenium jars in Classpath instead of Modulepath. Then under the Project tab on the top do a Clean to remove earlier buiid and then do a Run.
Are you using an IDE or working from command line? In Eclipse for example you can force downloading all dependencies by right clicking on your project, going to Maven menu item and then selecting Update Project. Then check the "Force Update of Snapshots/Releases" checkbox.
If you are opening from command line do:
mvn clean install -U
from your project path.
This is happening because you are selecting jar files under modulepath, you should add them under class path.
org.openqa.selenium is the package in the selenium-api-{version}.jar under the seleniumhq\selenium\selenium-api folder.
org.openqa.selenium.firefox is the package in the selenium-firefox-driver-{version}.jar under the seleniumhq\selenium\selenium-firefox-driver folder.
So there is no openqa folder, it's just the package name under the seleniumhq folder, you should have a check into these jar.
It's hard to say what caused NoClassDefFoundError exception without project structure and code detail. The exception is not the same as ClassNotFoundException. Maybe this answer https://stackoverflow.com/a/5756989/5374508 would be helpful.
What worked for me was to add this dependency to pom.xml:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>25.0-jre</version>
</dependency>
I was getting below error from past 2 days and what helped me was to remove all the selenium extra dependencies like selenium-support, selenium-chrome-driver etc and only keeping the below dependencies in POM file.
Error:-
java.lang.NoClassDefFoundError: org/openqa/selenium/HasAuthentication
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
Dependencies in the pom file after removing all other:-
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.4.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Have encountered this issue while running selenium test in eclipse IDE.
Navigate to following path:
1.Properties >> Java build path >> Libraries.
2.Add all selenium jars in Classpath instead of Modulepath.
3.Apply and close modal.
4.Now go to build path and click on "Configure Build Path".
5.Now run the selenium test.
I am trying to build a JAR library that can invoke R code.
I basically want this jar to be capable enough to be able to run on any machine that has support for running jar executables(No need of seperate R software).
For this I am using Maven. I am able to compile and create a jar without any errors. However, when I run it, I am unable to yield successful results.
This is my java code
package com.company.analytics.timeseries;
import org.rosuda.JRI.REXP;
import org.rosuda.JRI.Rengine;
public class App {
public static void main(String[] args) {
System.out.println("Creating Rengine (with arguments)");
String[] Rargs = { "--vanilla" };
Rengine re = new Rengine(Rargs, false, null);
System.out.println("Rengine created, waiting for R");
if (!re.waitForR()) {
System.out.println("Cannot load R");
return;
}
System.out.println("Done.");
}
}
This is my pom.xml file
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company.analytics</groupId>
<artifactId>timeseries</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>timeseries</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.nuiton.thirdparty</groupId>
<artifactId>JRI</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.rosuda.REngine</groupId>
<artifactId>REngine</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>central</id>
<name>Maven Central</name>
<url>http://repo1.maven.org/maven2</url>
</repository>
</repositories>
</project>
I used mvn clean and then mvn package to create the jar file.
A JAR file of 4KB is created in C:\MVN\project\analytics\timeseries\target. Thern, from the command line on Windows, when I run execute this jar file, I get the following error
C:\MVN\project\analytics\timeseries\target\classes>java com.company.analytics.timeseries.App
Creating Rengine (with arguments)
Exception in thread "main" java.lang.NoClassDefFoundError: org/rosuda/JRI/Rengine
at com.company.analytics.timeseries.App.main(App.java:10)
Caused by: java.lang.ClassNotFoundException: org.rosuda.JRI.Rengine
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
I am trying to figure out what mistake am I committing. I tried to find answers by googling, but I couldn't fix it.
Since I've been smashing my head against this for a day now and I'll likely forget in the future and reference this page - per what Gergely Basco's suggests in an above comment, strictly speaking both R and rJava need to be installed on the machine in order to resolve the Cannot find JRI native library! issue when instantiating your org.rosuda.REngine.REngine object, and this cannot be done exclusively by way of adding the JRIEngine dependency in your pom.xml (bummer).
Steps (for how I'm doing it anyway for my later image):
Install Brew (I just happen to be using Brew for other dependencies)
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Install R using brew:
brew tap homebrew/science
brew install R
Install rJava with R (takes a bit of compile time, grab a coffee)
install.packages("rJava")
add rJava/jri to java.library.path classpath, add R_HOME to environment variables (where you installed R - in my case, where Brew installed it). Note that if you're trying to run this in your IDE(I'm running IDEA16), it won't inherit the path you set in ~/.bash_profile, you need to set it in your run configuration.
-Djava.library.path="/usr/local/lib/R/3.3/site-library/rJava/jri/
R_HOME=/usr/local/Cellar/r/3.3.1_2/R.framework/Resources
Ensure maven has dependency for JRIEngine in pom.xml
<dependency>
<groupId>com.github.lucarosellini.rJava</groupId>
<artifactId>JRIEngine</artifactId>
<version>0.9-7</version>
</dependency>
Instantiate REngine (I need this version in order to pass dataframe to R from java)
String[] Args = {"--vanilla"};
REngine engine = REngine.engineForClass("org.rosuda.REngine.JRI.JRIEngine", Args, new REngineStdOutput (), false);
What you should end up with looks something like this at runtime, if you instantiate with the callback argument (new REngineStdOutput () ); otherwise if you just instantiate with the String engineForClass("org.rosuda.REngine.JRI.JRIEngine"), you'll wont get the below output from R on startup/elsewise, depending on if you want it or not:
/**R version 3.3.1 (2016-06-21) -- "Bug in Your Hair"
Copyright (C) 2016 The R Foundation for Statistical Computing
Platform: x86_64-apple-darwin15.5.0 (64-bit)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.
Natural language support but running in an English locale
R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.
Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.**/
Hope this helps someone in the future and saves them from the pain.
You need to build a jar with all your dependencies included. (aka fat jar) Since you are already using Maven, the only thing you need to do is to instruct Maven to include the dependencies by adding this plugin to your pom.xml file:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
You are missing the classpath argument. Your jar file contains your compiled code without any 3rd party jars. When you want to run it, you should add -cp and point to all your 3rd party jars.
You can also build a single jar with all dependencies using Maven's assembly plugin.
I've been toying around with the latest changes in the gwt-maven-plugin. Most notably, the new packagings gwt-app and gwt-lib.
To my understanding, if I have some code that I'd like to reuse between different GWT apps, gwt-lib packages all needed sources and *.gwt.xml files in the jar right next to all classes. It works like a charm.
If I opt for a multi-module maven reactor build, everything is detected on compile time and I'm able to build and deploy successfully without any hassle. If I try to develop however, the shiny GWT 2.7 SuperDevMode is unable to detect changes in the gwt-lib projects, obviously because they are referenced from the jars and not the actual sources directory where they were changed.
To illustrate, I used the modular-requestfactory archetype by Thomas Broyer.
mvn archetype:generate \
-DarchetypeCatalog=https://oss.sonatype.org/content/repositories/snapshots/ \
-DarchetypeGroupId=net.ltgt.gwt.archetypes \
-DarchetypeArtifactId=modular-requestfactorcom.testy \
-DarchetypeVersion=1.0-SNAPSHOT
and I entered the following information:
Define value for property 'artifactId': : mvngwt
Define value for property 'version': 1.0-SNAPSHOT: :
Define value for property 'package': com.test: :
Define value for property 'module': App: : MvngwtApp
Define value for property 'module-short-name': mvngwtapp: :
Afterwards I created an additional maven module called "mvn-gwt-client-api", which contains a single class that is to be used by the mvn-gwt-client. The end structure looks like this:
mvngwt/
--mvngwt-client/
--mvngwt-client-api/
--mvngwt-server/
--mvngwt-shared/
--pom.xml
The goal is to be able to edit the files in mvngwt-client-api (e. g. the only class currently: MvngwtApi.java), then recompile in SuperDevMode and actually see the changes immediately without restarting the CodeServer.
A working copy of the project can be found here: https://github.com/elnicko/maven-gwt-test
PS: I tried to work it out with the build-helper-maven-plugin:
<profiles>
<profile>
<!-- elnicko: add to support CodeServer hot compile for referenced libraries -->
<id>env-dev</id>
<activation>
<property>
<name>env</name>
<value>dev</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-shared-sources-to-classpath</id>
<!--
<phase>process-classes</phase>
<phase>compile</phase>
-->
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/../mvngwt-client-api/src/main/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
However it didn't improve the situation.
Any hints/pointers/ideas greatly appreciated.
Edit:
I am able to use the SuperDevMode incremental compilation by using the aforementioned build-helper-maven-plugin configuration, changing the mvngwt-client-api packaging from "gwt-lib" to "jar", and adding a "maven-source-plugin". That way maven compilation and deployment work the same way, but the CodeServer is made aware of the changes in the source directory of mvngwt-client-api. Nevertheless, the question remains open, how one can use the new "gwt-lib" without losing the CodeServer incremental compilation. The diff may be seen here: https://github.com/elnicko/maven-gwt-test/compare/master...working_wihtout_gwt-lib_but_with_jar_packaging
You have to use <type>gwt-lib</type> in your dependency.
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mvngwt-client-api</artifactId>
<version>${project.version}</version>
<type>gwt-lib</type>
</dependency>
Actually, if you run Maven with -X you'll see in the logs:
[DEBUG] Adding sources for com.test:mvngwt-client:gwt-app:1.0-SNAPSHOT
[DEBUG] Ignoring com.test:mvngwt-shared:jar:1.0-SNAPSHOT; neither a java-source, gwt-lib or jar:sources.
[DEBUG] Adding sources for com.test:mvngwt-shared:jar:1.0-SNAPSHOT
[DEBUG] Ignoring com.test:mvngwt-client-api:jar:1.0-SNAPSHOT; neither a java-source, gwt-lib or jar:sources.
[DEBUG] Ignoring com.google.gwt:gwt-user:jar:2.7.0; neither a java-source, gwt-lib or jar:sources.
[DEBUG] Ignoring com.google.gwt:gwt-dev:jar:2.7.0; neither a java-source, gwt-lib or jar:sources.
[DEBUG] Ignoring com.google.gwt:gwt-codeserver:jar:2.7.0; neither a java-source, gwt-lib or jar:sources.
Maybe those should be emitted at INFO level rather than DEBUG…
BTW, instead of the build-helper-maven-plugin, you could have just used a <type>java-source</type> or <classifier>sources</classifier> dependency, like it's done for the mvngwt-shared module.
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
Given the very poor documentation about scp/ssh and maven I tried different approaches, basically falling in two main categories: using scpexe wagon and scp wagon. Usually they both work without issue on both linux and mac, but on windows I never found a way to make it work on all machines.
scpexe approach (after installing complete putty and adding to path) - settings.xml configuration:
<server>
<id>internal</id>
<username>******</username>
<password>*******</password>
<configuration>
<sshExecutable>plink</sshExecutable>
<scpExecutable>pscp</scpExecutable>
</configuration>
</server>
scp approach - settings.xml :
<server>
<id>internal</id>
<username>*********</username>
<password>*********</password>
<configuration>
<StrictHostKeyChecking>ask</StrictHostKeyChecking>
</configuration>
</server>
I also tried putting StrictHostKeyChecking to "no", but, security risks aside, did not work on a particular machine.
Has someone found a way to use an internal ssh repository consistently on all machines?
There are three potential approaches to deploy Maven artifacts via SSH/SCP:
wagon-ssh (deprecated)
wagon-ssh-external (platform-specific concerns)
A wagon-ssh rewrite built on Apache Mina SSHD (does not actually exist yet as of this writing)
1. wagon-ssh
The Maven SSH wagon uses JSch, the pure-Java implementation of SSH, which works regardless of OS. (Perhaps that was not the case when this question was originally posted, but it is true now.)
Here is a sample configuration which I successfully used to deploy over SCP to a Linux box from a Windows 7 system with Maven 3.0.4.
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>hello</groupId>
<artifactId>hello</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Hello</name>
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.3</version>
</extension>
</extensions>
</build>
<distributionManagement>
<repository>
<id>my-ssh-repo</id>
<url>scp://my.server.url/path/to/ssh-repo</url>
</repository>
</distributionManagement>
</project>
settings.xml:
<settings>
<servers>
<server>
<id>my-ssh-repo</id>
<username>myUser</username>
<password>myPass</password>
</server>
</servers>
</settings>
Unfortunately, this wagon is now deprecated for two reasons: it is built on JSch which is not fully open source, and it is difficult to maintain due to complex and low level code needed. See WAGON-616 for details.
2. wagon-ssh-external
The Maven SSH External Wagon calls out to your system SSH/SCP commands. Unfortunately, there are some OS-specific configuration issues, particularly on Windows, as explained in the Deployment of artifacts in an external SSH command guide, and as highlighted in the question above.
3. wagon-ssh rewrite using Apache Mina SSHD
A viable hope for a pure-Java SSH/SCP wagon would be to rework the wagon-ssh implementation to use Apache Mina SSHD instead of JSch. Unfortunately, no one has actually done this yet, but the maintainer of wagon-ssh has indicated that it could be un-deprecated should anyone in the community step forward to tackle the project.