-
Notifications
You must be signed in to change notification settings - Fork 78
Bundles
ml-gradle provides a simple, Maven-repository-based mechanism for depending on external bundles of files for MarkLogic, where those files can be modules, resource config, data, system plugins, schemas, or anything else a bundle provider wants to include. This allows you to reuse MarkLogic assets without adding them to your own version control system, thus treating them as true thirdparty dependencies. This mechanism works for any module too - JavaScript, XQuery, REST extensions - anything you would normally load into a modules database can be loaded via this mechanism as well.
As an example of how to use this, this page refers to the marklogic-unit-test modules bundle. That Gradle file is also an example of how to create a bundle of reusable modules that can be published to any Maven repository and then depended on via the mechanism described below.
For a complete example that depends on a bundle including all kinds of supported files, please see this example project.
Prior to 3.13.0, the name of the Gradle configuration used for bundles was "mlRestApi". This is now named "mlBundle". "mlRestApi" is deprecated but still supported; both configurations are processed by the same ml-gradle task and are identical in function.
In our example, we'll have a project (such as the unit testing example project) that wants to reuse the marklogic-unit-test bundle of modules. With ml-gradle, all we need to do is add this to our build.gradle file:
repositories { mavenCentral() } // you may already have this in your Gradle file
dependencies { // If you already have a dependencies block, just add the line below to it
mlBundle "com.marklogic:marklogic-unit-test-modules:1.3.0"
}
That "mlBundle" configuration is created when the ml-gradle plugin is applied. It allows you to register any number of dependencies on bundles, such as marklogic-unit-test-modules.
The ml-gradle "mlPrepareBundles" task will then look for mlBundle dependencies. For each one that it finds, it extracts the expected zip file (which Gradle downloads for us automatically) to "build/mlBundle/(name of bundle)" (assuming "build" as the default Gradle build directory). Thus, if you were to run this task with the above dependency, you'll now have a "build/mlBundle/marklogic-unit-test-modules/ml-modules" directory containing all of the marklogic-unit-test modules.
A bundle can contain any number of directories and files. ml-gradle is only interested in certain directories though, as listed below:
- New in 3.14.0 - if an "ml-config" directory exists, its path will be prepended to the list of config paths that ml-gradle will load resource configuration files from. This allows for a bundle to e.g. include range indexes that are depended on by the modules that it provides. See the ml-app-deployer site for more information on which resource types support merging as well (merging is important if the bundle wishes to contribute configuration to a resource defined by your application as opposed to simply creating a new resource).
- If an "ml-data" directory exists, its path will be prepended to the list of data paths that ml-gradle will load data from - see Loading data for more information.
- If an "ml-modules" directory exists, its path will be prepended to the list of module paths that ml-gradle will load modules from. For example, on a DHF project, the set of module paths is usually "src/main/hub-internal/config" and "src/main/ml-config". If you depend on e.g. the marklogic-unit-test-modules, then your application will now have module paths of "build/mlBundle/marklogic-unit-test-modules/ml-modules", "src/main/hub-internal-config", and "src/main/ml-config".
- If an "ml-plugins" directory exists, its path will be prepended to the list of plugin paths that ml-gradle will install system plugins from - see Installing plugins for more information.
- If an "ml-schemas" directory exists, its path will be prepended to the list of schema paths that ml-gradle will load schemas from.
Now that we have a dependency on a bundle, we want to load the modules from that bundle into our modules database, in addition to our own application modules (we'll assume those are under the default directory of src/main/ml-modules).
It's rare that you'll run the aforementioned "mlPrepareBundles" task directly though. It's run automatically via mlDeploy, mlLoadModules, and mlReloadModules. Note that mlWatch does not depend on it - but see below for how to integrate bundles with mlWatch.
Thus, if we do a simple deployment using our example:
gradle mlDeploy
Then ml-gradle will load all of the marklogic-unit-test modules into the application's modules database.
The reason that these modules are loaded is because when mlPrepareBundles runs, it adds each "build/mlBundle/(name of bundle)/ml-modules" directory to the list of module paths that modules are loaded from. In addition, ml-gradle will load modules from these directories first, so that if your application modules - specifically REST API modules like services - import these library modules in these directory, those import statements will succeed.
The mlWatch task is very handy for automatically loading your application modules as you develop. Sometimes though, you may want to modify the code in a bundle to see what effect it'll have - perhaps in preparation for submitting a pull request to the owner of the bundle.
There are two ways to make mlWatch load modules from bundles. First, we can make mlWatch depend on mlPrepareBundles so that the list of module paths that mlWatch reads from includes those under "build/mlBundle/":
mlWatch.dependsOn mlPrepareBundles
Note if you take this approach, ml-gradle will overwrite any changes you've made already to files under "build/mlBundle" by extracting each bundle again.
Alternatively, you can modify mlModulePaths to explicitly add each directory - be sure to include your own application modules!
mlModulePaths=build/mlBundle/marklogic-unit-test-modules/ml-modules,src/main/ml-modules
This approach is useful to ensure that ml-gradle doesn't overwrite any changes you've made under build/mlBundle, as the mlPrepareBundles task won't be run.