diff --git a/asie-api/pom.xml b/asie-api/pom.xml index 66aee56..4c709bf 100644 --- a/asie-api/pom.xml +++ b/asie-api/pom.xml @@ -10,17 +10,12 @@ ../ - com.inteligr8.alfresco asie-api 1.1.1-asie2 jar ASIE Jakarta RS API Alfresco Search & Insight Engine Jakarta RS API - - - 23.2.0 - @@ -43,17 +38,6 @@ org.alfresco alfresco-data-model - - - * - * - - - - - org.apache.commons - commons-lang3 - 3.17.0 org.apache.logging.log4j @@ -63,7 +47,7 @@ com.inteligr8 common-rest-client - 3.0.2-jersey + ${commom-rest-client.base.version}-jersey test @@ -75,10 +59,27 @@ org.junit.jupiter junit-jupiter-api - 5.11.2 test + + + + + io.repaint.maven + tiles-maven-plugin + true + + + + + + + + + diff --git a/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/IndexRequest.java b/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/IndexRequest.java index 865a1fb..14c57d3 100644 --- a/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/IndexRequest.java +++ b/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/IndexRequest.java @@ -24,7 +24,7 @@ public class IndexRequest extends JsonFormattedResponseRequest { @QueryParam("acltxid") private Long aclTransactionId; - @QueryParam("nodeId") + @QueryParam("nodeid") private Long nodeId; @QueryParam("aclid") diff --git a/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/NewCoreRequest.java b/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/NewCoreRequest.java index 0b1b99b..6133cbe 100644 --- a/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/NewCoreRequest.java +++ b/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/NewCoreRequest.java @@ -3,7 +3,7 @@ package com.inteligr8.alfresco.asie.model.core; import java.util.Collection; import org.alfresco.service.cmr.repository.StoreRef; -import org.apache.commons.lang3.StringUtils; +import org.springframework.util.StringUtils; import com.inteligr8.solr.model.JsonFormattedResponseRequest; @@ -89,7 +89,7 @@ public class NewCoreRequest extends JsonFormattedResponseRequest } public NewCoreRequest withShardIds(Collection shardIds) { - this.shardIds = StringUtils.join(shardIds, ","); + this.shardIds = StringUtils.collectionToDelimitedString(shardIds, ","); return this; } diff --git a/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/PurgeRequest.java b/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/PurgeRequest.java index 2d0171c..e7f4519 100644 --- a/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/PurgeRequest.java +++ b/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/PurgeRequest.java @@ -24,7 +24,7 @@ public class PurgeRequest extends JsonFormattedResponseRequest { @QueryParam("acltxid") private Long aclTransactionId; - @QueryParam("nodeId") + @QueryParam("nodeid") private Long nodeId; @QueryParam("aclid") diff --git a/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/ReindexRequest.java b/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/ReindexRequest.java index 5cbdd58..59cc127 100644 --- a/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/ReindexRequest.java +++ b/asie-api/src/main/java/com/inteligr8/alfresco/asie/model/core/ReindexRequest.java @@ -24,7 +24,7 @@ public class ReindexRequest extends JsonFormattedResponseRequest @QueryParam("acltxid") private Long aclTransactionId; - @QueryParam("nodeId") + @QueryParam("nodeid") private Long nodeId; @QueryParam("aclid") diff --git a/asie-api/src/test/java/com/inteligr8/alfresco/asie/api/AbstractApiUnitTest.java b/asie-api/src/test/java/com/inteligr8/alfresco/asie/api/AbstractApiIT.java similarity index 93% rename from asie-api/src/test/java/com/inteligr8/alfresco/asie/api/AbstractApiUnitTest.java rename to asie-api/src/test/java/com/inteligr8/alfresco/asie/api/AbstractApiIT.java index 3d6ac07..e8e38da 100644 --- a/asie-api/src/test/java/com/inteligr8/alfresco/asie/api/AbstractApiUnitTest.java +++ b/asie-api/src/test/java/com/inteligr8/alfresco/asie/api/AbstractApiIT.java @@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory; import com.inteligr8.alfresco.asie.AsieClient; -public class AbstractApiUnitTest { +public class AbstractApiIT { protected Logger logger = LoggerFactory.getLogger(this.getClass()); diff --git a/asie-api/src/test/java/com/inteligr8/alfresco/asie/api/CoreAdminReindexUnitTest.java b/asie-api/src/test/java/com/inteligr8/alfresco/asie/api/CoreAdminReindexIT.java similarity index 94% rename from asie-api/src/test/java/com/inteligr8/alfresco/asie/api/CoreAdminReindexUnitTest.java rename to asie-api/src/test/java/com/inteligr8/alfresco/asie/api/CoreAdminReindexIT.java index 0457f3f..e57f481 100644 --- a/asie-api/src/test/java/com/inteligr8/alfresco/asie/api/CoreAdminReindexUnitTest.java +++ b/asie-api/src/test/java/com/inteligr8/alfresco/asie/api/CoreAdminReindexIT.java @@ -11,7 +11,7 @@ import com.inteligr8.solr.model.Action.Status; import com.inteligr8.solr.model.Cores; import com.inteligr8.solr.model.ResponseHeader; -public class CoreAdminReindexUnitTest extends AbstractApiUnitTest { +public class CoreAdminReindexIT extends AbstractApiIT { @Test public void reindex() { diff --git a/asie-api/src/test/java/com/inteligr8/alfresco/asie/api/CoreAdminStatusUnitTest.java b/asie-api/src/test/java/com/inteligr8/alfresco/asie/api/CoreAdminStatusIT.java similarity index 98% rename from asie-api/src/test/java/com/inteligr8/alfresco/asie/api/CoreAdminStatusUnitTest.java rename to asie-api/src/test/java/com/inteligr8/alfresco/asie/api/CoreAdminStatusIT.java index fb35228..0ede830 100644 --- a/asie-api/src/test/java/com/inteligr8/alfresco/asie/api/CoreAdminStatusUnitTest.java +++ b/asie-api/src/test/java/com/inteligr8/alfresco/asie/api/CoreAdminStatusIT.java @@ -19,7 +19,7 @@ import com.inteligr8.solr.model.core.StatusResponse; import jakarta.ws.rs.ProcessingException; -public class CoreAdminStatusUnitTest extends AbstractApiUnitTest { +public class CoreAdminStatusIT extends AbstractApiIT { @Test public void noHost() { diff --git a/enterprise-module/pom.xml b/enterprise-module/pom.xml index 6e8270d..6e1959a 100644 --- a/enterprise-module/pom.xml +++ b/enterprise-module/pom.xml @@ -16,10 +16,9 @@ ASIE Platform Module for ACS Enterprise - 4.9.0 - 23.3.0 - 23.3.0.98 - 10-2.1 + 25.1.0 + 25.1.0.71 + 2.3-tomcat-10.1.52 true @@ -37,10 +36,13 @@ + com.inteligr8.alfresco - asie-shared - ${project.version} + cxf-jaxrs-platform-module + 1.4.0-acs-v25.1 + amp + provided @@ -50,19 +52,11 @@ provided - + com.inteligr8.alfresco - cxf-jaxrs-platform-module - 1.3.2-acs-v23.3 - amp - - - - - com.inteligr8 - common-rest-client - provided + asie-shared + ${project.version} @@ -108,7 +102,6 @@ io.repaint.maven tiles-maven-plugin - 2.40 true diff --git a/pom.xml b/pom.xml index fa4615a..807d2c0 100644 --- a/pom.xml +++ b/pom.xml @@ -43,15 +43,21 @@ 17 17 true + + + 5.12.2 + + 3.0.3 + + 25.1.0 - + - - com.inteligr8 - common-rest-client - 3.0.3-cxf + org.junit.jupiter + junit-jupiter-api + ${junit.version} @@ -59,43 +65,48 @@ - - - maven-compiler-plugin - 3.14.1 - - + maven-site-plugin 3.21.0 - - maven-dependency-plugin - 3.9.0 + maven-compiler-plugin + 3.15.0 + + maven-dependency-plugin + 3.10.0 + + maven-surefire-plugin - 3.5.4 + 3.5.5 org.junit.jupiter junit-jupiter-engine - 5.14.0 + ${junit.version} maven-failsafe-plugin - 3.5.4 + 3.5.5 org.junit.jupiter junit-jupiter-engine - 5.14.0 + ${junit.version} + + + io.repaint.maven + tiles-maven-plugin + 2.43 + diff --git a/shared/pom.xml b/shared/pom.xml index f53220e..2518c45 100644 --- a/shared/pom.xml +++ b/shared/pom.xml @@ -17,7 +17,8 @@ 4.9.0 - 23.3.0 + + ${commom-rest-client.base.version}-cxf @@ -41,6 +42,7 @@ com.inteligr8 common-rest-client + ${common-rest-client.version} diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/service/AbstractNodeActionService.java b/shared/src/main/java/com/inteligr8/alfresco/asie/service/AbstractNodeActionService.java index db8012f..2ce701e 100644 --- a/shared/src/main/java/com/inteligr8/alfresco/asie/service/AbstractNodeActionService.java +++ b/shared/src/main/java/com/inteligr8/alfresco/asie/service/AbstractNodeActionService.java @@ -13,15 +13,12 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.alfresco.model.ContentModel; import org.alfresco.repo.index.shard.Floc; import org.alfresco.repo.index.shard.Shard; import org.alfresco.repo.index.shard.ShardInstance; import org.alfresco.repo.index.shard.ShardRegistry; import org.alfresco.repo.index.shard.ShardState; import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.search.SearchParameters; -import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.slf4j.Logger; @@ -151,7 +148,10 @@ public abstract class AbstractNodeActionService implements DisposableBean { } } - private Future _action(long nodeDbId, ActionCallback callback, Long fullQueueExpireTimeMillis) throws TimeoutException, InterruptedException { + private Future _action( + final long nodeDbId, + final ActionCallback callback, + Long fullQueueExpireTimeMillis) throws TimeoutException, InterruptedException { List eligibleInstances = this.findPossibleShardInstances(nodeDbId); this.logger.debug("Will attempt to {} ACS node against {} shard instances: {}", this.getActionName(), eligibleInstances.size(), nodeDbId); @@ -164,49 +164,12 @@ public abstract class AbstractNodeActionService implements DisposableBean { Callable callable = new Callable<>() { @Override public Void call() { - String core = instance.extractShard().getCoreName(); - SolrHost host = instance.extractNode(); - URL url = host.toUrl(apiService.isSecure() ? "https" : "http"); - CoreAdminApi api = apiService.createApi(url.toString(), CoreAdminApi.class); - try { - logger.debug("Performing {} of ACS node against shard instance: {}: {}", getActionName(), nodeDbId, instance); - BaseResponse apiResponse = execute(api, core, nodeDbId); - logger.trace("Performed {} of ACS node against shard instance: {}: {}", getActionName(), nodeDbId, instance); - - Action action = null; - if (apiResponse instanceof ActionCoreResponse) { - action = ((ActionCoreResponse) apiResponse).getCores().getByCore(core); - } else if (apiResponse instanceof ActionResponse) { - action = ((ActionResponse) apiResponse).getAction(); - } - - if (action == null) { - callback.unknownResult(instance); - } else { - switch (action.getStatus()) { - case Scheduled: - callback.scheduled(instance); - break; - case Success: - callback.success(instance); - break; - default: - if (apiResponse instanceof com.inteligr8.alfresco.asie.model.BaseResponse) { - com.inteligr8.alfresco.asie.model.BaseResponse asieResponse = (com.inteligr8.alfresco.asie.model.BaseResponse) apiResponse; - logger.debug("Performance of {} of ACS node against shard instance failed: {}: {}: {}", getActionName(), nodeDbId, instance, asieResponse.getException()); - callback.error(instance, asieResponse.getException()); - } else { - logger.debug("Performance of {} of ACS node against shard instance failed: {}: {}: {}", getActionName(), nodeDbId, instance, apiResponse.getResponseHeader().getStatus()); - callback.error(instance, String.valueOf(apiResponse.getResponseHeader().getStatus())); - } - } - } + actionToShard(nodeDbId, callback, instance); } catch (Exception e) { - logger.error("An exception occurred", e); + logger.error("An unexpected exception occurred", e); callback.error(instance, e.getMessage()); } - return null; } }; @@ -221,15 +184,58 @@ public abstract class AbstractNodeActionService implements DisposableBean { return future; } + @SuppressWarnings("unchecked") + protected void actionToShard(long nodeDbId, ActionCallback callback, com.inteligr8.alfresco.asie.model.ShardInstance instance) { + String core = instance.extractShard().getCoreName(); + SolrHost host = instance.extractNode(); + URL url = host.toUrl(this.apiService.isSecure() ? "https" : "http"); + CoreAdminApi api = this.apiService.createApi(url.toString(), CoreAdminApi.class); + + this.logger.debug("Performing {} of ACS node against shard instance: {}: {}", this.getActionName(), nodeDbId, instance); + BaseResponse apiResponse = execute(api, core, nodeDbId); + this.logger.trace("Performed {} of ACS node against shard instance: {}: {}", this.getActionName(), nodeDbId, instance); + + Action action = null; + if (apiResponse instanceof ActionCoreResponse) { + action = ((ActionCoreResponse) apiResponse).getCores().getByCore(core); + } else if (apiResponse instanceof ActionResponse) { + action = ((ActionResponse) apiResponse).getAction(); + } + + if (action == null) { + callback.unknownResult(instance); + } else { + switch (action.getStatus()) { + case Scheduled: + callback.scheduled(instance); + break; + case Success: + callback.success(instance); + break; + default: + if (apiResponse instanceof com.inteligr8.alfresco.asie.model.BaseResponse) { + com.inteligr8.alfresco.asie.model.BaseResponse asieResponse = (com.inteligr8.alfresco.asie.model.BaseResponse) apiResponse; + this.logger.debug("Performance of {} of ACS node against shard instance failed: {}: {}: {}", + this.getActionName(), nodeDbId, instance, asieResponse.getException()); + callback.error(instance, asieResponse.getException()); + } else { + this.logger.debug("Performance of {} of ACS node against shard instance failed: {}: {}: {}", + this.getActionName(), nodeDbId, instance, apiResponse.getResponseHeader().getStatus()); + callback.error(instance, String.valueOf(apiResponse.getResponseHeader().getStatus())); + } + } + } + } + protected abstract BaseResponse execute(CoreAdminApi api, String core, long nodeDbId); private List findPossibleShardInstances(long nodeDbId) { if (this.shardRegistry == null) throw new UnsupportedOperationException("ACS instances without a sharding configuration are not yet implemented"); - SearchParameters searchParams = new SearchParameters(); - searchParams.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO); - searchParams.setQuery("@" + this.formatForFts(ContentModel.PROP_NODE_DBID) + ":" + nodeDbId); +// SearchParameters searchParams = new SearchParameters(); +// searchParams.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO); +// searchParams.setQuery("@" + this.formatForFts(ContentModel.PROP_NODE_DBID) + ":" + nodeDbId); List instances = new LinkedList<>(); diff --git a/shared/src/main/java/com/inteligr8/alfresco/asie/service/SolrShardHashService.java b/shared/src/main/java/com/inteligr8/alfresco/asie/service/SolrShardHashService.java index a423257..972ba76 100644 --- a/shared/src/main/java/com/inteligr8/alfresco/asie/service/SolrShardHashService.java +++ b/shared/src/main/java/com/inteligr8/alfresco/asie/service/SolrShardHashService.java @@ -1,6 +1,9 @@ package com.inteligr8.alfresco.asie.service; import java.nio.charset.Charset; +import java.time.Instant; +import java.time.temporal.TemporalAccessor; +import java.util.Date; import java.util.regex.Matcher; import org.alfresco.error.AlfrescoRuntimeException; @@ -9,6 +12,7 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.apache.commons.codec.digest.MurmurHash3; +import org.joda.time.ReadablePartial; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -70,7 +74,20 @@ public class SolrShardHashService { } this.logger.trace("Discovered node property for sharding: {} => {}", nodeRef, fullPropertyValue); - String hashableValue = fullPropertyValue.toString(); + + String hashableValue = null; + if (fullPropertyValue instanceof TemporalAccessor) { + Instant instant = Instant.from((TemporalAccessor) fullPropertyValue); + hashableValue = instant.toString(); + } else if (fullPropertyValue instanceof ReadablePartial) { + hashableValue = ((ReadablePartial) fullPropertyValue).toString(); + } else if (fullPropertyValue instanceof Date) { + Instant instant = ((Date) fullPropertyValue).toInstant(); + hashableValue = instant.toString(); + } else { + hashableValue = fullPropertyValue.toString(); + } + if (shardset.getRegex() != null) { Matcher matcher = shardset.getRegex().matcher(hashableValue); if (!matcher.find()) { @@ -84,6 +101,7 @@ public class SolrShardHashService { int shardHash = this.hash(hashableValue, shardset.getShards().intValue()); this.logger.debug("Hash shardable value to shard instance ID: {}: {} => {}", nodeRef, hashableValue, shardHash); return shardHash; + // TODO replicate hash algorithm for other shard methods default: this.logger.trace("Unable to determine shard instance ID due to shard method: {}", shardset.getMethod()); return -1; diff --git a/solr-api/pom.xml b/solr-api/pom.xml index 8c3e21f..5287f9e 100644 --- a/solr-api/pom.xml +++ b/solr-api/pom.xml @@ -18,7 +18,7 @@ Apache Solr Jakarta RS API - 2.18.0 + 2.21.1