Intellij IDEA doesn't recognized XJC task attributes - ant

I have an ant build.xml file with XJC task definition:
<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
<classpath>
<fileset dir="jaxb" includes="*.jar" />
</classpath>
</taskdef>
jaxb dir cotnains jaxb-xjc.jar with XJCTask class inside.
Then I call xjc task in some target:
<target name="mytarget">
<xjc target="src" package="com.p1.Person" header="false">
<schema dir="src/com/p1" includes="Person.xsd"/>
</xjc>
</target>
Intellij IDEA doesn't recognize the structure/schema of the xjc call and highlights all attributes (target, package, header) and containing elements (schema) in red.
If I choose Ant options and add jaxb-xjc.jar to additional class path list this doesn't help.
I use bundled Ant 1.8.2
The bad thing is that when I compile it in IDEA I get a lot of related errors, but when I run build script everything works fine. I want to suppress these errors.
Any ideas?

The answer comes from this comment in a related bug in the IDEA issue tracker.
http://youtrack.jetbrains.net/issue/IDEA-11248#comment=27-57354
For the XJCTask issues with IDEA, just use XJC2Task in your taskdef.
If you look at the source of XJC2Task, it has the setters exposed so that IDEA can resolve them:
http://grepcode.com/file/repo1.maven.org/maven2/com.sun.xml.bind/jaxb-xjc/2.1.13/com/sun/tools/xjc/XJC2Task.java#XJC2Task.setPackage%28java.lang.String%29
However, XJCTask is just a class to dynamically delegate to JAXB1 or JAXB2 on the fly so IDEA is unable to resolve these properties since the class you are defining in the taskdef doesn't have the setters on it.
http://grepcode.com/file/repo1.maven.org/maven2/com.sun.xml.bind/jaxb-xjc/2.1.13/com/sun/tools/xjc/XJCTask.java#XJCTask.getCoreClassName%28%29
Edit:
Basically in JAXB2, XJCTask doesn't actually contain the task - it delegates to the actual task XJC2Task.
Here are some better links to the source:
XJCTask in JAXB 1
http://java.net/projects/jaxb/sources/version1/content/trunk/jaxb-ri/xjc/src/com/sun/tools/xjc/XJCTask.java?rev=197
XJCTask in JAXB2
http://java.net/projects/jaxb/sources/version2/content/trunk/jaxb-ri/xjc/facade/com/sun/tools/xjc/XJCTask.java?rev=3863
XJC2Task in JAXB2
http://java.net/projects/jaxb/sources/version2/content/trunk/jaxb-ri/xjc/src/com/sun/tools/xjc/XJC2Task.java?rev=3863
If you look at your jaxb-xjc-ri-2.x-xx.jar you will see that it contains a package called "1/com/sun/tools/xjc/"
This is what gets called from the XJCTask in JAXB2 if you run your ant task with setting the version to 1.0.
I expect it was put in to allow easier transitions to v2 from v1 back in the day.
XJC2Task is what is called if you are using v2.
Realistically you aren't going to set it to 1.0 so you might as just call the XJC2Task directly.

Related

Condition Property Override

I want to use an condition property to set the property value to X if another property is defined and Y otherwise. However, I don't want the user to be able to override the condition property from the command line.
How can this be achieved?
Starting from ant 1.8 for some use cases local task may be applicable. Since a property is made local it starts with an empty value. It's scope is limited to current target, but you may pass it to subsequent targets using param argument in antcall.
Nope, you can't override a property set on the command line. At least, it's not easy to do. The whole purpose of overriding properties on the command line is to allow users to override defaults in order to make modification in the way your project builds. For example:
<property file="${basedir}/build.properties"/>
<property name="javac.debug" value="no"/>
<target name="compile">
<javac destdir="${main.destdir}"
debug="${javac.debug}">
By default, the Java code is compiled without debugging information. Maybe this is done to make jar files smaller, or faster interpretation, or maybe to make the code harder to decompile and read. Whatever reason, this build won't put debug information into the classfiles.
However, developers do want this debugging information, so they want to be able to override this setting:
$ ant -Djavac.debug=true compile
Or, they can create a build.properties file and put the value in there.
This type of issue comes up when you're not using Ant for builds. I know several sites that use Ant scripts to do deployments. I usually discourage this because Ant isn't really made for this type of thing. For example, Ant doesn't have any built in logic or loops. Once a property is set, it can't be changed. These are good ideas for a build language, but a terrible idea for a general purpose programming language.
Also, developers shouldn't be doing builds for QA or production. Those should be done by a build server that won't override defaults.
Now how to destroy this whole well thought out system and cause absolute havoc:
You can use the ant-contrib tasks in your project. Doing this will allow you to access the Ant Contrib var task to unset properties.
Download the ant-contrib.jar file (whatever the latest version is), and put it in a lib directory under your project. Then you can do this:
<project name="danger-will-robinson" default="package" basedir="."
xmlns:ac="http://ant-contrib.sourceforge.net">
<!-- Define the Ant-Contrib tasks -->
<taskdef=resource="net/sf/antcontrib/antlib.xml"
uri="http://ant-contrib.sourceforge.net">
<classpath>
<fileset dir="${basedir}/lib">
<include name="ant-contrib*.jar"/>
</fileset>
</classpath>
</taskdef>
<!-- Unset Property "foo", so you can use it -->
<ac:var name="foo" unset="true"/>
Note that the <classpath> points to the ant-contrib jar in the ${basedir}/lib directory. If you check that into your source repository, it will allow everyone who checks out your project to be able to do the build without installing the ant-contrib jar on their system.
Note that I've defined a "ac" XML namespace, so Ant-Contrib tasks won't overlap other possible third party tasks.
Properties in ant once set are immutable by design. You may overwrite an existing property with any scripting language that provides access to ant api, i.e. javascript.
JDK >= 1.6 already ships with a javascript engine, so you may use something like :
<project>
<property name="x" value="whatever"/>
<script language="javascript">
project.getProperty('x') ?
project.setProperty('foo', 'true') :
project.setProperty('foo', 'false');
</script>
<echo>$$[foo} => ${foo}</echo>
</project>
out of the box.But that won't help if someone uses ant -f yourbuild.xml -Dfoo=bla !! as userproperties (those properties defined via -Dkey=value) have a special protection.
So your requirement "..However, I don't want the user to be able to override the condition property from the command line". is not fullfilled.
But the let task from Ant addon Flaka provides the possibillity to overwrite even userproperties :
<project xmlns:fl="antlib:it.haefelinger.flaka">
<property name="x" value="whatever"/>
<!--
:= defines a new property whereas
::= overwrites any existing property
even userproperties
-->
<fl:let> foo ::= has.property['x'] ? 'true' : 'false'</fl:let>
<echo>$$[foo} => ${foo}</echo>
</project>
Run both scripts with ant -f yourbuild.xml -Dfoo=bla to see the difference.
Ant api has also method project.setUserProperty(String,String) so you may use also:
...
<script language="javascript">
project.getProperty('x') ?
project.setProperty('foo', 'true') :
project.setProperty('foo', 'false');
project.getUserProperty('x') ?
project.setUserProperty('foo', 'true') :
project.setUserProperty('foo', 'false');
</script>
...
to prevent the foo property to be set via .. -D .. and it will work even if property x is defined on commandline -Dx=whatever You have to make your choice, script task with javascript out of the box or Flaka let task
oneline solution but Flaka jar needed.

How can I run a custom JUnit4 Runner on JUnit3 test classes with Ant?

We have test classes which are built on Spring 2.0.8's AbstractTransactionalDataSourceSpringContextTests. There are a huge number of these, all of which are written in JUnit3 style.
In order to use JUnit 4 filtering, we have concocted a replacement JUnit38Runner which allows us to match these tests to a specific application environment, and filter them out accordingly.
The whole test suite runs fine outside of Ant, by using the #RunWith annotation on our custom JUnit38Runner.
When we try to run in Ant, however, it forces individual tests to run either as junit.framework.TestSuite or wrapped in a JUnit4TestAdapter, both of which ignore #RunWith annotations under JUnit4. To make matters worse, our existing suites are explicitly overridden by Ant, which calls the suite() methods directly, rather than delegating to JUnit.
I have attempted to extend from the Ant JUnitTestRunner, and simply override the run() method, however the class is simply not written for extension.
Aside from copying the whole of the JUnitTestRunner and hacking it (which will open us up to brittle code issues), has anyone had any luck with other approaches to solving this problem?
We had a similar problem, and although it's not as clean as running the junit task, it's not terribly difficult to solve. We created a class with a main() that simply invokes the Junit4Runner. It adds a RunListener that attempts to write out the junit report output in XML. The idea was that the dataformat is much less likely to change than the runner, so it's less brittle.
I've stripped out a fair amount of environment-specific code, but this is the basic idea. Our test target in ant looks like this:
<java failonerror="yes"
fork="true"
classname="com.mycompany.test.Junit4Runner">
<classpath>
<pathelement location="${basedir}/bin" />
<pathelement path="${ProjectTest.classpath}" />
<!-- above classpath includes junit-4.8.1.jar -->
</classpath>
<arg value="${test.class}" />
</java>
You can view the code for the runner class here. It doesn't depend on anything outside Java 6 SE and Junit 4.8, and it may be compatible with Java 5 SE.

Ant 1.8 include or import with nested resource collection

I'd like to have Ant automatically include or import resources matching a particular pattern, but I'm really struggling with the syntax. Here's what I've tried:
<import>
<fileset dir="${basedir}" includes="*-graph.xml" />
</import>
However, I just get the error message
import requires file attribute or at least one nested resource
The documentation for import (and include) both say that you can use a nested resource collection, and the documentation for resource collections says <fileset> is a resource collection. I've Googled and can't find any useful examples at all.
I'm using Ant 1.8.1 (verified with ant -version)
EDIT
Found the problem. Firstly, SOMETHING has to match the expression. With no files that match, it blows up - even with optional=true, which is odd! Secondly, the matching files have be valid Ant file (even if they just contain <project/> - simply creating an empty file wasn't good enough).
Better error messages, please Apache! :-)
Try:
<foreach target="-import" param="file.name">
<fileset dir="${basedir}" includes="*-graph.xml" />
</foreach>
<target name="-import">
<import file="${file.name}" />
</target>
is in the ant-contrib tasks (http://ant-contrib.sourceforge.net/tasks/tasks/index.html) I'm not sure if this will work, I just came up with it on the fly.
Here is a simple way to deal with this problem:
<project name="the-name-of-the-project">
<import>
<fileset dir="${basedir}" includes="*-graph.xml" erroronmissingdir="false"/>
<fileset file="${ant.file.the-name-of-the-project}"/>
</import>
</project>
This way, the set of imported files is never empty since it includes the file containing this declaration. This works for <import> directives only, since it omits already imported files; <include> directives would trivially lead to a recursion.
Note the erroronmissingdir="false" is optional if basedir always exists.

What is the best way to compile J2ME and J2SE apps from the same codebase?

I'm trying to build an app for both J2ME and J2SE. The presentation code will obviously be different, but I'm hoping to keep the logic common, as much as possible.
My plan is to use Ant or Antenna's preprocessor to select either the J2ME or J2SE Graphics object, with that class being the only intersection between my logic and display code. All I need is to swap a line or two of imports in a few files during my Ant/Antenna build task.
I'd like some advice on how to get this set up.
I've currently got two Eclipse projects, one J2ME and one J2SE. I have a couple ideas for how I could set up the preprocessor:
Have the J2SE code be the default, and only preprocess the J2SE code to swap in the J2SE specific imports
Use the Antenna preprocessor for both the J2ME and J2SE projects
Use Ant text substitution to make the necessary source modifications
i. looks hard to get set up right
ii. feels a bit kludgy
iii. seems least bad, because I don't see myself ever needing to use much more than a few conditional imports.
Has anyone had experience with this sort of thing? Some advice would be much appreciated.
Both app versions have different ways to startup, right? One time it's a MIDlet and the other time a Java class with a static main method. In that case I don't see the requirement to use preprocessing. Both startup implementations could access the common code base and hand over either the J2ME or J2SE "graphics" object which implements an interface known to the common code base. This way the common code base does not need to know implementation details, it just needs the interface for the representation part.
BTW .. I had a similar situation some time ago and I felt more comfortable with setting up 3 Eclipse projects, a J2ME, a J2SE and a common logic project (technically also a J2ME project). This helps to prevent class name conflicts between the J2ME-/J2SE-only parts.
Antenna should do for most cases. The advantage of using a single source for both J2SE and J2ME is that you are saved from the maintenance of source code and you also eliminate the possibility of bugs creeping in. I too had similar problems, but I had to write a custom preprocessor that suited my need. But for most purposes antenna does the job beautifully
Edited: Sample build file
<project name="SomeProject" default="buildJ2ME" basedir="..">
...
...
...
<taskdef name="jadUpdater" classname="net.jxta.j2me.tools.Jad" classpath="${lib.dir}/jxta-tools.jar"/>
<taskdef resource="proguard/ant/task.properties" classpath="${lib.dir}/proguard.jar" />
<taskdef resource="antenna.properties" classpath="${lib.dir}/antenna-bin-1.0.2.jar" />
<macrodef name="preprocess">
<attribute name="source"/>
<attribute name="dest"/>
<attribute name="symbols"/>
<sequential>
<wtkpreprocess
version="2"
srcdir="#{source}"
destdir="#{dest}"
symbols="#{symbols}"
printsymbols="true">
</wtkpreprocess>
</sequential>
</macrodef>
<target name="compile" depends="init">
<copy todir="${temp.dir}/src" >
<fileset dir="${src.dir}"/>
</copy>
<preprocess source="${temp.dir}/src" dest="${temp.dir}/preprocessed" symbols="${symbols}"/>
<javac srcdir="${temp.dir}/preprocessed"
destdir="${temp.dir}/classes"
bootclasspath="${bootclasspath}"
classpath="${lib.dir}"
debug="off"
source="1.3"
target="1.1" />
<antcall target="jarForObfuscate"/>
</target>
<target name="buildJ2ME" depends="clean">
<property name="symbols" value="J2ME1,J2ME2"/>
<antcall target="compile"/>
</target>
<target name="buildJ2SE">
<property name="symbols" value="J2SE1,J2SE2"/>
<antcall target="compile"/>
</target>
...
...
...
</project>
Hope this helps!
I've done it once with all j2me libraries replaced by my own fakes. These fakes would call all the needed j2se lib calls.
Sounds like a lot of work, but actually a lot of calls are similar, and you are probably not using everything so you only need to create a small subset of the available j2me classes
Endresult: source code which nearly doesn't need any #ifdef stuff

Reasons for using Ant Properties files over "Properties Tasks"

I'm currently working with some developers who like to set up Ant tasks that define environment specific variables rather than using properties files. It seems they prefer to do this because it's easier to type:
ant <environment task> dist
Than it is to type:
ant -propertyfile <environment property file> dist
So for example:
<project name="whatever" default="dist">
<target name="local">
<property name="webXml" value="WebContent/WEB-INF/web-local.xml"/>
</target>
<target name="remote">
<property name="webXml" value="WebContent/WEB-INF/web-remote.xml"/>
</target>
<target name="build">
<!-- build tasks here --->
</target>
<target name="dist" depends="build">
<war destfile="/dist/foo.war" webxml="${webXml}">
<!-- rest of war tasks here -->
</war>
</target>
I am finding it hard to convince them that properties files are they right way to go. I believe properties files are better because:
They provides more flexibility - if you need a new environment just add a new properties file
It's clearer what's going on - You have to know about this little "trick" to realize what they're accomplishing
Doesn't provide default values and the ability to use overrides - if they used property files they could provide defaults at the top of the project but have the ability to override them with a file
Script won't break if an environment task isn't supplied on command line
Of course all they hear is that they need to change their Ant script and have to type more on the command line.
Can you provide any additional arguments in favor of properties files over "property tasks"?
Properties tasks tightly couple the build file to environments. If your fellow developers are arguing that they "have to change their ant script" with your suggestions, why aren't they arguing about changing it every time they have to deploy to a new environment? :)
Perhaps you can convince them to allow both properties file and command-line configuration. I set up my Ant builds so that if a build.properties exists in the same directory as the build.xml, it reads it in. Otherwise it uses a set of default properties hard-coded into the build. This is very flexible.
<project name="example">
<property file="build.properties"/>
<property name="foo.property" value="foo"/>
<property name="bar.property" value="bar"/>
...
</project>
I don't provide a build.properties with the project (i.e. build.properties is not versioned in SCM). This way developers aren't forced to use the property file. I do provide a build.properties.example file that developers can reference.
Since Ant properties, once set, are immutable, the build file will use properties defined in this order:
Properties provided with -D or -propertyfile via the command line
Properties loaded from build.properties
Default properties within build.xml
Advantages of this approach:
The build file is smaller and therefore more maintainable, less bug-prone
Developers that just can't get away from setting properties at the command line can still use them.
Properties files can be used, but aren't required
The arguments you have are already pretty compelling. If those arguments haven't worked, then arguing isn't going to solve the problem. In fact, nothing is going to solve the problem. Don't assume that people are rational and will do the most practical thing. Their egos are involved.
Stop arguing. Even if you win, the resentment and irritation you create will not be worth it. Winning an argument can be worse than losing.
Make your case, then let it go. It's possible that after a while they will decide to switch to your way (because it actually is better). If that happens, they will act like it was their own idea. There will be no mention of your having proposed it.
On the other hand, they may never switch.
The only solution is to work towards a position of authority, where you can say how things are to be done.
The problem with the first solution (using ant property) is basically hardcoding.
It can be convenient when you start a project for yourself but quickly you have to remove that bad habit.
I'm using a property file close to what said robhruska except that I have committed the build.properties file directly. This way you have a default one.
In other hand, I understand I could add those default values in the build.xml. (I will probably try that in the next hours/days ;-) ).
Anyway, I really don't like the first approach and I would force those guys to follow the second one ...

Resources