Skip to content

Commit

Permalink
[INJICERT-657] make Velocity template cacheable
Browse files Browse the repository at this point in the history
Signed-off-by: Harsh Vardhan <[email protected]>
  • Loading branch information
vharsh committed Dec 17, 2024
1 parent 0972eaa commit 7cb4475
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public class CertifyIssuanceServiceImpl implements VCIssuanceService {
@Value("${mosip.certify.data-provider-plugin.issuer-uri}")
private String issuerURI;

@Value("${mosip.certify.data-provider-plugin.svg-template-id:}")
@Value("${mosip.certify.data-provider-plugin.rendering-template-id:}")
private String svgTemplateId;

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,19 @@
* - VC 1.0 & 2.0 data model templating engine using Velocity
*/
public interface VCFormatter {
/**
* returns a templated VC as per the data in valueMap & some templateSettings
* @param valueMap data provided by a {@link DataProviderPlugin} implementation.
* @param templateSettings configurable tunables
* @return a templated & unsigned VC
*/
String format(JSONObject valueMap, Map<String, Object> templateSettings);

/**
* an internal method for VCFormatters to fetch a VC template as per the key
*
* @param key an identifier for a VC template
* @return Template String against a @param key
*/
String getTemplate(String key);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.time.format.DateTimeFormatter;
import java.util.*;

import io.mosip.certify.services.entity.CredentialTemplate;
import io.mosip.certify.services.spi.VCFormatter;
import io.mosip.certify.core.constants.Constants;
import io.mosip.certify.core.constants.VCDM2Constants;
Expand All @@ -32,6 +33,7 @@
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import static io.mosip.certify.services.templating.VelocityTemplatingConstants.*;
Expand All @@ -41,7 +43,7 @@
public class VelocityTemplatingEngineImpl implements VCFormatter {
VelocityEngine engine;
public static final String DELIMITER = ":";
Map<String, String> templateCache;
public static final String TEMPLATE_CACHE = "templatecache";
@Autowired
TemplateRepository templateRepository;
@Autowired
Expand All @@ -56,8 +58,6 @@ public void initialize() {
engine = new VelocityEngine();
// TODO: The DataSourceResourceLoader can be used instead if there's a
// single primary key column and the table has a last modified date.
templateCache = new HashMap<>();
templateRepository.findAll().stream().forEach((template -> templateCache.put(String.join(DELIMITER, template.getCredentialType(), template.getContext()), template.getTemplate())));
engine.setProperty(RuntimeConstants.INPUT_ENCODING, "UTF-8");
engine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8");
engine.init();
Expand All @@ -80,8 +80,12 @@ public void initialize() {
public String format(JSONObject valueMap, Map<String, Object> templateSettings) {
// TODO: Isn't template name becoming too complex with VC_CONTEXTS & CREDENTIAL_TYPES both?
String templateName = templateSettings.get(TEMPLATE_NAME).toString();
String template = getTemplate(templateName);
if (template == null) {
log.error("Template {} not found", templateName);
throw new TemplateException("Expected template not found");
}
String issuer = templateSettings.get(ISSUER_URI).toString();
String template = templateCache.get(templateName);
StringWriter writer = new StringWriter();
// 1. Prepare map
// TODO: Eventually, the credentialSubject from the plugin will be templated as-is
Expand Down Expand Up @@ -136,4 +140,25 @@ public String format(JSONObject valueMap, Map<String, Object> templateSettings)
}
return writer.toString();
}

/**
* getTemplate fetches the VelocityTemplate from the DB or Spring Cache
* @param key key is a combination of sorted credentialType & sorted
* context separated by a ':'.
* @return
*/
@Override
@Cacheable(cacheNames = TEMPLATE_CACHE, key = "#key")
public String getTemplate(String key) {
if (!key.contains(DELIMITER)) {
return null;
}
String credentialType = key.split(DELIMITER)[0];
String context = key.split(DELIMITER, 2)[1];
CredentialTemplate template = templateRepository.findByCredentialTypeAndContext(credentialType, context).orElse(null);
if (template != null) {
return template.getTemplate();
} else
return null;
}
}
17 changes: 11 additions & 6 deletions certify-service/src/main/resources/application-local.properties
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ mosip.certify.key-values={\
}}\
}\
}
mosip.certify.svg-templates=svg-template.json
mosip.certify.rendering-templates=svg-template.json

## ------------------------------------------- Integrations ------------------------------------------------------------
#mosip.certify.integration.scan-base-package=io.mosip.certify.sunbirdrc.integration
Expand All @@ -200,7 +200,11 @@ mosip.certify.vcformat.vc.expiry=true
## ------------------------------------------- Mock ID Integration properties ------------------------------------------------------------
mosip.certify.integration.scan-base-package=io.mosip.certify.mock.integration
mosip.certify.integration.audit-plugin=LoggerAuditService
mosip.certify.integration.vci-plugin=MockVCIssuancePlugin
#mosip.certify.integration.vci-plugin=MockVCIssuancePlugin
mosip.certify.integration.data-provider-plugin=MockCSVDataProviderPlugin
mosip.certify.mock.data-provider.csv.identifier-column=id
mosip.certify.mock.data-provider.csv.data-columns=id,name,phoneNumber,dateOfBirth,highestEducation,typeOfHouse,numberOfDependents,works,landArea,landOwnershipType,primaryCropType,secondaryCropType,maritalStatus
mosip.certify.mock.data-provider.csv-registry-uri=https://raw.githubusercontent.com/jainhitesh9998/digital-credential-plugins/refs/heads/develop/mock-certify-plugin/src/test/resources/farmer_identity_data.csv
mosip.certify.mock.vciplugin.verification-method=${mosip.certify.authn.jwk-set-uri}
mosip.certify.mock.authenticator.get-identity-url=http://localhost:8082/v1/mock-identity-system/identity
#TODO: get the secret for key-cert onboarded for local test
Expand All @@ -223,18 +227,19 @@ mosip.certify.cache.security.algorithm-name=AES/ECB/PKCS5Padding
#spring.data.redis.password=redis

spring.cache.type=simple
mosip.certify.cache.names=userinfo,vcissuance
mosip.certify.cache.names=userinfo,vcissuance,templatecache
spring.cache.cache-names=${mosip.certify.cache.names}
management.health.redis.enabled=false

mosip.certify.access-token-expire-seconds=86400

# VC template cache valid for half day
mosip.certify.templatecache-expire-seconds=43200
# Cache size setup is applicable only for 'simple' cache type.
# Cache size configuration will not be considered with 'Redis' cache type
mosip.certify.cache.size={'userinfo': 200, 'vcissuance' : 2000 }
mosip.certify.cache.size={'userinfo': 200, 'vcissuance' : 2000, 'templatecache': 20}

# Cache expire in seconds is applicable for both 'simple' and 'Redis' cache type
mosip.certify.cache.expire-in-seconds={'userinfo': ${mosip.certify.access-token-expire-seconds}, 'vcissuance': ${mosip.certify.access-token-expire-seconds}}
mosip.certify.cache.expire-in-seconds={'userinfo': ${mosip.certify.access-token-expire-seconds}, 'vcissuance': ${mosip.certify.access-token-expire-seconds}, 'templatecache': ${mosip.certify.templatecache-expire-seconds}}

##-----------------------------VCI related demo configuration---------------------------------------------##

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.mosip.certify;

import io.mosip.certify.api.exception.DataProviderExchangeException;
import io.mosip.certify.api.spi.DataProviderPlugin;
import io.mosip.certify.services.spi.DataProviderPlugin;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.mosip.certify.services;

import io.mosip.certify.api.spi.AuditPlugin;
import io.mosip.certify.api.spi.DataProviderPlugin;
import io.mosip.certify.api.spi.VCFormatter;
import io.mosip.certify.api.spi.VCSigner;
import io.mosip.certify.services.spi.DataProviderPlugin;
import io.mosip.certify.services.spi.VCFormatter;
import io.mosip.certify.services.spi.VCSigner;
import io.mosip.certify.core.constants.ErrorConstants;
import io.mosip.certify.core.constants.VCFormats;
import io.mosip.certify.core.dto.CredentialDefinition;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;

import static org.mockito.Mockito.when;

Expand All @@ -37,7 +34,6 @@ public class VelocityTemplatingEngineImplTest extends TestCase {
@SneakyThrows
@Before
public void setUp() {
List<CredentialTemplate> templates = new ArrayList<>();
CredentialTemplate vc1 = initTemplate("""
{
"@context": [
Expand Down Expand Up @@ -118,7 +114,9 @@ public void setUp() {
"MockVerifiableCredential,VerifiableCredential",
"https://vharsh.github.io/DID/mock-context.json,https://www.w3.org/2018/credentials/v1"
);
when(templateRepository.findAll()).thenReturn(List.of(vc1, vc2, vc3));
//when(templateRepository.findByCredentialTypeAndContext("MockVerifiableCredential,VerifiableCredential", "https://schema.org,https://www.w3.org/2018/credentials/v1")).thenReturn(Optional.of(vc1));
when(templateRepository.findByCredentialTypeAndContext("MockVerifiableCredential,VerifiableCredential", "https://example.org/Person.json,https://www.w3.org/ns/credentials/v2")).thenReturn(Optional.of(vc2));
//when(templateRepository.findByCredentialTypeAndContext("MockVerifiableCredential,VerifiableCredential", "https://vharsh.github.io/DID/mock-context.json,https://www.w3.org/2018/credentials/v1")).thenReturn(Optional.of(vc3));
ReflectionTestUtils.setField(formatter, "shouldHaveDates", true);
formatter.initialize();
// engine = new VelocityEngine();
Expand Down

0 comments on commit 7cb4475

Please sign in to comment.