New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize the project to mostly-Maven conventions #16

Open
wants to merge 1 commit into
base: master
from

Conversation

Projects
None yet
2 participants
@io7m

io7m commented Feb 14, 2017

Hello!

I began looking at the existing POM files, and after pulling on the initial thread I ended up unravelling the entire garment and ended up replacing the entire build system with a modern Maven-based implementation. There are a few new test failures, the causes of which I've not yet tracked down but which are almost certainly caused by resource files no longer being where the test suite assumes they are. See the rather lengthy commit message for details!

I can deploy the packages to Central (see #1) with or without these changes, so it's entirely up to you whether or not you integrate them. By the time this pull request has been posted, you should have received my signed contributor agreement at your published address.

This commit encompasses a number of changes to convert the project
from a traditional Ant-style build into a more modern Maven-style
build. This comes with the usual benefits of declarative dependency
management, easy deployment to Maven Central, centralization of project
metadata such as version numbers, the removal of fragile imperative
build scripts, better IDE support, and the production of *correct*
OSGi bundles by default.

Some trade-offs were made between strictly following Maven
conventions, and producing build artifacts that look and behave
the same as previous XOM releases. The choice was made to preserve
compatibility in preference to arguably more solid engineering
practices: No attempt was made to modularize the codebase, and the
general approach taken by the Ant build was minimally transformed
into its Maven equivalent. Primarily, this commit defines a new POM
file and moves the project sources into something fairly close to
the standard Maven conventions.

  * The bulk of the sources moved from src to src/main/java
  * The contents of "fatsrc" (the String based Text object
    implementation) were moved to src/main/java-fat
  * The default Text object implementation was moved from src
    to src/main/java-lowfat
  * Sample code was moved to src/samples/java
  * Unit tests were moved to src/test/java
  * Resource files such as characters.dat were moved from src
    to src/main/resources
  * The <= JDK 1.5 sources were moved to src/main/java-jdk15

This division of source files allows for stronger separation of
dependencies: The library previously declared a non-optional dependency
on JUnit simply because the test files lived in the same source tree.
A few very minimal code changes were required to look up resources
in /nu/xom instead of /src/java/nu/xom. This junit dependency actually
prevented the XOM bundle from resolving inside OSGi containers unless
the not-currently-OSGi-compatible junit package was deployed inside
the container.

The custom Ant tasks have been turned into Maven profiles: Enabling
the "nu.xom.lowfat" profile adds the src/main/java-lowfat directory
to the build. This happens by default. Enabling the "nu.xom.fat"
profile instead adds the src/main/java-fat directory to the build.
The "nu.xom.jdk15" profile is enabled if a JDK older than 1.6 is
detected, and this adds the src/main/java-jdk15 directory to the
build. Finally, the "nu.xom.deployment" profile is enabled if a
"nu.xom.deployment" property is defined in the environment (via
Maven's ~/.m2/settings.xml or on the command line with -D). This is
provided to conditionally enable the PGP signing of all artifacts
for deployment to Maven Central.

Additionally, this commit folds the website generation work
into declarations bound to the standard Maven "site" phase. It
uses the maven-source-plugin and maven-javadoc-plugin to generate
Central-compliant source and javadoc JARs that work nicely in IDEs.
The POM file also contains accurate links to the current mailing list,
issue tracker, GitHub source repos, etc. The Apache Felix Maven Bundle
plugin is used to produce JAR files that have manifests identical to
those produced by the old Ant task whilst also containing somewhat more
"correct" OSGi metadata.

Affects #8
Affects #1

Reorganize the project to mostly-Maven conventions
This commit encompasses a number of changes to convert the project
from a traditional Ant-style build into a more modern Maven-style
build. This comes with the usual benefits of declarative dependency
management, easy deployment to Maven Central, centralization of project
metadata such as version numbers, the removal of fragile imperative
build scripts, better IDE support, and the production of *correct*
OSGi bundles by default.

Some trade-offs were made between strictly following Maven
conventions, and producing build artifacts that look and behave
the same as previous XOM releases. The choice was made to preserve
compatibility in preference to arguably more solid engineering
practices: No attempt was made to modularize the codebase, and the
general approach taken by the Ant build was minimally transformed
into its Maven equivalent. Primarily, this commit defines a new POM
file and moves the project sources into something fairly close to
the standard Maven conventions.

  * The bulk of the sources moved from src to src/main/java
  * The contents of "fatsrc" (the String based Text object
    implementation) were moved to src/main/java-fat
  * The default Text object implementation was moved from src
    to src/main/java-lowfat
  * Sample code was moved to src/samples/java
  * Unit tests were moved to src/test/java
  * Resource files such as characters.dat were moved from src
    to src/main/resources
  * The <= JDK 1.5 sources were moved to src/main/java-jdk15

This division of source files allows for stronger separation of
dependencies: The library previously declared a non-optional dependency
on JUnit simply because the test files lived in the same source tree.
A few very minimal code changes were required to look up resources
in /nu/xom instead of /src/java/nu/xom. This junit dependency actually
prevented the XOM bundle from resolving inside OSGi containers unless
the not-currently-OSGi-compatible junit package was deployed inside
the container.

The custom Ant tasks have been turned into Maven profiles: Enabling
the "nu.xom.lowfat" profile adds the src/main/java-lowfat directory
to the build. This happens by default. Enabling the "nu.xom.fat"
profile instead adds the src/main/java-fat directory to the build.
The "nu.xom.jdk15" profile is enabled if a JDK older than 1.6 is
detected, and this adds the src/main/java-jdk15 directory to the
build. Finally, the "nu.xom.deployment" profile is enabled if a
"nu.xom.deployment" property is defined in the environment (via
Maven's ~/.m2/settings.xml or on the command line with -D). This is
provided to conditionally enable the PGP signing of all artifacts
for deployment to Maven Central.

Additionally, this commit folds the website generation work
into declarations bound to the standard Maven "site" phase. It
uses the maven-source-plugin and maven-javadoc-plugin to generate
Central-compliant source and javadoc JARs that work nicely in IDEs.
The POM file also contains accurate links to the current mailing list,
issue tracker, GitHub source repos, etc. The Apache Felix Maven Bundle
plugin is used to produce JAR files that have manifests identical to
those produced by the old Ant task whilst also containing somewhat more
"correct" OSGi metadata.

Affects #8
Affects #1
@io7m

This comment has been minimized.

io7m commented Feb 14, 2017

This is, of course, an initial pass at the problem and I'm open to suggestions for improvement. Right now, for example, the build doesn't produce a xom-samples.jar, so I should probably add this.

@elharo

This comment has been minimized.

Owner

elharo commented Feb 14, 2017

This is something I've considered and rejected in the past. It might be time to revisit this, but no promises.

@io7m

This comment has been minimized.

io7m commented Feb 14, 2017

Understood!

@elharo

I don't see a lot of benefit to moving all the files around and churning the repo. It should be possible to point maven to the relevant existing directories.

@io7m

This comment has been minimized.

io7m commented Feb 19, 2017

There were files moved for more than one reason:

  1. Separating the resource files such as characters.dat from the source files is a Maven convention. Viewed in isolation in a project such as XOM which only has a couple of resource files that aren't filtered or otherwise manipulated, there's no obvious benefit to doing this besides discoverability: Developers look at a Maven project and immediately know where everything is. In practical terms, you certainly could mix those resource files in with the source files, but then you'd have to instruct the resources plugin to ignore all the source files when inserting resources into the final JAR file.

  2. Separating the unit tests and the core sources happened for a number of reasons: Dependencies such as junit should not be in the same "scope" as the actual dependencies of the project. IDEs understand dependency scopes and automatically and separately configure the classpath correctly for the code and the tests. By placing the sources and the test sources in separate trees, IDEs tend to do the right thing immediately. By mixing the core sources and test sources in the same tree, you'd then have to tell the sources and javadoc plugins to explicitly include or ignore files depending on what artifacts they're supposed to be producing. Additionally, there's always the risk of polluting the OSGi metadata with unwanted dependencies (because the plugin will see that source files within the tree try to access junit and helpfully add imports for the junit packages unless explicitly overridden).

Were there other file moves that you don't like that I've forgotten about?

I'd argue that one of the main benefits of Maven is uniformity: I can (and do) routinely work with Maven projects without any prior knowledge of the projects and can always find everything I need right away as they follow a set of well-understood conventions. Each time you tell Maven to do something against those conventions, you lose a small piece of those benefits. I could have pushed this even further with the XOM build (creating separate modules for the optional dependencies), but that would have required breaking historical compatibility, so I didn't.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment