Specify/fix JDK used by wsimport in Ant build - java

I've got a NetBeans 14 free-form project using Ant. It utilizes wsimport in its build.xml, and a lot of the targets depend on wsimport. After ending up with several JDKs (at least 1.8 and 17) I'm having trouble building, from wsimport chosing the wrong JDK.
In the build.xml (extracts):
<taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
<classpath>
<pathelement location="${lib}/jaxws22/jaxws-tools.jar"/>
</classpath>
</taskdef>
<target name="wsimport">
<wsimport
wsdl="http://address/to/wsdl.xml"
catalog="${metainf}/jax-ws-catalog.xml"
destdir="${release}"
sourcedestdir="${src-gen}"
keep="true"
extension="true"
verbose="true">
<depends file="${metainf}/jax-ws-catalog.xml"/>
<depends file="${wsdl}/wsdl.xml"/>
<produces dir="${src-gen}"/>
</wsimport>
</target>
<target name="compile" depends="init,wsimport" description="compile the source">
<javac ... />
</target>
The problem is that when running wsimport seems to select JDK17, while I want it to select JDK1.8. The output is this:
command line: wsimportC:\path\to\jdk-17.0.2\bin\java.exe ... http://address/to/wsdl.xml
Which gives:
java.lang.NoClassDefFoundError: com/sun/org/apache/xml/internal/resolver/CatalogManager
at com.sun.tools.ws.wscompile.WsimportOptions.parseArguments(WsimportOptions.java:317)
...
Which I've got down to not working with JDK 17. How can I make wsimport use the correct JDK in this scenario?

Related

How to compile this code with Java 10, Ant and the Eclipse compiler?

I am trying to compile this simple code using Java 10, Ant and the Eclipse compiler:
import java.util.ArrayList;
import javax.xml.bind.JAXBException;
class Test {
void foo() throws JAXBException {
throw new JAXBException("hi there");
}
void bar() {
new ArrayList<String>();
}
}
This is the Ant file I am using:
<project name="Java 10 test">
<target name="compile-javac" depends="clean, print-version-info">
<javac release="10" includeantruntime="false">
<src path="."/>
<compilerarg value="--add-modules"/>
<compilerarg value="java.xml.bind"/>
</javac>
</target>
<target name="compile-ecj-4.7" depends="clean, print-version-info">
<javac compiler="org.eclipse.jdt.core.JDTCompilerAdapter"
release="10" includeantruntime="false">
<src path="."/>
<compilerclasspath>
<pathelement path="ecj-4.7.3a.jar"/>
</compilerclasspath>
<compilerarg value="--add-modules"/>
<compilerarg value="java.xml.bind"/>
</javac>
</target>
<target name="compile-ecj-4.8" depends="clean, print-version-info">
<javac compiler="org.eclipse.jdt.core.JDTCompilerAdapter"
release="10" includeantruntime="false">
<src path="."/>
<compilerclasspath>
<pathelement path="ecj-4.8RC2.jar"/>
</compilerclasspath>
<compilerarg value="--add-modules"/>
<compilerarg value="java.xml.bind"/>
</javac>
</target>
<target name="clean">
<delete file="Test.class"/>
</target>
<target name="print-version-info">
<echo message="Java home is ${java.home}"/>
<echo message="Java version is ${java.version}"/>
<echo message="Ant version is ${ant.version}"/>
</target>
</project>
The code compiles fine if I'm using javac (compile-javac target) but I can't get it to work with either the 4.7.3a or 4.8RC2 Eclipse compilers:
with 4.7.3a, I get the error parameterized types are only available if source level is 1.5 or greater even though I specify release="10"
with 4.7.3a, if I use source="10" and target="10" instead of release="10", the source level error disappears but I get a invalid module name: javax.xml.bind error
with 4.8RC2, I get the source level error and another JAXBException cannot be resolved to a type error, even though I specify that I would like to add the java.xml.bind module where JAXBException is defined.
The print-version-info target gives the following as output:
print-version-info:
[echo] Java home is C:\Program Files\Java\jdk-10
[echo] Java version is 10
[echo] Ant version is Apache Ant(TM) version 1.10.3 compiled on March 24 2018
May be it is a follow up for ecj bug 487421 or I just don't understand the command line options?

How to get class files even when the build fails with ant

I have a java project with java files more than 2500 and some of them may have compilation issue. I need to generate classfiles and route to a particular folder. Even with some of the compilation error, rest of jave turned to class files, with eclipse.
But I need to compile with build tools like ANT but it stops as build failed.
Hence no classfiles generated. Is there a way to compile and generated when project has some compilation error using ANT. The sample code is like
<?xml version="1.0"?>
<project name="REL854" basedir="." default="compile">
<target name="create" depends="delete">
<mkdir dir="src"/>
</target>
<target name="delete">
<delete dir ="src" />
<echo>exclude not working</echo>
</target>
<target name="copy" depends="create">
<copydir src="C:\ClearCase_Storage\Views\Snapshot\username_view6\opensource\Selenium\REL854\src" dest="C:\Users\username\neon\ANTBuildFor854\build\src" excludes="Samples"></copydir>
<copy todir ="C:\Users\username\neon\ANTBuildFor854\build\lib" overwrite="true">
<fileset dir="C:\ClearCase_Storage\Views\Snapshot\username_view6\opensource\Selenium\REL854\lib" ></fileset>
</copy>
</target>
<target name="compile" depends="copy"></target>
<javac failonerror="false" includeantruntime="false" srcdir="C:\Users\username\neon\ANTBuildFor854\build\src" destdir="C:\Users\username\neon\ANTBuildFor854\build\bin" includes="**/*.java"></javac>
</project>

Class org.eclipse.jdt.core.JDTCompilerAdapter could not be loaded because of an invalid dependency

I am creating a java agent that will be used to to do some bytecode modification to some classes org.eclipse.jdt.core.JDTCompilerAdapter is one of them. I am using javassit to modify some the execute() method of org.eclipse.jdt.core.JDTCompilerAdapter. So I have included ecj as in my agent project (using gradle)
compile group: 'org.eclipse.jdt.core.compiler' ,name: 'ecj', version :'4.3.1'
As I need to use some classes from ecj.
The goal of the agent is to intercept the calls to execute method, modify the execute method to add some calls to some of my classes in the aim of triggering some processing.
I am testing the agent against a Simple java project with 2 classes. the project is builded with ant and uses JDTCompilerAdapter as a compiler.
Here is the build.xml file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="build" name="TestProject">
<property file="build.properties" />
<property name="debuglevel" value="source,lines,vars"/>
<property name="target" value="1.7"/>
<property name="source" value="1.7"/>
<path id="PClasspath">
<pathelement location="bin"/>
</path>
<target name="init">
<mkdir dir="bin"/>
<copy includeemptydirs="false" todir="bin">
<fileset dir="src">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
<target name="clean">
<delete dir="bin"/>
</target>
<target depends="clean" name="cleanall"/>
<target depends="init" name="build">
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" includeantruntime="false" source="${source}" target="${target}">
<src path="src"/>
<classpath refid="PClasspath"/>
</javac>
</target>
<!--
<target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler">
<copy todir="${ant.library.dir}">
<fileset dir="${ECLIPSE_JDT_CORE}" includes="*.jar"/>
</copy>
</target>-->
<target name="build-e" >
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
<antcall target="build"/>
</target>
The agent is to be used when building a project.
So for testing the agent I use this command:
java -jar agent-wrapper.jar --outdir ./out --exec ./build_wrapper.sh
build_wrapper.sh contains this (I have added ecj dependency so I could compile the project with JDTCompilerAdapter as I have in bulid.xml <property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/> :
../ant/bin/ant -lib ../eclipse/plugins/ecj-4.3.1.jar build-e
The idea is that the agent-wrapper will parse the argument (outdir is used to generate some stuff and exec is a script used to launch a the build of my test project) get the command to be executed from build_wrapper.sh (in this case ../ant/bin/ant -lib ../eclipse/plugins/ecj-4.3.1.jar build-e) and add it self as java agent to the command.
The problem occurs during the execution of the agent. Here is the output:
java -jar custom-agent.jar --outdir ./out --exec ./build_wrapper.sh [10:18:53]
Picked up JAVA_TOOL_OPTIONS: -javaagent:/Users/dev/TestAgent/project/custom-agent.jar=OUTDIR=/Users/dev/TestAgent/project/./out
objc[30474]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/bin/java and /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
Buildfile: /Users/dev/TestAgent/project/build.xml
build-e:
init:
[mkdir] Created dir: /Users/dev/TestAgent/project/bin
build:
BUILD FAILED
/Users/dev/TestAgent/project/build.xml:47: The following error occurred while executing this line:
/Users/dev/TestAgent/project/build.xml:32: Class org.eclipse.jdt.core.JDTCompilerAdapter could not be loaded because of an invalid dependency.
Total time: 2 seconds
abnormal termination, exit code: 1
When I don't use ecj-4.3.1.jar inside my agent project, the build runs well I intercept the call to execute() method but I can't use the other classes from ecj jar.
The show stopper error is "Class org.eclipse.jdt.core.JDTCompilerAdapter could not be loaded because of an invalid dependency."
First hint at the fault might be found from reading this link
http://help.eclipse.org/mars/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-ant_javac_adapter.htm
The second hint might be that one of the jars required for running the JDTCompilerAdapter is missing.
To get the JDTCompilerAdapter to work I copied both the JDTCompilerAdapter.jar and org.eclipse.jdt.core.jar into the ant/lib folder.
There are differences based on version of eclipse and the version of java which are documented in the link mentioned above.

wsimport generates faulty code

I use wsimport to generate my java stub files. For this, I use an ant build file in Eclipse:
<taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
<classpath>
<fileset dir="../lib">
<include name="jaxws-tools.jar" />
</fileset>
</classpath>
</taskdef>
<target name="generate">
<wsimport wsdl="../wsdl/Knowledgebase.wsdl"
destdir="../bin"
sourcedestdir="../gen"
keep="true"
xendorsed="true">
</wsimport>
</target>
The task runs without any errors. It creates different java-files, also Knowledgebase.java and KnowledgebasePort.java. In der Knowledgebase.java, there are these constructors:
public Knowledgebase(WebServiceFeature... features) {
super(__getWsdlLocation(), KNOWLEDGEBASE_QNAME, features);
}
For them I get an error "The constructor Service(...) is undefined". I imported the current jax-ws jar files. Is my generation process broken, do I use the wrong jars or where is the error?
The Service object is provided by the Java EE SDK. It added a new constructor between Java EE 5 and Java EE 6. It would seem the wsimport you're using is from a Java EE 6 JDK and the compiler is using a Java EE 5 SDK?
If we using for example java 1.6.0_27 and Metro 2.2 we need to ENDORSE the webservices-api.jar.
We have to put this jar into folder java-install-dir\jre\lib\endorsed\
In case of using Eclipse, we have to ensure that we are using the correct JRE from the directory java-install-dir. This is done in Window->Preferences->Java->Installed JREs->Add.
Now the error "The constructor Service(...) is undefined" should disappear.
You can set xendorsed="true" and xnocompile="false" and let ant compile your generated java files and it worked for me
<taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
<classpath>
<fileset dir="${ext.myproject.path}/lib">
<include name="*.jar"/>
</fileset>
<fileset dir="${platformhome}/resources/ant/lib">
<include name="*.jar"/>
</fileset>
</classpath>
</taskdef>
<macrodef name="myproject_before_compile_core">
<sequential>
<mkdir dir="${ext.myproject.path}/gensrc"/>
<mkdir dir="${ext.myproject.path}/classes"/>
<echo message="Generating WS stubs for Simulate BOM Service"/>
<wsimport wsdl="${ext.myproject.path}/resources/wsdl/service.wsdl" package="com.xx.energy.yy.xyz.ws.stubs.service" xnocompile="false" destdir="${ext.myproject.path}/classes" sourcedestdir="${ext.myproject.path}/gensrc" keep="true" wsdlLocation="${ext.myproject.path}/resources/wsdl" xendorsed="true">
<produces dir="${ext.myproject.path}/gensrc/com/xx/energy/yy/xyz/ws/stubs/service">
<include name="*.java"/>
</produces>
<depends file="${ext.myproject.path}/resources/wsdl/service.wsdl"/>
</wsimport>
</sequential>
</macrodef>

How to use GCJ with Ant?

I'm fairly new to both Apache Ant and GCJ, and I'm having a hard time trying to build with GCJ via Ant.
My app is in Scala, so I need to use GCJ to take .class files as source. No problem compiling .scala to .class with Ant.
First I figured out how to manually compile a .class file to .o (object), this way:
gcj --classpath=(...) -c (somepath)MouseClickListener.class -o (somepath)MouseClickListener.o
I see here that Ant supports GCJ compilation through the javac tag. So I figured this should work:
<target name="gcjCompile" depends="compile">
<mkdir dir="${object.dir}" />
<javac srcdir="${build.dir}"
destdir="${object.dir}"
compiler="gcj"
executable="C:/gcc/gcc-4.3/bin/gcj.exe"
classpathref="gcjProject.classpath">
<include name="**/*.class"/>
</javac>
</target>
But this javac task does nothing and I get no errors. Any clues?
Thanks
It sounds like you want to link your app into a native executable. That means that you've already compiled the source into JVM bytecode (as you've figured out to do by compiling .scala into .class files). You'll need to run the gcj command manually using the <exec> task to compile the bytecode into gcc object code files.
I'd recommend something like this:
<property name="main.class" value="Main" />
<property name="class.dir" value="${basedir}/classes" />
<target name="compile">
<mkdir dir="${class.dir}" />
<javac srcdir="${build.dir}"
destdir="${class.dir}"
compiler="gcj"
executable="C:/gcc/gcc-4.3/bin/gcj.exe"
classpathref="gcjProject.classpath">
<include name="**/*.java"/>
</javac>
</target>
<target name="link" depends="compile">
<mkdir dir="${object.dir"} />
<exec cmd="C:/gcc/gcc-4.3/bin/gcj.exe">
<arg value="-classpath=${object.dir}" />
<arg value="-c" />
<arg value="*.class" />
</exec>
</target>
Keep in mind that you need to define the build.dir and object.dir properties, and you may need to add a depends task before the javac in the compile target (or just recompile from scratch each time). I may have missed a lot of things, you should check the manual pages (for gcj, gcc, and ant) if it doesn't work at first.

Categories

Resources