-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Normalize out resource type names into new hfj_resource_type table #6890
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
michaelabuckley
merged 41 commits into
master
from
6889-normalize-out-resource-type-names-into-new-hfj_resource_type-table
May 22, 2025
Merged
Changes from all commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
d8f95de
[6889] add migration tasks for new table and column updates
YalingPeiS 11c2155
[6889] correct FK column name
YalingPeiS 3afc835
[6889] add explicit index to the FK column
YalingPeiS f71bc4b
Merge remote-tracking branch 'refs/remotes/origin/master' into 6889-n…
YalingPeiS d3c9d90
[6889] update entities with the new column
YalingPeiS 2165910
Merge remote-tracking branch 'origin/master' into 6889-normalize-out-…
YalingPeiS 7e20404
[6889] add migration tasks to populate the new resource type table
YalingPeiS 989403b
Merge remote-tracking branch 'origin/master' into 6889-normalize-out-…
YalingPeiS 08149df
[6889] rename variables
YalingPeiS 7bc3eb2
[6889] minor update
YalingPeiS 4594097
[6889] update migration tasks to entities
YalingPeiS ca5d48f
[6889] load resource types using Fhir Context
YalingPeiS 4555205
[6889] apply spotless
YalingPeiS 07081f5
[6889] apply spotless
YalingPeiS 31a7702
Merge remote-tracking branch 'origin/master' into 6889-normalize-out-…
YalingPeiS 78b4197
[6889] update entity classes
YalingPeiS fc312d0
[6889] add new classes for resource type cache service and dao
YalingPeiS 9881bf9
Merge remote-tracking branch 'origin/master' into 6889-normalize-out-…
YalingPeiS 5d8bba8
[6889] write resource type id to the newly added resource rows
YalingPeiS fbdef68
[6889] add exception handling for unique index constraint
YalingPeiS 33ea430
[6889] add util class for generating resource types to be used in mul…
YalingPeiS c5158a1
[6889] fix the failed unit tests by caused by the extra query to the …
YalingPeiS 3036145
[6889] Pre-populate the resource type database table to fix failed tests
YalingPeiS 23c651c
[6889] fix the failed unit tests in R5
YalingPeiS 7cffffa
[6889] Revert back to not use HapiTransactionServer due to unit test …
YalingPeiS c6a330a
[6889] fix more unit tests
YalingPeiS 23d0933
[6889] fix more unit tests
YalingPeiS 40327f4
[6889] minor update
YalingPeiS 83e981c
[6889] add changelog and fix unit test failure in MdmEventIT
YalingPeiS ca42b1a
[6889] fix the failed unit tests in Mdm package
YalingPeiS d6ae6bd
Merge remote-tracking branch 'origin/master' into 6889-normalize-out-…
YalingPeiS 822d5f7
[6889] more unit test updates
YalingPeiS a7b6b80
[6889] more unit test updates
YalingPeiS 8d8cf11
Merge remote-tracking branch 'origin/master' into 6889-normalize-out-…
YalingPeiS a9c40b9
[6889] address review comment - remove resource type foreign key cons…
YalingPeiS 1c0d63d
[6889] address review comment - use IHapiTransactionService
YalingPeiS 6617bff
[6889] update unit tests
YalingPeiS ac6a1e0
Merge remote-tracking branch 'origin/master' into 6889-normalize-out-…
YalingPeiS 1adf94b
[6889] code cleaning
YalingPeiS 15e67a2
[6889] address review comment - change return value from Short to short
YalingPeiS 577d472
[6889] apply spotless
YalingPeiS File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
15 changes: 15 additions & 0 deletions
15
...resources/ca/uhn/hapi/fhir/changelog/8_4_0/6889-normalize-out-resource-type-to-table.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
type: add | ||
issue: 6889 | ||
title: "A new table `HFJ_RESOURCE_TYPE` has been introduced. This table stores all known resource types from all | ||
releases. It is pre-populated at server start up. New or custom resource types are added to this table on demand. | ||
A new column `HFJ_RESOURCE_TYPE_ID` has been added to the following tables. | ||
<ul> | ||
<li>HFJ_RESOURCE</li> | ||
<li>HFJ_RE_VER</li> | ||
<li>HFJ_RES_TAG</li> | ||
<li>HFJ_RES_HISTORY_TAG</li> | ||
<li>HFJ_RES_VER_LINK</li> | ||
</ul> | ||
This column is used to store the resource type ID which references the `HFJ_RESOURCE_TYPE` table." | ||
|
40 changes: 40 additions & 0 deletions
40
hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/cache/IResourceTypeCacheSvc.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* #%L | ||
* HAPI FHIR JPA Server | ||
* %% | ||
* Copyright (C) 2014 - 2025 Smile CDR, Inc. | ||
* %% | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* #L% | ||
*/ | ||
package ca.uhn.fhir.jpa.cache; | ||
|
||
public interface IResourceTypeCacheSvc { | ||
/** | ||
* Retrieves the resource type ID for the given resource type. | ||
* If the resource type does not exist, a new custom resource type will be created, | ||
* added to the database and cache, and its ID will be returned. | ||
* | ||
* @param theResType the resource type to retrieve or create | ||
* @return the resource type ID or throws an exception if the resource creation fails | ||
*/ | ||
short getResourceTypeId(String theResType); | ||
|
||
/** | ||
* Adds the given resource type and its corresponding ID to the cache. | ||
* | ||
* @param theResType the resource type to be added to the cache | ||
* @param theResTypeId the ID of the resource type to be added to the cache | ||
*/ | ||
void addToCache(String theResType, Short theResTypeId); | ||
} |
138 changes: 138 additions & 0 deletions
138
hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/cache/ResourceTypeCacheSvcImpl.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
/* | ||
* #%L | ||
* HAPI FHIR JPA Server | ||
* %% | ||
* Copyright (C) 2014 - 2025 Smile CDR, Inc. | ||
* %% | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* #L% | ||
*/ | ||
package ca.uhn.fhir.jpa.cache; | ||
|
||
import ca.uhn.fhir.jpa.config.util.ResourceTypeUtil; | ||
import ca.uhn.fhir.jpa.dao.data.IResourceTypeDao; | ||
import ca.uhn.fhir.jpa.dao.tx.IHapiTransactionService; | ||
import ca.uhn.fhir.jpa.model.entity.ResourceTypeEntity; | ||
import ca.uhn.fhir.jpa.util.MemoryCacheService; | ||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; | ||
import jakarta.annotation.PostConstruct; | ||
import org.apache.commons.collections4.CollectionUtils; | ||
import org.slf4j.Logger; | ||
import org.springframework.dao.DataIntegrityViolationException; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Propagation; | ||
|
||
import java.util.List; | ||
|
||
import static org.slf4j.LoggerFactory.getLogger; | ||
|
||
@Service | ||
public class ResourceTypeCacheSvcImpl implements IResourceTypeCacheSvc { | ||
private static final Logger ourLog = getLogger(ResourceTypeCacheSvcImpl.class); | ||
|
||
private final IHapiTransactionService myTransactionService; | ||
private final IResourceTypeDao myResourceTypeDao; | ||
private final MemoryCacheService myMemoryCacheService; | ||
|
||
public ResourceTypeCacheSvcImpl( | ||
IHapiTransactionService theTransactionService, | ||
IResourceTypeDao theResourceTypeDao, | ||
MemoryCacheService theMemoryCacheService) { | ||
myTransactionService = theTransactionService; | ||
myResourceTypeDao = theResourceTypeDao; | ||
myMemoryCacheService = theMemoryCacheService; | ||
} | ||
|
||
@PostConstruct | ||
public void start() { | ||
initResourceTypes(); | ||
ourLog.info( | ||
"Resource type cache size: {}", | ||
myMemoryCacheService.getEstimatedSize(MemoryCacheService.CacheEnum.RES_TYPE_TO_RES_TYPE_ID)); | ||
} | ||
|
||
@Override | ||
public short getResourceTypeId(String theResType) { | ||
Short resTypeId = myMemoryCacheService.get( | ||
MemoryCacheService.CacheEnum.RES_TYPE_TO_RES_TYPE_ID, theResType, this::lookupResourceTypeId); | ||
|
||
if (resTypeId == null) { | ||
ourLog.info("Creating a new Resource Type [{}]", theResType); | ||
ResourceTypeEntity entity = createResourceType(theResType); | ||
resTypeId = entity.getResourceTypeId(); | ||
addToCache(theResType, resTypeId); | ||
} | ||
return resTypeId; | ||
} | ||
|
||
@Override | ||
public void addToCache(String theResType, Short theResTypeId) { | ||
myMemoryCacheService.putAfterCommit( | ||
MemoryCacheService.CacheEnum.RES_TYPE_TO_RES_TYPE_ID, theResType, theResTypeId); | ||
} | ||
|
||
protected void initResourceTypes() { | ||
myTransactionService | ||
.withSystemRequestOnDefaultPartition() | ||
.withPropagation(Propagation.REQUIRES_NEW) | ||
.execute(() -> { | ||
List<ResourceTypeEntity> resTypeEntities = myResourceTypeDao.findAll(); | ||
if (CollectionUtils.isEmpty(resTypeEntities)) { | ||
List<ResourceTypeEntity> newEntities = ResourceTypeUtil.generateResourceTypes().stream() | ||
.map(r -> { | ||
ResourceTypeEntity entity = new ResourceTypeEntity(); | ||
entity.setResourceType(r); | ||
return entity; | ||
}) | ||
.toList(); | ||
|
||
myResourceTypeDao.saveAll(newEntities); | ||
ourLog.info("Table HFJ_RESOURCE_TYPE is populated with {} entries.", newEntities.size()); | ||
resTypeEntities = newEntities; | ||
} | ||
|
||
// Populate the cache | ||
resTypeEntities.forEach(r -> addToCache(r.getResourceType(), r.getResourceTypeId())); | ||
return null; | ||
}); | ||
} | ||
|
||
protected ResourceTypeEntity createResourceType(String theResourceType) { | ||
return myTransactionService | ||
.withSystemRequestOnDefaultPartition() | ||
.withPropagation(Propagation.REQUIRES_NEW) | ||
.execute(() -> { | ||
ResourceTypeEntity resTypeEntity = new ResourceTypeEntity(); | ||
resTypeEntity.setResourceType(theResourceType); | ||
try { | ||
resTypeEntity = myResourceTypeDao.save(resTypeEntity); | ||
myResourceTypeDao.flush(); | ||
} catch (DataIntegrityViolationException e) { | ||
if (e.getMessage().contains("Value too long for column")) { | ||
throw new InternalErrorException("Resource type name is too long: " + theResourceType, e); | ||
} | ||
// This can happen if the resource type already exists in the database | ||
ourLog.info("Resource type already exists: {}", theResourceType); | ||
resTypeEntity = myResourceTypeDao.findByResourceType(theResourceType); | ||
} | ||
|
||
return resTypeEntity; | ||
}); | ||
} | ||
|
||
private Short lookupResourceTypeId(String theResourceType) { | ||
return myTransactionService | ||
.withSystemRequestOnDefaultPartition() | ||
.execute(() -> myResourceTypeDao.findResourceIdByType(theResourceType)); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/util/ResourceTypeUtil.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/*- | ||
* #%L | ||
* HAPI FHIR JPA Server | ||
* %% | ||
* Copyright (C) 2014 - 2025 Smile CDR, Inc. | ||
* %% | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* #L% | ||
*/ | ||
package ca.uhn.fhir.jpa.config.util; | ||
|
||
import ca.uhn.fhir.context.FhirContext; | ||
import ca.uhn.fhir.context.FhirVersionEnum; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
public final class ResourceTypeUtil { | ||
|
||
public static List<String> generateResourceTypes() { | ||
return Stream.of(FhirVersionEnum.DSTU2, FhirVersionEnum.DSTU3, FhirVersionEnum.R4, FhirVersionEnum.R5) | ||
.map(FhirContext::forVersion) | ||
.flatMap(c -> c.getResourceTypes().stream()) | ||
.distinct() | ||
.sorted() | ||
.collect(Collectors.toList()); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/IResourceTypeDao.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* #%L | ||
* HAPI FHIR JPA Server | ||
* %% | ||
* Copyright (C) 2014 - 2025 Smile CDR, Inc. | ||
* %% | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* #L% | ||
*/ | ||
package ca.uhn.fhir.jpa.dao.data; | ||
|
||
import ca.uhn.fhir.jpa.model.entity.ResourceTypeEntity; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.data.jpa.repository.Query; | ||
import org.springframework.data.repository.query.Param; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@Repository | ||
public interface IResourceTypeDao extends JpaRepository<ResourceTypeEntity, Integer>, IHapiFhirJpaRepository { | ||
|
||
@Query(value = "SELECT t FROM ResourceTypeEntity t WHERE t.myResourceType = :resType") | ||
ResourceTypeEntity findByResourceType(@Param("resType") String theResType); | ||
|
||
@Query(value = "SELECT t.myResourceTypeId FROM ResourceTypeEntity t WHERE t.myResourceType = :resType") | ||
Short findResourceIdByType(@Param("resType") String theResType); | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.