I have some legacy Java 6 project and I want to bring some updates on them like Java 8 time library. I found that is possible by using ThreeTen backport. But I don't know how to use it with Ant build tool. Any good references or examples please ?
Overview:
Download the ThreeTen Backport JAR file into the lib folder of your Ant project
Make sure that JAR files in your lib folder are on the classpath for both compilation and running (this may already be the case).
In your Java source files add imports from org.threeten.bp with subpackages and use the imported classes in your code.
Download JAR
On http://www.threeten.org/threetenbp/, at the top select Releases -> Download to get to the Maven repository. In the first search result (currently threetenbp 1.3.6 from 10-Jul-2017), in the Download column click jar. Download the file (in this case threetenbp-1.3.6.jar) to or move it to the lib folder of your Ant project. Or where you’ve got your external JARs. If you haven’t got such a place, create a folder called lib for it.
Fix your classpath
If you haven’t previously got any external dependencies in the form of external JAR files that your program uses, you may need to prepare your build.xml file for these. In my build.xml I added
<property name="lib.dir" value="lib"/>
<path id="classpath">
<fileset dir="${lib.dir}" includes="**/*.jar"/>
</path>
This defines names for the lib folder and the classpath for use later. Note that I specify that all .jar files in the lib folder with subfolders are on the classpath, so in the future you can just drop JARs in to add them to your project. Then I added the classpath both to my compile target and to my run target:
<target name="compile">
<mkdir dir="${classes.dir}"/>
<javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/>
</target>
And
<target name="run" depends="jar">
<java fork="true" classname="${main-class}">
<classpath>
<path refid="classpath"/>
<path location="${jar.dir}/${ant.project.name}.jar"/>
</classpath>
</java>
</target>
We need to fix both targets because the external JAR(s) is/are needed both for compilation and for running.
Use java.time classes in your Java program
Here’s my program. Note that the import statements refer to org.threeten.bp.
package ovv.ant.threetenbp;
import java.util.Date;
import org.threeten.bp.Instant;
import org.threeten.bp.DateTimeUtils;
public class AntAndThreeTenBackportDemo {
public static void main(String... commandLineArguments) {
Instant once = Instant.parse("1939-11-19T16:30:00Z");
Date oldfashionedDateObject = DateTimeUtils.toDate(once);
System.out.println("As Date: " + oldfashionedDateObject);
}
}
When I run from Ant (on my computer in Europe/Copenhagen time zone) I get:
run:
[java] As Date: Sun Nov 19 17:30:00 CET 1939
I used Ant 1.9.7, but I think it’s the same in other versions.
Source and further reading
I used the Ant tutorial here, in particular the Using External Libraries section.
Related
We are trying to get the libphonenumber to run in our java project.
The java project is running as a service on one of our servers.
On our local machines, we are using the following shell commands to include the libraries (please ignore the version numbers):
export ANT_HOME="C:\DEV\apache-ant-1.9.16"
export JAVA_HOME="C:\Program Files\Java\jdk-15.0.2"
export MAVEN_HOME="C:\DEV\apache-maven-3.8.6"
export PATH=${PATH}:${JAVA_HOME}/bin:${ANT_HOME}/bin:${MAVEN_HOME}/bin
export MB_API_HOME="C:\DEV\java-rest-api\api\target"
After we run the "ant" command, we move the result file (jar) on our server in the respective folder.
These are the 3 files that are needed for the library:
We have copied them on the server, in the respective lib folder.
Everything runs fine until the following error shows up:
java.lang.NoClassDefFoundError: com/google/i18n/phonenumbers/PhoneNumberUtil
This happens when it comes to the following line:
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
We have found the following code on this website (https://www.baeldung.com/java-libphonenumber), where it is explained that this has to go to a pom-xml file:
<dependency>
<groupId>com.googlecode.libphonenumber</groupId>
<artifactId>libphonenumber</artifactId>
<version>8.12.10</version>
</dependency>
We have no clue which pom.xml they are writing about. These are the files that are being found by IntelliJ:
IntelliJ has no problems finding the classes and their methods when we type in the code window.
What else do we have to do and consider to get it to run on the server?
Thanks in advance.
Edit 1 of ?: As g00se suggested, we already have the class path mentioned in the build.xml, which looks like this:
I had the idea of removing the libphonenumber.jar from the lib folder on the server itself to see if we receive a different error. But it is still the same NoClassDefFoundError. It is as if the result file of ant has no clue about libphonenumber at all!
Edit 2 of ?:
I have experimented with this library on my private computer.
If I click on the run icon (1), it seems to work, as seen in (2).
However, going to the folder with the Main class (3) and running java Main, leads to the same error:
But then, I just copied the classes into the folder where the Main is, and the error changed:
Here is the snippet in the build.xml of my private project:
<target name="compile" depends="init"
description="compile the source">
<!-- Compile the Java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}">
<classpath>
<pathelement path="jars/libphonenumber.jar"/>
</classpath>
</javac>
</target>
I guess I am missing the right approach here, do I?
Edit 3 of ?: I created a repository of my private/test project.
Here it is: https://github.com/3rc4n/libphonenumberexperiment
I have an Android test project using Espresso that I am attempting to build with Ant. I can build the test application just fine. Install it to the device and everything. The problem is, whenever I try to run the test with
adb shell am instrument -w
com.test.package/com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner
I get this in my command prompt:
INSTRUMENTATION_RESULT: shortMsg=java.lang.ClassNotFoundException
INSTRUMENTATION_RESULT: longMsg=java.lang.ClassNotFoundException: Didn't find class "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner" on path: /system/framework/com.google.android.maps.jar:/system/framework/android.test.runner.jar:/data/app/test.apk:/data/app/myApp.apk
INSTRUMENTATION_CODE: 0
And this in the logcat:
E/AndroidRuntime(27558): java.lang.RuntimeException: Unable to
instantiate instrumentation
ComponentInfo{com.avai.app.test.automate/com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner}:
java.lang.ClassNotFoundException: Didn't find class
"com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
on path:
/system/framework/com.google.android.maps.jar:/system/framework/android.test.runner.jar:/data/app/test.apk:/data/app/myApp.apk
I can run the tests in Eclipse if I check the box next to my Espresso jar under Configure Build Path->Order and Export. I noticed that with this box unchecked I get the exact same error message as above.
What I need to know is how to emulate Eclipse's behavior here with Ant?
Here is a snippet from my build.xml file (mostly generated from Export->Ant build files in Eclipse:
<path id="Android 4.4.2.libraryclasspath">
... (lots of jars) ...
</path>
<path id="AutomationTests.classpath">
... (more jars) ...
</path>
<path id="AutomationTests.classpath">
<pathelement location="bin/classes"/>
<path refid="Android 4.4.2.libraryclasspath"/>
<path refid="Android Private Libraries.libraryclasspath"/>
<path refid="Android Dependencies.libraryclasspath"/>
<pathelement location="../../android-test-kit/bin/espresso-standalone/espresso-1.1-bundled.jar"/>
</path>
<javac encoding="${java.encoding}" source="${java.source}"
target="${java.target}"
debug="true" extdirs="" includeantruntime="false"
destdir="${out.classes.absolute.dir}"
bootclasspathref="project.target.class.path"
classpathref="project.javac.classpath">
...(stuff) ...
</javac>
The error you're seeing is caused by the third-party jar not being packaged inside the APK.
The default behaviour of the android ant build is that only the jars found in application project /libs folder are packaged into the apk.
Copy the espresso-1.1-bundled.jar to the /libs folder of the app project and you'll be fine.
Another thing to consider - you'll be better off generating the build.xml with Android tools as described here: http://developer.android.com/tools/projects/projects-cmdline.html#UpdatingAProject
I can get an ant compile to only rebuild java classes that have changed, but I can't get Gradle to do so.
I have a project with the structure
root
/src/main/java
/pkg1/File1.java
/pkg2/File2.java
/build.gradle
/build.xml (for comparing against ant)
File1 and File2 are not dependent on each other. File1 and File2 contain correct package information
my build.gradle file only has 1 line
apply plugin: 'java'
Ant: When I do a ant compile it creates two .class files File1.class and File2.class. When I change File2.java and recompile only File2 gets rebuilt. This is the behavior I expect?
Gradle: When I do a gradle compileJava it creates two .class files File1.class and File2.class. When I change only File2.java and recompile both File1 and File2 are rebuilt. Why is File1 recompiled here?
Could this be due to a configuration issue? Or is it just not possible with Gradle at the moment? Perhaps it's a bad idea to this in the first place, if so, why?
For completeness the ant file looks something like this :
<property name="src" location="src/main/java/"/>
<property name="build" location="build"/>
<target name="init">
<tstamp/>
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init" description="compile the source " >
<javac srcdir="${src}" destdir="${build}" includeDestClasses="true"/>
</target>
Gradle doesn't support incremental Java compilation at this time. In other words, if any input of the JavaCompile task changes, all sources will be recompiled. I do expect incremental compilation to be supported in a future release. Until then, compile time can be improved by spreading sources over multiple source sets (which effectively means multiple compile tasks) and projects. The former helps to make up-to-date checks more effective, the latter allows for parallel compilation when running with --parallel.
UPDATE: Gradle now supports incremental building since 2015.
I know this is an old post. Still answering for letting people know about this great and wonderful feature.
The incremental task for gradle is in incubation stage.
Please go through:
https://docs.gradle.org/current/userguide/custom_tasks.html#incremental_tasks
http://gradle.org/feature-spotlight-incremental-builds/
https://docs.gradle.org/current/dsl/org.gradle.api.tasks.incremental.IncrementalTaskInputs.html
We got a GWT project in Eclipse, that otherwise works.
Now I want to have a script that runs on the server, which pulls the latest version from source control and compiles it on the server and deploys it.
This will save us a lot of manual work and allow us to deploy new version when on a connection with limited bandwidth (since we won't have to upload the application to the server).
After pulling the latest version of the source code, the script tries to compile the code using the following command:
java -cp "/path/eclipse/plugins/com.google.gwt.eclipse.sdkbundle_2.5.0.v201211121240-rel-r42/gwt-2.5.0/*:/path/company/projects/pull-compile-deploy/X/X/src:/path/company/projects/pull-compile-deploy/X/X/war/WEB-INF/lib/*" com.google.gwt.dev.Compiler nl.company.projects.X
Compiling module nl.company.projects.X
Finding entry point classes
[ERROR] Unable to find type 'nl.company.projects.X.client.XMain'
[ERROR] Hint: Previous compiler errors may have made this type unavailable
[ERROR] Hint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly
All source code is in /path/company/projects/pull-compile-deploy/X/X/src and all used .jars (except for the GWT stuff) are in /path/company/projects/pull-compile-deploy/X/X/war/WEB-INF/lib/. Obviously something goes wrong.
Questions: The file /path/company/projects/pull-compile-deploy/X/X/src/nl/company/projects/X/client/XMain.java does exist and should imho be in the classpath?!
Anyone Any idea what might go wrong here?
Is it maybe possible to see in some log exactly the commands that eclipse executes for compilation? I looked at the build.xml that eclipse can export, but it seems that does not contain a target to compile for production.
something else: apperantly GWT expects the X.gwt.xml to be at /path/company/projects/pull-compile-deploy/X/X/src/nl/company/project/X.gwt.xml, whereas eclipse put it in /path/company/projects/pull-compile-deploy/X/X/src/nl/company/project/X/X.gwt.xml (i.e. nested one directory deeper), I fixed this by creating a symbolic link.
Further Edit:
Since one answer focused on how I invoked the compilation tools, I have rewritten that in Ant, see below.
The problem remains of course.
<!-- Compile the source using javac. -->
<target name="compile" depends="init">
<javac srcdir="src/" destdir="bin/">
<classpath refid="project.classpath"/>
</javac>
</target>
<!-- Use the GWT-compiler. -->
<target name="gwt-compile" depends="compile">
<java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
<classpath>
<path refid="project.classpath"/>
<pathelement location="src/"/>
<pathelement location="bin/"/>
</classpath>
<jvmarg value="-Xmx512M"/>
<arg value="${module.name}"/>
</java>
</target>
Anything wrong with the above Ant-script?
module.name = nl.company.projects.X and the path with refid="project.classpath" contains all used libraries aswell as the GWT libraries (gwt-user.jar, gwt-dev.jar and validation-api-1.0.0.GA(-source).jar).
The XMain class inherits nothing (other than from Object) and only implements EntryPoint (which is included in the gwt-user.jar). So I do not think the problem is related to the second hint that the compiler gives.
Any ideas?
GWT requires you to javac your classes, it needs both the *.java and the *.class files.
This has not always been the case, and should change back in the future (see https://code.google.com/p/google-web-toolkit/issues/detail?id=7602 for instance), but for now that's the state of affair: you need to javac before you can com.google.gwt.dev.Compiler.
javac -cp "/path/eclipse/plugins/com.google.gwt.eclipse.sdkbundle_2.5.0.v201211121240-rel-r42/gwt-2.5.0/*:/path/company/projects/pull-compile-deploy/X/X/war/WEB-INF/lib/*" -sourcepath /path/company/projects/pull-compile-deploy/X/X/src /path/company/projects/pull-compile-deploy/X/X/src/nl/company/projects/X.java -d /path/company/projects/pull-compile-deploy/X/X/bin
java -cp "/path/eclipse/plugins/com.google.gwt.eclipse.sdkbundle_2.5.0.v201211121240-rel-r42/gwt-2.5.0/*:/path/company/projects/pull-compile-deploy/X/X/src:/path/company/projects/pull-compile-deploy/X/X/bin:/path/company/projects/pull-compile-deploy/X/X/war/WEB-INF/lib/*" com.google.gwt.dev.Compiler nl.company.projects.X
(please double-check the above commands before use)
EDIT: (in response to your "question" re. the X.gwt.xml): GWT expects the X.gwt.xml at nl/company/projects/X.gwt.xml because that's what you told it to use: module.name = nl.company.projects.x. If the file is at nl/company/projects/X/X.gt.xml then use nl.company.projects.X.X as the module name. Using a symbolic link here is likely to be the problem: the source path for the module (search for <source at https://developers.google.com/web-toolkit/doc/latest/DevGuideOrganizingProjects#DevGuideModuleXml) will then be nl/company/projects/client and thus won't include nl/company/projects/X/client where your XMain class lives; it's this unavailable to the GWT compiler.
That said, I totally agree with SSR: use a decent build tool: Ant, Maven, Gradle, Make, whatever, it'll make your life so much easier. A build tool that manages dependencies (Ant+Ivy, Maven, Gradle) is even better IMO.
Why would you put yourself through such non-standard build exercise like this.
If it is non-academic project then USE maven. If you find maven difficult then use ant.
Examples for both type are provided by GWT team - http://code.google.com/p/google-web-toolkit/source/browse/#svn%2Ftrunk%2Fsamples.
Note - maven has plugins to do most of the stuff you are trying in standardized way.
I need to generate an apk file using an Ant script, but I'm having problems with the compile target. To automatically generate the Ant script, I've used the Android tool with the command android update project. The problem is that this project depends on another project, so I need to use a custom compile task.
For that reason, I've overridden that target: I've copied the compiled task from ant_rules_r3.xml and I've changed the javac task like this (see comments for what I changed):
<!--I've changed the target 1.5 to target 1.6 -->
<javac encoding="UTF8" target="1.6" debug="true" extdirs=""
destdir="${out.classes.absolute.dir}"
bootclasspathref="android.target.classpath"
verbose="${verbose}"
classpath="${extensible.classpath}"
classpathref="android.libraries.jars">
<src path="${source.absolute.dir}" />
<!--My project has two src directories -->
<src path="${source2.absolute.dir}" />
<src path="${gen.absolute.dir}" />
<src refid="android.libraries.src" />
<!--I've added here the src dir of the other project -->
<src path="${dep1.source.absolute.dir}"/>
<classpath>
<!--I've added here the lib dir of the other project -->
<fileset dir="${dep1.external.libs.absolute.dir}" includes="*.jar" />
<fileset dir="${external.libs.absolute.dir}" includes="*.jar" />
<fileset dir="${extensible.libs.classpath}" includes="*.jar" />
</classpath>
</javac>
The problem is that when I compile with ant compile, I get the following error:
[javac].... cannot find symbol
[javac] symbol : constructor IOException(java.lang.String,java.security.NoSuchAlgorithmException)
[javac] location: class java.io.IOException
[javac] throw new IOException("Algorithm not found", e);
It seems as though it's been compiled with JDK 1.5 instead of 1.6 even though I have set the target property to 1.6. My computer is using Java version 1.6.0_20.
I've tried using javac compiler="javac1.6", but I get the same error.
I've also set in my build.properties:
ant.build.javac.target=1.6
ant.build.javac.source=1.6
but it doesn't solve the problem either. Setting it to 1.3 instead of 1.6 causes more errors, so it seems it is using the JDK I'm setting here.
How can I get this to compile correctly?
Because you've specified the bootclasspath to use the Android SDK classes, these will probably be the ones that contain the IOException class that does not implement the two-arg constructor with a Throwable second arg. That constructor was new in Java 6, but according to recent Android (2.2) docs, the Android version only has Java-1.5 style constructors, and doesn't implement the two newer constructors that take Throwable args.
You didn't mention whether you'd got this to build successfully before bringing in the second project - so I'd recommend checking your local Android boot classes to see what constructors IOException offers.