Jenkins Project Can't Find Packages; build-project target fails - java

My project compiles and runs on my local machine, but on Jenkins the build-project target fails to compile due to being unable to find my packages. I can see that the jars that I think I need are in my ./bin/ folder, so I anticipate there is something about classpaths or my build-project target that is causing the issue.
build.xml -> build-project:
<target depends="init" name="build-project">
<echo message="${ant.project.name}: ${ant.file}" />
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" includeantruntime="false" source="${source}" target="${target}">
<src path="src" />
<classpath refid="sierraMadreTestScripts.classpath" />
</javac>
</target>
error message excerpt on Jenkins:
build-project:
[echo] sierraMadreTestScripts: /data/builds/jenkins/workspace/build.xml
[javac] Compiling 1 source file to /data/builds/jenkins/workspace/bin
[javac] /data/builds/jenkins/workspace/src/testScripts/TranslatorWorkflow.java:3: error: package org.junit does not exist
[javac] import static org.junit.Assert.fail;
[javac] ^
I can post my full build.xml, ivy.xml, ivysettings.xml, or whatever else would be necessary to diagnose the problem. Sorry if this is really basic; Ivy is still rather arcane to me. I'm running my local project within Eclipse.

The root cause of your problem is outlined in the following question:
Running ant build gives "package org.junit does not exist"
In short IDEs like Eclipse automatically put junit in your classpath..... Ivy is actually designed to help solve this problem and used properly it can be used to manage all aspects of your project's classpaths.
Without access to your build logic I must guess, but it looks like you're building both code and tests using a single javac? You have a classpath called "sierraMadreTestScripts.classpath", the next question is how is this created and managed. Your question implies that ivy is somehow involved :-)

Related

javac compilation issue with packages

Given this (game.Game.java, game.Player.java, game.io.InputConsole.java):
src
|_game
Game.java
Player.java
|_io
InputConsole.java
I've been trying to compile this project on console with javac (trying out various solutions found on SO and the internet) but I keep failing. I also tried using a batch file, but in either case, all I get are "cannot find symbol" errors.
Since almost all answers to related questions suggest to use a build tool like Ant or Maven, I decided to give it a try with Ant (first time). This is what my Ant file looks like:
<project default="run" name="Tic_Tac_Toe">
<target name="run" depends="compile">
<java classname="game.Main">
<classpath path="bin" />
</java>
</target>
<target name="compile">
<javac srcdir="." destdir="bin"/>
</target>
</project>
This is an excerpt of the output:
C:\Users\...\src\game\io\InputConsole.java:10: error: cannot find symbol
public Player getPlayer(Sign sign) {
symbol: class Player
location: class InputConsole
PS: It works when I move InputConsole.java into the game package. So I'm sure the classes themselves are fine.
I think the problem is either that I'm failing giving the compiler a proper path or my package structure is wrong.
You need to import in both. There is no hierarchy among packages and in spite of appearance game.io is not a "sub-package" of game, because there is no such thing as a sub-package.
For classes in package game; you need import game.io.InputConsole;. In package game.io; you need import game.*;.
Note that * is just convenience, it is probably better to import each referenced class individually.

Javac compiler bug with class name antbuild

I was trying to do an ant build that compiled a java project source code when i ran into a problem i could not explain. First my ant target:
<target name="compile-companymanage" depends="compile-company">
<mkdir dir="${companymanagebin}"/>
<javac destdir="${companymanagebin}">
<src path="${companymanagesrc}" />
<classpath refid="companyManage.classpath"/>
</javac>
</target>
After running that i get the error:
[javac] project\src\com\company\manage\vo\InvoiceL‌ineSupplierVM.java:31: error: class InvoiceLineSupplierVM is public, should be declared in a file named InvoiceLineSupplierVM.java
[javac] public class InvoiceL‌ineSupplierVM
[javac] ^
[javac] 1 error
We have tried it with different projects and they compile just fine. Hope someone can help me.
We have tried renaming the file and class with the same name.
Adding the answer for completeness sake and to simplify the lives of other people which will encounter this error in the future.
Most likely you have a non-printable character in one of your names, either your class name or your file name. This will cause a mismatch between what the compiler has or expects.
To solve this problem, what one usually does is to rename the files and classes involved. It is important that when renaming, you do not copy and paste the name but rather type it in. This will make sure that non-printable characters do not end up in the names of the file and class as happened.

Ant compiles but doesn't create the classes

Ok, sorry if it is repeated, but I promise I googled it, searched around forums and similar.
The thing is, I have to compile a big java project to create a war file. The problem is, it depends on a lot of classes and jars that I own.
So, I started building the project from command line, everything goes right, but when I tried to apply the same with ant, ant doesn't create the classes... or directories... or anything. It says that the compilation was successful but the output directory does not have any classes.
So, here's part of my partial build.xml, at least, the important part for me.
<target name="we">
<javac destdir="${proj.name}/${comp.res}">
<src path="${proj.name}/cnt.web/${proj.version}/exception" />
<src path="${proj.name}/cnt.web/${proj.version}/base" />
<src path="${proj.name}/cnt.web/${proj.version}/core" />
<classpath refid="my.path"/>
</javac>
</target>
I've tried with lots of combinations, from srcdir to this aproach. Nothing seems to work when I do:
ant we
It says that it's successful, that it registered n files to compile, and that's all, the resulting directories and classes aren't where they are suposed to be. I tried reading the debug and verbose but nothing seems to be wrong.
Any ideas could help.

Android.App.Activity - package does not exist

I got an andorid project files that are supposed to compile correctly.
I installed the latest eclipse and Andriod ADT plugins.
I then imported the project and right clicked build.xml to run as ANT build. but I got erors on some basic code which I am sure is originating from my misconfigured setup.
I also tried to run it using ANT from the command line. both times I got the same type of errors
What is wrong ?
Buildfile: /Users/admin/Downloads/moshe-5/build.xml
init:
process.annotations:
[javac] Compiling 9 source files to /Users/admin/Downloads/moshe-5/build/classes
[javac] /Users/admin/Downloads/moshe-5/src/ti/moshe/CustomAdapter.java:7: package android.app does not exist
[javac] import android.app.Activity;
[javac] ^
[javac] /Users/admin/Downloads/moshe-5/src/ti/moshe/CustomAdapter.java:8: package android.content does not exist
[javac] import android.content.Context;
[javac] ^
[javac] /Users/admin/Downloads/moshe-5/src/ti/moshe/CustomAdapter.java:9: package android.graphics does not exist
[javac] import android.graphics.Color;
In my case, it was due to the problem that I didn't have a default.properties file with the target field in it.
I had to manually create the file and put
target=android-9
Or other Android target version.
If you run
ant -v
with your build command, you'll probably see this line
Property "target" has not been set
and
[property] Unable to find property file: /PATH_TO/default.properties
Those messages are enough hints.
Hope this solves your problem too.
It is not finding the android packages. IN the build step you should include android.jar corresponding to the android version you want to port to.
When you write your compile target, you are overriding the default one given by android_rules.xml located in: C:\Program Files (x86)\Android\android-sdk\platforms\android-8\templates or wherever android_rules.xml is located on your computer.
Like Potter mentioned above it is not finding the android library and other libraries, so please look at android_rules.xml to see how it sets up the proper libraries:
<target name="compile" depends="-resource-src, -aidl"
description="Compiles project's .java files into .class files">
<!-- If android rules are used for a test project, its classpath should include
tested project's location -->
<condition property="extensible.classpath"
value="${tested.project.absolute.dir}/bin/classes" else=".">
<isset property="tested.project.absolute.dir" />
</condition>
<condition property="extensible.libs.classpath"
value="${tested.project.absolute.dir}/libs" else="./libs">
<isset property="tested.project.absolute.dir" />
</condition>
<javac encoding="ascii" target="1.5" debug="true" extdirs=""
destdir="${out.classes.absolute.dir}"
bootclasspathref="android.target.classpath"
verbose="${verbose}" classpath="${extensible.classpath}">
<src path="${source.absolute.dir}" />
<src path="${gen.absolute.dir}" />
<classpath>
<fileset dir="${external.libs.absolute.dir}" includes="*.jar" />
<fileset dir="${extensible.libs.classpath}" includes="*.jar" />
</classpath>
</javac>
</target>
Inside the classpath tags is where android.jar is included. You can add other libraries by adding more filesets
Some other good examples of code for writing the ANT compile target are:
Can't build and run an android test project created using "ant create test-project" when tested project has jars in libs directory <-- this worked for me
http://www.vogella.de/articles/ApacheAnt/article.html
http://www.alittlemadness.com/2010/05/31/setting-up-an-android-project-build/ <-- setting up ANT project
It's most likely not finding Android because you didn't define the sdk.dir property, which tells the build process where to find Android. This property is usually in a local.properties file and is populated when you do:
android update project
as described here:
http://developer.android.com/tools/projects/projects-cmdline.html#UpdatingAProject
Don't bother building using ANT.
Eclipse and the ADT plugin provide excellent tool to save you the trouble.
Simply right click the project, choose run as -> Android application

use system classpath for ant javac task

I want the javac task to use jars from the system classpath, by which I mean the classpath that is set in the shell's environment before ant is started. That classpath is
CLASSPATH=D:\local\lib\java\*;.;C:\lib\java\*;C:\lib\java\db\*
on my system. I have popular jars there that are used by many projects. The basic snippet I use in the build file is
<target name="build">
<mkdir dir="${obj}" />
<javac srcdir="${src}" destdir="${obj}"
includes="**/*.java"
excludes="**/package-info.java **/deprecated/*.java"
includeAntRuntime="no" debug="true" debuglevel="source,lines"
>
<compilerarg value="-Xlint"/>
</javac>
</target>
That way ant only passes the output directory as classpath.
[javac] '-classpath'
[javac] 'D:\dev\tbull-projects\jsonc\obj'
(jsonc is the project I'm working on, and D:\dev\tbull-projects\jsonc is the working directory.)
I browsed the documentation for a while and came up with two attempts. First one was adding the attribute classpath="${java.class.path}" to the javac tag. That would pass a tremendously long classpath to the compiler, listing every single jar from ant's own lib directory and finally tools.jar from the JDK. Not the classpath that I wanted.
The second shot was setting
<property name="build.sysclasspath" value="first" />
before javac was invoked, and that got me in the right direction. Now these lines were among the output:
dropping D:\dev\tbull-projects\jsonc\D:\local\lib\java\* from path as it doesn't exist
dropping D:\dev\tbull-projects\jsonc\C:\lib\java\* from path as it doesn't exist
dropping D:\dev\tbull-projects\jsonc\C:\lib\java\db\* from path as it doesn't exist
dropping D:\dev\tbull-projects\jsonc\C:\Program Files\Java\jdk1.6.0_18\jre\lib\sunrsasign.jar from path as it doesn't exist
dropping D:\dev\tbull-projects\jsonc\C:\Program Files\Java\jdk1.6.0_18\jre\classes from path as it doesn't exist
Well, you can imagine that these paths really don't exist. I just don't get why ant constructed them this way. It would know how to do path arithmetic on Windows, would it?
Maybe my approach is flawed more fundamentally, so I'll let you know what I'm actually after. So I'm developing this project (a library), which uses another library. The project is gonna be open source, so I want other developers to be able to build it after they have downloaded the dependency library and placed it somewhere in their classpath.
From what I saw in other questions about ant+classpath, it appears that it's a custom fashion to distribute the dependency libs with the source code (so the classpath can be just like ./libs). But I surely don't want to have jars in my git repo. So how could that be done?
Set includeJavaRuntime=true in javac task.
<target name="build">
<mkdir dir="${obj}" />
<javac srcdir="${src}" destdir="${obj}"
includes="**/*.java"
excludes="**/package-info.java **/deprecated/*.java"
includeAntRuntime="no" includeJavaRuntime="true"
debug="true" debuglevel="source,lines">
<compilerarg value="-Xlint"/>
</javac>
</target>
Why wouldn't you set CLASSPATH in Ant? It's perfectly suited to do just that. You're making a mistake if you do anything else. Not only will it work, bu your build.xml will document the requirements as well.
When javac compiles the code , it tries to find the files in rt.jar in a symbol file called ct.sym (which is also present in lib directory). some files are missing in this symbol file.
i have to add a compile option to ignore symbol file and look directly in rt.jar.
so i have used this option -XDignore.symbol.file for ant i put this value in javac tag. it works perfectly if you use eclipse or any other ide .
<compilerarg value="-XDignore.symbol.file"/>
So , whenever you get ClassNotFoundException in using classes from rt.jar , and if the class is still present there , just try to add this argument in java compiler
To reference rt.jar from ant you may use:
<fileset dir="${java.home}/lib" includes="rt.jar"/>
Original details were found here: http://www.javaroots.com/2013/01/javac-error-using-classes-from-rtjar.html
If someone is new to java/ANT world, people who suggest maven are idiots
whatever happened to KISS principle?
OP, instead of using javascript abomination try this
<project default="build">
<property name="src" value="src" />
<property name="obj" value="obj" />
<property name="parent.dir" value="/jakarta-tomcat/common/lib" />
<path id="project.class.path">
<pathelement location="lib/" />
<fileset dir="${parent.dir}" includes="**/*.jar" />
</path>
<target name="build">
<delete dir="${obj}" />
<mkdir dir="${obj}" />
<javac srcdir="${src}" destdir="${obj}" includes="**/*.java" excludes="**/package-info.java **/deprecated/*.java" debug="true" debuglevel="source,lines" classpathref="project.class.path" />
</target>
It's pretty clear the folks behind java, and (or at least), ant, really really really don't want to see $CLASSPATH end up as storage for user installed libraries of the sort that 95% of other mainstream languages (C/C++, perl, python, ruby, etc. etc.) use. So this is a tough paradigm to swallow if you are used to general programming in most other mainstream languages.
The disinclination goes so far that it is obvious ant intentionally strips $CLASSPATH out of the environment, but an easy way around this is to just use a different variable.
<property name="classpath" location="${env.JAVALIBPATH}"/>
This will then work, no fuss, with both <javac> and <java> commands (classpath="${classpath}) which is good, because if you try this instead:
<property name="classpath" location="${env.CLASSPATH}"/>
There is no includeAntRuntime="false" option to <java> which would allow this to work. You simply cannot get $CLASSPATH in and someone has gone to lengths to make sure of it (without, apparently, and yikes, adding in a ponderous javascript hack).
Of course that means you need to use a separate env variable and for your distributed/production version stick to the Java "Sorry no user libs!" paradigm. That's not a big problem if you use a variable name that, if it becomes involved, will almost certainly be undefined on the target system.
Alternatively, there are the Maven Ant Tasks. These will allow you to use Maven's dependency mechanism in a way that, IMO, is cleaner than Ivy. But it's still not a great solution.
Soo... seems I have to answer the question myself. Passing the original classpath to the javac task can be achieved with this:
<!-- load environment into the env property -->
<property environment="env" />
<javac srcdir="${src}" destdir="${obj}"
includes="**/*.java"
excludes="**/package-info.java **/deprecated/*.java"
includeAntRuntime="no" includeJavaRuntime="no"
debug="true" debuglevel="source,lines"
>
<!-- add -classpath option manually -->
<compilerarg value="-classpath" />
<compilerarg value="${env.CLASSPATH}" />
<compilerarg value="-Xlint"/>
</javac>
That does the trick at least so far that the javac task now gets passed the correct classpath. Yet it will still not work, javac now spits these complaints:
[javac] warning: [path] bad path element "D:\local\lib\java\*": no such file or directory
[javac] warning: [path] bad path element "C:\lib\java\*": no such file or directory
[javac] warning: [path] bad path element "C:\lib\java\db\*": no such file or directory
This is a straight lie, these paths do very much exist. I use them all the time, and if I manually craft an equivalent javac invocation at the shell, it works like a charm. I suspect ant's javac doesn't resolve the jar files in those directories. I have to examine that.
UPDATE
It is indeed as I suspected, the wildcard is not resolved to the individual present jar files by the javac task. I managed to do the resolving manually, and now it works as it should. And that resolving was in fact a struggle on its own. So I'll leave the solution here for those poor souls fighting the same stupidity, hopefully before they ask people that have nothing else to do than bullshitting around (yes Anon, talking about you).
Turns out, ant lacks the most basic functionality that you would expect from a build tool. Also turns out that I'm not the first one to notice that. While solutions are rare, there is a very good post about Using JavaScript to make Apache Ant less painful, which really saved my day. Yes, ant can indeed be scripted, which seems not to be widely known, although it is not kept secret. You can safely assume, that Javascript is already available without installing additional libraries if you run ant on Java 6.
Soo... down to business. Here is the thing:
<target name="expand_classpath">
<script language="javascript"><![CDATA[
// the original classpath
var ocp = java.lang.System.getenv("CLASSPATH");
// ... split in parts
var ocp_parts = ocp.split(project.getProperty("path.separator"));
// where our individual jar filenames go,
// together with pure directories from ocp_parts
var expanded_parts = [ ];
for each (var part in ocp_parts) {
if (part.endsWith('*')) {
var dir = part.substring(0, part.length() - 1);
var f = new java.io.File(dir);
// don't know how to construct a java.io.FilenameFilter,
// therefore filter the filenames manually
for each (var file in f.listFiles())
if (file.getPath().endsWith('.jar'))
expanded_parts.push(file.getPath());
} else
expanded_parts.push(part);
}
var expanded = expanded_parts.join(project.getProperty("path.separator"));
project.setProperty("classpath.expanded", expanded);
]]></script>
<!-- <echo message="classpath.expanded = ${classpath.expanded}" /> -->
</target>
<target name="build" depends="expand_classpath">
<mkdir dir="${obj}" />
<javac srcdir="${src}" destdir="${obj}"
classpath="${classpath.expanded}"
includes="**/*.java"
excludes="**/package-info.java **/deprecated/*.java"
includeAntRuntime="no" includeJavaRuntime="no"
debug="true" debuglevel="source,lines"
>
<compilerarg value="-Xlint"/>
<compilerarg value="-Xlint:-fallthrough"/>
</javac>
</target>
I will assume that your "popular" JARs are well-known open-source projects. This means that they're available in the Maven central repository.
While I believe that using Maven is the best answer to this question, you can also hack something using Ant's <get> task. For example, to download the JUnit JAR (may have typos):
<property name="dependency.dir" value="${basedir}/dependencies"/>
<property name="junit.jar" value="junit-4.8.2.jar"/>
<property name="junit.url" value="http://search.maven.org/remotecontent?filepath=junit/junit/4.8.2/${junit.jar}"/>
<target name="download.dependencies">
<mkdir dir="${dependency.dir}/>
<get url="${junit.url}" dest="${dependency.dir}/${junit.jar}"/>
</target>
Of course, if you do this then you'll have to carefully configure your build scripts so that you don't do the download with every run. And you'll increase load on the Maven Central repository.

Categories