Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ on [Keep a CHANGELOG](http://keepachangelog.com/). This project adheres to

## [Unreleased]

## [25.104.0-M9] - 2026-07-28
### Changed
- **Elasticsearch client migration `7.17` → `9.2.2`** (cherry-picked from Java-17 DD-41592): `RestHighLevelClient` → `co.elastic.clients.elasticsearch.ElasticsearchClient` across the `unifiedsearch-client` library (DocumentService, DefaultUnifiedSearchService, SearchRequestFactory/SearchResultConverter, client producers/factories) and `unifiedsearch-test-utils`; new `BulkRequest` / `SearchResponse(JsonData)` / `indices()` APIs. `javax`→`jakarta` conflicts resolved during the port.
- Bumped `cpp.common-bom.version` `25.104.0-M2` → `25.104.0-M3` — picks up ES 9.2.2 dependency management + jackson `2.21.5` (**CVE-2026-54515**).
- Advanced all framework references to the released milestones (platform tracks the framework chain): parent `parent-pom` `M1` → `M2`, `file-service.version` `M6` → `M7`, `framework-libraries.version` `M10` → `M11`, `framework.version` (cp-microservice-framework) `M3` → `M4`, `event-store.version` `M4` → `M5`. Carries jackson `2.21.5` (**CVE-2026-54515**), the `org.junit:junit-bom` import, maven-shade `3.6.0` / jacoco `0.8.14`, and the event-store `EntityManagerFlushInterceptorPresenceVerifier` deploy-guard.
- Bumped cross-context RAML interfaces to their latest released versions (required by `enforce-moj-latest-interfaces`): `hearing.version` `17.104.176` → `17.104.180`, `referencedata.version` `17.103.133` → `17.104.137`, `assignment.version` `8.0.5` → `8.0.7`, `usersgroups.version` `17.104.48` → `17.104.50`, `progression.version` `17.0.262` → `17.0.279`, `sjp.version` `17.103.169` → `17.104.181`.

## [25.104.0-M7] - 2026-07-07
### Changed
- Updated `framework.version` (`cp-microservice-framework`) to `25.104.0-M3`
Expand Down
4 changes: 2 additions & 2 deletions healthchecks-parent/unifiedsearch-healthchecks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
</dependency>

<!-- Test Dependencies -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,17 @@

import java.io.IOException;

import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.cluster.HealthResponse;

/**
* Wrapper class for the unmockable parts of getting a health response from elastic search
*/
public class ElasticSearchHealthQuerier {

public ClusterHealthResponse getClusterHealth(
final RestHighLevelClient restHighLevelClient,
final RequestOptions requestOptions) throws IOException {
public HealthResponse getClusterHealth(
final ElasticsearchClient client) throws IOException {

return restHighLevelClient
.cluster()
.health(new ClusterHealthRequest(), requestOptions);
return client.cluster().health();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package uk.gov.justice.services.unifiedsearch.healthchecks;

import static co.elastic.clients.elasticsearch._types.HealthStatus.Green;
import static java.lang.String.format;
import static org.elasticsearch.client.RequestOptions.DEFAULT;
import static org.elasticsearch.cluster.health.ClusterHealthStatus.GREEN;
import static uk.gov.justice.services.healthcheck.api.HealthcheckResult.failure;
import static uk.gov.justice.services.healthcheck.api.HealthcheckResult.success;
import static uk.gov.justice.services.unifiedsearch.client.utils.UnifiedSearchSecurityConstants.MONITOR_USER;
Expand All @@ -15,15 +14,16 @@
import jakarta.inject.Inject;
import jakarta.inject.Named;

import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.health.ClusterHealthStatus;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.HealthStatus;
import co.elastic.clients.elasticsearch.cluster.HealthResponse;


public class ElasticSearchHealthcheck implements Healthcheck {

@Inject
@Named(MONITOR_USER)
private RestHighLevelClient restHighLevelClient;
private ElasticsearchClient restHighLevelClient;

@Inject
private ElasticSearchHealthQuerier elasticSearchHealthQuerier;
Expand All @@ -35,24 +35,23 @@ public String getHealthcheckName() {

@Override
public String healthcheckDescription() {
return "Verifies Elastic Search Health Status is '" + GREEN + "'";
return "Verifies Elastic Search Health Status is '" + Green + "'";
}

@Override
public HealthcheckResult runHealthcheck() {

try {
final ClusterHealthResponse clusterHealthResponse = elasticSearchHealthQuerier.getClusterHealth(
restHighLevelClient,
DEFAULT);
final HealthResponse clusterHealthResponse = elasticSearchHealthQuerier.getClusterHealth(
restHighLevelClient);

final ClusterHealthStatus healthStatus = clusterHealthResponse.getStatus();
final HealthStatus healthStatus = clusterHealthResponse.status();

if (healthStatus == GREEN) {
if (healthStatus == Green) {
return success();
}

return failure(format("Elastic Search healthcheck failed. CLuster Health Status should be '%s' but was '%s'", GREEN, healthStatus));
return failure(format("Elastic Search healthcheck failed. CLuster Health Status should be '%s' but was '%s'", Green, healthStatus));

} catch (final IOException e) {
throw new ElasticSearchHealtcheckQueryException(format("IOException thrown when calling Elastic Search. Exception message: '%s'", e.getMessage()), e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
package uk.gov.justice.services.unifiedsearch.healthchecks;

import static co.elastic.clients.elasticsearch._types.HealthStatus.Green;
import static java.util.Optional.empty;
import static java.util.Optional.of;
import static org.elasticsearch.client.RequestOptions.DEFAULT;
import static org.elasticsearch.cluster.health.ClusterHealthStatus.GREEN;
import static org.elasticsearch.cluster.health.ClusterHealthStatus.RED;
import static org.elasticsearch.cluster.health.ClusterHealthStatus.YELLOW;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.HealthStatus;
import co.elastic.clients.elasticsearch.cluster.HealthResponse;
import org.junit.jupiter.api.extension.ExtendWith;
import uk.gov.justice.services.healthcheck.api.HealthcheckResult;

import java.io.IOException;

import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
Expand All @@ -29,7 +26,7 @@
public class ElasticSearchHealthcheckTest {

@Mock
private RestHighLevelClient restHighLevelClient;
private ElasticsearchClient restHighLevelClient;

@Mock
private ElasticSearchHealthQuerier elasticSearchHealthQuerier;
Expand All @@ -46,16 +43,16 @@ public void shouldReturnCorrectHealthcheckName() throws Exception {
@Test
public void shouldReturnCorrectHealthcheckDescription() throws Exception {

assertThat(elasticSearchHealthcheck.healthcheckDescription(), is("Verifies Elastic Search Health Status is 'GREEN'"));
assertThat(elasticSearchHealthcheck.healthcheckDescription(), is("Verifies Elastic Search Health Status is 'Green'"));
}

@Test
public void shouldReturnSuccessIfElasticSearchHealthStatusIsGreen() throws Exception {

final ClusterHealthResponse clusterHealthResponse = mock(ClusterHealthResponse.class);
final HealthResponse clusterHealthResponse = mock(HealthResponse.class);

when(elasticSearchHealthQuerier.getClusterHealth(restHighLevelClient, DEFAULT)).thenReturn(clusterHealthResponse);
when(clusterHealthResponse.getStatus()).thenReturn(GREEN);
when(elasticSearchHealthQuerier.getClusterHealth(restHighLevelClient)).thenReturn(clusterHealthResponse);
when(clusterHealthResponse.status()).thenReturn(Green);

final HealthcheckResult healthcheckResult = elasticSearchHealthcheck.runHealthcheck();
assertThat(healthcheckResult.isPassed(), is(true));
Expand All @@ -65,35 +62,35 @@ public void shouldReturnSuccessIfElasticSearchHealthStatusIsGreen() throws Excep
@Test
public void shouldFailHealthcheckIfElasticSearchHealthStatusIsRed() throws Exception {

final ClusterHealthResponse clusterHealthResponse = mock(ClusterHealthResponse.class);
final HealthResponse clusterHealthResponse = mock(HealthResponse.class);

when(elasticSearchHealthQuerier.getClusterHealth(restHighLevelClient, DEFAULT)).thenReturn(clusterHealthResponse);
when(clusterHealthResponse.getStatus()).thenReturn(RED);
when(elasticSearchHealthQuerier.getClusterHealth(restHighLevelClient)).thenReturn(clusterHealthResponse);
when(clusterHealthResponse.status()).thenReturn(HealthStatus.Red);

final HealthcheckResult healthcheckResult = elasticSearchHealthcheck.runHealthcheck();
assertThat(healthcheckResult.isPassed(), is(false));
assertThat(healthcheckResult.getErrorMessage(), is(of("Elastic Search healthcheck failed. CLuster Health Status should be 'GREEN' but was 'RED'")));
assertThat(healthcheckResult.getErrorMessage(), is(of("Elastic Search healthcheck failed. CLuster Health Status should be 'Green' but was 'Red'")));
}

@Test
public void shouldFailHealthcheckIfElasticSearchHealthStatusIsYellow() throws Exception {

final ClusterHealthResponse clusterHealthResponse = mock(ClusterHealthResponse.class);
final HealthResponse clusterHealthResponse = mock(HealthResponse.class);

when(elasticSearchHealthQuerier.getClusterHealth(restHighLevelClient, DEFAULT)).thenReturn(clusterHealthResponse);
when(clusterHealthResponse.getStatus()).thenReturn(YELLOW);
when(elasticSearchHealthQuerier.getClusterHealth(restHighLevelClient)).thenReturn(clusterHealthResponse);
when(clusterHealthResponse.status()).thenReturn(HealthStatus.Yellow);

final HealthcheckResult healthcheckResult = elasticSearchHealthcheck.runHealthcheck();
assertThat(healthcheckResult.isPassed(), is(false));
assertThat(healthcheckResult.getErrorMessage(), is(of("Elastic Search healthcheck failed. CLuster Health Status should be 'GREEN' but was 'YELLOW'")));
assertThat(healthcheckResult.getErrorMessage(), is(of("Elastic Search healthcheck failed. CLuster Health Status should be 'Green' but was 'Yellow'")));
}

@Test
public void shouldFailIfQueryingElasticSearchThrowsIOException() throws Exception {

final IOException ioException = new IOException("It all went wrong");

when(elasticSearchHealthQuerier.getClusterHealth(restHighLevelClient, DEFAULT)).thenThrow(ioException);
when(elasticSearchHealthQuerier.getClusterHealth(restHighLevelClient)).thenThrow(ioException);

final ElasticSearchHealtcheckQueryException elasticSearchHealtcheckQueryException = assertThrows(
ElasticSearchHealtcheckQueryException.class,
Expand Down
24 changes: 12 additions & 12 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>uk.gov.moj.cpp.common</groupId>
<artifactId>parent-pom</artifactId>
<version>25.104.0-M1</version>
<version>25.104.0-M2</version>
</parent>

<groupId>uk.gov.moj.platform.libraries</groupId>
Expand Down Expand Up @@ -42,22 +42,22 @@
<jakarta.xml.bind-api.raml.version>2.3.2</jakarta.xml.bind-api.raml.version>

<!-- Github libraries versions -->
<cpp.common-bom.version>25.104.0-M2</cpp.common-bom.version>
<file-service.version>25.104.0-M6</file-service.version>
<cpp.common-bom.version>25.104.0-M3</cpp.common-bom.version>
<file-service.version>25.104.0-M7</file-service.version>

<!-- Framework versions -->
<framework-libraries.version>25.104.0-M10</framework-libraries.version>
<framework.version>25.104.0-M3</framework.version>
<event-store.version>25.104.0-M4</event-store.version>
<framework-libraries.version>25.104.0-M11</framework-libraries.version>
<framework.version>25.104.0-M4</framework.version>
<event-store.version>25.104.0-M5</event-store.version>

<cpp.framework.version>${framework.version}</cpp.framework.version>

<assignment.version>8.0.5</assignment.version>
<usersgroups.version>17.104.48</usersgroups.version>
<progression.version>17.0.262</progression.version>
<hearing.version>17.104.176</hearing.version>
<sjp.version>17.103.169</sjp.version>
<referencedata.version>17.103.133</referencedata.version>
<assignment.version>8.0.7</assignment.version>
<usersgroups.version>17.104.50</usersgroups.version>
<progression.version>17.0.279</progression.version>
<hearing.version>17.104.180</hearing.version>
<sjp.version>17.104.181</sjp.version>
<referencedata.version>17.104.137</referencedata.version>
<versions-manven-plugin.version>2.15.0</versions-manven-plugin.version>
</properties>

Expand Down
19 changes: 16 additions & 3 deletions unifiedsearch-library-parent/unifiedsearch-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,25 @@

<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<artifactId>elasticsearch-rest-client</artifactId>
</dependency>

<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
</dependency>

<!-- Apache HTTP Async Client -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.2.1</version>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5</artifactId>
<version>5.2.1</version>
</dependency>

<!-- Test Dependencies -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@

import jakarta.enterprise.context.ApplicationScoped;

import org.elasticsearch.action.get.GetRequest;
import co.elastic.clients.elasticsearch.core.GetRequest;

@ApplicationScoped
public class GetRequestFactory {

public GetRequest getRequest(final String indexName, final UUID documentId) {
return new GetRequest(indexName).id(documentId.toString());
return GetRequest.of(r -> r
.index(indexName)
.id(documentId.toString()));
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package uk.gov.justice.services.unifiedsearch.client.factory;

import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.NONE;
import static org.elasticsearch.xcontent.XContentType.JSON;

import uk.gov.justice.services.unifiedsearch.client.index.UnifiedSearchIndexerHelper;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.json.JsonObject;

import org.elasticsearch.action.index.IndexRequest;
import co.elastic.clients.elasticsearch.core.IndexRequest;

@ApplicationScoped
public class IndexRequestFactory {
Expand All @@ -18,14 +14,16 @@ public class IndexRequestFactory {
private UnifiedSearchIndexerHelper unifiedSearchIndexerHelper;

public IndexRequest indexRequest(final String indexName,
final JsonObject document,
final long sequenceNumber,
final long primaryTerm) {
return new IndexRequest(indexName)
.source(document.toString(), JSON)
.id(unifiedSearchIndexerHelper.getCaseId(document).toString())
.setRefreshPolicy(NONE)
.setIfSeqNo(sequenceNumber)
.setIfPrimaryTerm(primaryTerm);
final Object document,
final String caseId,
final Long sequenceNumber,
final Long primaryTerm) {
return IndexRequest.of(i -> i
.index(indexName)
.id(caseId)
.document(document)
.ifSeqNo(sequenceNumber)
.ifPrimaryTerm(primaryTerm)
);
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
package uk.gov.justice.services.unifiedsearch.client.factory;

import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.NONE;
import static org.elasticsearch.xcontent.XContentType.JSON;

import jakarta.enterprise.context.ApplicationScoped;

import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import co.elastic.clients.elasticsearch.core.IndexRequest;
import co.elastic.clients.elasticsearch.core.UpdateRequest;

@ApplicationScoped
public class UpdateRequestFactory {


public UpdateRequest updateRequest(final String indexName,
final String documentId,
final String caseDetailsString,
final Object document,
final IndexRequest indexRequest) {
return new UpdateRequest(indexName, documentId)
.doc(caseDetailsString, JSON)
.setRefreshPolicy(NONE)
.upsert(indexRequest);
return UpdateRequest.of(u -> u
.index(indexName)
.id(documentId)
.doc(document)
.upsert(indexRequest)
);
}

}
Loading
Loading