Compiling with Ant - java

I have two .class files that I'm supposed to black box test. These are in a package one.two.three. My tests are also in the same package. There is a third .class file in the same package whose purpose is to hold an enum variable for the Orders class I'm supposed to test. In eclipse, I'm able to get the junit tests for Orders to work by importing the enum directly e.g.
import one.two.three.Orders.ShippingMethod;
If I try to do this using Ant or via the command line, I get the error "package one.two.three.Orders does not exist". If I change the import statement to
import one.two.three.*;
Ant, Eclipse, and the terminal cannot find any of the classes I have. I need to compile and run the test cases with Ant. The classes are in bin/one/two/three Any help would be greatly appreciated, thanks.

Import Orders, as it is the class, and assuming that ShippingMethod is an enum within that class, the correct way to reference its type is Orders.ShippingMethod.
Attempting to import a class's internal types sometimes works oddly in Eclipse. This is likely due to Eclipse not using the javac compiler packaged in your jdk, while Ant does (it has to, because Ant doesn't ship an embedded compiler).
import one.two.three.Orders;
public class Whatever {
private Orders.ShippingMethod shipMethod;
}
This should work in everything, as it's the right way to do it.
import one.two.three.Orders.ShippingMethod;
could easily confuse most compilers as there is not a
one/two/three/Orders/ShippingMethod.class
file, which means the class loader won't find it at runtime.
I'll bet it's a bug in the Eclipse embedded compiler, as I've seen quite a few. On the bright side, the Eclipse embedded compiler exists to provide faster, tighter integration between code editing and Eclipse. On the dark side, that means that sometimes the Eclipse compiler and the javac compiler differ. When in doubt, the javac compiler is probably correct.

You'll need to set the classpath.
I don't know exactly on Eclipse (I use NetBeans), but I click on Libraries -> add JAR/Folder.
For command line, you need to specify class path
java -cp path/to/my/files (...)

Related

how to avoid using javac -cp

I have a Java class which uses a .jar file.
Every time that I want to compile this class, I have to do something like javac -cp ".:myJar.jar" myClass.java and every time that I want to execute it, I have to do the similar thing but with java instead of javac.
Is there a way to avoid doing this?
I know that I could put this jar file into my class path but I don't want to do that. I don't neither want to do a maven projet.
There is nothing preventing you from using an IDE, taking advantage of all its super useful features when developing the program, and then submit just the source code and associated jars to the professor.
Advantages of using IDE that your professor don't need:
Syntax color-coded editors with auto-complete.
Built-in display of javadoc, so you know what all the built-in Java methods do, and how they work.
Instant high-lighting of syntax errors.
Never having to compile the code, since IDE always keeps the code compiled.
Easy single-button execution of the program when you want to run it.
Debugger. Very important feature when your code is not working as you intended.
... more ...

How javac works while importing a package?

I am having a doubt.
My understanding is that jdk has [ jre + development tools (Java, javac, debugger etc.) + source code (src.zip) ].
Now working of java compiler is nothing to do with the running of class file.
If I am compiling a .java file then from where the java compiler is importing the package?
I could find the packages under jre.
If I do not opt to install jre while installing jdk, does that mean I will not be able to compile the java file having import statement?
Please help.
First, as a minor remark, a statement like
import java.util.List;
just introduces an abbreviation, allowing you to use the simple word List later in your code instead of the full class name java.util.List. So it's not so much the import statement itself, but the usage of a class like java.util.List that needs some explanation.
You understand correctly that, to compile your java file, the compiler needs some information about every class you use, and it typically finds this information in some jar file containing that class.
Now, where is this jar file containing the java.util.List class that the compiler reads? You're correct, it comes from the JRE, from the rt.jar that's part of the system classpath (the Java compiler itself is a java program that needs the basic classes itself, so wherever you successfully run javac, you always have an rt.jar available).
If your source code used a class from some other library, you'd have to specify that library on the javac command line, using an option like -cp.
Jdk = JRE + other tools like you mentioned.
When you are compiling your java file and you are using java inbuild library then it uses rt.jar to resolve dependency i.e import statements.
You can refer below link for the difference
What is the difference between JVM, JDK, JRE & OpenJDK?

Is Java's import keyword for source files or binary files?

I know I can include a class or collection of classes in my Java project using the import statement.
For example, import java.io.utils.* imports (i.e. makes available for use in my Java program) all the classes in the java.io.utils package.
My question is, do the classes in an imported package need to be compiled? Or can packages also include uncompiled Java files? If it can be either, when can we use class files and when can we use Java files?
Import just means "make the imported classes available by their simple names" - you can remove imports entirely if you use fully-qualified names everywhere. It's definitely not like #include in C for example.
When you compile, if you try to refer to uncompiled code it will be compiled at that point, assuming the compiler can guess where to find the source code. The result never refers to uncompiled code, because the compiler needs to know what each type exposes.
As a complete example, construct the following file structure:
// src/foo/A.java
package foo;
import bar.*;
public class A {
public static void main(String[] args) {
B.sayHello();
}
}
// src/bar/B.java
package bar;
public class B {
public static void sayHello() {
System.out.println("Hello");
}
}
Then in the src directory, run:
javac foo/A.java
That will automatically compile bar/B.java - but wouldn't compile any other code that isn't referenced (potentially transitively).
I would strongly recommend against using this "compile on demand" behaviour anyway though - if you compile class A that depends on class B, it will compile B the first time, but after that if you change B and recompile A, the compiler won't recompile B. I would organize your code into appropriate projects, and always recompile a complete project at a time, adding a project's output directory to the classpath for a project that depends on it, rather than allowing compiling one project to recompile bits of another on demand.
(Note that this isn't talking about the incremental compilation that many IDEs support... that's a rather different matter, and is fine assuming it's been implemented properly.)
Unlike C, import in Java does not "copy" stuff. Packages in Java is simply a way of avoiding ambiguity. javax.swing.Timer and java.utils.Timer are different Timers. When you say import javax.swing.Timer, you are telling the compiler that you mean javax.swing.Timer, not any other Timer.
All these things that you can import comes from the JDK or some other libraries you're using, or they are created by you. The classes that fall into the former category is already compiled (.class). The classes you created are compiled as well, when you do javac. You can't refer to any uncompiled classes. Since they are uncompiled, the computer does not know they exist.
The reason why your IDE knows your packages and classes before you compile your code is because IDEs are smart. They compile your code before you even notice it.
As Java documentation reports.
You might have to set your CLASSPATH so that the compiler and the JVM can find the .class files for your types.
link: https://docs.oracle.com/javase/tutorial/java/package/summary-package.html

Import Error in Java Using Ant but not Eclipse

I can compile my program just fine if I specify sublibraries of com.itextpdf.*, but for some reason, my compile fails if I simply do import com.itextpdf.*. But, like I said, if I specify the sublibraries I'm using, such as
import com.itextpdf.text.Font.*;
import com.itextpdf.text.pdf.*;
Everything compiles just fine. In the case where it fails, the error I'm getting is "package com.itextpdf does not exist", but I know it does. I include it properly in the build path, and Eclipse doesn't give any compile errors in any case. The error only comes up when I try to build with Ant.
At this point, I don't mind specifying the sub libraries I'm going to use to make sure I get a build. But I am curious, why wouldn't Ant allow this?
You, and Eclipse, think of java namespaces as a hierarchy. However, in the Java specification, they are not. There is no relationship between "com.itextpdf.text" and "com.itextpdf.text.Font". They are different strings, end of story.
As a matter of style, you may want to set up Eclipse to automatically organize your imports and explicitly specify every class you use in the import section of your class. This avoids ambiguity when "com.itextpdf.text.Font.String" and "com.itextpdf.text.pdf.String" both exist, but you only want to reference one of them. This style would be incredibly tedious and inconvenient if you were programming in emacs or vi, but with Eclipse it is automatic and invisible, unless you scroll to the top of your file.

Eclipse 3.5+ - Annotation processor: Generated classes cannot be imported

I am using a 3rd party annotation processor for generating meta-data code (.java files) from the annotated classes in my project.
I have successfully configured the processor through Eclipse (Properties -> Java Compiler -> Annotation Processing) and the code generation works fine (code is automatically created and generated). Also, Eclipse successfully auto-completes the generated classes and their fields, without any errors. Let's say that I have a class "some.package.Foo" and that the generated meta-data class is "some.package.Foo_". By the help of auto-completion, I can get the following code in the Eclipse editor, without any errors:
import some.package.Foo_;
...
public class Test {
void test() {
Foo_.someField = null; // try to access a field from the generated class Foo_
}
}
However, as soon as I actually build the project (or just save the file since Build automatically is enabled), I get the error which tells that "some.package.Foo_" cannot be resolved.
It seems like Eclipse is generating and compiling the some.package.Foo_ at the same time, or more likely.
I found two temporary solutions (which are practically hindering the use of the annotation processor in the first place):
Before each build of that generated classes, right click on every generated file go to Properties and uncheck the "Derived" tick. After that, I do the cleanup of the project and the imports are fine - there are no more errors. However, if I do the cleanup one more time, the errors again show up, because the generation of the files causes the "Derived" tick to be checked again (automatically). So this is really annoying and time-consuming.
I also uncheck the "Derived" tick
from all those files, and this time
I uncheck the "Derived" tick from
the source folder and packages which
contain those files. Then I disable
the annotation processor, and then
do the cleanup. There are no more
import errors, even if I do another
cleanup, but there is no benefit of
using the annotation processor,
because if I was to change something
which would update the model, I need
to turn the annotation processor
back on, and repeat this tedious
procedure to turn it off, after it
has generated the new version of
those files.
Is this a bug in Eclipse? If yes, is there a better workaround or quick-fix than the two I have stated above? If not, what should I try to solve the problem?
I also tried rearranging the order of the libraries on the build path and it doesn't help.
I assume that you are generating sources in the last processor round. This is not recommended way and leads exactly to the problem that you had.
Explanation is here: http://code.google.com/p/acris/wiki/CodeGenerationPlatform_Pitfall_Rounds
So the my advise is to generate sources in regular processing rounds and final round should be used just for notification that processing is over or something like that.
Hopefully this helps you.
I have a similar problem, and the only thing I've found is that it's the imports specifically that don't work, but the references in the class itself do work. The workaround I've used is to use the FQCN in all cases where the generated class is needed (except when the generated class is in the same package, since then the import is obviously not needed).
So to use your example, I'd do:
public class Test {
void test() {
some.package.Foo_.someField = null; // try to access a field from the generated class Foo_
}
}
My only guess then is that the eclipse compiler is processing the imports before doing the annotation processing, which imho must be a bug in eclipse.
I know this question is over a year old, so I'd be interested to know if you've found any other way to fix it.
We were experiencing a similar problem and apparently just solved it, so thought of sharing it at SO, in case it helps someone.
We are using:
Eclipse Indigo (Build id: 20120216-1857)
m2e Connector for maven
openJPA for static metamodel class generation
Our problem:
Say, we have a package named com.abc.xyz and an entity class in there named OurEntity. When we build the projects (JPA, EJB, EAR etc. all together with an mvn clean at the beginning) the metamodel classes get generated. And also get appropriately packaged within the PU jar. But when we try to import the generated metamodel class com.abc.xyz.OurEntity_, Eclipse cannot resolve it. OP apparently got past this point:-). Maven build failed, saying it could not resolve that class. Not much help from google except for a few bug reports such as this one: https://bugs.eclipse.org/bugs/show_bug.cgi?id=350378
That bug report said importing the whole package as opposed to the single class helped. So, tried that, but with no benefit. It also said (and so did David Heitzman) that using the fully qualified class name worked for them. That did not work either.
The solution:
Added the PU jar to Eclipse build path for the project that needed to use the metamodel classes. All of a sudden all the red underlines went away (not a surprise). But the fear was there might be two PUs in the same ear. But maven automagically took care of that.
As this rather old question got some attention without pointing to the very probable eclipse bug the OP was specifically asking for, I'd like to complement the above answers with a pointer to the eclipse bug tracker:
Cannot resolve import for generated class IF processing annotations with parameters referencing constants
The workarounds include
doing a wildcard import of the package defining the generated classes (i.e. import some.package.*;)
using the fully qualified name of your generated class, i.e. referring to some.package.Foo in your code and not using an import
switch to a newer Eclipse. This specific eclipse bug is resolved with Eclipse version 4.4 (aka Luna).

Categories