diff --git a/app/src/main/resources/default-application.yml b/app/src/main/resources/default-application.yml
index e0b76179..29251dba 100644
--- a/app/src/main/resources/default-application.yml
+++ b/app/src/main/resources/default-application.yml
@@ -39,10 +39,6 @@ spring:
driver-class-name: @db.driver@
hikari:
maximum-pool-size: 50
- cache:
- type: caffeine
- caffeine:
- spec: expireAfterAccess=60s,maximumSize=10000
artemis:
embedded:
enabled: true
@@ -50,7 +46,6 @@ spring:
persistent: true
data-directory: ${dhis2.home}/services/fhir-adapter/artemis
-
hystrix:
command:
default:
@@ -73,6 +68,21 @@ dhis2.fhir-adapter:
system-authentication:
username: @dhis2.username@
password: @dhis2.password@
+ cache:
+ dhis:
+ type: caffeine
+ caffeine:
+ spec: expireAfterAccess=60s,maximumSize=10000
+ redis:
+ time-to-live: 60s
+ key-prefix: fhir-adapter:dhis
+ fhir:
+ type: caffeine
+ caffeine:
+ spec: expireAfterAccess=120s,maximumSize=10000
+ redis:
+ time-to-live: 120s
+ key-prefix: fhir-adapter:fhir
remote:
processor:
max-search-count: 10000
diff --git a/app/src/main/resources/logback-spring.xml b/app/src/main/resources/logback-spring.xml
index 487a408d..6d17170a 100644
--- a/app/src/main/resources/logback-spring.xml
+++ b/app/src/main/resources/logback-spring.xml
@@ -41,6 +41,8 @@
+
+
diff --git a/common/pom.xml b/common/pom.xml
index 6a8b4fa8..39414203 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -50,5 +50,9 @@
artemis-jms-server
provided
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
diff --git a/common/src/main/java/org/dhis2/fhir/adapter/cache/AbstractSimpleCacheConfig.java b/common/src/main/java/org/dhis2/fhir/adapter/cache/AbstractSimpleCacheConfig.java
new file mode 100644
index 00000000..54c75a11
--- /dev/null
+++ b/common/src/main/java/org/dhis2/fhir/adapter/cache/AbstractSimpleCacheConfig.java
@@ -0,0 +1,140 @@
+package org.dhis2.fhir.adapter.cache;
+
+/*
+ * Copyright (c) 2004-2018, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.caffeine.CaffeineCacheManager;
+import org.springframework.cache.support.NoOpCacheManager;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.serializer.RedisElementReader;
+import org.springframework.data.redis.serializer.RedisElementWriter;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Nonnull;
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ * Abstract simple cache configuration that can be extended multiple times for specific use cases.
+ */
+@Validated
+public abstract class AbstractSimpleCacheConfig implements Serializable
+{
+ private static final long serialVersionUID = 3060542002074294407L;
+
+ @NotNull
+ private SimpleCacheType type = SimpleCacheType.NONE;
+
+ @Valid
+ @NotNull
+ private SimpleCaffeineCacheConfig caffeine = new SimpleCaffeineCacheConfig();
+
+ @Valid
+ @NotNull
+ private SimpleRedisCacheConfig redis = new SimpleRedisCacheConfig();
+
+ @Nonnull
+ public SimpleCacheType getType()
+ {
+ return type;
+ }
+
+ public void setType( @Nonnull SimpleCacheType type )
+ {
+ this.type = type;
+ }
+
+ @Nonnull
+ public SimpleCaffeineCacheConfig getCaffeine()
+ {
+ return caffeine;
+ }
+
+ public void setCaffeine( @Nonnull SimpleCaffeineCacheConfig caffeine )
+ {
+ this.caffeine = caffeine;
+ }
+
+ @Nonnull
+ public SimpleRedisCacheConfig getRedis()
+ {
+ return redis;
+ }
+
+ public void setRedis( @Nonnull SimpleRedisCacheConfig redis )
+ {
+ this.redis = redis;
+ }
+
+ @Nonnull
+ protected CacheManager createCacheManager( @Nonnull ObjectProvider redisConnectionFactoryProvider, @Nonnull RedisSerializer redisSerializer )
+ {
+ switch ( getType() )
+ {
+ case NONE:
+ return new NoOpCacheManager();
+ case CAFFEINE:
+ final CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
+ caffeineCacheManager.setCacheSpecification( caffeine.getSpec() );
+ return caffeineCacheManager;
+ case REDIS:
+ return RedisCacheManager.builder( redisConnectionFactoryProvider.getObject() ).cacheDefaults( createRedisCacheConfiguration( redisSerializer ) ).build();
+ default:
+ throw new AssertionError( "Unhandled cache type: " + getType() );
+ }
+ }
+
+ @Nonnull
+ protected RedisCacheConfiguration createRedisCacheConfiguration( @Nonnull RedisSerializer redisSerializer )
+ {
+ return RedisCacheConfiguration.defaultCacheConfig().computePrefixWith( getRedis().getKeyPrefix() )
+ .entryTtl( getRedis().getTimeToLive() ).serializeValuesWith( new RedisSerializationContext.SerializationPair()
+ {
+ @Override
+ @Nonnull
+ public RedisElementReader getReader()
+ {
+ return RedisElementReader.from( redisSerializer );
+ }
+
+ @Override
+ @Nonnull
+ public RedisElementWriter getWriter()
+ {
+ return RedisElementWriter.from( redisSerializer );
+ }
+ } );
+ }
+}
diff --git a/common/src/main/java/org/dhis2/fhir/adapter/cache/SimpleCacheType.java b/common/src/main/java/org/dhis2/fhir/adapter/cache/SimpleCacheType.java
new file mode 100644
index 00000000..fadadb06
--- /dev/null
+++ b/common/src/main/java/org/dhis2/fhir/adapter/cache/SimpleCacheType.java
@@ -0,0 +1,39 @@
+package org.dhis2.fhir.adapter.cache;
+
+/*
+ * Copyright (c) 2004-2018, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * The type of simple cache to be used.
+ *
+ * @author volsch
+ */
+public enum SimpleCacheType
+{
+ NONE, CAFFEINE, REDIS
+}
diff --git a/common/src/main/java/org/dhis2/fhir/adapter/cache/SimpleCaffeineCacheConfig.java b/common/src/main/java/org/dhis2/fhir/adapter/cache/SimpleCaffeineCacheConfig.java
new file mode 100644
index 00000000..81a3b885
--- /dev/null
+++ b/common/src/main/java/org/dhis2/fhir/adapter/cache/SimpleCaffeineCacheConfig.java
@@ -0,0 +1,61 @@
+package org.dhis2.fhir.adapter.cache;
+
+/*
+ * Copyright (c) 2004-2018, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Nonnull;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ * Simple cache configuration of a Caffeine cache.
+ *
+ * @author volsch
+ */
+@Validated
+public class SimpleCaffeineCacheConfig implements Serializable
+{
+ private static final long serialVersionUID = 8632490027903813823L;
+
+ @NotNull
+ private String spec = StringUtils.EMPTY;
+
+ @Nonnull
+ public String getSpec()
+ {
+ return spec;
+ }
+
+ public void setSpec( @Nonnull String spec )
+ {
+ this.spec = spec;
+ }
+}
diff --git a/common/src/main/java/org/dhis2/fhir/adapter/cache/SimpleRedisCacheConfig.java b/common/src/main/java/org/dhis2/fhir/adapter/cache/SimpleRedisCacheConfig.java
new file mode 100644
index 00000000..9f2a7aa6
--- /dev/null
+++ b/common/src/main/java/org/dhis2/fhir/adapter/cache/SimpleRedisCacheConfig.java
@@ -0,0 +1,84 @@
+package org.dhis2.fhir.adapter.cache;
+
+/*
+ * Copyright (c) 2004-2018, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.springframework.data.redis.cache.CacheKeyPrefix;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Nonnull;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.time.Duration;
+
+/**
+ * Simple cache configuration of a Redis cache.
+ *
+ * @author volsch
+ */
+@Validated
+public class SimpleRedisCacheConfig implements Serializable
+{
+ private static final long serialVersionUID = 7668397012800515816L;
+
+ @NotNull
+ private Duration timeToLive = Duration.ZERO;
+
+ @NotNull
+ private CacheKeyPrefix keyPrefix = CacheKeyPrefix.simple();
+
+ @Nonnull
+ public Duration getTimeToLive()
+ {
+ return timeToLive;
+ }
+
+ public void setTimeToLive( @Nonnull Duration timeToLive )
+ {
+ this.timeToLive = timeToLive;
+ }
+
+ @Nonnull
+ public CacheKeyPrefix getKeyPrefix()
+ {
+ return keyPrefix;
+ }
+
+ public void setKeyPrefix( @Nonnull String keyPrefix )
+ {
+ this.keyPrefix = new CacheKeyPrefix()
+ {
+ @Override
+ @Nonnull
+ public String compute( @Nonnull String cacheName )
+ {
+ return keyPrefix + ":" + cacheName + ":";
+ }
+ };
+ }
+}
diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/config/DhisMetadataCacheConfig.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/config/DhisMetadataCacheConfig.java
new file mode 100644
index 00000000..200180f4
--- /dev/null
+++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/config/DhisMetadataCacheConfig.java
@@ -0,0 +1,61 @@
+package org.dhis2.fhir.adapter.dhis.config;
+
+/*
+ * Copyright (c) 2004-2018, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.dhis2.fhir.adapter.cache.AbstractSimpleCacheConfig;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cache.CacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Cache configuration for FHIR Resources.
+ */
+@Configuration
+@ConfigurationProperties( "dhis2.fhir-adapter.cache.dhis" )
+@Validated
+public class DhisMetadataCacheConfig extends AbstractSimpleCacheConfig
+{
+ private static final long serialVersionUID = 3060542002074294407L;
+
+ @Primary
+ @Bean
+ @Nonnull
+ protected CacheManager dhisCacheManager( @Nonnull ObjectProvider redisConnectionFactoryProvider )
+ {
+ return createCacheManager( redisConnectionFactoryProvider, new JdkSerializationRedisSerializer() );
+ }
+}
diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/orgunit/impl/OrganisationUnitServiceImpl.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/orgunit/impl/OrganisationUnitServiceImpl.java
index 62bb06a6..015fc7eb 100644
--- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/orgunit/impl/OrganisationUnitServiceImpl.java
+++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/orgunit/impl/OrganisationUnitServiceImpl.java
@@ -52,7 +52,7 @@
* @author volsch
*/
@Service
-@CacheConfig( cacheNames = "organisationUnit" )
+@CacheConfig( cacheNames = "organisationUnit", cacheManager = "dhisCacheManager" )
public class OrganisationUnitServiceImpl implements OrganisationUnitService
{
protected static final String FIELDS = "id,code";
diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/impl/ProgramMetadataServiceImpl.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/impl/ProgramMetadataServiceImpl.java
index 75259aac..591cf224 100644
--- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/impl/ProgramMetadataServiceImpl.java
+++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/impl/ProgramMetadataServiceImpl.java
@@ -54,7 +54,7 @@
* @author volsch
*/
@Service
-@CacheConfig( cacheNames = "programMetadata" )
+@CacheConfig( cacheNames = "programMetadata", cacheManager = "dhisCacheManager" )
public class ProgramMetadataServiceImpl implements ProgramMetadataService
{
protected static final String FIELDS =
diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/impl/TrackedEntityMetadataServiceImpl.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/impl/TrackedEntityMetadataServiceImpl.java
index 8e850a8c..0f2da9fe 100644
--- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/impl/TrackedEntityMetadataServiceImpl.java
+++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/impl/TrackedEntityMetadataServiceImpl.java
@@ -73,7 +73,7 @@ public TrackedEntityMetadataServiceImpl( @Nonnull @Qualifier( "systemDhis2RestTe
}
@HystrixCommand
- @Cacheable( "trackedEntityTypes" )
+ @Cacheable( value = "trackedEntityTypes", cacheManager = "dhisCacheManager" )
@Nonnull
@Override
public Optional extends TrackedEntityType> getType( @Nonnull Reference reference )
@@ -107,7 +107,7 @@ public Optional extends TrackedEntityType> getType( @Nonnull Reference referen
}
@HystrixCommand
- @Cacheable( "trackedEntityAttributes" )
+ @Cacheable( value = "trackedEntityAttributes", cacheManager = "dhisCacheManager" )
@Nonnull
@Override
public TrackedEntityAttributes getAttributes()
@@ -118,7 +118,7 @@ public TrackedEntityAttributes getAttributes()
}
@HystrixCommand
- @Cacheable( "requiredValues" )
+ @Cacheable( value = "requiredValues", cacheManager = "dhisCacheManager" )
@Override
@Nonnull
public RequiredValues getRequiredValues( @Nonnull String attributeId )
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/FhirResourceCacheConfig.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/FhirResourceCacheConfig.java
new file mode 100644
index 00000000..0cd24d91
--- /dev/null
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/FhirResourceCacheConfig.java
@@ -0,0 +1,58 @@
+package org.dhis2.fhir.adapter.fhir.repository.impl;
+
+/*
+ * Copyright (c) 2004-2018, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.dhis2.fhir.adapter.cache.AbstractSimpleCacheConfig;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cache.CacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Cache configuration for FHIR Resources.
+ */
+@Configuration
+@ConfigurationProperties( "dhis2.fhir-adapter.cache.fhir" )
+@Validated
+public class FhirResourceCacheConfig extends AbstractSimpleCacheConfig
+{
+ private static final long serialVersionUID = 3060542002074294407L;
+
+ @Bean
+ @Nonnull
+ protected CacheManager fhirCacheManager( @Nonnull ObjectProvider redisConnectionFactoryProvider, @Nonnull FhirResourceRedisSerializer redisSerializer )
+ {
+ return createCacheManager( redisConnectionFactoryProvider, redisSerializer );
+ }
+}
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/FhirResourceRedisSerializer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/FhirResourceRedisSerializer.java
new file mode 100644
index 00000000..2448f671
--- /dev/null
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/FhirResourceRedisSerializer.java
@@ -0,0 +1,147 @@
+package org.dhis2.fhir.adapter.fhir.repository.impl;
+
+/*
+ * Copyright (c) 2004-2018, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import ca.uhn.fhir.context.FhirContext;
+import org.dhis2.fhir.adapter.fhir.model.FhirVersion;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Serializer for HAPI FHIR Resources for caching them in Redis.
+ *
+ * @author volsch
+ */
+@Component
+public class FhirResourceRedisSerializer implements RedisSerializer
+{
+ private static final byte[] EMPTY_ARRAY = new byte[0];
+
+ private final Map fhirContexts;
+
+ public FhirResourceRedisSerializer( @Nonnull ObjectProvider> fhirContexts )
+ {
+ this.fhirContexts = fhirContexts.getIfAvailable( Collections::emptyList ).stream().filter( fc -> (FhirVersion.get( fc.getVersion().getVersion() ) != null) )
+ .collect( Collectors.toMap( fc -> FhirVersion.get( fc.getVersion().getVersion() ), fc -> fc ) );
+ }
+
+ @Override
+ public byte[] serialize( @Nullable IBaseResource resource ) throws SerializationException
+ {
+ if ( resource == null )
+ {
+ return EMPTY_ARRAY;
+ }
+
+ final FhirVersion fhirVersion = FhirVersion.get( resource.getStructureFhirVersionEnum() );
+ if ( fhirVersion == null )
+ {
+ throw new SerializationException( "Could not serialize FHIR resource since FHIR version " + resource.getStructureFhirVersionEnum() + " is not supported." );
+ }
+ final FhirContext context = fhirContexts.get( fhirVersion );
+ if ( context == null )
+ {
+ throw new SerializationException( "Could not serialize FHIR resource since FHIR context is not available for FHIR version " + fhirVersion + "." );
+ }
+
+ final ByteArrayOutputStream bs = new ByteArrayOutputStream( 512 );
+ try
+ {
+ final DataOutputStream out = new DataOutputStream( bs );
+ out.writeUTF( fhirVersion.name() );
+ final Writer w = new OutputStreamWriter( out, StandardCharsets.UTF_8 );
+ context.newJsonParser().encodeResourceToWriter( resource, w );
+ // flush internal buffers to byte array output stream
+ w.close();
+ out.close();
+ bs.close();
+ }
+ catch ( IOException e )
+ {
+ throw new SerializationException( "Could not serialize FHIR resource.", e );
+ }
+
+ return bs.toByteArray();
+ }
+
+ @Override
+ public IBaseResource deserialize( byte[] bytes ) throws SerializationException
+ {
+ if ( (bytes == null) || (bytes.length == 0) )
+ {
+ return null;
+ }
+
+ final DataInputStream in = new DataInputStream( new ByteArrayInputStream( bytes ) );
+ try
+ {
+ final String fhirVersionString = in.readUTF();
+ final FhirVersion fhirVersion;
+ try
+ {
+ fhirVersion = FhirVersion.valueOf( fhirVersionString );
+ }
+ catch ( IllegalArgumentException e )
+ {
+ throw new SerializationException( "Unknown FHIR version: " + fhirVersionString );
+ }
+
+ final FhirContext context = fhirContexts.get( fhirVersion );
+ if ( context == null )
+ {
+ throw new SerializationException( "Could not deserialize FHIR resource since FHIR context is not available for FHIR version " + fhirVersion + "." );
+ }
+
+ return context.newJsonParser().parseResource( new InputStreamReader( in, StandardCharsets.UTF_8 ) );
+ }
+ catch ( IOException e )
+ {
+ throw new SerializationException( "Could not deserialize FHIR resource.", e );
+ }
+ }
+}
diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/RemoteFhirRepositoryImpl.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/RemoteFhirRepositoryImpl.java
index dc72e8f0..435056dc 100644
--- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/RemoteFhirRepositoryImpl.java
+++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/RemoteFhirRepositoryImpl.java
@@ -62,7 +62,7 @@
* @author volsch
*/
@Component
-@CacheConfig( cacheNames = "fhirResources" )
+@CacheConfig( cacheNames = "fhirResources", cacheManager = "fhirCacheManager" )
public class RemoteFhirRepositoryImpl implements RemoteFhirRepository
{
private final Logger logger = LoggerFactory.getLogger( getClass() );
@@ -74,7 +74,6 @@ public class RemoteFhirRepositoryImpl implements RemoteFhirRepository
public RemoteFhirRepositoryImpl( @Nonnull RemoteSubscriptionRepository repository, @Nonnull ObjectProvider> fhirContexts )
{
this.repository = repository;
-
this.fhirContexts = fhirContexts.getIfAvailable( Collections::emptyList ).stream().filter( fc -> (FhirVersion.get( fc.getVersion().getVersion() ) != null) )
.collect( Collectors.toMap( fc -> FhirVersion.get( fc.getVersion().getVersion() ), fc -> fc ) );
}