Allow server assigned UUIDs instead of sequential IDs if conigured to do

so
This commit is contained in:
James Agnew 2017-12-06 23:16:10 -06:00
parent 0fb10b2636
commit 36e719f92f
4 changed files with 153 additions and 27 deletions

View File

@ -149,6 +149,10 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
}
}
if (myDaoConfig.getResourceIdStrategy() == DaoConfig.IdStrategyEnum.UUID) {
theResource.setId(UUID.randomUUID().toString());
}
return doCreate(theResource, theIfNoneExist, thePerformIndexing, new Date(), theRequestDetails);
}

View File

@ -109,6 +109,7 @@ public class DaoConfig {
private boolean myAutoCreatePlaceholderReferenceTargets;
private Integer myCacheControlNoStoreMaxResultsUpperLimit = 1000;
private Integer myCountSearchResultsUpTo = null;
private IdStrategyEnum myResourceIdStrategy = IdStrategyEnum.SEQUENTIAL_NUMERIC;
/**
* Constructor
@ -160,18 +161,18 @@ public class DaoConfig {
* whether a "total count" is included in the response bundle for searches that
* return large amounts of data.
* <p>
* For a search that returns 10000 results, if this value is set to
* 10000 the search coordinator will find all 10000 results
* prior to returning, so the initial response bundle will have the
* total set to 10000. If this value is null (or less than 10000)
* the response bundle will likely return slightly faster, but will
* not include the total. Subsequent page requests will likely
* include the total however, if they are performed after the
* search coordinator has found all results.
* For a search that returns 10000 results, if this value is set to
* 10000 the search coordinator will find all 10000 results
* prior to returning, so the initial response bundle will have the
* total set to 10000. If this value is null (or less than 10000)
* the response bundle will likely return slightly faster, but will
* not include the total. Subsequent page requests will likely
* include the total however, if they are performed after the
* search coordinator has found all results.
* </p>
* <p>
* Set this value to <code>0</code> to always load all
* results before returning.
* Set this value to <code>0</code> to always load all
* results before returning.
* </p>
*/
public Integer getCountSearchResultsUpTo() {
@ -185,18 +186,18 @@ public class DaoConfig {
* whether a "total count" is included in the response bundle for searches that
* return large amounts of data.
* <p>
* For a search that returns 10000 results, if this value is set to
* 10000 the search coordinator will find all 10000 results
* prior to returning, so the initial response bundle will have the
* total set to 10000. If this value is null (or less than 10000)
* the response bundle will likely return slightly faster, but will
* not include the total. Subsequent page requests will likely
* include the total however, if they are performed after the
* search coordinator has found all results.
* For a search that returns 10000 results, if this value is set to
* 10000 the search coordinator will find all 10000 results
* prior to returning, so the initial response bundle will have the
* total set to 10000. If this value is null (or less than 10000)
* the response bundle will likely return slightly faster, but will
* not include the total. Subsequent page requests will likely
* include the total however, if they are performed after the
* search coordinator has found all results.
* </p>
* <p>
* Set this value to <code>0</code> to always load all
* results before returning.
* Set this value to <code>0</code> to always load all
* results before returning.
* </p>
*/
public void setCountSearchResultsUpTo(Integer theCountSearchResultsUpTo) {
@ -408,8 +409,11 @@ public class DaoConfig {
/**
* This may be used to optionally register server interceptors directly against the DAOs.
*/
public void setInterceptors(List<IServerInterceptor> theInterceptors) {
myInterceptors = theInterceptors;
public void setInterceptors(IServerInterceptor... theInterceptor) {
setInterceptors(new ArrayList<IServerInterceptor>());
if (theInterceptor != null && theInterceptor.length != 0) {
getInterceptors().addAll(Arrays.asList(theInterceptor));
}
}
/**
@ -466,6 +470,25 @@ public class DaoConfig {
myResourceEncoding = theResourceEncoding;
}
/**
* This setting configures the strategy to use in generating IDs for newly
* created resources on the server. The default is {@link IdStrategyEnum#SEQUENTIAL_NUMERIC}.
*/
public IdStrategyEnum getResourceIdStrategy() {
return myResourceIdStrategy;
}
/**
* This setting configures the strategy to use in generating IDs for newly
* created resources on the server. The default is {@link IdStrategyEnum#SEQUENTIAL_NUMERIC}.
*
* @param theResourceIdStrategy The strategy. Must not be null.
*/
public void setResourceIdStrategy(IdStrategyEnum theResourceIdStrategy) {
Validate.notNull(theResourceIdStrategy, "theResourceIdStrategy must not be null");
myResourceIdStrategy = theResourceIdStrategy;
}
/**
* If set, an individual resource will not be allowed to have more than the
* given number of tags, profiles, and security labels (the limit is for the combined
@ -1007,11 +1030,8 @@ public class DaoConfig {
/**
* This may be used to optionally register server interceptors directly against the DAOs.
*/
public void setInterceptors(IServerInterceptor... theInterceptor) {
setInterceptors(new ArrayList<IServerInterceptor>());
if (theInterceptor != null && theInterceptor.length != 0) {
getInterceptors().addAll(Arrays.asList(theInterceptor));
}
public void setInterceptors(List<IServerInterceptor> theInterceptors) {
myInterceptors = theInterceptors;
}
/**
@ -1062,4 +1082,16 @@ public class DaoConfig {
DISABLED
}
public enum IdStrategyEnum {
/**
* This strategy is the default strategy, and it simply uses a sequential
* numeric ID for each newly created resource.
*/
SEQUENTIAL_NUMERIC,
/**
* Each resource will receive a randomly generated UUID
*/
UUID
}
}

View File

@ -0,0 +1,86 @@
package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.Patient;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.hamcrest.Matchers.matchesPattern;
import static org.junit.Assert.*;
public class FhirResourceDaoR4CreateTest extends BaseJpaR4Test {
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoR4CreateTest.class);
@After
public void afterResetDao() {
myDaoConfig.setResourceIdStrategy(new DaoConfig().getResourceIdStrategy());
}
@Test
public void testCreateWithUuidResourceStrategy() throws Exception {
myDaoConfig.setResourceIdStrategy(DaoConfig.IdStrategyEnum.UUID);
Patient p = new Patient();
p.addName().setFamily("FAM");
IIdType id = myPatientDao.create(p).getId().toUnqualified();
assertThat(id.getIdPart(), matchesPattern("[a-z0-9]{8}-.*"));
p = myPatientDao.read(id);
assertEquals("FAM", p.getNameFirstRep().getFamily());
}
@Test
public void testTransactionCreateWithUuidResourceStrategy() throws Exception {
myDaoConfig.setResourceIdStrategy(DaoConfig.IdStrategyEnum.UUID);
Organization org = new Organization();
org.setId(IdType.newRandomUuid());
org.setName("ORG");
Patient p = new Patient();
p.setId(IdType.newRandomUuid());
p.addName().setFamily("FAM");
p.getManagingOrganization().setReference(org.getId());
Bundle input = new Bundle();
input.setType(Bundle.BundleType.TRANSACTION);
input.addEntry()
.setResource(org)
.setFullUrl(org.getId())
.getRequest()
.setMethod(Bundle.HTTPVerb.POST);
input.addEntry()
.setResource(p)
.setFullUrl(p.getId())
.getRequest()
.setMethod(Bundle.HTTPVerb.POST);
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(input));
Bundle output = mySystemDao.transaction(mySrd, input);
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
assertThat(output.getEntry().get(0).getResponse().getLocation(), matchesPattern("Organization/[a-z0-9]{8}-.*"));
assertThat(output.getEntry().get(1).getResponse().getLocation(), matchesPattern("Patient/[a-z0-9]{8}-.*"));
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}
}

View File

@ -21,6 +21,10 @@
Searching in JPA server using a combination of _content and _id parameters
failed. Thanks to Jeff Weyer for reporting!
</action>
<action type="add">
A new configuration option has been added to DaoConfig which allows newly created
resources to be assigned a UUID by the server instead of a sequential ID
</action>
</release>
<release version="3.1.0" date="2017-11-23">
<action type="add">