Search assets and update status with Java API
- Derya Özdemir
- Tolga Tunca
This page is about Assets & Inventory Plugin for Jira DC. Using Cloud? Click here.
This example searches for assets with asset type All types
and asset IDs between 10494
and 10495
, and then extracts asset field values that contain core, system, and attribute values.
If you would like to override security use aipIndexService.queryDocsForObjectOverrideSecurity
. If you want permission check with the current user, use aipIndexService.queryDocsForObject
.
Script
// 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.index.search.QueryIndexParam
import inventoryplugin.service.index.search.QueryIndexResult
import inventoryplugin.service.index.search.QueryIndexSearchParam
import inventoryplugin.service.rest.dto.SystemFieldDto
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)
@WithPlugin("plugin.jip")
// Import plugin module aipIndexService - it's used to search for assets
@PluginModule
AipIndexService aipIndexService
// Import plugin module inventoryController - it's used to update assets
@PluginModule
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.setQuerySource(QueryIndexParam.QuerySource.GENERIC_SEARCH);
queryIndexParam.setSortField("asset.name"); // 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.setFieldType("LIST");
query.setField("form.name"); // 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('----------------------------------------------------')
logger.debug('Asset Type id: ' + oneAsset.formId + ', Asset Type name: ' + oneAsset.formName)
logger.debug('Asset id: ' + oneAsset.id + ', Asset name: ' + oneAsset.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.
inventoryplugin.service.rest.dto.InventoryDto inventoryDtoToSave = new inventoryplugin.service.rest.dto.InventoryDto();
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, "", oneAsset.id,
inventoryDtoToSave, null,
false, false, false, InventoryController.ReferenceAssetFetchMethod.ID_THEN_NAME);
}
}
return assets.size;
} catch (Exception e) {
logger.debug(e.getMessage())
return e.getMessage();
}
Output
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 also be used to find different types. Developer tools Network tab is exactly the same for search API. To utilize it:
Make a search. In our example, we will filter two fields:
Asset type
and adate field
.Enable developer tools and filter "query.json" in the Network tab.
Click Payload to display the API call parameters.
Apply to the code.
Â