How to Cache HTTP Requests made with Netflix's Feign library in a Java Spring app - spring

In a spring boot application using Netflix's Feign to make HTTP requests to a service, is there an easy way to cache and return these cached values automatically? The cache should be based on the parameters passed to the request (similar to memoizing a function for X minutes).
I'm looking for something like the #Cache annotation below:
#Component
#FeignClient(value = "facebook", url = "${auth.facebook.url}")
public interface FacebookClient {
#Cache(600) // Something like this.
#RequestMapping(method = RequestMethod.GET, value = "/debug_token?input_token={input_token}&access_token={access_token}")
Map debugToken(#PathVariable("input_token") String inputToken, #PathVariable("access_token") String appToken);
}
Of course I could cache it myself using a decorator around the FacebookClient, I was wondering if there was a quicker/less code way.

Springs #Cacheable does what you need.
Check: Caching Data with Spring

Feign does not support caching. I would prefer the JCache (JSR-107) and maybe use it via the spring-boot-starter-cache described in the spring guide
JCache is an abstraction for the proprietary implementation of EhCache, Hazelcast, ... so it is possible to change the implementation with very less impact on the application. At first I would prefer EhCache 3.

Feign client doesn't support caching.
Another better way would be to create a Service class which calls FeignClient and put up cache on methods of this new Service class.

Related

How to inject Feign Client with out using Spring Boot and call a REST Endpoint

I have two Java processes - which get spawned from the same Jar using different run configurations
Process A - Client UI component , Developed Using Spring bean xml based approach. No Spring Boot is there.
Process B - A new Springboot Based component , hosts REST End points.
Now from Process A , on various button click how can I call the REST end points on Process B using Feign Client.
Note - Since Process A is Spring XML based , right at the moment we can not convert that to Spring boot. Hence #EnableFeignClients can not be used to initialise the Feign Clients
So Two questions
1) If the above is possible how to do it ?
2) Till Process A is moved to Spring boot - is Feign still an easier option than spring REST template ?
Feign is a Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSockets and you can easily use feign without spring boot. And Yes, feign still better option to use because Feign Simplify the HTTP API Clients using declarative way as Spring REST does.
1) Define http methods and endpoints in interface.
#Headers({"Content-Type: application/json"})
public interface NotificationClient {
#RequestLine("POST")
String notify(URI uri, #HeaderMap Map<String, Object> headers, NotificationBody body);
}
2) Create Feign client using Feign.builder() method.
Feign.builder()
.encoder(new JacksonEncoder())
.decoder(customDecoder())
.target(Target.EmptyTarget.create(NotificationClient.class));
There are various decoders available in feign to simplify your tasks.
You are able to just initialise Feign in any code (without spring) just like in the readme example:
public static void main(String... args) {
GitHub github = Feign.builder()
.decoder(new GsonDecoder())
.target(GitHub.class, "https://api.github.com");
...
}
Please take a look at the getting started guide: feign on github

Spring Boot: Retrieve config via rest call upon application startup

I d like to make a REST call once on application startup to retrieve some configuration parameters.
For example, we need to retrieve an entity called FleetConfiguration from another server. I d like to do a GET once and save the keep the data in memory for the rest of the runtime.
What s the best way of doing this in Spring? using Bean, Config annotations ..?
I found this for example : https://stackoverflow.com/a/44923402/494659
I might as well use POJOs handle the lifecycle of it myself but I am sure there s a way to do it in Spring without re-inventing the wheel.
Thanks in advance.
The following method will run once the application starts, call the remote server and return a FleetConfiguration object which will be available throughout your app. The FleetConfiguration object will be a singleton and won't change.
#Bean
#EventListener(ApplicationReadyEvent.class)
public FleetConfiguration getFleetConfiguration(){
RestTemplate rest = new RestTemplate();
String url = "http://remoteserver/fleetConfiguration";
return rest.getForObject(url, FleetConfiguration.class);
}
The method should be declared in a #Configuration class or #Service class.
Ideally the call should test for the response code from the remote server and act accordingly.
Better approach is to use Spring Cloud Config to externalize every application's configuration here and it can be updated at runtime for any config change so no downtime either around same.

Apply #PostFilter / #PostAuthorize for all endpoints

I have been able to use #PostFilter / #PostAuthorize successfully as follows:
#RestController
public class MyController{
#PostFilter("hasPermission(filterObject, 'blah')")
public List<MyObject> getIt();
}
However, what I would like to do is configure the hasPermission (or some similar) check on all endpoints in my application. In other words, doing something like a Spring Security Fitler but using the domain object prior to it being marshalled in the HttpServletResponse. I would prefer not to use a Filter because of the marshalling / unmarshalling aspect especially when doing filtering (#PostFilter) as it changes the result.
The idea is that I would like this filtering behavior to be a cross-cutting security concern and therefore not have to remember to add it to each endpoint as it is added. This would also allow me to do testing of this filtering once for the application instead of for each endpoint.

How to generate Java client proxy for RESTful service implemented with Spring?

We use Spring to implement REST controller, for example:
#Controller
#RequestMapping("/myservice")
public class MyController {
#RequestMapping(value = "foo", method = RequestMethod.GET)
public #ResponseBody string foo() {...}
}
I can call this service using spring RestTemplate, and it works fine, but I would prefer to invoke it using a proxy, instead of typeless invocation using string url:
// client code:
MyController proxy = getProxy("baseUrl", MyController.class);
String results = proxy.foo();
So the input to proxy generation is java interface with annotations describing REST details.
I read this article and it looks like all types of remote calls do have proxies, and all I need for REST is something like RestProxyFactoryBean, that would take my REST java interface and return type-safe proxy that uses RestTemplate as implementation.
The closest solution I found is JBoss RESTEasy.
But it seems to use different set of annotations, so I am not sure it will work with annotations I already have: #Controller, #RequestMapping.
Are there other options, or RESTEasy is the only one?
Note, I am spring newbie so some obvious spring things are pretty new to me.
Thank you.
Dima
You can try Feign by Netflix, a lightweight proxy-based REST client. It works declaratively through annotations, and it's used by Spring Cloud projects to interact with Netflix Eureka.
One of the reasons the REST paradigm was invented was because expirience with other remoting technologies (RMI, CORBA, SOAP) shows us that often, the proxy-based approach creates more problems than it solves.
Theoretically, a proxy makes the fact that a function call is remote transparent to its users, so they can use the function exactly the same way as if it were a local function call.
In practice however this promise cannot be fulfilled, because remote function calls simply have other properties than local calls. Network outages, congestion, timeouts, load problems to name just a few. If you choose to ignore all these things that can go wrong with remote calls, your code probably won't be very stable.
TL;DR: You probably shouldn't work with a proxy, it's not state of the art any more. Just use RestTemplate.
Here is a project trying to generate runtime proxies from the controller annotations (using RestTemplate in the background to handle proxy calls): spring-rest-proxy-client Very early in implementation though.
This seems to do it: https://swagger.io/swagger-codegen/, and swagger has many other nice things for REST API.
Have a look at https://github.com/ggeorgovassilis/spring-rest-invoker.
All you need is to register FactoryBean:
#Configuration
public class MyConfiguration {
#Bean
SpringRestInvokerProxyFactoryBean BankService() {
SpringRestInvokerProxyFactoryBean proxyFactory = new SpringRestInvokerProxyFactoryBean();
proxyFactory.setBaseUrl("http://localhost/bankservice");
proxyFactory.setRemoteServiceInterfaceClass(BankService.class);
return proxyFactory;
}
and after that you can autowire the interface class:
#Autowired
BookService bookService;
I also ended up making my own library for this. I wanted something that is as small as possible, adds only itself to classpath and no transitive dependencies.
A client is created like:
final StoreApi storeApi = SpringRestTemplateClientBuilder
.create(StoreApi.class)
.setRestTemplate(restTemplate)
.setUrl(this.getMockUrl())
.build();
And rest-requests will be performed when invoking the methods:
storeApi.deleteOrder(1234L);
The is supports both method signatures:
ResponseEntity<X> deleteOrder(Long)
X deleteOrder(Long)

Available paths listing for Spring actions

I have an application which exposes RESTful actions using spring annotations and Spring MVC.
It looks like
#RequestMapping(value = "/example/{someId}",
method = RequestMethod.GET, consumes=MediaType.APPLICATION_JSON_VALUE,
produces=MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public void isRegisteredToThread(#PathVariable long someId, HttpServletResponse response) {
[something]
}
What I want is an automatically generated listing of all URL's, methods and available parameters - possibly within a WSDL. Is there a plugin or is it somehwere available?
WSDL is not done for rest, it's used for SOAP.
You might use WADL, but I really do not suggest it.
In my project I always use swagger (there is a release for spring). You may find more info here https://github.com/martypitt/swagger-springmvc and here http://blog.zenika.com/index.php?post/2013/07/11/Documenting-a-REST-API-with-Swagger-and-Spring-MVC
Give it a try.
As an alternative, if you don't need something web-based, you may try rest-shell (https://github.com/spring-projects/rest-shell)
You could take a look at the source code of RequestMappingEndpoint provided by the Spring Boot and see how Spring Boot reports the mappings.
Looking through that code one can see that the mappings (both handler and method mappings) can easily be obtained from the applicationContext
(using
applicationContext.getBeansOfType(AbstractUrlHandlerMapping.class)
and
applicationContext.getBeansOfType(AbstractHandlerMethodMapping.class)
respectively). After you have obtained the mapping you can process them anyway you like.
You might want to create a library that could include in all your projects that processes the mapping your organizations desired form

Resources