Skip to content

Writing your own task

Rob Rudin edited this page Jan 25, 2023 · 9 revisions

Custom tasks that talk to the Manage API

ml-gradle wraps ml-app-deployer with a number of tasks, but in case you want to do something with the MarkLogic Manage API that isn't yet supported by ml-gradle, you can simply write a new Gradle task and use an instance of ManageClient to easily invoke Management API endpoints. The ManageClient wraps an instance of Spring's RestTemplate and is already configured with the connection properties in your gradle.properties file.

The sample-project Gradle file shows an example of how to do this, and an example is shown below as well. This simple example invokes a database endpoint for merging a database, and it utilizes the "postJson" convenience method on ManageClient along with configuration data found in the AppConfig instance returned by "getAppConfig".

task mergeContentDatabase(type: com.marklogic.gradle.task.MarkLogicTask) {
    doLast {
        getManageClient().postJson("/manage/v2/databases/" + getAppConfig().getContentDatabaseName(), '{"operation":"merge-database"}')
    }
}

If your task is performing some action that you'd like to be part of a deployment, you can add it to the end of a deployment via the following in your build.gradle file:

mlPostDeploy.dependsOn myCustomTask

Also see Configuring ml-gradle for more information on the AppConfig object and how to manipulate it.

Custom tasks that talk to the Client REST API

If you need to talk to the REST API port associated with your application, you can extend MarkLogicTask and get an instance of a MarkLogic DatabaseClient:

task example(type: com.marklogic.gradle.task.MarkLogicTask) {
  doLast {
    def client = newClient()
    // Do something with the client - see http://docs.marklogic.com/javadoc/client/index.html
  }
}

New in 3.8.0 - if you're looking to call a custom REST service - e.g. something of the /v1/resources/(name of resource) variety - you can use CallResourceTask:

task callMyService(type: com.marklogic.gradle.task.client.CallResourceTask) {
  // client = hubConfig.newFinalClient() - This defaults to newClient(), and you may want to override this in a Data Hub Framework application
  resourceName = "changeme" // The name of the resource
  method = "GET" // or PUT, POST, or DELETE
  params = [:] // Create a Groovy map here of any parameters you wish to pass in
  mimeType = "application/json" // This is the default value, override as needed
  body = '{"hello":"world"}' // For a PUT or POST, the request body to send
  outputFilePath = "build/output.txt" // If the call returns a response, can write it to a file instead of to stdout
}

You can also write a task with custom XQuery or JavaScript code by extending ServerEvalTask, which uses the DatabaseClient returned by newClient():

task myXQueryTask(type: com.marklogic.gradle.task.ServerEvalTask) {
  xquery = "my XQuery code here"
}

task myJavascriptTask(type: com.marklogic.gradle.task.ServerEvalTask) {
  javascript = "my JS code here"
}

Starting in 3.14.0, you can also specify a custom DatabaseClient on an instance of ServerEvalTask - for example, in a Data Hub project, you may do:

task myJavascriptTask(type: com.marklogic.gradle.task.ServerEvalTask) {
  client = hubConfig.newStagingClient()
  javascript = "my JS code here"
}

You can also use the following approach to access any database - though bear in mind, when you use the App-Services port, you likely won't have access to your modules database:

task myJavascriptTask(type: com.marklogic.gradle.task.ServerEvalTask) {
  client = mlAppConfig.newAppServicesDatabaseClient("name of database")
  javascript = "my JS code here"
}

Note that ServerEvalTask will simply print any result it receives from MarkLogic. If you wish to make a call to MarkLogic and do something with the result, it's better to follow the example above that defines a task based on MarkLogicTask - for example:

task example(type: com.marklogic.gradle.task.MarkLogicTask) {
  doLast {
    def client = newClient() // Or construct a DatabaseClient however you wish
    def script = "fn.currentDateTime()" // Replace this with whatever script you wish to run
    def result = client.newServerEval().javascript(script).evalAs(String.class)
    // And now do whatever you want with the result
  }
}
Clone this wiki locally