Skip to content

Commit ee9cb65

Browse files
milanmajchrakkosarkokuchtiak-ufalCopilotPaurikova2
authored
UFAL/Release hotfix 2026 02 26 - Merge PR (#1260)
* UFAL/Fixed failing integration test (ufal#1332) (#1249) * Add debug messages to fauling test (cherry picked from commit 4cc3694) Co-authored-by: Milan Kuchtiak <kuchtiak@ufal.mff.cuni.cz> * [Port to dtq-dev] Fix OpenAIRE integration: null handling and HTTP client lifecycle (#1248) * Fix OpenAIRE integration: null handling and HTTP client lifecycle (ufal#1330) * Add test for OpenAIRE connector * Add null check for OpenAIRE response to prevent NullPointerException Co-authored-by: kosarko <1842385+kosarko@users.noreply.github.com> * Fix HTTP client lifecycle to prevent premature connection closure Co-authored-by: kosarko <1842385+kosarko@users.noreply.github.com> * Keep the try with resources but copy the response into an in memory stream and return that * license:check --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: kosarko <1842385+kosarko@users.noreply.github.com> (cherry picked from commit 02984db) * Handle NumberFormatException in OpenAIREFundingDataProvider.getNumberOfResults and use explicit UTF-8 charset in OpenAIRERestConnectorTest --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: kosarko <1842385+kosarko@users.noreply.github.com> Co-authored-by: milanmajchrak <milan.majchrak@dataquest.sk> * UFAL/Added a comment to do not forget mounting the file which is changed via ocnfiguration feature (#1247) * UFAL/Issue 1315: Store file preview to database when file preview is created on Item Page load. (ufal#1316) (#1241) * Issue ufal/clarin-dspace1315: Store file preview to database when file preview is created on item page load * PR comments: commit context only when any of the file preview is successfully created (cherry picked from commit aab626b) Co-authored-by: Milan Kuchtiak <kuchtiak@ufal.mff.cuni.cz> * UFAL/Issue 1313: fixed error when file preview is not generated for bitstream with store_number = 77 (ufal#1318) (#1240) * Issue ufal#1313: fixed error when file preview is not generated for bitstream with store number = 77 (cherry picked from commit 04d64f7) Co-authored-by: Milan Kuchtiak <kuchtiak@ufal.mff.cuni.cz> * UFAL/Nw version metadata issues (#1236) * Issue ufal#1266: dc.date.available and dc.relation.replaces metadata not cleared properly (ufal#1307) * Issue ufal#1266: dc.date.available and dc.relation.replaces metadata not cleaned properly in new item version * resolve MR comments - update ignoredMetadataFields in versioning-service.xml * update ClarinVersionedHandleIdentifierProviderIT test to check dc.identifier.uri metadata for new version (cherry picked from commit 7ffaf9a) * Issue 1319: do not copy dc.identifier.doi metadata when new item version is created (cherry picked from commit 1b7ed17) --------- Co-authored-by: Milan Kuchtiak <kuchtiak@ufal.mff.cuni.cz> * UFAL/Fix: add bitstream download-by-handle endpoint for curl instructions (#1252) * fix: add bitstream download-by-handle endpoint for curl instructions Adds GET /api/core/bitstreams/handle/{prefix}/{suffix}/{filename} endpoint that directly serves bitstream content by item handle and filename. This resolves the issue where curl download instructions generated by the UI produced URLs pointing to non-existent backend endpoints, resulting in 404 errors when users attempted to download files via command line. The new endpoint resolves the handle to an Item, finds the bitstream by exact filename in ORIGINAL bundles, and streams the raw content with correct Content-Type and Content-Disposition headers. Refs: dataquest-dev/dspace-angular#1210 * Fixed compliing errors * Small refactoring - use constants and removed unnecessary changes * added comments, return 404 status instead of 402 * unauthorized instead of forbidden * fix: use RFC 5987 Content-Disposition for non-ASCII filenames curl -J on Windows cannot create files with non-ASCII characters (e.g. diacritics like e/a) from a raw UTF-8 Content-Disposition filename header. Uses filename*=UTF-8''percent-encoded-name (RFC 5987/6266) which curl properly decodes. Also includes an ASCII fallback in filename param. * fix: move context.complete() after streaming to prevent truncated downloads context.complete() was called before bitstreamService.retrieve(), closing the DB connection and causing 'end of response with X bytes missing' errors. Now context.complete() is called only after the full content has been streamed. For S3 redirect and HEAD paths, context.complete() remains before return since no streaming is needed. * fix: use real UTF-8 filename in Content-Disposition instead of ASCII fallback The filename parameter now contains the original name (with diacritics like e/a) instead of replacing non-ASCII chars with underscores. Characters in the ISO-8859-1 range are transmitted correctly by Tomcat and understood by curl on Western/Central-European systems. The filename* parameter still provides RFC 5987 percent-encoded UTF-8 for modern clients (curl 7.56+). * fix: revert to ASCII fallback in Content-Disposition, add edge-case tests Content-Disposition filename parameter now uses ASCII fallback (non-ASCII replaced with underscore) per RFC 6266. Modern clients use filename* (RFC 5987) which has the full UTF-8 name. The curl command no longer relies on Content-Disposition at all (uses -o instead of -OJ). New integration tests for edge cases: - Multiple dots in filename (archive.v2.1.tar.gz) - Double quotes in filename (escaped in Content-Disposition) - CJK characters (beyond ISO-8859-1) - Same filename in ORIGINAL and TEXT bundles (only ORIGINAL served) * fix: resolve compilation errors and fix IT test assertions - Remove duplicate HttpStatus import (apache vs spring) - Add missing MediaType import (spring) - Fix Content-Type assertion to include charset=UTF-8 - Use URI.create() for pre-encoded URLs in tests to prevent double-encoding (%25) rejection by StrictHttpFirewall All 15 integration tests pass. * test: add complex filename test (diacritics, plus, hash, unmatched paren) New IT test for filename 'Media (+)#9) ano' verifying correct URL decoding, Content-Disposition encoding, and content delivery. 16/16 tests pass. * fix authorization, comments, tests * fix: change expected status from 401 to 403 for authenticated non-admin user The test downloadBitstreamByHandleUnauthorizedForNonAdmin uses getClient(token) which means the user IS authenticated. The controller correctly returns 403 (Forbidden) for authenticated users without access, not 401 (Unauthorized). 401 is only for anonymous/unauthenticated requests. --------- Co-authored-by: Paurikova2 <michaela.paurikova@dataquest.sk> --------- Co-authored-by: Ondřej Košarko <ko_ok@centrum.cz> Co-authored-by: Milan Kuchtiak <kuchtiak@ufal.mff.cuni.cz> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: kosarko <1842385+kosarko@users.noreply.github.com> Co-authored-by: Paurikova2 <michaela.paurikova@dataquest.sk>
1 parent e9f293f commit ee9cb65

19 files changed

Lines changed: 1314 additions & 38 deletions

File tree

checkstyle-suppressions.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
on JMockIt Expectations blocks and similar. See https://github.com/checkstyle/checkstyle/issues/3739 -->
99
<suppress checks="Indentation" files="src[/\\]test[/\\]java"/>
1010
<suppress checks="Regexp" files="DSpaceHttpClientFactory\.java"/>
11+
<suppress checks="Regexp" files="OpenAIRERestConnectorTest\.java"/>
1112
</suppressions>

dspace-api/src/main/java/org/dspace/external/OpenAIRERestConnector.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,11 @@ public InputStream get(String file, String accessToken) {
207207
break;
208208
}
209209

210-
// do not close this httpClient
211-
result = getResponse.getEntity().getContent();
210+
// the client will be closed, we need to copy the response stream to a new one that we can return
211+
try (InputStream is = getResponse.getEntity().getContent()) {
212+
byte[] bytes = is.readAllBytes();
213+
result = new java.io.ByteArrayInputStream(bytes);
214+
}
212215
}
213216
} catch (MalformedURLException e1) {
214217
getGotError(e1, url + '/' + file);

dspace-api/src/main/java/org/dspace/external/provider/impl/OpenAIREFundingDataProvider.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,19 @@ public int getNumberOfResults(String query) {
169169
String encodedQuery = encodeValue(query);
170170

171171
Response projectResponse = connector.searchProjectByKeywords(0, 0, encodedQuery);
172-
return Integer.parseInt(projectResponse.getHeader().getTotal());
172+
if (projectResponse == null || projectResponse.getHeader() == null) {
173+
return 0;
174+
}
175+
String total = projectResponse.getHeader().getTotal();
176+
if (StringUtils.isBlank(total)) {
177+
return 0;
178+
}
179+
try {
180+
return Integer.parseInt(total);
181+
} catch (NumberFormatException e) {
182+
log.error("Failed to parse search result count from OpenAIRE: {}", e.getMessage());
183+
return 0;
184+
}
173185
}
174186

175187
/**

dspace-api/src/main/java/org/dspace/storage/bitstore/SyncBitstreamStorageServiceImpl.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88
package org.dspace.storage.bitstore;
99

10+
import java.io.File;
1011
import java.io.IOException;
1112
import java.io.InputStream;
1213
import java.sql.SQLException;
@@ -185,12 +186,17 @@ public Map computeChecksumSpecStore(Context context, Bitstream bitstream, int st
185186
}
186187

187188
@Override
188-
public InputStream retrieve(Context context, Bitstream bitstream)
189-
throws SQLException, IOException {
189+
public InputStream retrieve(Context context, Bitstream bitstream) throws SQLException, IOException {
190190
int storeNumber = this.whichStoreNumber(bitstream);
191191
return this.getStore(storeNumber).get(bitstream);
192192
}
193193

194+
@Override
195+
public File retrieveFile(Context context, Bitstream bitstream) throws IOException {
196+
int storeNumber = whichStoreNumber(bitstream);
197+
return this.getStore(storeNumber).getFile(bitstream);
198+
}
199+
194200
@Override
195201
public void cleanup(boolean deleteDbRecords, boolean verbose) throws SQLException, IOException, AuthorizeException {
196202
Context context = new Context(Context.Mode.BATCH_EDIT);

dspace-api/src/main/java/org/dspace/versioning/DefaultItemVersionProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ protected void copyRelationships(
202202
*/
203203
private void manageRelationMetadata(Context c, Item itemNew, Item previousItem) throws SQLException {
204204
// Remove copied `dc.relation.replaces` metadata for the new item.
205-
itemService.clearMetadata(c, itemNew, "dc", "relation", "replaces", null);
205+
itemService.clearMetadata(c, itemNew, "dc", "relation", "replaces", Item.ANY);
206206

207207
// Add metadata `dc.relation.replaces` to the new item.
208208
// The metadata value is: `dc.identifier.uri` from the previous item.

dspace-api/src/test/java/org/dspace/builder/WorkspaceItemBuilder.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,29 @@ public WorkspaceItemBuilder withFulltext(String name, String source, InputStream
249249
return this;
250250
}
251251

252+
/**
253+
* Add bitstream with specific store number.
254+
*
255+
* @param name bitstream name
256+
* @param source bitstream test source location
257+
* @param is input stream of the bitstream
258+
* @param storeNumber store number
259+
*
260+
* @return this WorkspaceItemBuilder
261+
*/
262+
public WorkspaceItemBuilder withBitstream(String name, String source, InputStream is, int storeNumber) {
263+
try {
264+
Item item = workspaceItem.getItem();
265+
Bitstream b = itemService.createSingleBitstream(context, is, item);
266+
b.setStoreNumber(storeNumber);
267+
b.setName(context, name);
268+
b.setSource(context, source);
269+
} catch (Exception e) {
270+
handleException(e);
271+
}
272+
return this;
273+
}
274+
252275
/**
253276
* Create workspaceItem with any metadata
254277
* @param schema metadataSchema name e.g. `dc`
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* The contents of this file are subject to the license and copyright
3+
* detailed in the LICENSE and NOTICE files at the root of the source
4+
* tree and available online at
5+
*
6+
* http://www.dspace.org/license/
7+
*/
8+
package org.dspace.external;
9+
10+
import static org.junit.Assert.assertTrue;
11+
import static org.mockito.Mockito.doReturn;
12+
import static org.mockito.Mockito.spy;
13+
import static org.mockito.Mockito.when;
14+
15+
import java.io.IOException;
16+
import java.io.InputStream;
17+
import java.nio.charset.StandardCharsets;
18+
19+
import eu.openaire.jaxb.model.Response;
20+
import okhttp3.mockwebserver.MockResponse;
21+
import okhttp3.mockwebserver.MockWebServer;
22+
import org.apache.http.client.methods.HttpGet;
23+
import org.apache.http.impl.client.CloseableHttpClient;
24+
import org.apache.http.impl.client.HttpClientBuilder;
25+
import org.dspace.app.client.DSpaceHttpClientFactory;
26+
import org.junit.Test;
27+
import org.mockito.MockedStatic;
28+
import org.mockito.Mockito;
29+
30+
31+
public class OpenAIRERestConnectorTest {
32+
33+
@Test
34+
public void searchProjectByKeywords() {
35+
try (InputStream is = this.getClass().getResourceAsStream("openaire-projects.xml");
36+
MockWebServer mockServer = new MockWebServer()) {
37+
String projects = new String(is.readAllBytes(), StandardCharsets.UTF_8)
38+
.replaceAll("( mushroom)", "( DEADBEEF)");
39+
mockServer.enqueue(new MockResponse().setResponseCode(200).setBody(projects));
40+
41+
// setup mocks so we don't have to set whole DSpace kernel etc.
42+
// still, the idea is to test how the get method behaves
43+
CloseableHttpClient httpClient = spy(HttpClientBuilder.create().build());
44+
doReturn(httpClient.execute(new HttpGet(mockServer.url("").toString())))
45+
.when(httpClient).execute(Mockito.any());
46+
47+
DSpaceHttpClientFactory mock = Mockito.mock(DSpaceHttpClientFactory.class);
48+
when(mock.build()).thenReturn(httpClient);
49+
50+
try (MockedStatic<DSpaceHttpClientFactory> mockedFactory =
51+
Mockito.mockStatic(DSpaceHttpClientFactory.class)) {
52+
mockedFactory.when(DSpaceHttpClientFactory::getInstance).thenReturn(mock);
53+
OpenAIRERestConnector connector = new OpenAIRERestConnector(mockServer.url("").toString());
54+
Response response = connector.searchProjectByKeywords(0, 10, "keyword");
55+
// Basically check it doesn't throw UnmarshallerException and that we are getting our mocked response
56+
assertTrue("Expected the query to contain the replaced keyword",
57+
response.getHeader().getQuery().contains("DEADBEEF"));
58+
}
59+
} catch (IOException e) {
60+
e.printStackTrace();
61+
}
62+
}
63+
}

dspace-api/src/test/java/org/dspace/external/provider/impl/OpenAIREFundingDataProviderTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
import java.util.List;
1515
import java.util.Optional;
1616

17+
import eu.openaire.jaxb.model.Response;
1718
import org.dspace.AbstractDSpaceTest;
19+
import org.dspace.external.OpenAIRERestConnector;
1820
import org.dspace.external.factory.ExternalServiceFactory;
1921
import org.dspace.external.model.ExternalDataObject;
2022
import org.dspace.external.provider.ExternalDataProvider;
@@ -102,4 +104,21 @@ public void testGetDataObjectWInvalidId() {
102104

103105
assertTrue("openAIREFunding.getExternalDataObject.notExists:WRONGID", result.isEmpty());
104106
}
107+
108+
@Test
109+
public void testGetNumberOfResultsWhenResponseIsNull() {
110+
// Create a mock connector that returns null
111+
OpenAIREFundingDataProvider provider = new OpenAIREFundingDataProvider();
112+
provider.setSourceIdentifier("test");
113+
provider.setConnector(new OpenAIRERestConnector("test") {
114+
@Override
115+
public Response searchProjectByKeywords(int page, int size, String... keywords) {
116+
return null;
117+
}
118+
});
119+
120+
// Should return 0 when response is null, not throw NullPointerException
121+
int result = provider.getNumberOfResults("test");
122+
assertEquals("Should return 0 when response is null", 0, result);
123+
}
105124
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/**
2+
* The contents of this file are subject to the license and copyright
3+
* detailed in the LICENSE and NOTICE files at the root of the source
4+
* tree and available online at
5+
*
6+
* http://www.dspace.org/license/
7+
*/
8+
package org.dspace.identifier;
9+
10+
import static org.hamcrest.CoreMatchers.equalTo;
11+
import static org.hamcrest.CoreMatchers.not;
12+
import static org.hamcrest.CoreMatchers.startsWith;
13+
import static org.hamcrest.MatcherAssert.assertThat;
14+
15+
import java.text.SimpleDateFormat;
16+
import java.util.ArrayList;
17+
import java.util.Calendar;
18+
import java.util.List;
19+
import java.util.TimeZone;
20+
21+
import org.dspace.AbstractIntegrationTestWithDatabase;
22+
import org.dspace.builder.CollectionBuilder;
23+
import org.dspace.builder.CommunityBuilder;
24+
import org.dspace.builder.ItemBuilder;
25+
import org.dspace.builder.VersionBuilder;
26+
import org.dspace.content.Collection;
27+
import org.dspace.content.Item;
28+
import org.dspace.content.MetadataValue;
29+
import org.dspace.content.factory.ContentServiceFactory;
30+
import org.dspace.content.service.InstallItemService;
31+
import org.dspace.content.service.ItemService;
32+
import org.dspace.kernel.ServiceManager;
33+
import org.dspace.services.factory.DSpaceServicesFactory;
34+
import org.dspace.workflow.WorkflowItem;
35+
import org.dspace.workflow.WorkflowItemService;
36+
import org.dspace.workflow.factory.WorkflowServiceFactory;
37+
import org.junit.Before;
38+
import org.junit.Test;
39+
40+
/**
41+
* Unit Tests for ClarinVersionedHandleIdentifierProvider
42+
*
43+
* @authorMilan Kuchtiak
44+
*/
45+
public class ClarinVersionedHandleIdentifierProviderIT extends AbstractIntegrationTestWithDatabase {
46+
private IdentifierServiceImpl identifierService;
47+
private InstallItemService installItemService;
48+
private ItemService itemService;
49+
private WorkflowItemService workflowItemService;
50+
51+
private Collection collection;
52+
53+
@Before
54+
@Override
55+
public void setUp() throws Exception {
56+
super.setUp();
57+
context.turnOffAuthorisationSystem();
58+
59+
ServiceManager serviceManager = DSpaceServicesFactory.getInstance().getServiceManager();
60+
identifierService = serviceManager.getServicesByType(IdentifierServiceImpl.class).get(0);
61+
62+
itemService = ContentServiceFactory.getInstance().getItemService();
63+
installItemService = ContentServiceFactory.getInstance().getInstallItemService();
64+
workflowItemService = WorkflowServiceFactory.getInstance().getWorkflowItemService();
65+
66+
// Clean out providers to avoid any being used for creation of community and collection
67+
identifierService.setProviders(new ArrayList<>());
68+
69+
parentCommunity = CommunityBuilder.createCommunity(context)
70+
.withName("Parent Community")
71+
.build();
72+
collection = CollectionBuilder.createCollection(context, parentCommunity)
73+
.withName("Collection")
74+
.build();
75+
}
76+
77+
@Test
78+
public void testNewVersionMetadata() throws Exception {
79+
registerProvider(ClarinVersionedHandleIdentifierProvider.class);
80+
Item itemV1 = ItemBuilder.createItem(context, collection)
81+
.withTitle("First version")
82+
.build();
83+
84+
// new item "dc.relation.replaces" metadata has to be set to this value
85+
String itemV1HandleRef = itemService.getMetadataFirstValue(itemV1, "dc", "identifier", "uri", Item.ANY);
86+
87+
// set "dc.relation.replaces" metadata on itemV1
88+
itemService.addMetadata(context, itemV1, "dc", "relation", "replaces", null, "some_value");
89+
// replace "dc.date.available" metadata on itemV1 to some old value
90+
itemService.clearMetadata(context, itemV1, "dc", "date", "available", Item.ANY);
91+
itemService.addMetadata(context, itemV1, "dc", "date", "available", null, "2020-01-01");
92+
// simulate itemV1 having a DOI identifier assigned
93+
itemService.addMetadata(context, itemV1, "dc", "identifier", "doi", null,
94+
"https://handle.stage.datacite.org/10.5072/dspace-1");
95+
96+
Item itemV2 = VersionBuilder.createVersion(context, itemV1, "Second version").build().getItem();
97+
98+
// check that "dc.date.available", metadata is not copied to itemV2
99+
assertThat(itemService.getMetadata(itemV2, "dc", "date", "available", Item.ANY).size(), equalTo(0));
100+
101+
// check that "dc.identifier.uri", metadata is not copied to itemV2
102+
assertThat(itemService.getMetadata(itemV2, "dc", "identifier", "uri", Item.ANY).size(), equalTo(0));
103+
104+
// check that "dc.identifier.doi", metadata is not copied to itemV2
105+
assertThat(itemService.getMetadata(itemV2, "dc", "identifier", "doi", Item.ANY).size(), equalTo(0));
106+
107+
// check that "dc.relation.replaces" points to itemV1
108+
List<MetadataValue> metadataValues = itemService.getMetadata(itemV2, "dc", "relation", "replaces", Item.ANY);
109+
assertThat(metadataValues.size(), equalTo(1));
110+
assertThat(metadataValues.get(0).getValue(), equalTo(itemV1HandleRef));
111+
112+
WorkflowItem workflowItem = workflowItemService.create(context, itemV2, collection);
113+
Item installedItem = installItemService.installItem(context, workflowItem);
114+
115+
// get current date
116+
Calendar calendar = Calendar.getInstance();
117+
calendar.setTimeInMillis(System.currentTimeMillis());
118+
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
119+
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
120+
String date = sdf.format(calendar.getTime());
121+
122+
// check that "dc.relation.replaces" points to itemV1
123+
metadataValues = itemService.getMetadata(installedItem, "dc", "relation", "replaces", Item.ANY);
124+
assertThat(metadataValues.size(), equalTo(1));
125+
assertThat(metadataValues.get(0).getValue(), equalTo(itemV1HandleRef));
126+
127+
// Check that itemV2 has the correct "dc.date.available" metadata set to current date
128+
metadataValues = itemService.getMetadata(installedItem, "dc", "date", "available", Item.ANY);
129+
assertThat(metadataValues.size(), equalTo(1));
130+
assertThat(metadataValues.get(0).getValue(), startsWith(date));
131+
132+
// check "dc.identifier.uri" metadata has new value different from itemV1
133+
metadataValues = itemService.getMetadata(installedItem, "dc", "identifier", "uri", Item.ANY);
134+
assertThat(metadataValues.size(), equalTo(1));
135+
assertThat(metadataValues.get(0).getValue(), not(itemV1HandleRef));
136+
}
137+
138+
private void registerProvider(Class type) {
139+
// Register our new provider
140+
IdentifierProvider identifierProvider =
141+
(IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager()
142+
.getServiceByName(type.getName(), type);
143+
if (identifierProvider == null) {
144+
DSpaceServicesFactory.getInstance().getServiceManager().registerServiceClass(type.getName(), type);
145+
identifierProvider = (IdentifierProvider) DSpaceServicesFactory.getInstance().getServiceManager()
146+
.getServiceByName(type.getName(), type);
147+
}
148+
149+
// Overwrite the identifier-service's providers with the new one to ensure only this provider is used
150+
identifierService = DSpaceServicesFactory.getInstance().getServiceManager()
151+
.getServicesByType(IdentifierServiceImpl.class).get(0);
152+
identifierService.setProviders(new ArrayList<>());
153+
identifierService.setProviders(List.of(identifierProvider));
154+
}
155+
}

0 commit comments

Comments
 (0)