This repository holds the hand-made parts of https://javadoc.scijava.org/: the front page, its stylesheet and its icons. It also documents how the rest of the site, the javadoc itself, is generated: by pombast, from the components managed by pom-scijava.
To contribute, please:
- fork the project,
- make your changes, commit and push,
- open a Pull Request.
-
Javadoc for each component, at a versioned path. E.g.
/org.scijava/scijava-common/2.100.1/. Analogous to javadoc.io, but also covering artifacts deployed to maven.scijava.org, and prepared in advance rather than on demand. -
A unioned index of all components managed by a BOM, per BOM release. E.g.
/org.scijava/pom-scijava/45.1.0/. Useful as a single link target for thejavadoctool, or for browsing the libraries of one BOM version. The union holds no class pages of its own: each one 301-redirects to the component that owns it. For example:/org.scijava/pom-scijava/45.1.0/net/imglib2/img/Img.htmlredirects to:
/net.imglib2/imglib2/8.0.0/net/imglib2/img/Img.htmlsince the
net.imglib2.img.Imgclass is part ofnet.imglib2:imglib2:8.0.0, the version pom-scijava 45.1.0 manages. -
Named unions over parts of a BOM, e.g. all of ImgLib2's components:
/org.scijava/pom-scijava/45.1.0/net.imglib2/. Each works like the full union, with its own index and landing page. -
latestaliases, which float to the newest release on the site:/net.imagej/ij/latest/→/net.imagej/ij/1.54p/, and/org.scijava/pom-scijava/latest/…→ the newest pom-scijava. These are 302 (temporary) redirects, so browsers never cache a stale target. A page the newest union no longer has (e.g. a class since removed) is sent to the newest older union that does, instead of a 404. -
The front page, from this repository.
The site also keeps old links working. Its earlier incarnation served
unversioned trees such as /ImageJ2/, /SciJava/ and /ImgLib2/; their
front pages now redirect to the project's named union, or else its main
component (e.g. /ImgLib2/ → /org.scijava/pom-scijava/latest/net.imglib2/),
and their class pages to the same class via a union (e.g. /ImgLib2/net/imglib2/img/Img.html →
/org.scijava/pom-scijava/latest/net.imglib2/net/imglib2/img/Img.html).
/Java{N}/ and /JavaFX{N}/ proxy the JDK and JavaFX API docs. Projects
whose javadoc lives elsewhere redirect there.
The site is designed around the idea of a Bill of Materials (BOM), which provides a list of managed components at particular versions that are tested and working together. By importing the BOM into your build, you can then depend on any combination of the managed components without explicitly declaring their versions, and the versions will be inferred from the BOM.
Now suppose you are developing a Java library L that depends on several managed
components: A, B, C, D, etc. One of the steps when building L is to generate
its javadoc, package it into a JAR file with classifier javadoc, and deploy
the resulting L-x.y.z-javadoc.jar artifact to a remote Maven repository.
These javadoc artifacts are useful for IDEs to browse javadoc on demand from within the user interface. But there are two major drawbacks:
-
Humans cannot read the javadoc directly in a web browser.
-
The
javadoctool cannot consume them as links when generating downstream javadoc, so your library L will not have hyperlinks to classes from dependencies A, B, C, D, etc.
For projects deployed to Maven Central, one solution is javadoc.io, which
offers on-demand browsing of any project that publishes javadoc classifier
artifacts as described above. Links to javadoc.io-hosted javadoc
(e.g. SciJava Common v2.87.1) can be passed to the javadoc tool as links,
and the javadoc for your library L will then have hyperlinks to the classes
of dependencies A, B, C, D, etc., for which javadoc.io links were provided.
There are still challenges, however:
-
For each link given to the
javadoctool, itselement-list(package-listin older versions of Java) index must be fetched. Unfortunately, this step is slow, scaling linearly by the number of links given. For projects with many dependencies, each with its own javadoc.io link, this can bloat javadoc generation time by many minutes. In an empirical test, building javadoc for a small project with no links took 11 seconds, with 37 links took 48 seconds, and with 231 links took 215 seconds. -
The javadoc.io service does not support javadoc artifacts published to Maven repositories other than Maven Central. So projects published to maven.scijava.org, for example, cannot be browsed there. And as far as I know, the server-side javadoc.io code is not open source, so configuring javadoc.scijava.org to work analogously, but for maven.scijava.org instead of Maven Central, requires coding our own solution.
That solution is pombast's javadoc command. Its BOM union gives the
javadoc tool a single, fast link target, so builds stay quick and embed
permanent, reproducible links. Every available javadoc of every component
managed by every pom-scijava release on the site sits at a canonical,
versioned location.
For each release of the BOM, pombast javadoc:
-
Resolves every managed component's full dependency closure, as Maven would, so the components it depends on are included too.
-
Unpacks each component's
-javadocJAR into/{groupId}/{artifactId}/{version}/. Where none is published, or it is an empty stub (as some projects publish to satisfy Maven Central's rules), it generates the javadoc from the component's-sourcesJAR instead, as leniently as thejavadoctool allows. -
Cross-links each component's javadoc against the versions it actually depends on, not the versions the BOM manages, so a component's pages are the same whichever BOM brought it in. Old javadoc that linked to the unversioned trees (e.g.
/SciJava/org/scijava/Context.html) is rewritten to link to the exact versioned page instead, class names that were never linked become links, and JDK links point at the component's target Java version under/Java{N}/. -
Builds the unions for that BOM release, and regenerates the site-wide redirect maps (union paths,
latestversions, andlatestfallbacks) from everything on disk.
Component javadoc is cached per version, so each new BOM release only adds
the component versions it introduces. pombast keeps its load on Maven
repositories low: requests are spaced out, misses (e.g. a component that
publishes no -javadoc JAR) are remembered rather than retried each run,
and a run stops at the first refusal from a repository. Each run reports
how many requests it made.
| What | Where |
|---|---|
| Front page, stylesheet, icons | this repository |
| The generator, and the script that publishes its output | pombast (pombast javadoc, bin/publish-javadoc.sh) |
| What is built: settings and named unions | pom-scijava's pombast.toml, [javadoc] section |
Redirect rules (legacy paths, latest, unions, proxies) |
uw-loci/loci-servers (private), apache/sites/javadoc.scijava.org.include |
JHotDraw 7.6.0's javadoc was imported once from the old site, since no
-javadoc or -sources JAR of it is published.
On the server, build each new pom-scijava release into the build tree, then publish:
cd pom-scijava
pombast javadoc --workers 2 -o ~/javadoc-build org.scijava:pom-scijava:45.1.0
../pombast/bin/publish-javadoc.sh -s ../javadoc.scijava.org \
~/javadoc-build /var/www/javadoc/releases /var/www/javadoc/currentpublish-javadoc.sh hard-links the build tree into a new, timestamped
snapshot under /var/www/javadoc/releases/, lays this repository's files
over it, converts the redirect maps into the format Apache reads, and then
switches the /var/www/javadoc/current symlink to it in a single step.
/var/www/javadoc.scijava.org, the web server's document root, points at
current. Visitors therefore see either the old site or the new one, never a
half-published one. Since the snapshots share unchanged files, each costs
about a gigabyte rather than another copy of the site. The newest three are
kept; to roll back, point current at an older one:
cd /var/www/javadoc
ln -sfn releases/OLDER-STAMP current.new && mv -T current.new currentUse publish-javadoc.sh -n to see what it would do without doing it.
.tests/check.py checks the live site's URL behavior, following redirects
while they stay on the site:
contract: the expectations in.tests/contract.txt, one path per line with the status or URL it must end at: versioned pages, unions,latest, legacy paths, proxies, and external redirects.legacy: the links in.tests/legacy-urls.txt, sampled from real traffic to the site's old unversioned trees, must each still reach the same page.index: every link on the front page, from this checkout'sindex.html, so a proposed change is checked before it is published.
python3 .tests/check.py # all checks, against javadoc.scijava.org
python3 .tests/check.py index -v # one check, listing passes too
python3 .tests/check.py --base http://localhost:8080 contractIt needs only Python 3. GitHub Actions runs it on every push and pull request.
Since most breakage would come from outside this repository (the server's
configuration, a new publish, or a proxied site changing), it should also run
after each publish, and daily on the server, where -q keeps it silent
unless something fails, so cron mails only failures:
17 6 * * * cd ~/code/scijava/javadoc.scijava.org && git pull -q && python3 .tests/check.py -q- Add a 64×64 icon to
images/. - Add a box to
index.htmllinking to the project'slatestjavadoc, e.g.org.example/example/latest/, or to a named union for a project of many components. - If the project should get a named union, add it to pom-scijava's
[javadoc.unions]. - Publish as above.