...
Whether we use vanilla Apereo code or make Yale modifications depends on Yale requirements, staffing, and management. There is a cost and commitment to maintaining a modification, but there is also a problem if some application does not work correctly or if some Yale need is not being properly addressed.
The Parent pom.xml
The top level directory is the "parent" project. Typically it is named "cas-server" although this is simply a choice you make when you check the source out from SVN into Eclipse. The only thing in the parent project is its pom.xml file, and a few README-type files.
Changing the parent pom.xml file is one of the most complicated problems of migration from one CAS release to another. Any other file in CAS, whether Java source or HTML has pretty much the same purpose at Yale that it had in the original Apereo code.
However, the top level pom.xml file is not just about compiling the source and building the template WAR file (which is the part Yale needs). Apereo is in the business of maintaining an Open Source Project that is distributed widely on the Internet. A large part of their concern is to make sure that all the legal boilerplate is properly maintained. Do the files all have a proper copyright notice? Are all the licenses to the dependency files properly listed? Maven has some impressive support for doing all this open source release management, but unless that is something you specifically have learned, setting up the legal boilerplate is a daunting task.
Yale is a CAS customer. We may have our own files, but unless and until we contribute them back to Apereo we do not care if a file that nobody sees outside Yale has a proper open source copyright notice and license declaration. If we try to use the Apereo top level pom.xml file as distributed, then every time we try to cut a Yale release we get error messages for all the boilerplate that is missing from our own files. So we generally modify the Apereo top level POM file to remove the "open source project and distribution management" junk we don't need. This has to be done again each time we get a new release of CAS.
Every so often Apereo generates a release that has some new processing step added to the build, and that in turn requires adding something to the top level pom.xml file. When that happens we have to notice it and add the same configuration item to our version of the file.
The Yale top level pom.xml file contains the following sections:
- Version - The Yale pom.xml has Yale version IDs (1.1.2-SNAPSHOT) instead of Apereo (3.5.2.1).
- SCM - defines the Yale Subversion server where all Yale projects maintain their production source.
- Repositories - defines Yale's Artifactory, but merged with other sources for artifacts from the Apereo pom.
- pluginManagement - Maven is a modular system of extensible functions implemented by optional "plugin" modules. Yale has to maintain the plugin configurations that actually build the code (the AspectJ processing plugin for example) while dumping the open source project boilerplate managing steps (the maven-license-plugin and maven-notice-plugin for example). We also reconfigure some plugins. For example, when you are done working on Version 1.1.1-SNAPSHOT and want to create the official 1.1.1 Yale version of CAS and then reset the project to begin work on 1.1.2-SNAPSHOT, you call the Yale Jenkins Build job "Perform Maven Release" operation, which in turn uses the maven-release-plugin. At Yale we find that running the JUnit tests during this process is not only slow but a bad idea, so we change the configuration of the release plugin in the parent pom to bypass tests.
- dependencyMangement - the top level pom.xml lists standard version numbers for dependency JAR libraries shared by all the projects at compile and run time. Unfortunately, when Yale develops its own code it may need a later version of the same library. For example, Apereo is happy with commons-io Version 2.0, but Yale code needs Version 2.4. Apache is smart enough to make the 2.4 library downward compatible with programs written for 2.0, but swapping a newer better version of a library is tricky. The first step is that our top level pom.xml declares the 2.4 version to be the one we want so that all our projects use the same version. This also ensures that the 2.4 version of the commons-io JAR will be merged into the WAR during the Overlay processing.
- However, there is a final processing step that has to be done in the WAR Overlay project and is related to but not directly specified in the parent pom.xml file. Because we are using some unmodified CAS 3.5.2.1 modules (particularly cas-server-webapp) and then we merge in new libraries from the WAR Overlay project, the resulting cas.war file would have a WEB-INF/lib with both commons-io-2.0.jar (from vanilla cas-server-webapp) and commons-io-2.4.jar from the Yale Overlay WAR project. So we have to add an exclude statement in the configuration of maven-war-plugin in the WAR Overlay project to remove the unwanted commons-io-2.0.jar file). Generally speaking, we remove any file that the build process would normally include that is bad for JBoss or where there are multiple versions of the same code and we only want to keep the latest version.
- modules - The directory contains the source and pom files for all the Apereo code. However, we only want to compile things that have been changed. Maven only looks at subdirectories mentioned by a <module> statement in the top level pom.xml file. Initially we comment out all the Apereo <module> statements and add statements for the Yale subprojects. When an Apereo project is to be changed, then it is reassigned a Yale (1.1.x-SNAPSHOT) ID and its <module> statement is uncommented. From one CAS release to another the inventory of Apereo projects and <module> statements changes and has to be updated even if they start out all commented out.
- Parameters - At the end of the POM there are <parameter> statements that Apereo uses to specify the version numbers of dependency libraries and Java.
Subversion
One weakness of Subversion is that it tracks history based on the name and path of a file. If you rename or move a file, Subversion "loses" its history. Git does not suffer from this problem, and if we really did serious ongoing "development" in CAS all the time Git would be a much better source repository for us to use.
However, Subversion is the Yale standard for source used in production deployment, so everything has to be checked into Subversion at some point if only to put it into the DEV, TEST, and PROD computers in the machine room. Since Yale does not do continuous CAS development, but rather generates a CAS release and then runs it for years before starting work on a new release, a break in source control file history across that two year gap is acceptable.
So in any given cycle of CAS development, you begin by obtaining a copy of the current CAS release from Apereo. You then replace the top level pom.xml with a new one created by merging any changes made by Apereo since the last release with the prior Yale top level pom.xml (and this has to be done manually by someone who understands Maven). Then you merge in the Yale added subdirectories.
This becomes a new project in the /cas area of Yale Subversion. Because it is nominally new, you start without history. If you want to see the history for Apereo code, use Git. If you want to see the actual history of Yale modules, find the Subversion directory of previous CAS development projects.
...
Subversion
If you check out a project from Subversion, then you rename a file or copy it to another directory, and then commit the changes, Subversion doesn't realize that the file has been renamed or moved. It sees that the original file name is no longer where it once was, and that a new file name has appeared in the directory, so it treats this as a delete and a create. All the file history is lost.
The command level Subversion client has commands that copy a file and link its old history to its new location. So if it matters, there are some things you should do with Subversion outside the Eclipse environment. This is easy to learn with any Linux Sandbox development environment.
During Sandbox development your complied JAR and WAR artifacts are stored in the local Maven repository on the Sandbox machine. However, the result of Sandbox development is to make and commit source changes to the Subversion version of the project. When you move to DEV (and then TEST and PROD) the Jenkins Build process will check out and compile the project and build new copies of the artifacts on the Jenkins managed machines and store them in the Artifactory network server.
An Eclipse project is built when you check a Maven project out of Subversion into the Eclipse Workspace. Generally a Sandbox instance will contain an Eclipse Workspace directory, it will contain a CAS project, and that project will contain source from some earlier version of CAS development. The first step when you begin work on CAS is to update the source in the workspace project with the latest version from Subversion.
There is a small amount of customization that has to be done manually after the project is checked out of Subversion into an Eclipse Workspace. For example, every Maven J2EE project seems to default to Java 1.6 while Yale CAS modules are written to use Java 1.7. So you have to manually go in and change the project defaults and the generated library section of the Eclipse Build configuration. Updating the contents of an existing Eclipse project preserves this customization, while checking out a complete new Maven project from Subversion means you will have to redo the small amount of post checkout project cleanup.
The Jenkins Build and Install Jobs
...