Hello all
I'm back on work more immediately related to ISO 19115 and I'm still
facing a blocking issue. A solution exists, but is not very satisfying.
The ISO/OGC standards are huge, and use a large amount of different XML
schemas with different prefixes. The new revision of ISO 10115 (to be
published this year) adds yet more prefixes in the mix. Some of those
prefixes are hard-coded in Apache SIS [1], but this list is still
incomplete.
XML uses prefixes in order to differentiate tags of different schemas, a
little bit like Java uses package names to differentiate classes of
different libraries. Problem is: those prefixes are auto-generated by
JAXB at marshalling time, and those auto-generated names are not very
informative ("ns1", "ns2", "ns3", etc.). JAXB provides a @XmlSchema
annotation allowing us to specify explicitly the prefixes, but it
doesn't seem to work well with JAXB 2.1.
With JAXB 2.1, there is apparently no other way to control the prefixes
than subclassing com.sun.xml.internal.bind.NamespacePrefixMapper.
Problem is: this class is obviously internal, so we are not supposed to
use it. However in this particular case, Sun/Oracle seems to have made
an exception to their own rules since NamespacePrefixMapper is publicly
advised as the way to control prefixes ([2], [3]).
I have read reports on internet saying that the @XmlSchema annotation
has been fixed in JAXB 2.2.4. However while JDK 1.7.0_15 is bundled with
JAXB 2.2.4-2 (so it would theoretically work), JDK 1.6.0_37 is still
bundled with JAXB 2.1.10 so @XmlSchema would not work on that platform.
Furthermore I have not yet verified if @XmlSchema on JDK7 really works
for us, and even the JAXB 2.2.6 documentation still advise
NamespacePrefixMapper as the way to control prefix names [3].
So I'm tempted to continue to use NamespacePrefixMapper for now (this is
what was done on Geotk), until we verified that the standard annotations
work. We may have to commit the NamespacePrefixMapper hack anyway since
(in my understanding) @XmlSchema will never work on Oracle JDK6. At some
later time, we could remove the hack on the JDK7 branch while keeping it
on the JDK6 branch.
However while com.sun.xml.internal.bind.NamespacePrefixMapper exists in
every Oracle JDK6/7 distributions, it is not accessible by the javac
compiler. Some possible workaround are:
* Use the non-standard -XDignore.symbol.file javac option, which will
disable the exclusion of "com.sun" packages. However this is an
Oracle-specific option.
* Explicitly put rt.jar on the classpath as a Maven dependency using
<scope>system</scope>. But this is again Oracle-specific, and is ugly.
* Provide a skeleton of
com.sun.xml.internal.bind.NamespacePrefixMapper in the sis-utility
module with only the signature of the methods that we need to
override (hopefully it would not be a licensing violation if we do
not provide any code), and exclude that class file from the JAR file.
The last workaround seems the only JDK-independent solution to me.
However if we choose this approach, we still have to find how to exclude
the com/** classes from the JAR file. The maven-jar-plugin has an
<exclude> configuration option for that [4], but despite all my attempts
I have been unable to make it work - I tried in the root pom.xml, in the
module pom.xml, inside and outside <execution> block, with different
goals, with different paths (relative, absolute), Maven seems to just
ignores any configuration and unconditionally include the com.sun files.
Surely I'm doing something wrong, but I didn't found what. I also tried
the maven-clean-plugin execution under the "process-classes" phase,
without more luck (plugin is executed, but my include/exclude
configuration is ignored). This leave us with one more goal we could
define in our custom sis-build-helper plugin...
So in summary, one way to go forward would be:
* Use NamespacePrefixMapper despite being in a package that we are not
supposed to use.
* Commit a skeleton of NamespacePrefixMapper in sis-utility module, so
we can compile.
* Add a goal in sis-build-helper for deleting the above class before
building the JAR file.
* After we verified that the tests pass, try to replace
NamespacePrefixMapper by the standard @XmlSchema annotation on the
JDK7 branch (but we would probably have to keep
NamespacePrefixMapper on the JDK6 branch). It is possible that
@XmlSchema still doesn't work well enough on JDK7 and that we have
to wait for JDK8 before removing NamespacePrefixMapper.
Is there any comment, or an other approach that we could try? For the
record, JIRA task is at [5].
Martin
[1]
https://svn.apache.org/repos/asf/sis/trunk/sis-utility/src/main/java/org/apache/sis/xml/Namespaces.java
[2] http://java.sun.com/webservices/docs/1.5/jaxb/vendorProperties.html
[3]
http://jaxb.java.net/nonav/2.2.6/docs/ch03.html#marshalling-changing-prefixes
[4] http://maven.apache.org/plugins/maven-jar-plugin/usage.html
[5] https://issues.apache.org/jira/browse/SIS-74