NOTE: Please do not comment on all the perils of cross-compiling. Thank you.
I have a situation where we need to have Java 6 source compiled for a Java 5 JVM (to be sure that JAX-WS usage is correct). Previously we have done this with ant ant script (which apparently can), but after migrating to Maven we have found that it ends up with javac complaining:
$ javac -source 1.6 -target 1.5
javac: source release 1.6 requires target release 1.6
Is there any Java distribution for Linux (Ubuntu 11.10, x86) where the javac can do this?
EDIT: It appears not, as the limitation is in javac which is the same. The solution (which made this need go away) was to change from the default javac compiler to the eclipse compiler in maven-compiler-plugin.
EDIT: I've found that the Eclipse compiler generates byte code for anonymous inner classes that the javadoc utility disagrees with. I am preparing a bug report for this issue.
According to the documentation (Java 5, Java 6), the Oracle SDK should be able to do this when you follow the instructions in the Cross-Compilation Example.
Java 6 should support any version between 1.3 to 1.6 as -target
; it doesn't say anything what happens when you use generics and other "compatible" features in the source. The compiler should be able to strip them.
Another culprit in the game might be javac
: The compiler might be able to handle this set of arguments but the command line tool might take offense.
In this case, write your own command line using the Java Compiler API. That might allow to pull of some tricks that you can't achieve otherwise.
You can also try the Eclipse compiler (see "Using the batch compiler").
This might fail because of how Java works: Java X code can run on Java Y as long as X <= Y. So while you can easily compile Java 1.4 code for a Java 6 VM, the reverse is not always true.
If everything else fails, write a preprocessor that reads the source and strips unsupported elements (like @Override
on interfaces). As long as you compile the code with the annotations once in a while with Java 6, the converted code should be safe as well (unless your code stripper has a bug ...)
This answer is an implementation of what @ThorbjørnRavnAndersen explained in the comments as a solution. Using the example code from here, and fixing a few typos, I was able to come up with an example using Eclipse Compiler.
Calculator.java
package example;
// there needs to be a package to avoid A "@WebService.targetNamespace must be specified on classes with no package"
// when running this
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.xml.ws.Endpoint;
@WebService
public class Calculator {
@WebMethod
public int add(int a, int b) {
return a+b;
}
public static void main(String[] args){
// create and publish an endpoint
Calculator calculator = new Calculator();
Endpoint endpoint = Endpoint.publish("http://localhost:8080/calculator", calculator);
}
}
pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>fi.eis.applications</groupId>
<artifactId>ws-calculator</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.6</source>
<target>1.5</target>
<compilerId>eclipse</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
That you can compile with mvn clean compile
and then run with java Calculator
on the target/classes/example
folder. It will start up a web service on port 8080, which you can test with url http://localhost:8080/calculator?wsdl on your browser.