I am implementing a Rest WS using Spring 4 (Spring Boot).
The basic idea is I want to consume a JSON payload specifying an identifier (e.g. social security number or something) and run multiple subServices on that identifier.
Here is a sample payload:
{
"ssNumber" : "1111111111111111",
"subServicesDetails" :
[
{ "subServiceName" : "Foo" , "requestParameters" : {} },
{ "subServiceName" : "Dummy", "requestParameters" : {} }
]
}
In my code I have multiple "sub-services" (FooService, DummyService) implementing the SubService interface:
package com.johnarnold.myws.service;
import com.johnarnold.myws.model.SubServiceDetails;
public interface SubService {
public boolean service(String ssNumber, SubServiceDetails ssd);
}
And below is the FooService code.
package com.johnarnold.myws.service;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.johnarnold.myws.dao.FooDao;
import com.johnarnold.myws.model.Foo;
import com.johnarnold.myws.model.SubServiceDetails;
#Component
public class FooService implements SubService{
private static Logger log = Logger.getLogger(FooService.class);
#Autowired
private FooDao dao;
public FooService()
{
log.debug("FooService ctor");
}
public boolean service(String ssNumber, SubServiceDetails ssd)
{
log.debug("FooService service");
Map <String, String> responseParameters = new HashMap<String, String>();
try
{
Foo foo = dao.getFoo(ssNumber);
if(foo.isCompromised())
{
responseParameters.put("listed", "true");
}
else
{
responseParameters.put("listed", "false");
}
ssd.setResponseParameters(responseParameters);
return true;
}
catch(Throwable ex)
{
log.error("Exception in service ", ex);
}
return false;
}
}
Now I wrote my own factory to create the subservices but when I did that of course because I am explictly creating my beans (e.g. FooService) below - my container is not auomatically injecting any of the #Autowired members - FooDao for example:
package com.johnarnold.myws.service;
public class SubServiceFactory {
/*
* Instantiates a SubService for the supplied subServiceName or throws an exception if
* no valid SubService exists
*/
public static SubService createSubService(String subServiceNameStr)
{
SubService subService = null;
System.out.println("subServiceName [" + subServiceNameStr + "]");
if(subServiceNameStr.equals("Foo"))
{
subService = new FooService();
}
if(subServiceNameStr.equals("Dummy"))
{
subService = new DummyService();
}
else
{
System.out.println("subServiceName [" + subServiceNameStr + "] is not defined");
}
return subService;
}
}
For completeness here is the Controller:
package com.johnarnold.myws.controller;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.apache.log4j.Logger;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.johnarnold.myws.model.RawsPayload;
import com.johnarnold.myws.model.SubServiceDetails;
import com.johnarnold.myws.service.SubService;
import com.johnarnold.myws.service.SubServiceFactory;
import com.johnarnold.myws.web.ValidMessage;
#RestController
#RequestMapping("/raws/")
public class RawsController {
private static final Logger logger = Logger.getLogger(RawsController.class);
//#Autowired
//SubService [] subSvcs;
#RequestMapping(value="/{version}/status", method=RequestMethod.GET)
public ResponseEntity<ValidMessage> getServiceStatus()
{
return new ResponseEntity<>(new ValidMessage() , HttpStatus.OK);
}
/*
* Main entry point - orchestrates all of the WS Sub Services
*/
#RequestMapping(value="/{version}/raws", method=RequestMethod.PUT)
public ResponseEntity<String> raws(#Valid #RequestBody RawsPayload rawsPayload,
HttpServletRequest request)
{
logger.info("Request received");
System.out.println("payl " + rawsPayload);
System.out.println("ssNumber=" + rawsPayload.getSsNumber());
System.out.println("sub svcs details=" + rawsPayload.getSubServicesDetails().length);
SubServiceDetails[] subServiceDetails = rawsPayload.getSubServicesDetails();
for(SubServiceDetails ssd : subServiceDetails)
{
String subServiceNameStr = ssd.getSubServiceName();
System.out.println("svcname=" + subServiceNameStr);
System.out.println("svc req params=" + ssd.getRequestParameters());
System.out.println("svc resp params=" + ssd.getResponseParameters());
SubService subService = SubServiceFactory.createSubService(subServiceNameStr);
// Probably wrap the below with some timings
subService.service(rawsPayload.getSsNumber(), ssd);
}
//System.out.println("svcs are " + subSvcs + "size=" + subSvcs.length);
return new ResponseEntity<>("foo" , HttpStatus.OK);
}
}
And here is the main payload class:
package com.johnarnold.myws.model;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.apache.log4j.Logger;
import org.hibernate.validator.constraints.Length;
public class RawsPayload {
static Logger log = Logger.getLogger(RawsPayload.class);
#NotNull
#Length(min=16, max=19)
private String ssNumber;
#Valid
#NotNull
#Size(min=1, max=3)
private SubServiceDetails [] subServicesDetails;
public String getSsNumber() {
return ssNumber;
}
public void setSsNumber(String ssNumber) {
log.info("setSsNumber()");
this.ssNumber = ssNumber;
}
public SubServiceDetails[] getSubServicesDetails() {
return subServicesDetails;
}
public void setSubServicesDetails(SubServiceDetails[] subServicesDetails) {
this.subServicesDetails = subServicesDetails;
}
}
I've read a number of answers on StackOverflow regarding Spring 4 Conditional Beans - but this functionality appears to be targeted at Context / Configuration type information rather than Request message content (as in this case).
Can anyone point me in the right direction. I can provide further context if necessary
KRgds
John
Two possible ways of solving this problem:
Add all your subService beans to the Spring context then select from them using a ServiceLocatorFactoryBean. This is the nicer approach (from architectural point of view), but it might require a bit more time to implement if you have never used this concept before.
There is a simpler alternative below if you want to stick with basic Spring solutions:
Have the subservice beans injected into your main service as a list, and then select from that. It would look something like this:
#Bean
public List<SubService> subServices(){
List<SubService> list = new SubService<>();
list.add(new AService());
list.add(new BService());
return list;
}
THEN
public SubService selectServiceByName() {
//iterate through the list, pick the service with the right name and return - this solution will require you to bind by beannames
}
#john-arnold First, crate all the services like this, or annotate them with #Service/#Component with explicit names like below: names are start with the values of subServiceName param and contains a common suffix, "Service" here, thats important.
#Bean("FooService")
public SubService fooService() {
return new FooService();
}
#Bean("DummyService")
public SubService dummyService() {
return new DummyService();
}
Then change your factory like this:
#Component
public class SubServiceFactory implements BeanFactoryAware{
private BeanFactory beanFactory;
private static final String MY_SERVICE_SUFFIX = "Service";
#Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public <T> T getServiceImplementation(String name, Class<T> requiredType) {
return beanFactory.getBean(name + MY_SERVICE_SUFFIX, requiredType);
}
}
Now what we have here is a BeanFactoryAware class that you can inject to your Rest Endpoint and instead of if statement, try this:
subServiceFactory.getServiceImplementation(subServiceNameStr, SubService.class);
This will return your bean or an exception if it doesn't find one. If you don't want an exception, you can catch it and return null or you can create a Service imp. just for these and return that instance. Your choice.
Edit:
As a shortcut, you can define your imp. Beans and than add this to your rest endpoint
#Autowired
private Map<String, SubService> mySubServices;
Spring will automatically inject all your imp. ref. so you can just use get() method of the map. But i prefer the first one..
You don't need anything fancy here. Just implement all your services that implement your service interface, annotate them all with either #Component or #Service and scan them as usual.
Then, wherever you have to choose a concrete service implementation, autowire all implementations of your service like this:
#Autowired
Map<String, SubService> subServices;
The key of the map will be the name of the service as specified in the #Component annotation of every sub service implementation, and the value will be the instance.
So, when you receive you JSON, just get the name of the sub service (i.e. Foo), and get the specific service of the map:
SubService fooSubService = subServices.get(subServiceName + "Service");
where subServiceName is the uncapitalized name of the sub service you're receiving in your JSON (i.e. if you're receiving Foo this would be foo).
The convention is to use the uncapitalized name of the class that implements the interface as the bean name, i.e. for the FooService class the bean name will be fooService, and this is the key you have to look for in the map.
Related
`
#RestController
public class TestController {
#Cacheable(cacheNames = "testCache", key = "#name")
#GetMapping("/test/{name}")
public String test(#PathVariable String name) {
System.out.println("########Test Called ###### " + name);
return HttpStatus.OK.toString();
}
}
Here cacheNames is Stirng array, if name is not exists in cacheNames then it should add first then shloud do rest of the things.
I'm using spring boot cache and I have to add cacheNames depend on request parameters.
You can do something like this if you want much flexibility:
import org.springframework.cache.CacheManager;
import org.springframework.cache.Cache;
// other imports
#RestController
public class TestController {
private final Cache myCache;
public TestController(#Autowired CacheManager cacheManager) {
this.myCache = cacheManager.getCache("myCache");
}
#GetMapping("/test/{name}")
public String test(#PathVariable String name) {
return myCache.get(name, () -> {
// your expensive operation that needs to be cached.
System.out.println("########Test Called ###### " + name);
return HttpStatus.OK.toString();
});
}
}
Cache name will not be dynamic in that case, but the cache key will be. And this is probably what you want.
Say we have a FileLoader Interface:
public interface FileLoader {
default String loadFile(String fileId) {
// Default business logic
return "Default implementation for FileLoader. Loading file" + fileId;
}
}
And different implementations for different countries:
public class USAFileLoader implements FileLoader {
#Override
public String loadFile(String fileId) {
// ... Specific business logic for USA
return "USA implementation for FileLoader. Loading file" + fileId;
}
}
public class FRAFileLoader implements FileLoader {
#Override
public String loadFile(String fileId) {
// ... Specific business logic for France
return "France implementation for FileLoader. Loading file" + fileId;
}
}
And we create an endpoint to load files:
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class FileUploadController {
FileLoader fileLoader;
#PostMapping("/load/{fileId}/{countryCode}")
public String loadFile(#PathVariable String fileId, #PathVariable String countryCode) {
fileLoader = ... // Inject the right loader based on countryCode
return fileLoader.loadFile(fileId);
}
}
How can I inject the right FileLoader at runtime for every request, based on countryCode? I've found something in Spring called FactoryBean that apparently may work, but I'm now sure if it's the right tool, or if this is the right way to address this problem. Also, I don't know how injection will behave with requests being proccessed at the same time.
The best thing you can do here using run time polymorphism, add one more abstract method in interface FileLoader for country code
public interface FileLoader {
default String loadFile(String fileId) {
// Default business logic
return "Default implementation for FileLoader. Loading file" + fileId;
}
public abstract String getCountryCode();
}
And then implement it in every implementation class with return the appropriate country code
public class USAFileLoader implements FileLoader {
#Override
public String loadFile(String fileId) {
// ... Specific business logic for USA
return "USA implementation for FileLoader. Loading file" + fileId;
}
public String getCountryCode(){
return "USA";
}
}
And then you can Autowire all beans of type FileLoader into List and call loadFile on appropriate bean
#RestController
public class FileUploadController {
#Autowire
List<FileLoader> fileLoaders;
#PostMapping("/load/{fileId}/{countryCode}")
public String loadFile(#PathVariable String fileId, #PathVariable String countryCode) {
return fileLoaders.stream()
.filter(f->f.getCountryCode().equlas(countryCode))
.findFirst()
.map(loader->loader.loadFile(fileId))
.orElse(()-> FileLoader.super.loadFile(fileId)); //calling interface default method
}
}
You can receive a bean with another way at runtime using ApplicationContext::getBean:
#Autowired
ApplicationContext
#PostMapping("/load/{fileId}/{countryCode}")
public String loadFile(#PathVariable String fileId, #PathVariable String countryCode) {
FileLoader fileloader = (FileLoader) applicationContext.getBean(countryCode);
return fileLoader.loadFile(fileId);
}
However, I'd recommend creating a service layer that aggregates the country-specific implementations and uses a factory pattern. There is nothing bad on such implementation.
I am trying to change the value of the RequestMapping annotation at runtime for a HTTP GET method - hello (which returns a simple string) inside a rest service class - SpringRestController.
The value of the uri defined in the #RequestMapping annotation on the hello method is "/hello/{name}". I am able to change the value of the annotation at runtime to "hi/{name}" using reflection in the constructor of the SpringRestController class.
I am able to verify the modified value by printing the value of the annotation inside an init method annotated with #PostConstruct annotation and also inside another controller. However, when I am trying to access the GET method in a browser:
with the modified value - http://localhost:9090/spring-boot-rest/rest/hi/Pradeep (does not work)
with the original value - http://localhost:9090/spring-boot-rest/rest/hello/Pradeep (works fine)
I expect the HTTP GET method hello to be accessible using the modified path value at runtime - "/hi/{name}" instead of the original path value - "/hello/{name}".
P.S - This is a requirement for us and needs to be done this way so that value of #RequestMapping can be configured externally without changes to the source code.
Here is the code - SpringRestController.java
package com.example.spring.rest.controller;
import javax.annotation.PostConstruct;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.spring.rest.custom.annotations.ConfigurableRequestMapping;
import com.example.spring.rest.reflection.ReflectionUtils;
#RestController
#RequestMapping("/rest")
public class SpringRestController {
public SpringRestController() {
RequestMapping rm = SpringRestController.class.getAnnotation(RequestMapping.class);
System.out.println("Old annotation : " + rm.value()[0]);
RequestMapping rmNew = new ConfigurableRequestMapping("/rest");
ReflectionUtils.alterAnnotationValueJDK8_v2(SpringRestController.class, RequestMapping.class, rmNew);
RequestMapping rmModified = SpringRestController.class.getAnnotation(RequestMapping.class);
System.out.println("Constructor -> New annotation : " + rmModified.value()[0]);
}
#RequestMapping(value = "/hello/{name}")
public String hello(#PathVariable String name) {
System.out.println("Name : " + name);
return "Hello " + name;
}
#PostConstruct
private void init(){
System.out.println("Annotations initialization post construct.");
RequestMapping rmModified = SpringRestController.class.getAnnotation(RequestMapping.class);
System.out.println("Init method -> New annotation : " + rmModified.value()[0]);
}
}
Code for changing annotation value -
ReflectionUtils.java
package com.example.spring.rest.reflection;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.spring.rest.controller.SpringRestController;
import com.example.spring.rest.custom.annotations.ConfigurableRequestMapping;
import com.example.spring.rest.utils.PropertyReader;
public class ReflectionUtils {
#SuppressWarnings("unchecked")
public static Object changeAnnotationValue(Annotation annotation, String key, Object newValue){
Object handler = Proxy.getInvocationHandler(annotation);
Field f;
try {
f = handler.getClass().getDeclaredField("memberValues");
} catch (NoSuchFieldException | SecurityException e) {
throw new IllegalStateException(e);
}
f.setAccessible(true);
Map<String, Object> memberValues;
try {
memberValues = (Map<String, Object>) f.get(handler);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
Object oldValue = memberValues.get(key);
if (oldValue == null || oldValue.getClass() != newValue.getClass()) {
throw new IllegalArgumentException();
}
memberValues.put(key,newValue);
return oldValue;
}
}
This is not possible to change the annotation value in runtime since Spring already registered that value. Aside from being curious about what do you really try to achieve, feel free to use multiple #PathVariable parameters, and handle the evaluation yourself.
// Either hardcoded values or loaded from elsewhere
private static List<String> GREETINGS = Arrays.asList("Hello", "Hi");
...
#GetMapping(value = "/{greeting}/{name}")
public String greeting(#PathVariable String greeting, #PathVariable String name) {
System.out.println("Name : " + name);
if (GREETINGS.stream().anyMatch(greeting::equalsIgnoreCase)) {
return greeting + " " + name;
}
throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
"Unknown greeting " + greeting, e);
}
Moreover, the point of the REST API endpoints is to be predictable. What you try to achieve seems like a contradiction to it. You can have multiple endpoints such as /hi/{name} and /hello/{name}, however, in this particular case either the usage of multiple parameters is correct, or this following endpoint that respects the resource and uses #RequestParam. I'd design it rather with this way since greeting is the resource.
A sample endpoint: /greeting?greeting={greeting}&name={name}
A sample call: /greeting?greeting=Hello&name=Pradeep%20Prabhakaran
I have a method annotated with #ApiParam as follows:
#RestController
#RequestMapping({LinksBuilder.BASE_URL})
#Api(tags = "Stuff Initiation", description="Stuff Initiation Service")
public class StuffResource {
#ApiOperation(value = "some description", tags = "Stuff Initiation")
#PostMapping(value = "/{stuffProduct}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Stuff InitiationResponse> postInitiateStuff (
#ApiParam(required=true,value="Stuff initiation payload")
#Valid #RequestBody Stuff Initiation stuffInitiation,
#ApiParam(name="stuffProduct", required= true, allowableValues="productStuff1,productStuff2,productStuff3")
#PathVariable String stuffProduct) throws StuffServiceException { ... }
...
}
The issue is that the swagger document generated by springfox (2.9.2) has a "allowEmptyValue":false which is disallowed on a path parameter by the swagger standard.
In an attempt to remedy this, I have implemented a solution similar to springfox hide allowEmptyValue when field annotated with #ApiModelProperty:
package com.example.config;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.google.common.base.Optional;
import io.swagger.annotations.ApiParam;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.ParameterBuilderPlugin;
import springfox.documentation.spi.service.contexts.ParameterContext;
import springfox.documentation.swagger.common.SwaggerPluginSupport;
#Component
#Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 100)
public class CustomizedParameterBuilderPlugin implements ParameterBuilderPlugin {
#Override
public boolean supports(final DocumentationType arg0) {
return true;
}
#Override
public void apply(ParameterContext context) {
//Optional<ApiModelProperty> annotation = empty();
Optional<ApiParam> apiParam = context.resolvedMethodParameter().findAnnotation(ApiParam.class);
if (apiParam.isPresent()) {
//apiParam.get().allowEmptyValue();
context.parameterBuilder().allowEmptyValue(null);
System.err.println(apiParam.get().name() + "\t" + apiParam.get().type());
}
}
}
I get the right elements, but apparently the setting of context.parameterBuilder().allowEmptyValue(null); doesn't work... the elements are still generated
I am aware that the root cause is a known bug, and is set as status fixed, but I have not got the possibility of using 3.0.0-SNAPSHOT
I'm using Spring-security-oauth to secure a RESTful application, and I'm triying to implement a custom OAuthProviderTokenServices class in order to store tokens in a database.
All I got from the docs is:
When creating your OAuthProviderTokenServices implementation, you may
want to consider extending the RandomValueProviderTokenServices which
creates tokens via random value and handles everything except for the
persistence of the tokens. There is also an in-memory implementation
of the OAuthProviderTokenServices that may be suitable [...]
which is fine, so I created a new custom class:
package experiments;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.security.oauth.provider.token.OAuthProviderTokenImpl;
import org.springframework.security.oauth.provider.token.RandomValueProviderTokenServices;
/**
* Implementation of TokenServices that stores tokens in a database.
*
* #author Seether
*/
public class DatabaseProviderTokenServices extends RandomValueProviderTokenServices {
protected final ConcurrentHashMap<String, OAuthProviderTokenImpl> tokenStore = new ConcurrentHashMap<String, OAuthProviderTokenImpl>();
protected OAuthProviderTokenImpl readToken(String token) {
return tokenStore.get(token);
}
protected void storeToken(String tokenValue, OAuthProviderTokenImpl token) {
tokenStore.put(tokenValue, token);
}
protected OAuthProviderTokenImpl removeToken(String tokenValue) {
return tokenStore.remove(tokenValue);
}
}
which for now, as you can see, is identical to the InMemoryProviderTokenServices class.
My application uses the AccessConfirmationController from sparkl example, which is this:
package experiments;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.oauth.provider.ConsumerDetails;
import org.springframework.security.oauth.provider.ConsumerDetailsService;
import org.springframework.security.oauth.provider.token.OAuthProviderToken;
import org.springframework.security.oauth.provider.token.OAuthProviderTokenServices;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* Controller for retrieving the model for and displaying the confirmation page for access to a protected resource.
*
* #author Ryan Heaton
*/
#Controller
public class AccessConfirmationController {
private OAuthProviderTokenServices tokenServices;
private ConsumerDetailsService consumerDetailsService;
#RequestMapping("/oauth/confirm_access")
public ModelAndView getAccessConfirmation(HttpServletRequest request, HttpServletResponse response)
throws Exception {
String token = request.getParameter("oauth_token");
if (token == null) {
throw new IllegalArgumentException("A request token to authorize must be provided.");
}
OAuthProviderToken providerToken = tokenServices.getToken(token);
ConsumerDetails consumer = consumerDetailsService
.loadConsumerByConsumerKey(providerToken.getConsumerKey());
String callback = request.getParameter("oauth_callback");
TreeMap<String, Object> model = new TreeMap<String, Object>();
model.put("oauth_token", token);
if (callback != null) {
model.put("oauth_callback", callback);
}
model.put("consumer", consumer);
return new ModelAndView("access_confirmation", model);
}
public void setTokenServices(OAuthProviderTokenServices tokenServices) {
this.tokenServices = tokenServices;
}
public void setConsumerDetailsService(ConsumerDetailsService consumerDetailsService) {
this.consumerDetailsService = consumerDetailsService;
}
}
Now the question is: how do I tell my application to use my tokenServices implementation rather than the default one (which right now I belive is InMemoryProviderTokenServices)?
I tried messing around with the controller, but the fews attempt all led me to java.lang.IllegalStateExceptions.
I also noticed that there is a line in the config XML:
<oauth:token-services id="tokenServices"/>
Which might be a critical piece of the puzzle, as the related help reads:
Element for declaring and configuring an in-memory implementation of
the provider token service.
If I just remove it, I get:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'accessConfirmationController' defined in
ServletContext resource [/WEB-INF/mvc-dispatcher-servlet.xml]: Cannot
resolve reference to bean 'tokenServices' while setting bean property
'tokenServices'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
bean named 'tokenServices' is defined
Funny as answers come out of nowhere sometimes, expecially after it's been some time since you've started looking for them and you've just posted here. Oh well.
According to a code snippet randomly found here, it looks like all I needed to do was to comment out that line from the XML configuration file:
<!-- <oauth:token-services id="tokenServices"/> -->
and replace it with this one:
<beans:bean id="tokenServices" class="experiments.DatabaseProviderTokenServices" />
where the class is of course my implementation.
By doing this, the DatabaseProviderTokenServices class is used in place of the default InMemoryProviderTokenServices class.