Search in sources :

Example 6 with QuotaConfig

use of com.github.ambry.config.QuotaConfig in project ambry by linkedin.

the class AmbryQuotaManagerTest method buildAmbryQuotaManagerWithNoEnforcers.

/**
 * Build {@link AmbryQuotaManager} object with no enforcers.
 * @return AmbryQuotaManager object.
 * @throws ReflectiveOperationException in case the {@link AmbryQuotaManager} object could not be created.
 */
private AmbryQuotaManager buildAmbryQuotaManagerWithNoEnforcers() throws ReflectiveOperationException {
    quotaConfig = new QuotaConfig(new VerifiableProperties(new Properties()));
    quotaConfig.requestQuotaEnforcerSourcePairInfoJson = new JSONObject().put(QuotaConfig.QUOTA_ENFORCER_SOURCE_PAIR_INFO_STR, new JSONArray()).toString();
    QuotaMetrics quotaMetrics = new QuotaMetrics(new MetricRegistry());
    AmbryQuotaManager ambryQuotaManager = createAmbryQuotaManager(quotaConfig, quotaMetrics);
    Assert.assertTrue(ambryQuotaManager.quotaEnforcers.isEmpty());
    return ambryQuotaManager;
}
Also used : JSONObject(org.json.JSONObject) VerifiableProperties(com.github.ambry.config.VerifiableProperties) MetricRegistry(com.codahale.metrics.MetricRegistry) QuotaConfig(com.github.ambry.config.QuotaConfig) JSONArray(org.json.JSONArray) Properties(java.util.Properties) VerifiableProperties(com.github.ambry.config.VerifiableProperties)

Example 7 with QuotaConfig

use of com.github.ambry.config.QuotaConfig in project ambry by linkedin.

the class SimpleRequestQuotaCostPolicyTest method testCalculateRequestQuotaCharge.

@Test
public void testCalculateRequestQuotaCharge() throws Exception {
    QuotaConfig quotaConfig = new QuotaConfig(new VerifiableProperties(new Properties()));
    SimpleRequestQuotaCostPolicy quotaRequestCostPolicy = new SimpleRequestQuotaCostPolicy(quotaConfig);
    RestResponseChannel restResponseChannel = mock(RestResponseChannel.class);
    when(restResponseChannel.getHeader(anyString())).thenReturn(0);
    String blobUri = "/AAYIAQSSAAgAAQAAAAAAABpFymbGwe7sRBWYa5OPlkcNHQ.bin";
    // test for a 4 MB GET request.
    long blobSize = 4 * MB;
    RestRequest restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri, -1);
    Map<String, Double> costMap = quotaRequestCostPolicy.calculateRequestQuotaCharge(restRequest, blobSize);
    verifyReadCost(costMap, Math.ceil(blobSize / (double) quotaConfig.quotaAccountingUnit));
    // test for a small GET request (fractional CU).
    blobSize = 6 * MB;
    costMap = quotaRequestCostPolicy.calculateRequestQuotaCharge(restRequest, blobSize);
    verifyReadCost(costMap, Math.ceil(blobSize / (double) quotaConfig.quotaAccountingUnit));
    // test for a GET request of blob of size 0.
    restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri, -1);
    costMap = quotaRequestCostPolicy.calculateRequestQuotaCharge(restRequest, 0);
    verifyReadCost(costMap, 1);
    // test for a GET request of blob of size 512.
    blobSize = 512;
    restRequest = createMockRequestWithMethod(RestMethod.GET, blobUri, -1);
    costMap = quotaRequestCostPolicy.calculateRequestQuotaCharge(restRequest, blobSize);
    verifyReadCost(costMap, 1);
    // test for a small POST request (fractional storage cost).
    blobSize = 8 * MB;
    restRequest = createMockRequestWithMethod(RestMethod.POST, blobUri, blobSize);
    costMap = quotaRequestCostPolicy.calculateRequestQuotaCharge(restRequest, blobSize);
    verifyWriteCost(costMap, Math.ceil(blobSize / (double) quotaConfig.quotaAccountingUnit), 8 * 1024 * 1024 / (double) QuotaUtils.BYTES_IN_GB);
    // test for a large POST request.
    blobSize = 4 * QuotaUtils.BYTES_IN_GB;
    restRequest = createMockRequestWithMethod(RestMethod.POST, blobUri, blobSize);
    costMap = quotaRequestCostPolicy.calculateRequestQuotaCharge(restRequest, blobSize);
    verifyWriteCost(costMap, Math.ceil(blobSize / (double) quotaConfig.quotaAccountingUnit), 4);
    // test for a POST request of blob of size 0.
    restRequest = createMockRequestWithMethod(RestMethod.POST, blobUri, 0);
    costMap = quotaRequestCostPolicy.calculateRequestQuotaCharge(restRequest, 0);
    verifyWriteCost(costMap, 1, 0);
    // test for a POST request of blob of size 512.
    restRequest = createMockRequestWithMethod(RestMethod.POST, blobUri, 0);
    costMap = quotaRequestCostPolicy.calculateRequestQuotaCharge(restRequest, 512);
    verifyWriteCost(costMap, 1, 0);
    // test for a HEAD request.
    restRequest = createMockRequestWithMethod(RestMethod.HEAD, blobUri, -1);
    costMap = quotaRequestCostPolicy.calculateRequestQuotaCharge(restRequest, quotaConfig.quotaAccountingUnit);
    verifyReadCost(costMap, 1);
    // test for a DELETE request.
    restRequest = createMockRequestWithMethod(RestMethod.DELETE, blobUri, -1);
    costMap = quotaRequestCostPolicy.calculateRequestQuotaCharge(restRequest, quotaConfig.quotaAccountingUnit);
    verifyWriteCost(costMap, 1, 0.0);
    // test for a PUT request.
    restRequest = createMockRequestWithMethod(RestMethod.PUT, blobUri, -1);
    costMap = quotaRequestCostPolicy.calculateRequestQuotaCharge(restRequest, quotaConfig.quotaAccountingUnit);
    verifyWriteCost(costMap, 1, 0.0);
}
Also used : RestRequest(com.github.ambry.rest.RestRequest) VerifiableProperties(com.github.ambry.config.VerifiableProperties) QuotaConfig(com.github.ambry.config.QuotaConfig) RestResponseChannel(com.github.ambry.rest.RestResponseChannel) Properties(java.util.Properties) VerifiableProperties(com.github.ambry.config.VerifiableProperties) Test(org.junit.Test)

Example 8 with QuotaConfig

use of com.github.ambry.config.QuotaConfig in project ambry by linkedin.

the class AmbryCUQuotaSourceFactoryTest method testGetQuotaSource.

@Test
public void testGetQuotaSource() throws IOException {
    QuotaConfig quotaConfig = new QuotaConfig(new VerifiableProperties(new Properties()));
    AccountService mockAccountService = Mockito.mock(AccountService.class);
    AmbryCUQuotaSourceFactory ambryCUQuotaSourceFactory = new AmbryCUQuotaSourceFactory(quotaConfig, mockAccountService);
    Assert.assertEquals(AmbryCUQuotaSource.class, ambryCUQuotaSourceFactory.getQuotaSource().getClass());
}
Also used : VerifiableProperties(com.github.ambry.config.VerifiableProperties) QuotaConfig(com.github.ambry.config.QuotaConfig) Properties(java.util.Properties) VerifiableProperties(com.github.ambry.config.VerifiableProperties) AccountService(com.github.ambry.account.AccountService) Test(org.junit.Test)

Example 9 with QuotaConfig

use of com.github.ambry.config.QuotaConfig in project ambry by linkedin.

the class FrontendRestRequestServiceFactory method getRestRequestService.

/**
 * Returns a new instance of {@link FrontendRestRequestService}.
 * @return a new instance of {@link FrontendRestRequestService}.
 */
@Override
public RestRequestService getRestRequestService() {
    try {
        IdSigningService idSigningService = Utils.<IdSigningServiceFactory>getObj(frontendConfig.idSigningServiceFactory, verifiableProperties, clusterMap.getMetricRegistry()).getIdSigningService();
        NamedBlobDb namedBlobDb = Utils.isNullOrEmpty(frontendConfig.namedBlobDbFactory) ? null : Utils.<NamedBlobDbFactory>getObj(frontendConfig.namedBlobDbFactory, verifiableProperties, clusterMap.getMetricRegistry(), accountService).getNamedBlobDb();
        IdConverterFactory idConverterFactory = Utils.getObj(frontendConfig.idConverterFactory, verifiableProperties, clusterMap.getMetricRegistry(), idSigningService, namedBlobDb);
        UrlSigningService urlSigningService = Utils.<UrlSigningServiceFactory>getObj(frontendConfig.urlSigningServiceFactory, verifiableProperties, clusterMap.getMetricRegistry()).getUrlSigningService();
        AccountAndContainerInjector accountAndContainerInjector = new AccountAndContainerInjector(accountService, frontendMetrics, frontendConfig);
        AccountStatsStore accountStatsStore = Utils.<AccountStatsStoreFactory>getObj(frontendConfig.accountStatsStoreFactory, verifiableProperties, clusterMapConfig, clusterMap.getMetricRegistry()).getAccountStatsStore();
        QuotaConfig quotaConfig = new QuotaConfig(verifiableProperties);
        QuotaManager quotaManager = ((QuotaManagerFactory) Utils.getObj(quotaConfig.quotaManagerFactory, quotaConfig, new SimpleQuotaRecommendationMergePolicy(quotaConfig), accountService, accountStatsStore, clusterMap.getMetricRegistry())).getQuotaManager();
        SecurityServiceFactory securityServiceFactory = Utils.getObj(frontendConfig.securityServiceFactory, verifiableProperties, clusterMap, accountService, urlSigningService, idSigningService, accountAndContainerInjector, quotaManager);
        return new FrontendRestRequestService(frontendConfig, frontendMetrics, router, clusterMap, idConverterFactory, securityServiceFactory, urlSigningService, idSigningService, namedBlobDb, accountService, accountAndContainerInjector, clusterMapConfig.clusterMapDatacenterName, clusterMapConfig.clusterMapHostName, clusterMapConfig.clusterMapClusterName, accountStatsStore, quotaManager);
    } catch (Exception e) {
        throw new IllegalStateException("Could not instantiate FrontendRestRequestService", e);
    }
}
Also used : NamedBlobDb(com.github.ambry.named.NamedBlobDb) AccountStatsStore(com.github.ambry.accountstats.AccountStatsStore) QuotaManagerFactory(com.github.ambry.quota.QuotaManagerFactory) NamedBlobDbFactory(com.github.ambry.named.NamedBlobDbFactory) QuotaConfig(com.github.ambry.config.QuotaConfig) SimpleQuotaRecommendationMergePolicy(com.github.ambry.quota.SimpleQuotaRecommendationMergePolicy) QuotaManager(com.github.ambry.quota.QuotaManager)

Example 10 with QuotaConfig

use of com.github.ambry.config.QuotaConfig in project ambry by linkedin.

the class SimpleQuotaRecommendationMergePolicyTest method testRecommend.

/**
 * Test for {@link SimpleQuotaRecommendationMergePolicy#mergeEnforcementRecommendations}
 */
@Test
public void testRecommend() {
    QuotaConfig quotaConfig = new QuotaConfig(new VerifiableProperties(new Properties()));
    SimpleQuotaRecommendationMergePolicy simpleThrottlePolicy = new SimpleQuotaRecommendationMergePolicy(quotaConfig);
    // test for empty quota recommendation list
    ThrottlingRecommendation throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(Collections.emptyList());
    assertEquals(ThrottlingRecommendation.NO_RETRY_AFTER_MS, throttlingRecommendation.getRetryAfterMs());
    assertEquals(QuotaUsageLevel.HEALTHY, throttlingRecommendation.getQuotaUsageLevel());
    assertFalse(throttlingRecommendation.shouldThrottle());
    assertTrue(throttlingRecommendation.getQuotaUsagePercentage().isEmpty());
    // test for a single quota recommendation.
    QuotaRecommendation quotaRecommendation = new QuotaRecommendation(QuotaAction.DELAY, 101, QuotaName.READ_CAPACITY_UNIT, 5);
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(Collections.singletonList(quotaRecommendation));
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, true, Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, (float) 101.0), 5, throttlingRecommendation);
    // test for retry after interval
    List<QuotaRecommendation> quotaRecommendationList = new ArrayList<>();
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.ALLOW, 101, QuotaName.READ_CAPACITY_UNIT, 5));
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.ALLOW, 101, QuotaName.READ_CAPACITY_UNIT, 10));
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.ALLOW, 101, QuotaName.READ_CAPACITY_UNIT, 1));
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(quotaRecommendationList);
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, false, Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, (float) 101.0), 10, throttlingRecommendation);
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.ALLOW, 101, QuotaName.READ_CAPACITY_UNIT, 12));
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(quotaRecommendationList);
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, false, Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, (float) 101.0), 12, throttlingRecommendation);
    // test for should throttle
    quotaRecommendationList = new ArrayList<>();
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.ALLOW, 101, QuotaName.READ_CAPACITY_UNIT, 5));
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.ALLOW, 101, QuotaName.READ_CAPACITY_UNIT, 5));
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.ALLOW, 101, QuotaName.READ_CAPACITY_UNIT, 5));
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(quotaRecommendationList);
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, false, Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, (float) 101.0), 5, throttlingRecommendation);
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.DELAY, 101, QuotaName.READ_CAPACITY_UNIT, 5));
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(quotaRecommendationList);
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, true, Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, (float) 101.0), 5, throttlingRecommendation);
    // test for warning level
    quotaRecommendationList = new ArrayList<>();
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.ALLOW, 70, QuotaName.READ_CAPACITY_UNIT, 5));
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(quotaRecommendationList);
    verifyThrottlingRecommendation(QuotaUsageLevel.HEALTHY, false, Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, (float) 70.0), 5, throttlingRecommendation);
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.ALLOW, 81, QuotaName.READ_CAPACITY_UNIT, 5));
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(quotaRecommendationList);
    verifyThrottlingRecommendation(QuotaUsageLevel.WARNING, false, Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, (float) quotaConfig.quotaUsageWarningThresholdInPercentage + 1), 5, throttlingRecommendation);
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.ALLOW, 96, QuotaName.READ_CAPACITY_UNIT, 5));
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(quotaRecommendationList);
    verifyThrottlingRecommendation(QuotaUsageLevel.CRITICAL, false, Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, (float) 96.0), 5, throttlingRecommendation);
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.REJECT, 101, QuotaName.READ_CAPACITY_UNIT, 5));
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(quotaRecommendationList);
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, true, Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, (float) 101.0), 5, throttlingRecommendation);
    // Test when the request throttling is disabled
    Properties prop = new Properties();
    prop.setProperty(QuotaConfig.REQUEST_THROTTLING_ENABLED, "false");
    simpleThrottlePolicy = new SimpleQuotaRecommendationMergePolicy(new QuotaConfig(new VerifiableProperties(prop)));
    // test for a request quota recommendation.
    quotaRecommendation = new QuotaRecommendation(QuotaAction.REJECT, 101, QuotaName.READ_CAPACITY_UNIT, 5);
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(Collections.singletonList(quotaRecommendation));
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, false, Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, (float) 101.0), 5, throttlingRecommendation);
    quotaRecommendationList.clear();
    quotaRecommendationList.add(quotaRecommendation);
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.DELAY, 101, QuotaName.STORAGE_IN_GB, 5));
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(quotaRecommendationList);
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, true, new HashMap<QuotaName, Float>() {

        {
            put(QuotaName.READ_CAPACITY_UNIT, (float) 101.0);
            put(QuotaName.STORAGE_IN_GB, (float) 101.0);
        }
    }, 5, throttlingRecommendation);
    // Test when the storage quota throttling is disabled
    prop = new Properties();
    prop.setProperty(StorageQuotaConfig.SHOULD_THROTTLE, "false");
    simpleThrottlePolicy = new SimpleQuotaRecommendationMergePolicy(new QuotaConfig(new VerifiableProperties(prop)));
    // test for a storage quota recommendation.
    quotaRecommendation = new QuotaRecommendation(QuotaAction.DELAY, 101, QuotaName.STORAGE_IN_GB, 5);
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(Collections.singletonList(quotaRecommendation));
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, false, Collections.singletonMap(QuotaName.STORAGE_IN_GB, (float) 101.0), 5, throttlingRecommendation);
    quotaRecommendationList.clear();
    quotaRecommendationList.add(quotaRecommendation);
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.DELAY, 101, QuotaName.READ_CAPACITY_UNIT, 5));
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(quotaRecommendationList);
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, true, new HashMap<QuotaName, Float>() {

        {
            put(QuotaName.READ_CAPACITY_UNIT, (float) 101.0);
            put(QuotaName.STORAGE_IN_GB, (float) 101.0);
        }
    }, 5, throttlingRecommendation);
    // Test when both quota throttling are disabled
    prop = new Properties();
    prop.setProperty(StorageQuotaConfig.SHOULD_THROTTLE, "false");
    prop.setProperty(QuotaConfig.REQUEST_THROTTLING_ENABLED, "false");
    simpleThrottlePolicy = new SimpleQuotaRecommendationMergePolicy(new QuotaConfig(new VerifiableProperties(prop)));
    quotaRecommendation = new QuotaRecommendation(QuotaAction.DELAY, 101, QuotaName.READ_CAPACITY_UNIT, 5);
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(Collections.singletonList(quotaRecommendation));
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, false, Collections.singletonMap(QuotaName.READ_CAPACITY_UNIT, (float) 101.0), 5, throttlingRecommendation);
    quotaRecommendation = new QuotaRecommendation(QuotaAction.REJECT, 101, QuotaName.WRITE_CAPACITY_UNIT, 5);
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(Collections.singletonList(quotaRecommendation));
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, false, Collections.singletonMap(QuotaName.WRITE_CAPACITY_UNIT, (float) 101.0), 5, throttlingRecommendation);
    quotaRecommendation = new QuotaRecommendation(QuotaAction.REJECT, 101, QuotaName.STORAGE_IN_GB, 5);
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(Collections.singletonList(quotaRecommendation));
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, false, Collections.singletonMap(QuotaName.STORAGE_IN_GB, (float) 101.0), 5, throttlingRecommendation);
    quotaRecommendationList.clear();
    quotaRecommendationList.add(quotaRecommendation);
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.REJECT, 101, QuotaName.READ_CAPACITY_UNIT, 5));
    quotaRecommendationList.add(new QuotaRecommendation(QuotaAction.REJECT, 101, QuotaName.WRITE_CAPACITY_UNIT, 5));
    throttlingRecommendation = simpleThrottlePolicy.mergeEnforcementRecommendations(quotaRecommendationList);
    verifyThrottlingRecommendation(QuotaUsageLevel.EXCEEDED, false, new HashMap<QuotaName, Float>() {

        {
            put(QuotaName.READ_CAPACITY_UNIT, (float) 101.0);
            put(QuotaName.WRITE_CAPACITY_UNIT, (float) 101.0);
            put(QuotaName.STORAGE_IN_GB, (float) 101.0);
        }
    }, 5, throttlingRecommendation);
}
Also used : VerifiableProperties(com.github.ambry.config.VerifiableProperties) QuotaConfig(com.github.ambry.config.QuotaConfig) StorageQuotaConfig(com.github.ambry.config.StorageQuotaConfig) ArrayList(java.util.ArrayList) Properties(java.util.Properties) VerifiableProperties(com.github.ambry.config.VerifiableProperties) Test(org.junit.Test)

Aggregations

QuotaConfig (com.github.ambry.config.QuotaConfig)14 VerifiableProperties (com.github.ambry.config.VerifiableProperties)13 Properties (java.util.Properties)13 Test (org.junit.Test)7 MetricRegistry (com.codahale.metrics.MetricRegistry)5 ArrayList (java.util.ArrayList)3 JSONArray (org.json.JSONArray)3 JSONObject (org.json.JSONObject)3 Account (com.github.ambry.account.Account)2 AccountService (com.github.ambry.account.AccountService)2 InMemAccountService (com.github.ambry.account.InMemAccountService)2 AccountStatsStore (com.github.ambry.accountstats.AccountStatsStore)2 QuotaManager (com.github.ambry.quota.QuotaManager)2 QuotaSource (com.github.ambry.quota.QuotaSource)2 SimpleQuotaRecommendationMergePolicy (com.github.ambry.quota.SimpleQuotaRecommendationMergePolicy)2 AmbryCUQuotaEnforcer (com.github.ambry.quota.capacityunit.AmbryCUQuotaEnforcer)2 RestRequest (com.github.ambry.rest.RestRequest)2 Before (org.junit.Before)2 TypeReference (com.fasterxml.jackson.core.type.TypeReference)1 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1