-
-
Notifications
You must be signed in to change notification settings - Fork 502
Resolve competing web module war definitions
| Date | July 7 2020 | Contacts | Jody Garnett |
| Status | proposed | Release | 3.12 |
| Resources | Ticket # | pending | |
| Source code | pending | ||
| Funding | GeoCat, GeoNetwork Enterprise and professional services | ||
The web app contains competing build configurations (for both war:war and jetty:run) on the management of schema-plugins leading to build instability.
This proposal refactors web module structure to resolve this issue.
This proposal should simplify the build experience for everyone, and preserve the developer workflow you are used to, and document the result so it is easier to understand where to make any changes.
Initially proposed as a simple change to take advantage public OSGeo repository; this change has shown several limitations of the core-geonetwork build system for schema-plugins:
-
Use of schema-plugin version
3.7across different branches ofcore-geonetwork, combined with transitive dependencies, ensure conflicts across active branches ofcore-geonetwork. -
web app build copies contents folder to folder, rather than make use of schema plugin artifact
zipandjar.- The web app
warandjettyconfigurations actually directly watch some folders across module boundaries (sidestepping the distinction between copying folder content or unpackingzipcontents). This duplication gives some uncertainty when a change is noticed, and how to reliability pick up a change.
- The web app
-
web app contains competing build configurations (for both
war:warandjetty:run) on the management of schema-plugins leading to build instability -
See "baseline" heading further down this page for a detailed review of the current build system
The above limitations result in an unstable build environment.
References:
This approach:
-
Any required content is staged into a distinct
targetfolder byprocess-resources -
Respect that
target/geonetworkis reserved for use by the war plugin (andjetty:run-wartesting) and never stage content here directly -
Make
jetty:runa new folder fordata_directorynot insrc(which is static) ortarget(which is subject tomvn clean). -
Focuses on locking down the
wardefinition using unpack to extract distinct dependencieszipartifacts managed by maven (with no copying between folders).- Use of distinct
targetfolders - Use of a custom war assembly, if required, to produce exactly the war we want.
- There is an opportunity to use
jetty:run-warto test the war build chain. While this would respond tomvn process-resources, it would not be intended for interactive development.
- Use of distinct
-
Allow the
jettyconfiguration to work across folders- In this workflow
web-uiresources, and schema plugins folders would be used directly, noprocess-resourcesrequired. - Care taken to only use the maven dependencies to take advantage of jetty ability to watch the maven reactor and notice
mvn installbeing used. - If this approach works using
jetty:runwould be quicker and just focused on rapid development, there would not be any need to useprocess-resources(just update files directly for html, javascript and xslt, or use mvn install for java files).
- In this workflow
Discussion:
-
This proposal has the advantage of clearly supporting the two distinct workflows enjoyed by geonetwork developers.
This represent an improvement for developers as
process-resourcesis no longer be required to pick up changes. However there is a duplication of effort, and there may be some frustration testing thewarbundle as a result.Example:
- If you were using
jetty:runandprocess-resourcesto try out a schematron rule change - And then packaged a war for a customer
- You would of missed out including your rule change in the war
To fix:
- Use
mvn installto package the schema plugin intojarandzipfiles in the local maven repository - And then package war for customer (it will pick up the rule change which is provided by schema plugin
zipartifact)
- If you were using
-
Consider use of web context to replace use of filters, have multiple
jetty-context.xmlfiles to test differentdev,prod,inspire.The use of
jetty:runis primarily used withdevfilter. Thewar:warmakes use ofprodandinspirefilters are used to produce distinctwarbundles.This is a larger discussion, offering greater control to administrators, and will need to be the subject of its own proposal.
-
Q: The
gndatabase is created in the current directory, can this move totargetfolder?A: The only reason to keep in sources can be to avoid loosing the info with
mvn clean, but maybe then can be configured a profile to externalize the data directory? -
Q: Is it desirable to keep
data geonetworkandgndatabase?A: Yes, see above.
-
How to handle schema plugins
schfiles being compiled intoxsltfiles when GeoNetwork first starts up?If
jetty:runis using schema plugin directly to ideally generatexlsxinto a different location to avoid both the risk of accidental commit and accidentally including these files is generated war.
migrate module: a new module to package database migration into jar and zip artifacts.
src/main/javasrc/main/resources
Care needed to ensure zip artifact produced:
src/main/resources
The package-resources and compile stages use:
src/main/filterssrc/main/javasrc/main/resourcessrc/main/webappsrc/main/datasrc/main/webResourcestarget/classes-
target/doc- copied docs -
target/schemas- schema plugins updated bymvn process-resources -
target/webGenerated- generated webapp contents fromfiltersandwebResources
The war configuration uses:
-
src/assembly- custom war assembly to include license and avoid accidentally packaging contents src/main/resourcessrc/main/webappsrc/main/datatarget/classestarget/doc-
target/schemas- schema plugins updated bymvn process-resources target/webGenerated-
target/migrate- unpacked content from migrate module -
target/geonetwork/WEB-INF/lib/-gn-webjar and dependencies staged here
The jetty configuration uses:
src/main/resourcessrc/main/webapptest/java/org/fao/geonet/Start.java-
test/resources/jetty-context.xml- these dev settings (assume inspire or prod not needed here) -
test/webGenerated- generated webapp contents fromfilters/dev-env.propertiesandwebResources target/classes-
data_directory/data/- created from src/main/data for use by jetty -
../web-ui/src/main/resources- direct use of web-ui files -
../migrate/src/main/resources- direct use of sql files -
../schemas/../**/plugin/- direct use of schema plugins folders
The web module has quite a complex build chain supporting:
-
warcreation of ageonetwork.warthat includes schema plugins, a default data directory, and some environment specific customizations -
jetty:runsupporting something like:- immediate recognition of changes to html files and javascript files
- delayed recognition of changes to XSLT files (using
mvn process-resources) - creation of
gnh2 database in thewebfolder - direct use of
data directoryinsrc/main/webapp
For this discussion keep in mind the maven build life cycle (common steps in italic, default war stages described):
- validate
- initialize
- generate-sources
- process-sources
- generate-resources
- process-resources - resources:resource goal
- compile - compiler:compile goal
- process-classes
- generate-test-sources
- process-test-sources
- generate-test-resources
- process-test-resources - resources:testResources goal
- test-compile - compiler:testCompile goal
- process-test-classes
- test - surefire:test goal
- prepare-package
- package - war:war goal
- pre-integration-test
- integration-test
- post-integration-test
- verify
- install - install:install goal
- deploy - deploy:deploy goal
Each pom packaging type (pom, jar, war, ...) registers maven plugins to specific stages of the maven life cycle, along with appropriate plugin configuration. As an example war plugin configuration defines a default assembly definition that includes src/webapp.
References:
- http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference
- https://maven.apache.org/plugins/maven-war-plugin/index.html
- http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
The war packaging for the module defines several src folders:
-
src/main/javaDefine Geonetwork and other classes (compiled into
target/classes) -
src/main/resourcesDefine resources (compiled into
target/classes) -
src/webappStatic outline of war contents.
-
conversion -
doc -
htmlCache -
images -
loc- translations -
resources -
WEB-INFweb.xml
-
xml -
xsl -
xslt -
geonetwork.css -
modalbox.css
-
The build generate
-
src/main/filtersUsed to process
webResourcesintotarget/webapp -
src/webResourcesWEB-INF
Content processed into
target/webapp
The generate-sources registers two additional src folders:
-
src/main/java- add-src folder containingGeonetworkclass -
src/webapp/main/webapp/WEB-INF/classes/setup/sql/migrate- add-src folder for sql migration
The process-resources stages content into:
-
src/main/webapp/WEB-INF/data/config/schema_pluginsCollected from schema
plugincontent -
src/webapp/doc- from documentation manuals -
target/webappCopy filter
src/main/webResourcebased on env configuration
The compile stage builds:
-
target/classes- fromjavaandresources
The maven-war-plugin generates jar:
-
target/geonetwork/WEB-INF/lib/web-app-3.11.0-SNAPSHOT.jarContaining:
-
src/main/javacompiled classes -
src/main/resourcescontents -
src/webapp/main/webapp/WEB-INF/classes/setup/sql/migratecompiled classesThis is unusual having java source code in
src/webapp!
-
The maven-war-plugin generates war structure into target/geonetwork:
catalogconversiondochtmlCacheimageslocMETA-INFresourcesWEB-INFxmlxslxsltmodalbox.cssgeonetwork.css
Where content is collected from:
-
target/geonetwork:src/main/webappfiles -
target/geonetwork:target/webappfiles that have been processed -
target/geonetwork:../web-ui/src/main/resourcesfiles -
target/geonetwork/WEB-INF/data/config/schema_plugins:../schemasfiles from eachpluginfolder -
target/geonetwork/WEB-INF/lib/: maven dependencies -
with many excludes ...
xml/schemas/WEB-INF/data/*.dbWEB-INF/data/index/**- ...
These appear to be a safety measure to avoid including files produced when
src/main/webappis used as a live directory byjettybelow.
Observations:
-
⚠️ The handling ofsqlis very unusual -
The processing (using
filters) ofwebResourcesappears to duplicate functionality that should be controlled by web container.- Some work put into making the application configurable should remove the need to make custom wars for different environments.
- If needed for local testing a jetty context for each of these configurations would be a clean approach
-
⚠️ Working with the data directory insrc/main/webappresults in lots of strange workarounds:- Excludes in the war definition to avoid packaging "running" content
- Not quite documented process to "reset" your environment if you want a clean start
-
⚠️ : war definition including content form web-ui and schema plugins directly, whileprocess-resourceincludes the same content
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
<manifestEntries>
<Implementation-Build>${git.commit.id}</Implementation-Build>
</manifestEntries>
</archive>
<archiveClasses>true</archiveClasses>
<!-- Filter resources according to current profile properties
(see src/main/filters) and copy them to the webapp -->
<webResources>
<resource>
<directory>${project.basedir}/../schemas</directory>
<includes>
<include>**/src/main/plugin/*</include>
</includes>
<targetPath>WEB-INF/data/config/schema_plugins</targetPath>
</resource>
<resource>
<directory>${project.basedir}/../web-ui/src/main/resources</directory>
</resource>
<resource>
<directory>${build.webapp.resources}</directory>
</resource>
</webResources>
<!-- <packagingExcludes>WEB-INF/data/**</packagingExcludes> -->
<packagingExcludes>
xml/schemas/**,
WEB-INF/data/*.db,
WEB-INF/data/index/**,
WEB-INF/data/data/backup/**,
WEB-INF/data/data/resources/htmlcache/**,
catalog/lib/style/bootstrap/docs/**,
catalog/lib/style/bootstrap/fonts/**,
catalog/lib/style/bootstrap/grunt/**,
catalog/lib/style/bootstrap/test-infra/**,
catalog/lib/style/font-awesome/css/**,
catalog/lib/style/font-awesome/src/**,
catalog/lib/style/font-awesome/scss/**,
catalog/lib/style/font-awesome/*.json,
catalog/lib/style/font-awesome/Gemfile*,
catalog/lib/style/font-awesome/.*,
catalog/lib/style/font-awesome/*.txt,
catalog/lib/style/font-awesome/*.md,
catalog/lib/style/bootstrap/*.json,
catalog/lib/style/bootstrap/Gemfile*,
catalog/lib/style/bootstrap/.*,
catalog/lib/style/bootstrap/*.txt,
catalog/lib/style/bootstrap/*.md,
catalog/lib/bootstrap-table/*.json,
catalog/lib/bootstrap-table/Gemfile*,
catalog/lib/bootstrap-table/.*,
catalog/lib/bootstrap-table/*.txt,
catalog/lib/bootstrap-table/*.md,
catalog/lib/bootstrap-table/docs/**
</packagingExcludes>
<!-- <warSourceDirectory>src/main/geonetwork</warSourceDirectory> -->
<webXml>${build.webapp.resources}/WEB-INF/web.xml</webXml>
<attachClasses>true</attachClasses>
<warName>${application.name}</warName>
<webappDirectory>${project.build.directory}/geonetwork</webappDirectory>
</configuration>
</plugin>
The jetty-maven-plugin defines web application using:
- maven dependencies
target/geonetworksrc/main/webapp../web-ui/src/main/resources/target/webapp-
jett-context.xml: used to prevent jetty scanning jars during startup
Observations:
-
This configuration has been setup to use the "live"
src/main/webapplocation and pick up any changes each timemvn process-resourcesis called above. -
⚠️ schemas plugin folders are included twice:- in
target/geonetworkvia war definition - in
src/main/webapp/via process-resource copy
- in
-
⚠️ jars are included twice:-
target/geonetworklibs folder - as maven dependency
- example: An error starting up (where
domainjar has a conflict between jar included in libs and included by maven)
-
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<contextXml>${basedir}/jetty-context.xml</contextXml>
<webAppSourceDirectory>${project.build.directory}/geonetwork</webAppSourceDirectory>
<webApp>
<contextPath>/${application.name}</contextPath>
<descriptor>${project.build.directory}/WEB-INF/web.xml</descriptor>
<baseResource implementation="org.eclipse.jetty.util.resource.ResourceCollection">
<resourcesAsCSV>
${project.basedir}/src/main/webapp,
${rootProjectDir}/web-ui/src/main/resources/,
${build.webapp.resources}
</resourcesAsCSV>
</baseResource>
</webApp>
<systemProperties>
<systemProperty>
<name>org.eclipse.jetty.server.Request.maxFormContentSize</name>
<value>5000000</value>
</systemProperty>
</systemProperties>
<httpConnector>
<port>${jetty.port}</port>
</httpConnector>
<stopKey>JETTY_TOP</stopKey>
<stopPort>${jetty.stop.port}</stopPort>
</configuration>
</plugin>
- Type: Build system
- Module: schema plugins, metadata101, webapp, root
Vote Proposed: 14 July 2020
Project Steering Committee (voting):
- Emanuele Tajariol
- Florent Gravin
- Francois Prunayre
- Jeroen Ticheler
- Jesse Eichar
- Jose Garcia
- Paul van Genuchten
- Simon Pigot
- Jo Cook
Community support (non-voting):
- @jodygarentt (initial proposal)
- @jodygarentt
If you have some comments, start a discussion, raise an issue or use one of our other communication channels to talk to us.