Contact Free trial Login

VeevaVault Connector Examples - Mule 4

You can use the provided example project as a starting point for your MuleSoft project.

Create Documents on the Vault

This example creates documents in bulk with document metadata fetched from an external source (database). Before creating documents on the Vault, the document files are uploaded using the Veeva Vault FTP server. The documents' created status is inserted into the database.

To create the Mule flow:

  1. Drag and drop HTTP Listener from the Mule Palette to the project canvas.

  2. Configure HTTP Listener for your environment.

  3. Drag the Database Select operation to fetch document metadata from the table.

  4. Configure the Database Connector configuration with your connection credentials.

  5. Drag the Flow Reference element to reference the Sub Flow upload-files-on-vault-ftp-server.

  6. Drag the Transform Message component to transform document metadata into CSV format.

  7. Drag the Create Documents operation from the VeevaVault Connector palette.

  8. Enter the values for the Veeva Vault connection:

    • Username

    • Password

    • Vault URL

    • Vault version

    • Vault client ID

  9. Drag the Database Bulk Insert operation to insert the document created status data into the database table.

  10. Drag the Logger component to log information in the console or log file.

  11. Create a sub-flow with the Logger component to log information for the sub-flow.

  12. Drag the For-Each scope containing the Read file operation and FTPS Write operation to write the file to the Veeva Vault FTP server.

  13. Configure the FTPS Connector configuration with the credentials for the Veeva Vault FTP server.

Studio Flows

veevavault connector create documents example
veevavault connector upload documents example

XML Code

The following example XML code shows the Create Documents operation flow:

<flow name="create-documents-operationFlow"
doc:id="98fe428d-3961-41e9-afaf-1cbe2b38dee5" >
    <http:listener doc:name="Listener" doc:id="a894ea19-6344-4553-aa50-b7827c8e8096" config-ref="HTTP_Listener_config" path="/create-documents"/>
    <db:select doc:name="Select" doc:id="e5af2ee1-faf6-4397-aea8-7df1ca873abb" config-ref="Database_Config">
        <db:sql >SELECT * FROM createdocuments</db:sql>
    </db:select>
    <!-- <flow-ref doc:name="upload-files-on-vault-ftp-server" doc:id="8be764bb-bf76-4c9f-870b-fe708077e28e" name="upload-files-on-vault-ftp-server"/> -->
    <ee:transform doc:name="Transform Message" doc:id="ac21fdf2-9117-4201-a595-907e4dd1ea12">
        <ee:message>
            <ee:set-payload><![CDATA[%dw 2.0
output application/csv headerLineNumber = 0 , header = true
---
payload map ( payload01 , indexOfPayload01 ) -> {
	lifecycle__v: payload01.lifecycle__v,
	study__v: payload01.study__v,
	subtype__v: payload01.subtype__v,
	name__v: payload01.name__v ++ '--' ++ randomInt(10000) as String,
	type__v: payload01.type__v,
	classification__v: payload01.classification__v,
	product__v: payload01.product__v,
	file: payload01.file as String
	}]]></ee:set-payload>
        </ee:message>
    </ee:transform>
    <veevavault:create-documents metadataFormat="CSV" doc:name="Create Documents" doc:id="5b98678c-1559-4827-80a9-289aad4a8873" config-ref="Veeva_Vault_Config"/>
    <db:bulk-insert doc:name=__"Bulk insert" doc:id="e8dd307e-40db-42bb-b82a-b72f6b235d00" config-ref="Database_Config">
        <db:bulk-input-parameters ><![CDATA[#[output application/java
---
payload.data map () -> {
	'id': $.id as String,
	'external_id__v': $.external_id__v as String,
	'responseStatus': $.responseStatus
	}]]]>
        </db:bulk-input-parameters>
        <db:sql >INSERT into documents (id, external_id__v, responseStatus) VALUES (:id: external_id__v, :responseStatus)
</db:sql>
    </db:bulk-insert>
    <logger level="INFO" doc:name="Logger" doc:id="a447ff60-8deb-471c-a1be-cc6c01dfcc29" message="Document Created :: #[output application/json --- payload]"/>
    <error-handler >
        <on-error-propagate enableNotifications="true" logException="true" doc:name="On Error Propagate" doc:id="19d98427-1566-4f82-b694-f59cc6eb169a" type="ANY" >
            <logger level="INFO" doc:name="Logger" doc:id="9c23d079-fbf2-42e7-afe2-b5186a7b9a3f" message="Flow Exception Handled --  #[payload]" />
        </on-error-propagate>
    </error-handler>
</flow>

Retrieve Document Details

This example retrieves document details based on type, subtype, and classification and stores the document details in the database.

To create the Mule flow:

  1. Drag and drop HTTP Listener from the Mule Palette to the project canvas.

  2. Configure HTTP Listener for your environment.

  3. Drag and drop the Get Documents operation from VeevaVault Connector palette.

  4. Enter the values for the Veeva Vault connection:

    • Username

    • Password

    • Vault URL

    • Vault version

    • Vault client ID

  5. Click the respective refresh button to fetch the document type, subtype, and classification list.

  6. Select the type, subtype, and classification from each of the respective drop-down lists.

  7. Add the document properties in the Document Properties list for your business requirements to incorporate the properties name in the VQL query to build dynamically.

  8. Drag the For-Each scope after the Veeva Vault Get Documents operation.

  9. Drop the Transform Message component and Database Connector Insert operation onto the project from the respective palettes.

  10. Configure the transformation according to your business requirements using Dataweave.

  11. Configure the Database Insert query to insert data into table.

  12. Drag the Set Payload transformer after For-Each to set a payload to return to the triggered source.

  13. Drag the Logger component to log information in the console or log file.

veevavault connector get documents example

XML Code

<flow name=__"get-documents-operationFlow"__ doc:id=__"facc29d2-8025-4b58-a3ec-322ded221705"__ >
	<http:listener doc:name=__"Listener"__ doc:id=__"93298153-7da4-4fcc-b028-00e692b0d19e"__ config-ref=__"HTTP_Listener_config"__ path=__"/get-documents"__/>
	<veevavault:get-documents doc:name=__"Get Documents"__ doc:id=__"c9e9f482-91ce-40d2-a7f7-92b39fc7e8a3"__ config-ref=__"Veeva_Vault_Config"__>
		<veevavault:documents type=__"site_management__c"__>
		<veevavault:document-properties >
		<veevavault:document-property value=__"name__v"__ />
		<veevavault:document-property value=__"type__v"__ />
		<veevavault:document-property value=__"subtype__v"__ />
		<veevavault:document-property value=__"classification__v"__ />
		<veevavault:document-property value=__"lifecycle__v"__ />
		<veevavault:document-property value=__"status__v"__ />
		<veevavault:document-property value=__"study__v"__ />
		<veevavault:document-property value=__"product__v"__ />
		</veevavault:document-properties>
		</veevavault:documents>
	</veevavault:get-documents>
	<foreach doc:name=__"For Each"__ doc:id=__"a05bd532-48eb-42a8-af56-7c9830a4433d"__ >
	<ee:transform doc:name=__"Transform Message"__ doc:id=__"d5bf0da9-e544-4728-a3e9-57dc05a02fa9"__ >
		<ee:message >
		<ee:set-payload ><![CDATA[%dw 2.0
		output application/json
		---
		payload]]></ee:set-payload>
		</ee:message>
	</ee:transform>
	<db:insert doc:name=__"Insert"__ doc:id=__"bf5a1288-8f37-456d-b26c-d18b8ea411db"__ config-ref=__"Database_Config"__>
		<db:sql >INSERT INTO [.underline]#createdocuments# (name__v, type__v, subtype__v, classification__v, lifecycle__v,
		product__v, status__v, study__v, file) VALUES (:name__v, :type__v, :subtype__v, :classification__v, :lifecycle__v, :product__v, :status__v, :study__v, :file)</db:sql>
		<db:input-parameters ><![CDATA[#[%dw 2.0
		output application/json
		---
		{
			'name__v': payload.name__v as String,
			'type__v': payload.type__v as String,
			'subtype__v': payload.subtype__v as String,
			'classification__v': payload.classification__v as String,
			'lifecycle__v': payload.lifecycle__v as String,
			'product__v': payload.product__v[0],
			'status__v': payload.status__v as String,
			'study__v': payload.study__v[0],
			'file': "CDA.docx"
		}]]]></db:input-parameters>
	</db:insert>
	</foreach>
	<set-payload value=__"#[output application/json --- payload.payload]"__ doc:name=__"Set Payload"__ doc:id=__"abcb3160-55a5-49f8-9b31-d7e61dca3d2e"__ />
	<logger level=__"INFO"__ doc:name=__"Logger"__ doc:id=__"ab49834e-389e-483e-84a4-2b61752bba72"__ message=__"Document Details :: #[payload]"__/>
	<error-handler >
	<on-error-propagate enableNotifications=__"true"__ logException=__"true"__ doc:name=__"Error Propagate"__ doc:id=__"a7ac2cf2-ec74-408b-8a02-ee1a0d24e8f4"__ type=__"ANY"__ >
	<logger level=__"INFO"__ doc:name=__"Logger"__ doc:id=__"2b932042-57f3-45d8-9e6b-3cd9fcda6509"__ message=__"Flow Exception Handled -- #[payload]"__ />
	</on-error-propagate>
	</error-handler>
	</flow>

Fetch Document or Object Data

In this Mule flow, you fetch document or object data from Veeva Vault using a VQL query.

To create the Mule flow:

  1. Drag and drop HTTP Listener from the Mule Palette to the project canvas.

  2. Configure HTTP Listener for your environment.

  3. Drag the Veeva Vault Query operation from Veeva Vault Connector palette.

  4. Enter the values for the Veeva Vault connection:

    • Username

    • Password

    • Vault URL

    • Vault version

    • Vault client ID

  5. Define the VQL query according to your business requirement.

  6. Add an input placeholder if used in the VQL query to incorporate dynamically with VQL at runtime.

  7. Drag the For-Each scope after the Veeva Vault Query operation.

  8. Drop the Transform Message and File - Write operations from the respective palette.

  9. Configure the transformation using Dataweave according to your business needs for transforming the payload.

  10. Configure the File Connector configuration with the working file path.

  11. Configure the Write operation to write payload data into the specified file.

  12. Drag the Set Payload transformer after For-Each to set a payload to return to the triggered source.

  13. Drag the Logger component to log information in the console or log file.

veevavault connector query example

XML Code

<flow name="query-operation-with-database-operationFlow" doc:id="451f0f78-1e2e-4cc4-b56d-4f427f01e30a" >
		<http:listener doc:name="Listener" doc:id="454e6602-2c2f-4e98-8569-b3e928bf3da5" config-ref="HTTP_Listener_config" path="/query"/>
		<veevavault:query doc:name="Query" doc:id="e4310f17-b0f5-49c0-8662-bc2d798fd9de" fetchSize="1000" config-ref="Veeva_Vault_Config">
			<veevavault:vql >SELECT id, name__v, type__v, subtype__v, classification__v, lifecycle__v, status__v, study__v, product__v  from :table WHERE name__v= 'F22611234--6764'</veevavault:vql>
			<veevavault:input-parameters ><![CDATA[#[{
				'table': 'documents'
			}]]]></veevavault:input-parameters>
		</veevavault:query>
		<foreach doc:name="For Each" doc:id="55a3f3e9-b0ad-4c6d-8ccf-96f2d11f7bc8" >
		<ee:transform doc:name="Transform Message" doc:id="f4875262-fe32-42e6-8e21-a21e592a729d" >
			<ee:message >
				<ee:set-payload ><![CDATA[%dw 2.0
				output application/json
				---
				payload]]></ee:set-payload>
			</ee:message>
		</ee:transform>
		<file:write doc:name="Write" doc:id="cb88f995-b31f-4dcf-b508-ea8340ae84fb" path="query.json" config-ref="File_Config" mode="APPEND">
			<file:content><![CDATA[#[output application/json
			---
			payload]]]></file:content>
						</file:write>

		</foreach>
		<set-payload value="#['Flow Completed']" doc:name="Set Payload" doc:id="66f96a83-dfc9-4855-a65c-c35327cfec2a" />
		<logger level="INFO" doc:name="Logger" doc:id="016dc7a0-7014-44d9-bcbd-d2f540c2fc2e" message="Query Operation flow Completed - #[payload]"/>
		<error-handler >
			<on-error-propagate enableNotifications="true" logException="true" doc:name="On Error Propagate" doc:id="6a7998b6-4384-41fb-bb5a-625f5410003a" type="ANY">
				<logger level="INFO" doc:name="Logger" doc:id="46ee422c-4430-4b63-b1c3-6c993ad732fa" message="Flow Exception Handled --  #[payload]"/>
			</on-error-propagate>
		</error-handler>
	</flow>

Validating a Spark Message

In this Mule flow, a Spark message triggered from the Vault is validated.

To create the Mule flow:

  1. Drag and drop HTTP Listener from the Mule Palette to the project canvas.

  2. The JKS Certificate for HTTPS Connector requires the .jks file for HTTPS Listener to receive Spark messages over a TLS connection with Veeva Vault.
    Following are the steps to create a .jks file (you can use the Java Keytool located under the <JDK_HOME>/bin directory. The following is an example:

    1. Run the following command from the <JDK_HOME>/bin directory:

      `keytool -genkey -keyalg RSA -alias mule -keystore spark-listener.jks -storepass password -validity 360 -keysize 2048`
      This creates a `spark-listener.jks` file in the current directory.
    2. Copy and import the spark-listener.jks file under the src/main/resources project directory.

      • Configure HTTPS Listener as follows:

    3. In the General tab, configure the following:

      • Protocol: HTTPS

      • Host: 0.0.0.0

      • Port: 8082

    4. In TLS Tab > Key Store, configure the following:

      • Type: JKS

      • Path: spark-listener.jks

      • Alias: mule

      • Key Password: password

      • Password: password

  3. Drag the Spark Validator operation from the Veeva Vault palette onto the project canvas.

  4. Enter the values for the Veeva Vault connection:

    • Username

    • Password

    • Vault URL

    • Vault version

    • Vault client ID

  5. Configure the Spark Validator parameters as follows:

    • Include Spark Header: FALSE

    • Public Key Path: ${file.keyPath} Define the file.keyPath property in the configuration.yaml with the path to where the public key file (00001.pem) is stored.

    • Spark Headers: #[attributes.headers]

    • Spark Message: #[payload]

  6. Drag the Set Payload operation onto the project canvas, and define the following in the Value field:

    ----
    output application/json --- {
    	"payload" : payload,
    	"attributes": attributes
    }
    ----
  7. Drag the Logger component onto the project canvas to log the payload with the following message:

	Spark Message :: #[payload]

veevavault connector spark validator example

XML Code

<flow name="spark-message-validator-operationFlow" doc:id="de35a9a3-61f3-4cd1-9c58-f645c95187d3" >
    <http:listener doc:name="Listener" doc:id="687a4226-b8df-4657-a329-1a79e4b8b2ea" config-ref="Spark_Listener" path="/"/>
    <veevavault:spark-message-validator doc:name="Spark Validator" doc:id="384e963f-3f1c-4117-a6f3-1e8b09a585a9" config-ref="Veeva_Vault_Config" publicKeyPath="${file.keyPath}" includeSparkHeader="TRUE"/>
    <set-payload value='#[output application/json --- {
			"payload" : payload,
			"attributes": attributes
		}]' doc:name="Set Payload" doc:id="69071232-9e9b-459f-8061-59f44e76ae98" />
    <logger level="INFO" doc:name="Logger" doc:id="3ce348b9-bfbb-4c16-8663-48ecb401fbb2" message="Spark Message :: #[payload]"/>
</flow>

Create a Single Document Through Invoke REST API.

To create the Mule flow:

  1. Drag and drop HTTP Listener from the Mule Palette to the project canvas.

  2. Configure the HTTP Listener with the values for your environment.

  3. From the Mule Palette, drag the File Connector > Read operation to the project canvas and configure the file path to read from the file content that is associated with the Vault document.

  4. From the Mule Paletee, drag the Veeva Vault Invoke Rest API operation onto the canvas.

  5. Enter the values for the Veeva Vault connection:

    • Username

    • Password

    • Vault URL

    • Vault version

    • Vault client ID

  6. Configure the following parameters:

    Method: POST,
    Path: "/objects/documents",
    Headers:
    	Key: "Accept"
    	Value: "application/json"
    	Key: "Content-Type"
    	Value: "multipart/form-data; boundary=abcdefg"
    URI Parameters: Leave it empty.
    Query Parameters: Leave it empty.
    Body:
    
    %dw 2.0
    output multipart/form-data boundary='abcdefg'
    ---
    {
    	parts: {
    		file: {
    			headers: {
    				"Content-Disposition": {
    					"name": "file",
    					"filename": attributes.fileName
    				},
    				"Content-Type": payload.^mimeType
    			},
    			content : payload
    		},
    		name__v: {
    			headers: {
    
    			},
    			content: 'Test Document'
    		},
    		type__v: {
    			headers: {
    
    			},
    			content: 'Trial Management'
    		},
    		subtype__v: {
    			headers: {
    
    			},
    			content: 'Meetings'
    		},
    		classification__v: {
    			headers: {
    
    			},
    			content: 'Kick-off Meeting Material'
    		},
    		lifecycle__v: {
    			headers: {
    
    			},
    			content: 'Base Doc Lifecycle'
    		},
    		study__v: {
    			headers: {
    
    			},
    			content: '0ST000000000301'
    		},
    		comments__c: {
    			headers: {
    
    			},
    			content: 'Test Document'
    		}
    	}
    }
  7. You can configure the PUT request in a similar way:

    Method: PUT,
    Path: "/objects/documents/{doc_id}",
    Headers:
    	Key: "Accept"
    	Value: "application/json"
    	Key: "Content-Type"
    	Value: "application/x-www-form-urlencoded"
    URI Parameters:
    	Key: "doc_id"
    	Value: "259592"
    Query Parameters: Leave it empty.
    Body:
    
    %dw 2.0
    output application/x-www-form-urlencoded
    ---
    {
    	"id": "259592",
    	"name__v": "Kick-off Meeting Material Updated",
    	"product__v": "00P000000000403",
    	"study__v": "0ST000000000202",
    	"notes__v": "Notes Updated"
    }

    Note: Configure the above parameters according to your requirements to invoke the Vault REST API.

  8. Drag the Logger component onto the project canvas to log the payload with the following message:

	Invoke Veeva API response :: #[payload]

image

XML Code

	<flow name="invoke-veeva-api-operationFlow" doc:id="fc3c7fa8-2934-4089-aa2a-dfa4f41fdb1a" >
		<http:listener doc:name="Listener" doc:id="26ab408f-73db-4fe9-80ec-4121938e0828" config-ref="HTTP_Listener_config" path="/invoke-veeva-api"/>
		<file:read doc:name="Read" doc:id="7f8bd32f-7ad2-4cd8-a4e7-dd9cc6834963" config-ref="File_Config" path="#['testdata/Test Document Renditions.pdf']" outputMimeType="application/octet-stream"/>
		<veevavault:invoke-rest-api doc:name="Invoke REST API" doc:id="ed667811-1343-49ae-bb38-0ac3e59bb4cb" config-ref="Veeva_Vault_Config" path="/objects/documents" method="POST">
			<veevavault:body ><![CDATA[#[%dw 2.0
output multipart/form-data boundary='abcdefg'
---
{
	parts: {
		file: {
			headers: {
				"Content-Disposition": {
					"name": "file",
					"filename": attributes.fileName
				},
				"Content-Type": payload.^mimeType
			},
			content : payload
		},
		name__v: {
			headers: {

			},
			content: 'Test Document'
		},
		type__v: {
			headers: {

			},
			content: 'Trial Management'
		},
		subtype__v: {
			headers: {

			},
			content: 'Meetings'
		},
		classification__v: {
			headers: {

			},
			content: 'Kick-off Meeting Material'
		},
		lifecycle__v: {
			headers: {

			},
			content: 'Base Doc Lifecycle'
		},
		study__v: {
			headers: {

			},
			content: '0ST000000000301'
		},
		comments__c: {
			headers: {

			},
			content: 'Test Document'
		}
	}
}]]]></veevavault:body>
			<veevavault:headers ><![CDATA[#[output application/java
---
{
	"Accept" : "application/json",
	"Content-Type" : "multipart/form-data; boundary=abcdefg"
}]]]></veevavault:headers>
		</veevavault:invoke-rest-api>
		<logger level="INFO" doc:name="Logger" doc:id="182eb2ad-d346-4f30-8d64-ad37fc574c21" message="Invoke Veeva API response :: #[payload]" />
	</flow>
----


== Templates

*Use Case* : Integrate https://anypoint.mulesoft.com/exchange/c5788341-a495-4d6f-a931-875757082c63/filesystem-to-veeva-vault-template/[FileSystem to VeevaVault]

*Use Case* : Integrate https://anypoint.mulesoft.com/exchange/c5788341-a495-4d6f-a931-875757082c63/veevavault-connector-project-templates/[VeevaVault to FileSystem]

*Use Case* : Auto approval of loan applications through Spark message https://anypoint.mulesoft.com/exchange/c5788341-a495-4d6f-a931-875757082c63/spark-message-solution-template/[Spark Message End Solution]

== See Also

https://help.mulesoft.com[MuleSoft Help Center]