Search assets and Update status with Java Api

This example searches for assets with asset type "all types" and asset ids between 10494 and 10495. And then extracts asset field values which contains core, system and attribute values.

If you would like to override security use aipIndexService.queryDocsForObjectOverrideSecurity, if you want permission check with current user use aipIndexService.queryDocsForObject.


// Prepare Imports
import com.atlassian.jira.component.ComponentAccessor
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import groovy.transform.Field
import inventoryplugin.dto.portable.InventoryDto
import inventoryplugin.helper.JipUtilityHelper
import inventoryplugin.service.index.AipIndexService
import inventoryplugin.service.controller.InventoryController
import org.apache.log4j.Level
import org.apache.log4j.Logger

// prepare logger
@Field Logger logger = Logger.getLogger("snapbytes.inventoryplugin.groovy.script")
logger.setLevel(Level.DEBUG); // logging level to DEBUG to get more detailed logging when the code is executed

// enable Assets and Inventory plugin for theis script (This feature comes with ScriptRunner)

// Import plugin module aipIndexService - it's used to search for assets
AipIndexService aipIndexService

// Import plugin module inventoryController - it's used to update assets
InventoryController inventoryController

try {
    // Prepared QueryIndexParam - this is the main parameters object as search assets
    QueryIndexParam queryIndexParam = new QueryIndexParam();
    // We just tell we are making generic search (other search options are out of scope for this usage)
    queryIndexParam.setSortField(""); // specify sort field
    queryIndexParam.setSortDirection("asc");   // specify sort order
    queryIndexParam.setSortType("STRING"); // specify sort field type
    queryIndexParam.setSearchType("basic");  // specify srach type - this is basic as we specify options
    queryIndexParam.setPageNumber(1); // first page of results
    queryIndexParam.setPageSize(1000); // max number of assets to return
    queryIndexParam.setQueryIndexSearchParams(new ArrayList<>()); // init array for search options

    // filter by asset type
    QueryIndexSearchParam query = new QueryIndexSearchParam(); // object for search option 1 - asset type
    query.setField(""); // field name
    query.setKeywords(new ArrayList<>()); // init keywords
    query.getKeywords().add("Tablet 4"); // asset type name
    queryIndexParam.getQueryIndexSearchParams().add(query); // add this option to search

    QueryIndexSearchParam query2 = new QueryIndexSearchParam(); // object for search option 2 - relative date
    query2.setField("Warranty Expiration Date"); // field name
    query2.setFieldType("DATE"); // it's a relative type - no hard coded fix dates
    query2.setRange(true);  // it's a range search
    query2.setRelative(true); // it's a relative type - no hard coded fix dates
    query2.setRelativeMin("0d"); // start date, 0d means 0 days
    query2.setRelativeMax("2d"); // end date, 3d means 3 days. you can set it as 30d
    queryIndexParam.getQueryIndexSearchParams().add(query2); // add this option to search

    // now search parameters are ready, we can call Java search API

    // get current user (if there's any) for the search -
    //   user does not have any effect for search when security is overriden
    def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser();

    // queryDocsForObjectOverrideSecurity does not respect to permissions for the user. Assumes we have browse permission for all assets
    QueryIndexResult queryIndexResult = aipIndexService.queryDocsForObjectOverrideSecurity(queryIndexParam, user);

    // queryDocsForObject applies assets permissions by the user. If the user has no right to browse assets, no assets will returm
    //QueryIndexResult queryIndexResult = aipIndexService.queryDocsForObject(queryIndexParam, user);

    // result is a string of json so we need to convert it to an object with JipUtilityHelper class
    List<InventoryDto> assets = JipUtilityHelper.convertJsonStringToListSafe(queryIndexResult.getAssets(), InventoryDto.class);

    if (assets != null) {
        logger.debug(assets.size() + ' assets found')

        // for each asset we are looping
        for (InventoryDto oneAsset : assets) {
            logger.debug('Asset Type id: ' + oneAsset.formId + ', Asset Type name: ' + oneAsset.formName)
            logger.debug('Asset id: ' + + ', Asset name: ' +;

            logger.debug('--- Attributes ----------------------')
            List<inventoryplugin.dto.portable.InventoryItemDto> inventoryItems = oneAsset.getInventoryItems();
            for (inventoryplugin.dto.portable.InventoryItemDto assetAttr : inventoryItems) {
                if (assetAttr.attributeName == "Warranty Expiration Date") {
                    logger.debug(assetAttr.attributeName + ': ' + assetAttr.value );

            // We are going to update the assets with new status and substatus values

            // there are 2 packages for InventoryDto, we used "inventoryplugin.dto.portable.InventoryDto" in the import so we write full package name below.
   inventoryDtoToSave = new;
            inventoryDtoToSave.setFormId(oneAsset.formId); // we set asset type id (~formId)
            List<SystemFieldDto> systemFields = new ArrayList<>(); // Status and substatus are systemFields. So we initialize a list of SystemFieldDto
            systemFields.add(new SystemFieldDto("asset.status", "3")); // set first field status
            systemFields.add(new SystemFieldDto("asset.substatus", "1")); // set second field substatus
            inventoryDtoToSave.setSystemFields(systemFields); // set parent object to actual object we will save
            // updateInventoryAssetOverrideSecurity is used to override security and permissions - as this code will be
            //   executed as scheduled task, we won't want to deal with user and permissions
             * updateInventoryAssetOverrideSecurity has the follwing signature:
             *    String updateInventoryAssetOverrideSecurity(int version, String contextPath, final Integer id, final InventoryDto inventoryDto,
             ApplicationUser remoteUser, boolean ignoreNonExistenceAttribute, boolean ignoreInvalidValues,
             boolean createUnknownValues, ReferenceAssetFetchMethod referenceAssetFetchMethod)
            inventoryController.updateInventoryAssetOverrideSecurity(InventoryController.VERSION_2, "",,
                    inventoryDtoToSave, null,
                    false, false, false, InventoryController.ReferenceAssetFetchMethod.ID_THEN_NAME);

    return assets.size;

} catch (Exception e) {
    return e.getMessage();


2022-06-28 18:08:10,397 DEBUG [groovy.script]: 2 assets found
2022-06-28 18:08:10,397 DEBUG [groovy.script]: ----------------------------------------------------
2022-06-28 18:08:10,397 DEBUG [groovy.script]: Asset Type id: 67, Asset Type name: Tablet 4
2022-06-28 18:08:10,398 DEBUG [groovy.script]: Asset id: 10488, Asset name: Tablet-001
2022-06-28 18:08:10,398 DEBUG [groovy.script]: --- Attributes ----------------------
2022-06-28 18:08:10,399 DEBUG [groovy.script]: Warranty Expiration Date: 29/06/2022
2022-06-28 18:08:10,890 DEBUG [groovy.script]: ----------------------------------------------------
2022-06-28 18:08:10,890 DEBUG [groovy.script]: Asset Type id: 67, Asset Type name: Tablet 4
2022-06-28 18:08:10,890 DEBUG [groovy.script]: Asset id: 10487, Asset name: Tablet-003
2022-06-28 18:08:10,890 DEBUG [groovy.script]: --- Attributes ----------------------
2022-06-28 18:08:10,890 DEBUG [groovy.script]: Warranty Expiration Date: 30/06/2022

Asset navigator can be used to find different type searches. Developer tools Network tab is exactly the same for search API