MIFOSX-259: support runtime switching of cache through API. By default no-cache implementation is used.
This commit is contained in:
@@ -9091,6 +9091,92 @@ Request Body: { }
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a id="cache" name="cache" class="old-syle-anchor"> </a>
|
||||
<div class="method-section">
|
||||
<div class="method-description">
|
||||
<h3>Cache</h3>
|
||||
<p>The following settings are possible for cache:
|
||||
<ul>
|
||||
<li><b>No Caching</b>: caching turned off</li>
|
||||
<li><b>Single node</b>: caching on for single instance deployments of platorm (works for multiple tenants but only one tomcat)</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>By default caching is set to <i>No Caching</i>. Switching between caches results in the cache been clear e.g. from <i>Single node</i> to <i>No cache</i> and back again would clear down the single node cache.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a id="caches_list" name="caches_list" class="old-syle-anchor"> </a>
|
||||
<div class="method-section">
|
||||
<div class="method-description">
|
||||
<h4>Retrieve Cache Types</h4>
|
||||
<p>Returns the list of caches.</p>
|
||||
<p>Example Requests:</p>
|
||||
<div class=apiClick>caches</div>
|
||||
</div>
|
||||
<div class="method-example">
|
||||
<code class="method-declaration">
|
||||
GET https://DomainName/api/v1/caches
|
||||
</code>
|
||||
<code class="method-response">
|
||||
[
|
||||
{
|
||||
"cacheType": {
|
||||
"id": 1,
|
||||
"code": "cacheType.noCache",
|
||||
"value": "No cache"
|
||||
},
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"cacheType": {
|
||||
"id": 2,
|
||||
"code": "cacheType.singleNode",
|
||||
"value": "Single node"
|
||||
},
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"cacheType": {
|
||||
"id": 3,
|
||||
"code": "cacheType.multiNode",
|
||||
"value": "Multi node"
|
||||
},
|
||||
"enabled": false
|
||||
}
|
||||
]
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a id="caches_switch" name="caches_switch"
|
||||
class="old-syle-anchor"> </a>
|
||||
<div class="method-section">
|
||||
<div class="method-description">
|
||||
<h4>Switch Cache</h4>
|
||||
<p>Switches the cache to chosen one.</p>
|
||||
</div>
|
||||
<div class="method-example">
|
||||
<code class="method-declaration">
|
||||
PUT https://DomainName/api/v1/caches
|
||||
</code>
|
||||
<code class="method-request">
|
||||
PUT caches
|
||||
Content-Type: application/json
|
||||
Request Body:
|
||||
{
|
||||
"cacheType": 2
|
||||
}
|
||||
</code>
|
||||
<code class="method-response">
|
||||
{
|
||||
"changes": {
|
||||
"cacheType": 2
|
||||
}
|
||||
}
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a id="configs_codes" name="configs_codes" class="old-syle-anchor"> </a>
|
||||
<div class="method-section">
|
||||
<div class="method-description">
|
||||
@@ -19359,6 +19445,14 @@ GET https://DomainName/api/v1/search?query=000000111
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td><a href="#cache">Cache</a></td>
|
||||
<td>caches</td>
|
||||
<td></td>
|
||||
<td><a href="#caches_list">List Cache Types</a></td>
|
||||
<td><a href="#caches_switch">Switch Cache</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="alt">
|
||||
<td><a href="#centers">Center</a></td>
|
||||
<td>centers</td>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
DROP TABLE IF EXISTS `c_cache`;
|
||||
CREATE TABLE `c_cache` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`cache_type_enum` tinyint(1) NOT NULL DEFAULT '1',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
INSERT INTO `c_cache`
|
||||
(`id`,`cache_type_enum`)
|
||||
VALUES
|
||||
(1, 1);
|
||||
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('configuration', 'READ_CACHE', 'CACHE', 'READ', 0);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('configuration', 'UPDATE_CACHE', 'CACHE', 'UPDATE', 0);
|
||||
+9
-5
@@ -112,15 +112,15 @@ public class CommandWrapper {
|
||||
}
|
||||
|
||||
public boolean isCreateDatatable() {
|
||||
return (this.actionName.equalsIgnoreCase("CREATE") && this.href.startsWith("/datatables/") && this.entityId == null);
|
||||
return this.actionName.equalsIgnoreCase("CREATE") && this.href.startsWith("/datatables/") && this.entityId == null;
|
||||
}
|
||||
|
||||
public boolean isDeleteDatatable() {
|
||||
return (this.actionName.equalsIgnoreCase("DELETE") && this.href.startsWith("/datatables/") && this.entityId == null);
|
||||
return this.actionName.equalsIgnoreCase("DELETE") && this.href.startsWith("/datatables/") && this.entityId == null;
|
||||
}
|
||||
|
||||
public boolean isUpdateDatatable() {
|
||||
return (this.actionName.equalsIgnoreCase("UPDATE") && this.href.startsWith("/datatables/") && this.entityId == null);
|
||||
return this.actionName.equalsIgnoreCase("UPDATE") && this.href.startsWith("/datatables/") && this.entityId == null;
|
||||
}
|
||||
|
||||
public String getTaskPermissionName() {
|
||||
@@ -185,8 +185,8 @@ public class CommandWrapper {
|
||||
|
||||
public boolean isUpdate() {
|
||||
// permissions resource has special update which involves no resource.
|
||||
return (isPermissionResource() && isUpdateOperation()) || (isCurrencyResource() && isUpdateOperation())
|
||||
|| (isUpdateOperation() && this.entityId != null);
|
||||
return isPermissionResource() && isUpdateOperation() || isCurrencyResource() && isUpdateOperation() || isCacheResource() && isUpdateOperation()
|
||||
|| isUpdateOperation() && this.entityId != null;
|
||||
}
|
||||
|
||||
public boolean isUpdateOperation() {
|
||||
@@ -615,4 +615,8 @@ public class CommandWrapper {
|
||||
public boolean isSaveOrUpdateAttendance() {
|
||||
return this.actionName.equalsIgnoreCase("SAVEORUPDATEATTENDANCE");
|
||||
}
|
||||
|
||||
public boolean isCacheResource() {
|
||||
return this.entityName.equalsIgnoreCase("CACHE");
|
||||
}
|
||||
}
|
||||
+12
-5
@@ -844,7 +844,7 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/savingsaccounts/" + accountId + "?command=activate";
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder closeSavingsAccountApplication(final Long accountId) {
|
||||
this.actionName = "CLOSE";
|
||||
this.entityName = "SAVINGSACCOUNT";
|
||||
@@ -1076,7 +1076,7 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/groups/" + groupId + "?command=assignStaff";
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder closeGroup(final Long groupId) {
|
||||
this.actionName = "CLOSE";
|
||||
this.entityName = "GROUP";
|
||||
@@ -1085,7 +1085,7 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/groups/" + groupId + "?command=close";
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder createCollateral(final Long loanId) {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "COLLATERAL";
|
||||
@@ -1162,7 +1162,7 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/centers/" + centerId + "?command=saveCollectionSheet";
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder closeCenter(final Long centerId) {
|
||||
this.actionName = "CLOSE";
|
||||
this.entityName = "CENTER";
|
||||
@@ -1195,7 +1195,7 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/accountingrules/" + accountingRuleId;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder updateTaxonomyMapping(final Long mappingId) {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "XBRLMAPPING";
|
||||
@@ -1331,4 +1331,11 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/" + supportedEntityType + "/" + supportedEntityId + "/meetings/" + entityId + "?command=saveOrUpdateAttendance";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateCache() {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "CACHE";
|
||||
this.href = "/cache";
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -519,7 +519,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
|
||||
} else if (wrapper.isXBRLMappingResource()) {
|
||||
if (wrapper.isUpdate()) {
|
||||
handler = applicationContext.getBean("updateTaxonomyMappingCommandHandler", NewCommandSourceHandler.class);
|
||||
handler = this.applicationContext.getBean("updateTaxonomyMappingCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
@@ -544,6 +544,12 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isCacheResource()) {
|
||||
if (wrapper.isUpdateOperation()) {
|
||||
handler = this.applicationContext.getBean("updateCacheCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isMeetingResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = this.applicationContext.getBean("createMeetingCommandHandler", NewCommandSourceHandler.class);
|
||||
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
package org.mifosplatform.infrastructure.cache;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class CacheApiConstants {
|
||||
|
||||
public static final String RESOURCE_NAME = "CACHE";
|
||||
public static final String cacheTypeParameter = "cacheType";
|
||||
public static final Set<String> REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(cacheTypeParameter));
|
||||
|
||||
}
|
||||
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.infrastructure.cache;
|
||||
|
||||
import org.mifosplatform.infrastructure.cache.domain.CacheType;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
public class CacheEnumerations {
|
||||
|
||||
public static EnumOptionData cacheType(final int id) {
|
||||
return cacheType(CacheType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData cacheType(final CacheType cacheType) {
|
||||
EnumOptionData optionData = new EnumOptionData(CacheType.INVALID.getValue().longValue(), CacheType.INVALID.getCode(),
|
||||
"Invalid");
|
||||
switch (cacheType) {
|
||||
case INVALID:
|
||||
optionData = new EnumOptionData(CacheType.INVALID.getValue().longValue(), CacheType.INVALID.getCode(), "Invalid");
|
||||
break;
|
||||
case NO_CACHE:
|
||||
optionData = new EnumOptionData(CacheType.NO_CACHE.getValue().longValue(), CacheType.NO_CACHE.getCode(), "No cache");
|
||||
break;
|
||||
case SINGLE_NODE:
|
||||
optionData = new EnumOptionData(CacheType.SINGLE_NODE.getValue().longValue(), CacheType.SINGLE_NODE.getCode(), "Single node");
|
||||
break;
|
||||
case MULTI_NODE:
|
||||
optionData = new EnumOptionData(CacheType.MULTI_NODE.getValue().longValue(), CacheType.MULTI_NODE.getCode(), "Multi node");
|
||||
break;
|
||||
}
|
||||
|
||||
return optionData;
|
||||
}
|
||||
}
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
package org.mifosplatform.infrastructure.cache;
|
||||
|
||||
import org.mifosplatform.infrastructure.cache.service.RuntimeDelegatingCacheManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
package org.mifosplatform.infrastructure.cache;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.ehcache.EhCacheCacheManager;
|
||||
import org.springframework.cache.support.NoOpCacheManager;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* At present this implementation of {@link CacheManager} just delegates to the
|
||||
* real {@link CacheManager} to use.
|
||||
*
|
||||
* By default it is {@link NoOpCacheManager} but we can change that by checking
|
||||
* some persisted configuration in the database on startup and allow user to
|
||||
* switch implementation through UI/API
|
||||
*/
|
||||
@Component
|
||||
public class RuntimeDelegatingCacheManager implements CacheManager {
|
||||
|
||||
private final CacheManager ehcacheCacheManager;
|
||||
private final CacheManager noOpCacheManager = new NoOpCacheManager();
|
||||
private CacheManager currentCacheManager = this.noOpCacheManager;
|
||||
|
||||
@Autowired
|
||||
public RuntimeDelegatingCacheManager(final EhCacheCacheManager ehCacheCacheManager) {
|
||||
this.ehcacheCacheManager = ehCacheCacheManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cache getCache(final String name) {
|
||||
return this.currentCacheManager.getCache(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getCacheNames() {
|
||||
return this.currentCacheManager.getCacheNames();
|
||||
}
|
||||
|
||||
// TODO - Annuruddha - you need to create API to call to switch caching
|
||||
// approach from NoOp to Single instance Echache - we can tackle the
|
||||
// distributed cache through memcache then - didnt see the configuration for
|
||||
// that.
|
||||
// example method to switch caching mechanism used
|
||||
private void switchToEhCache() {
|
||||
this.currentCacheManager = this.ehcacheCacheManager;
|
||||
}
|
||||
}
|
||||
Vendored
+84
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.infrastructure.cache.api;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.mifosplatform.commands.domain.CommandWrapper;
|
||||
import org.mifosplatform.commands.service.CommandWrapperBuilder;
|
||||
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.mifosplatform.infrastructure.cache.data.CacheData;
|
||||
import org.mifosplatform.infrastructure.cache.service.RuntimeDelegatingCacheManager;
|
||||
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/caches")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Component
|
||||
@Scope("singleton")
|
||||
public class CacheApiResource {
|
||||
|
||||
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id"));
|
||||
private final String resourceNameForPermissions = "CACHE";
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final DefaultToApiJsonSerializer<CacheData> toApiJsonSerializer;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final RuntimeDelegatingCacheManager cacheService;
|
||||
|
||||
@Autowired
|
||||
public CacheApiResource(final PlatformSecurityContext context, @Qualifier("runtimeDelegatingCacheManager") final RuntimeDelegatingCacheManager cacheService,
|
||||
final DefaultToApiJsonSerializer<CacheData> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
|
||||
this.context = context;
|
||||
this.cacheService = cacheService;
|
||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||
}
|
||||
|
||||
@GET
|
||||
public String retrieveAll(@Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
|
||||
|
||||
final Collection<CacheData> codes = this.cacheService.retrieveAll();
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, codes, this.RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
@PUT
|
||||
public String switchCache(final String apiRequestBodyAsJson) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateCache().withJson(apiRequestBodyAsJson).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.infrastructure.cache.command;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||
import org.mifosplatform.infrastructure.cache.CacheApiConstants;
|
||||
import org.mifosplatform.infrastructure.cache.domain.CacheType;
|
||||
import org.mifosplatform.infrastructure.cache.service.CacheWritePlatformService;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
@Service
|
||||
public class UpdateCacheCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final CacheWritePlatformService cacheService;
|
||||
|
||||
@Autowired
|
||||
public UpdateCacheCommandHandler(final CacheWritePlatformService cacheService) {
|
||||
this.cacheService = cacheService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
final String json = command.json();
|
||||
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
command.checkForUnsupportedParameters(typeOfMap, json, CacheApiConstants.REQUEST_DATA_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(CacheApiConstants.RESOURCE_NAME.toLowerCase());
|
||||
|
||||
final int cacheTypeEnum = command.integerValueSansLocaleOfParameterNamed(CacheApiConstants.cacheTypeParameter);
|
||||
baseDataValidator.reset().parameter(CacheApiConstants.cacheTypeParameter).value(Integer.valueOf(cacheTypeEnum)).notNull()
|
||||
.isOneOfTheseValues(Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3));
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
|
||||
final CacheType cacheType = CacheType.fromInt(cacheTypeEnum);
|
||||
|
||||
final Map<String, Object> changes = this.cacheService.switchToCache(cacheType);
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).with(changes).build();
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.infrastructure.cache.data;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
public class CacheData {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final EnumOptionData cacheType;
|
||||
@SuppressWarnings("unused")
|
||||
private final boolean enabled;
|
||||
|
||||
public static CacheData instance(final EnumOptionData cacheType, final boolean enabled) {
|
||||
return new CacheData(cacheType, enabled);
|
||||
}
|
||||
|
||||
private CacheData(final EnumOptionData cacheType, final boolean enabled) {
|
||||
this.cacheType = cacheType;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
Vendored
+66
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.infrastructure.cache.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum CacheType {
|
||||
|
||||
INVALID(0, "cacheType.invalid"), //
|
||||
NO_CACHE(1, "cacheType.noCache"), //
|
||||
SINGLE_NODE(2, "cacheType.singleNode"), //
|
||||
MULTI_NODE(3, "cacheType.multiNode");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
private static final Map<Integer, CacheType> intToEnumMap = new HashMap<Integer, CacheType>();
|
||||
|
||||
static {
|
||||
for (final CacheType type : CacheType.values()) {
|
||||
intToEnumMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static CacheType fromInt(final Integer value) {
|
||||
CacheType type = intToEnumMap.get(value);
|
||||
if (type == null) {
|
||||
type = INVALID;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private CacheType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public boolean isNoCache() {
|
||||
return NO_CACHE.getValue().equals(this.value);
|
||||
}
|
||||
|
||||
public boolean isEhcache() {
|
||||
return SINGLE_NODE.getValue().equals(this.value);
|
||||
}
|
||||
|
||||
public boolean isDistributedCache() {
|
||||
return MULTI_NODE.getValue().equals(this.value);
|
||||
}
|
||||
}
|
||||
Vendored
+44
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.infrastructure.cache.domain;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "c_cache")
|
||||
public class PlatformCache extends AbstractPersistable<Long> {
|
||||
|
||||
@Column(name = "cache_type_enum")
|
||||
private Integer cacheType;
|
||||
|
||||
protected PlatformCache() {
|
||||
this.cacheType = null;
|
||||
}
|
||||
|
||||
public PlatformCache(final CacheType cacheType) {
|
||||
this.cacheType = cacheType.getValue();
|
||||
}
|
||||
|
||||
public boolean isNoCachedEnabled() {
|
||||
return CacheType.fromInt(this.cacheType).isNoCache();
|
||||
}
|
||||
|
||||
public boolean isEhcacheEnabled() {
|
||||
return CacheType.fromInt(this.cacheType).isEhcache();
|
||||
}
|
||||
|
||||
public boolean isDistributedCacheEnabled() {
|
||||
return CacheType.fromInt(this.cacheType).isDistributedCache();
|
||||
}
|
||||
|
||||
public void update(final CacheType cacheType) {
|
||||
this.cacheType = cacheType.getValue();
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.infrastructure.cache.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface PlatformCacheRepository extends JpaRepository<PlatformCache, Long>, JpaSpecificationExecutor<PlatformCache> {
|
||||
//
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.infrastructure.cache.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.mifosplatform.infrastructure.cache.domain.CacheType;
|
||||
|
||||
public interface CacheWritePlatformService {
|
||||
|
||||
Map<String, Object> switchToCache(CacheType cacheType);
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.infrastructure.cache.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.mifosplatform.infrastructure.cache.domain.CacheType;
|
||||
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class CacheWritePlatformServiceJpaRepositoryImpl implements CacheWritePlatformService {
|
||||
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final RuntimeDelegatingCacheManager cacheService;
|
||||
|
||||
@Autowired
|
||||
public CacheWritePlatformServiceJpaRepositoryImpl(final ConfigurationDomainService configurationDomainService,
|
||||
@Qualifier("runtimeDelegatingCacheManager") final RuntimeDelegatingCacheManager cacheService) {
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
this.cacheService = cacheService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public Map<String, Object> switchToCache(final CacheType toCacheType) {
|
||||
|
||||
final boolean ehCacheEnabled = this.configurationDomainService.isEhcacheEnabled();
|
||||
|
||||
final Map<String, Object> changes = this.cacheService.switchToCache(ehCacheEnabled, toCacheType);
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
this.configurationDomainService.updateCache(toCacheType);
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package org.mifosplatform.infrastructure.cache.service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.mifosplatform.infrastructure.cache.CacheApiConstants;
|
||||
import org.mifosplatform.infrastructure.cache.CacheEnumerations;
|
||||
import org.mifosplatform.infrastructure.cache.data.CacheData;
|
||||
import org.mifosplatform.infrastructure.cache.domain.CacheType;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.ehcache.EhCacheCacheManager;
|
||||
import org.springframework.cache.support.NoOpCacheManager;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* At present this implementation of {@link CacheManager} just delegates to the
|
||||
* real {@link CacheManager} to use.
|
||||
*
|
||||
* By default it is {@link NoOpCacheManager} but we can change that by checking
|
||||
* some persisted configuration in the database on startup and allow user to
|
||||
* switch implementation through UI/API
|
||||
*/
|
||||
@Component(value = "runtimeDelegatingCacheManager")
|
||||
public class RuntimeDelegatingCacheManager implements CacheManager {
|
||||
|
||||
private final EhCacheCacheManager ehcacheCacheManager;
|
||||
private final CacheManager noOpCacheManager = new NoOpCacheManager();
|
||||
private CacheManager currentCacheManager = this.noOpCacheManager;
|
||||
|
||||
@Autowired
|
||||
public RuntimeDelegatingCacheManager(final EhCacheCacheManager ehCacheCacheManager) {
|
||||
this.ehcacheCacheManager = ehCacheCacheManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cache getCache(final String name) {
|
||||
return this.currentCacheManager.getCache(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getCacheNames() {
|
||||
return this.currentCacheManager.getCacheNames();
|
||||
}
|
||||
|
||||
public Collection<CacheData> retrieveAll() {
|
||||
|
||||
final boolean ehcacheEnabled = false;
|
||||
final boolean noCacheEnabled = !ehcacheEnabled;
|
||||
final boolean distributedCacheEnabled = false;
|
||||
|
||||
final EnumOptionData noCacheType = CacheEnumerations.cacheType(CacheType.NO_CACHE);
|
||||
final EnumOptionData singleNodeCacheType = CacheEnumerations.cacheType(CacheType.SINGLE_NODE);
|
||||
final EnumOptionData multiNodeCacheType = CacheEnumerations.cacheType(CacheType.MULTI_NODE);
|
||||
|
||||
final CacheData noCache = CacheData.instance(noCacheType, noCacheEnabled);
|
||||
final CacheData singleNodeCache = CacheData.instance(singleNodeCacheType, ehcacheEnabled);
|
||||
final CacheData distributedCache = CacheData.instance(multiNodeCacheType, distributedCacheEnabled);
|
||||
|
||||
final Collection<CacheData> caches = Arrays.asList(noCache, singleNodeCache, distributedCache);
|
||||
return caches;
|
||||
}
|
||||
|
||||
public Map<String, Object> switchToCache(final boolean ehcacheEnabled, final CacheType toCacheType) {
|
||||
|
||||
final Map<String, Object> changes = new HashMap<String, Object>();
|
||||
|
||||
final boolean noCacheEnabled = !ehcacheEnabled;
|
||||
final boolean distributedCacheEnabled = !ehcacheEnabled;
|
||||
|
||||
switch (toCacheType) {
|
||||
case INVALID:
|
||||
break;
|
||||
case NO_CACHE:
|
||||
if (!noCacheEnabled) {
|
||||
changes.put(CacheApiConstants.cacheTypeParameter, toCacheType.getValue());
|
||||
this.currentCacheManager = this.noOpCacheManager;
|
||||
}
|
||||
break;
|
||||
case SINGLE_NODE:
|
||||
if (!ehcacheEnabled) {
|
||||
changes.put(CacheApiConstants.cacheTypeParameter, toCacheType.getValue());
|
||||
clearEhCache();
|
||||
this.currentCacheManager = this.ehcacheCacheManager;
|
||||
}
|
||||
break;
|
||||
case MULTI_NODE:
|
||||
if (!distributedCacheEnabled) {
|
||||
changes.put(CacheApiConstants.cacheTypeParameter, toCacheType.getValue());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
private void clearEhCache() {
|
||||
this.ehcacheCacheManager.getCacheManager().clearAll();
|
||||
}
|
||||
}
|
||||
+4
@@ -5,6 +5,8 @@
|
||||
*/
|
||||
package org.mifosplatform.infrastructure.configuration.domain;
|
||||
|
||||
import org.mifosplatform.infrastructure.cache.domain.CacheType;
|
||||
|
||||
public interface ConfigurationDomainService {
|
||||
|
||||
boolean isMakerCheckerEnabledForTask(String taskPermissionCode);
|
||||
@@ -14,4 +16,6 @@ public interface ConfigurationDomainService {
|
||||
boolean allowTransactionsOnHolidayEnabled();
|
||||
boolean allowTransactionsOnNonWorkingDayEnabled();
|
||||
boolean isConstraintApproachEnabledForDatatables();
|
||||
boolean isEhcacheEnabled();
|
||||
void updateCache(CacheType cacheType);
|
||||
}
|
||||
+22
-1
@@ -6,24 +6,31 @@
|
||||
package org.mifosplatform.infrastructure.configuration.domain;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mifosplatform.infrastructure.cache.domain.CacheType;
|
||||
import org.mifosplatform.infrastructure.cache.domain.PlatformCacheRepository;
|
||||
import org.mifosplatform.infrastructure.cache.domain.PlatformCache;
|
||||
import org.mifosplatform.infrastructure.configuration.exception.GlobalConfigurationPropertyNotFoundException;
|
||||
import org.mifosplatform.useradministration.domain.Permission;
|
||||
import org.mifosplatform.useradministration.domain.PermissionRepository;
|
||||
import org.mifosplatform.useradministration.exception.PermissionNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class ConfigurationDomainServiceJpa implements ConfigurationDomainService {
|
||||
|
||||
private final PermissionRepository permissionRepository;
|
||||
private final GlobalConfigurationRepository globalConfigurationRepository;
|
||||
private final PlatformCacheRepository cacheTypeRepository;
|
||||
|
||||
@Autowired
|
||||
public ConfigurationDomainServiceJpa(final PermissionRepository permissionRepository,
|
||||
final GlobalConfigurationRepository globalConfigurationRepository) {
|
||||
final GlobalConfigurationRepository globalConfigurationRepository,
|
||||
final PlatformCacheRepository cacheTypeRepository) {
|
||||
this.permissionRepository = permissionRepository;
|
||||
this.globalConfigurationRepository = globalConfigurationRepository;
|
||||
this.cacheTypeRepository = cacheTypeRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,4 +94,18 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
||||
if (property == null) { throw new GlobalConfigurationPropertyNotFoundException(colunnValue); }
|
||||
return property.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEhcacheEnabled() {
|
||||
return this.cacheTypeRepository.findOne(Long.valueOf(1)).isEhcacheEnabled();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void updateCache(final CacheType cacheType) {
|
||||
final PlatformCache cache = this.cacheTypeRepository.findOne(Long.valueOf(1));
|
||||
cache.update(cacheType);
|
||||
|
||||
this.cacheTypeRepository.save(cache);
|
||||
}
|
||||
}
|
||||
+23
-17
@@ -5,10 +5,12 @@
|
||||
*/
|
||||
package org.mifosplatform.infrastructure.core.api;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
@@ -24,7 +26,7 @@ import com.google.gson.JsonElement;
|
||||
|
||||
/**
|
||||
* Immutable representation of a command.
|
||||
*
|
||||
*
|
||||
* Wraps the provided JSON with convenience functions for extracting parameter
|
||||
* values and checking for changes against an existing value.
|
||||
*/
|
||||
@@ -97,7 +99,7 @@ public final class JsonCommand {
|
||||
public String jsonFragment(final String paramName) {
|
||||
String jsonFragment = null;
|
||||
if (this.parsedCommand.getAsJsonObject().has(paramName)) {
|
||||
JsonElement fragment = this.parsedCommand.getAsJsonObject().get(paramName);
|
||||
final JsonElement fragment = this.parsedCommand.getAsJsonObject().get(paramName);
|
||||
jsonFragment = this.fromApiJsonHelper.toJson(fragment);
|
||||
}
|
||||
return jsonFragment;
|
||||
@@ -234,7 +236,7 @@ public final class JsonCommand {
|
||||
}
|
||||
|
||||
public boolean parameterExists(final String parameterName) {
|
||||
return this.fromApiJsonHelper.parameterExists(parameterName, parsedCommand);
|
||||
return this.fromApiJsonHelper.parameterExists(parameterName, this.parsedCommand);
|
||||
}
|
||||
|
||||
public boolean hasParameter(final String parameterName) {
|
||||
@@ -259,7 +261,7 @@ public final class JsonCommand {
|
||||
}
|
||||
|
||||
public Long longValueOfParameterNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractLongNamed(parameterName, parsedCommand);
|
||||
return this.fromApiJsonHelper.extractLongNamed(parameterName, this.parsedCommand);
|
||||
}
|
||||
|
||||
public boolean isChangeInDateParameterNamed(final String parameterName, final Date existingValue) {
|
||||
@@ -280,15 +282,15 @@ public final class JsonCommand {
|
||||
}
|
||||
|
||||
public LocalDate localDateValueOfParameterNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractLocalDateNamed(parameterName, parsedCommand);
|
||||
return this.fromApiJsonHelper.extractLocalDateNamed(parameterName, this.parsedCommand);
|
||||
}
|
||||
|
||||
public MonthDay extractMonthDayNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractMonthDayNamed(parameterName, parsedCommand);
|
||||
return this.fromApiJsonHelper.extractMonthDayNamed(parameterName, this.parsedCommand);
|
||||
}
|
||||
|
||||
public Date DateValueOfParameterNamed(final String parameterName) {
|
||||
LocalDate localDate = this.fromApiJsonHelper.extractLocalDateNamed(parameterName, parsedCommand);
|
||||
final LocalDate localDate = this.fromApiJsonHelper.extractLocalDateNamed(parameterName, this.parsedCommand);
|
||||
if (localDate == null) { return null; }
|
||||
return localDate.toDateMidnight().toDate();
|
||||
}
|
||||
@@ -303,12 +305,12 @@ public final class JsonCommand {
|
||||
}
|
||||
|
||||
public String stringValueOfParameterNamed(final String parameterName) {
|
||||
final String value = this.fromApiJsonHelper.extractStringNamed(parameterName, parsedCommand);
|
||||
final String value = this.fromApiJsonHelper.extractStringNamed(parameterName, this.parsedCommand);
|
||||
return StringUtils.defaultIfEmpty(value, "");
|
||||
}
|
||||
|
||||
|
||||
public String stringValueOfParameterNamedAllowingNull(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractStringNamed(parameterName, parsedCommand);
|
||||
return this.fromApiJsonHelper.extractStringNamed(parameterName, this.parsedCommand);
|
||||
}
|
||||
|
||||
public boolean isChangeInBigDecimalParameterNamedDefaultingZeroToNull(final String parameterName, final BigDecimal existingValue) {
|
||||
@@ -359,7 +361,7 @@ public final class JsonCommand {
|
||||
}
|
||||
|
||||
public BigDecimal bigDecimalValueOfParameterNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(parameterName, parsedCommand);
|
||||
return this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(parameterName, this.parsedCommand);
|
||||
}
|
||||
|
||||
public BigDecimal bigDecimalValueOfParameterNamedDefaultToNullIfZero(final String parameterName) {
|
||||
@@ -398,7 +400,7 @@ public final class JsonCommand {
|
||||
}
|
||||
|
||||
public Integer integerValueOfParameterNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractIntegerWithLocaleNamed(parameterName, parsedCommand);
|
||||
return this.fromApiJsonHelper.extractIntegerWithLocaleNamed(parameterName, this.parsedCommand);
|
||||
}
|
||||
|
||||
public Integer integerValueOfParameterNamedDefaultToNullIfZero(final String parameterName) {
|
||||
@@ -415,7 +417,7 @@ public final class JsonCommand {
|
||||
}
|
||||
|
||||
public Integer integerValueSansLocaleOfParameterNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractIntegerSansLocaleNamed(parameterName, parsedCommand);
|
||||
return this.fromApiJsonHelper.extractIntegerSansLocaleNamed(parameterName, this.parsedCommand);
|
||||
}
|
||||
|
||||
public boolean isChangeInBooleanParameterNamed(final String parameterName, final Boolean existingValue) {
|
||||
@@ -431,14 +433,14 @@ public final class JsonCommand {
|
||||
* Returns {@link Boolean} that could possibly be null.
|
||||
*/
|
||||
public Boolean booleanObjectValueOfParameterNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractBooleanNamed(parameterName, parsedCommand);
|
||||
return this.fromApiJsonHelper.extractBooleanNamed(parameterName, this.parsedCommand);
|
||||
}
|
||||
|
||||
/**
|
||||
* always returns true or false
|
||||
*/
|
||||
public boolean booleanPrimitiveValueOfParameterNamed(final String parameterName) {
|
||||
final Boolean value = this.fromApiJsonHelper.extractBooleanNamed(parameterName, parsedCommand);
|
||||
final Boolean value = this.fromApiJsonHelper.extractBooleanNamed(parameterName, this.parsedCommand);
|
||||
return (Boolean) ObjectUtils.defaultIfNull(value, Boolean.FALSE);
|
||||
}
|
||||
|
||||
@@ -452,11 +454,11 @@ public final class JsonCommand {
|
||||
}
|
||||
|
||||
public String[] arrayValueOfParameterNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractArrayNamed(parameterName, parsedCommand);
|
||||
return this.fromApiJsonHelper.extractArrayNamed(parameterName, this.parsedCommand);
|
||||
}
|
||||
|
||||
public JsonArray arrayOfParameterNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractJsonArrayNamed(parameterName, parsedCommand);
|
||||
return this.fromApiJsonHelper.extractJsonArrayNamed(parameterName, this.parsedCommand);
|
||||
}
|
||||
|
||||
public boolean isChangeInPasswordParameterNamed(final String parameterName, final String existingValue,
|
||||
@@ -480,4 +482,8 @@ public final class JsonCommand {
|
||||
public Locale extractLocale() {
|
||||
return this.fromApiJsonHelper.extractLocaleParameter(this.parsedCommand.getAsJsonObject());
|
||||
}
|
||||
|
||||
public void checkForUnsupportedParameters(final Type typeOfMap, final String json, final Set<String> requestDataParameters) {
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, requestDataParameters);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user