From: Ray Lee Date: Tue, 16 May 2023 02:39:34 +0000 (-0400) Subject: DRYD-1233: Automatically add/update batch jobs on startup. (#349) X-Git-Url: https://git.aero2k.de/?a=commitdiff_plain;h=d03baa371657d3e83af17cb8cd5b16f322c6ba29;p=tmp%2Fjakarta-migration.git DRYD-1233: Automatically add/update batch jobs on startup. (#349) --- diff --git a/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CSpaceResteasyBootstrap.java b/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CSpaceResteasyBootstrap.java index abc0e7ea1..adf2ccfc4 100644 --- a/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CSpaceResteasyBootstrap.java +++ b/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CSpaceResteasyBootstrap.java @@ -10,13 +10,16 @@ import javax.ws.rs.core.UriInfo; import org.jboss.resteasy.core.Dispatcher; import org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap; import org.jboss.resteasy.specimpl.PathSegmentImpl; +import org.apache.commons.io.IOUtils; import org.collectionspace.authentication.AuthN; import org.collectionspace.authentication.CSpaceTenant; import org.collectionspace.services.account.Tenant; import org.collectionspace.services.account.TenantResource; import org.collectionspace.services.authorization.AuthZ; +import org.collectionspace.services.batch.BatchResource; import org.collectionspace.services.client.AbstractCommonListUtils; import org.collectionspace.services.client.AuthorityClient; +import org.collectionspace.services.client.BatchClient; import org.collectionspace.services.client.CollectionSpaceClient; import org.collectionspace.services.client.PayloadOutputPart; import org.collectionspace.services.client.PoxPayloadOut; @@ -50,6 +53,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; +import java.io.InputStream; import java.lang.reflect.Constructor; import java.net.URI; import java.net.URLEncoder; @@ -67,8 +71,10 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { private static final String RESET_AUTHORITIES_PROPERTY = "org.collectionspace.services.authorities.reset"; private static final String RESET_ELASTICSEARCH_INDEX_PROPERTY = "org.collectionspace.services.elasticsearch.reset"; private static final String RESET_REPORTS_PROPERTY = "org.collectionspace.services.reports.reset"; + private static final String RESET_BATCH_JOBS_PROPERTY = "org.collectionspace.services.batch.reset"; private static final String QUICK_BOOT_PROPERTY = "org.collectionspace.services.quickboot"; private static final String REPORT_PROPERTY = "report"; + private static final String BATCH_PROPERTY = "batch"; @Override public void contextInitialized(ServletContextEvent event) { @@ -90,6 +96,7 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { // The below properties can be set in the tomcat/bin/setenv.sh (or setenv.bat) file. String resetAuthsString = System.getProperty(RESET_AUTHORITIES_PROPERTY, Boolean.FALSE.toString()); String resetElasticsearchIndexString = System.getProperty(RESET_ELASTICSEARCH_INDEX_PROPERTY, Boolean.FALSE.toString()); + String resetBatchJobsString = System.getProperty(RESET_BATCH_JOBS_PROPERTY, Boolean.TRUE.toString()); String resetReportsString = System.getProperty(RESET_REPORTS_PROPERTY, Boolean.TRUE.toString()); initializeAuthorities(app.getResourceMap(), Boolean.valueOf(resetAuthsString)); @@ -101,6 +108,10 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { if (Boolean.valueOf(resetReportsString) == true) { resetReports(); } + + if (Boolean.valueOf(resetBatchJobsString) == true) { + resetBatchJobs(); + } } logger.info("CollectionSpace Services JAX-RS application started."); @@ -234,6 +245,122 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { } } + public void resetBatchJobs() throws Exception { + logger.info("Resetting batch jobs"); + + TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader(); + Hashtable tenantBindingsTable = tenantBindingConfigReader.getTenantBindings(false); + + for (TenantBindingType tenantBinding : tenantBindingsTable.values()) { + ServiceBindingType batchServiceBinding = null; + + for (ServiceBindingType serviceBinding : tenantBinding.getServiceBindings()) { + if (serviceBinding.getName().toLowerCase().trim().equals(BatchClient.SERVICE_NAME)) { + batchServiceBinding = serviceBinding; + + break; + } + } + + Set batchNames = new HashSet(); + + if (batchServiceBinding != null) { + for (PropertyType property : batchServiceBinding.getProperties()) { + for (PropertyItemType item : property.getItem()) { + if (item.getKey().equals(BATCH_PROPERTY)) { + batchNames.add(item.getValue()); + } + } + } + } + + if (batchNames.size() > 0) { + CSpaceTenant tenant = new CSpaceTenant(tenantBinding.getId(), tenantBinding.getName()); + + resetTenantBatchJobs(tenant, batchNames); + } + } + } + + private void resetTenantBatchJobs(CSpaceTenant tenant, Set batchNames) throws Exception { + logger.info("Resetting batch jobs for tenant {}", tenant.getId()); + + AuthZ.get().login(tenant); + + CollectionSpaceJaxRsApplication app = (CollectionSpaceJaxRsApplication) deployment.getApplication(); + ResourceMap resourceMap = app.getResourceMap(); + BatchResource batchResource = (BatchResource) resourceMap.get(BatchClient.SERVICE_NAME); + + for (String batchName : batchNames) { + InputStream batchMetadataInputStream = BatchResource.getBatchMetadataInputStream(batchName); + + if (batchMetadataInputStream == null) { + logger.warn( + "Metadata file not found for batch {}", batchName); + + continue; + } + + String payload = IOUtils.toString(batchMetadataInputStream, StandardCharsets.UTF_8); + + batchMetadataInputStream.close(); + + UriInfo uriInfo = new UriInfoImpl( + new URI(""), + new URI(""), + "", + "pgSz=0&classname=" + URLEncoder.encode(batchName, StandardCharsets.UTF_8.toString()), + Arrays.asList((PathSegment) new PathSegmentImpl("", false)) + ); + + AbstractCommonList list = batchResource.getList(uriInfo); + + if (list.getTotalItems() == 0) { + logger.info("Adding batch job " + batchName); + + try { + batchResource.create(resourceMap, null, payload); + } catch(Exception e) { + logger.error(e.getMessage(), e); + } + } else { + for (ListItem item : list.getListItem()) { + String csid = AbstractCommonListUtils.ListItemGetCSID(item); + + // Update an existing batch job iff: + // - it was created autmatically (i.e., by the SPRING_ADMIN user) + // - it was last updated automatically (i.e., by the SPRING_ADMIN user) + // - it is not soft-deleted + + PoxPayloadOut batchPayload = batchResource.getResourceFromCsid(null, null, csid); + PayloadOutputPart corePart = batchPayload.getPart(CollectionSpaceClient.COLLECTIONSPACE_CORE_SCHEMA); + + String createdBy = corePart.asElement().selectSingleNode(CollectionSpaceClient.COLLECTIONSPACE_CORE_CREATED_BY).getText(); + String updatedBy = corePart.asElement().selectSingleNode(CollectionSpaceClient.COLLECTIONSPACE_CORE_UPDATED_BY).getText(); + String workflowState = corePart.asElement().selectSingleNode(CollectionSpaceClient.COLLECTIONSPACE_CORE_WORKFLOWSTATE).getText(); + + if ( + createdBy.equals(AuthN.SPRING_ADMIN_USER) + && updatedBy.equals(AuthN.SPRING_ADMIN_USER) + && !workflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) + ) { + logger.info("Updating batch job {} with csid {}", batchName, csid); + + try { + batchResource.update(resourceMap, null, csid, payload); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } else { + logger.info( + "Not updating batch job {} with csid {} - it was not auto-created, or was updated or soft-deleted", + batchName, csid); + } + } + } + } + } + public void resetElasticSearchIndex() throws Exception { boolean isEnabled = Boolean.parseBoolean(Framework.getProperty(ES_ENABLED_PROPERTY, "true")); diff --git a/services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java b/services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java index 503d62d52..9fb96512d 100644 --- a/services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java +++ b/services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java @@ -48,6 +48,7 @@ import org.collectionspace.services.authorization.PermissionException; import org.collectionspace.services.authorization.URIResourceImpl; import org.collectionspace.services.authorization.perms.ActionType; +import java.io.InputStream; import java.util.List; import javax.ws.rs.Consumes; @@ -96,7 +97,7 @@ public class BatchResource extends NuxeoBasedResource { MultivaluedMap queryParams = ctx.getQueryParams(); DocumentHandler handler = createDocumentHandler(ctx); String docType = queryParams.getFirst(IQueryManager.SEARCH_TYPE_DOCTYPE); - String filename = queryParams.getFirst(IQueryManager.SEARCH_TYPE_FILENAME); + String className = queryParams.getFirst(IQueryManager.SEARCH_TYPE_CLASS_NAME); List modes = queryParams.get(IQueryManager.SEARCH_TYPE_INVOCATION_MODE); String whereClause = null; DocumentFilter documentFilter = null; @@ -109,9 +110,9 @@ public class BatchResource extends NuxeoBasedResource { documentFilter.appendWhereClause(whereClause, IQueryManager.SEARCH_QUALIFIER_AND); } - if (filename != null && !filename.isEmpty()) { - whereClause = QueryManager.createWhereClauseForInvocableByFilename( - common_part, filename); + if (className != null && !className.isEmpty()) { + whereClause = QueryManager.createWhereClauseForInvocableByClassName( + common_part, className); documentFilter = handler.getDocumentFilter(); documentFilter.appendWhereClause(whereClause, IQueryManager.SEARCH_QUALIFIER_AND); } @@ -291,4 +292,17 @@ public class BatchResource extends NuxeoBasedResource { throw bigReThrow(e, msg); } } + + public static InputStream getBatchMetadataInputStream(String batchName) { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + try { + Class clazz = classLoader.loadClass(batchName); + String metadataFileName = clazz.getSimpleName() + ".xml"; + + return clazz.getResourceAsStream(metadataFileName); + } catch (Exception e) { + return null; + } + } } diff --git a/services/batch/service/src/main/resources/org/collectionspace/services/batch/nuxeo/MergeAuthorityItemsBatchJob.xml b/services/batch/service/src/main/resources/org/collectionspace/services/batch/nuxeo/MergeAuthorityItemsBatchJob.xml new file mode 100644 index 000000000..436da12cf --- /dev/null +++ b/services/batch/service/src/main/resources/org/collectionspace/services/batch/nuxeo/MergeAuthorityItemsBatchJob.xml @@ -0,0 +1,22 @@ + + + Merge Authority Items + Merge an authority item into a target, and update all referencing records. Runs on a single record only. + + Chronology + Workitem + Person + Conceptitem + Placeitem + Citation + Organization + Locationitem + + true + false + false + false + false + org.collectionspace.services.batch.nuxeo.MergeAuthorityItemsBatchJob + + diff --git a/services/batch/service/src/main/resources/org/collectionspace/services/batch/nuxeo/UpdateInventoryStatusBatchJob.xml b/services/batch/service/src/main/resources/org/collectionspace/services/batch/nuxeo/UpdateInventoryStatusBatchJob.xml new file mode 100644 index 000000000..2dc19f225 --- /dev/null +++ b/services/batch/service/src/main/resources/org/collectionspace/services/batch/nuxeo/UpdateInventoryStatusBatchJob.xml @@ -0,0 +1,15 @@ + + + Update Inventory Status + Set the inventory status of selected Object records. Runs on a record list only. + + CollectionObject + + false + true + false + false + false + org.collectionspace.services.batch.nuxeo.UpdateInventoryStatusBatchJob + + diff --git a/services/batch/service/src/main/resources/org/collectionspace/services/batch/nuxeo/UpdateObjectLocationBatchJob.xml b/services/batch/service/src/main/resources/org/collectionspace/services/batch/nuxeo/UpdateObjectLocationBatchJob.xml new file mode 100644 index 000000000..2b7f544d9 --- /dev/null +++ b/services/batch/service/src/main/resources/org/collectionspace/services/batch/nuxeo/UpdateObjectLocationBatchJob.xml @@ -0,0 +1,15 @@ + + + Update Current Location + Recompute the current location of Object records, based on the related Location/Movement/Inventory records. Runs on a single record or all records. + + CollectionObject + + true + false + false + true + false + org.collectionspace.services.batch.nuxeo.UpdateObjectLocationBatchJob + + diff --git a/services/client/src/main/java/org/collectionspace/services/client/IQueryManager.java b/services/client/src/main/java/org/collectionspace/services/client/IQueryManager.java index 3c23228e4..2208b561f 100644 --- a/services/client/src/main/java/org/collectionspace/services/client/IQueryManager.java +++ b/services/client/src/main/java/org/collectionspace/services/client/IQueryManager.java @@ -41,6 +41,7 @@ public interface IQueryManager { final static String SEARCH_TYPE_PARTIALTERM = "pt"; final static String SEARCH_TYPE_DOCTYPE = "doctype"; final static String SEARCH_TYPE_FILENAME = "filename"; + final static String SEARCH_TYPE_CLASS_NAME = "classname"; final static String SEARCH_TYPE_INVOCATION_MODE = "mode"; final static String SEARCH_TYPE_INVOCATION = "inv"; final static String SEARCH_QUALIFIER_AND = SEARCH_TERM_SEPARATOR + "AND" + SEARCH_TERM_SEPARATOR; @@ -172,6 +173,15 @@ public interface IQueryManager { */ public String createWhereClauseForInvocableByFilename(String schema, String filename); + /** + * Creates a filtering where clause from class name, for invocables. + * + * @param schema the schema name for this invocable + * @param docType the class name + * @return the where clause + */ + public String createWhereClauseForInvocableByClassName(String schema, String className); + /** * Creates a filtering where clause from invocation mode, for invocables. * diff --git a/services/common/src/main/cspace/config/services/tenants/tenant-bindings-proto-unified.xml b/services/common/src/main/cspace/config/services/tenants/tenant-bindings-proto-unified.xml index bc3dd22b8..7052bdee3 100644 --- a/services/common/src/main/cspace/config/services/tenants/tenant-bindings-proto-unified.xml +++ b/services/common/src/main/cspace/config/services/tenants/tenant-bindings-proto-unified.xml @@ -305,6 +305,20 @@ org.collectionspace.services.batch.nuxeo.BatchValidatorHandler + + + batch + org.collectionspace.services.batch.nuxeo.MergeAuthorityItemsBatchJob + + + batch + org.collectionspace.services.batch.nuxeo.UpdateInventoryStatusBatchJob + + + batch + org.collectionspace.services.batch.nuxeo.UpdateObjectLocationBatchJob + +