Spring cache/fallback framework - java

My use case is that I want to cache certain request:response in my service caller classes:
public class Abc{
public Response serviceCall(Request r){}
}
public class Memcached{
public Response get(Request r){}
public void put(Request r, Response rs){}
}
I want to use memcached for caching . The request would be the key and value would be the response. Whenever serviceCall() is called I want to check if request is already present in cache if so then return response from the cache.
If not then actually execute serviceCall() method and put request:response key:value in memcached
Is there any way in spring to achieve the same.
I did look into #Cacheable here http://www.baeldung.com/spring-cache-tutorial
But I am unable to understand how I make spring use my "Memcached" class, more specifically where do I wire my "Memcached" class so that it is available to class "Abc" in above example
Could you please help . I am working in spring boot completely annotation based and looking for annotation based solution

Spring caching doesn't support Memcached by out-of-the-box (Supported Cache Providers).
If you want to use Memcached in your project please check out Memcached Spring Boot caching library.
There is also an example Java project of how to use Memcached with Spring.

You don't need the memcached class. Just put the #Cacheable annotation on Abc.serviceCall as per the baeldung tutorial.

Related

Is there a possibility to add custom spring boot metrics tags at runtime?

I'm using Spring Boot with micrometer-registry-prometheus, trying to store custom tags from http headers, security context, etc.
So I found MeterFilter iterface and tried to use it to store the data I need.
But MeterFilter method works after request is completed, so at that point I don't have any information about request.
Seems like the case is pretty common, is there any possibility to achieve it?
If you're using Spring MVC you can define a bean that implements WebMvcTagsProvider to take complete control over the tags that are added to metrics for request-response exchanges. Alternatively, you can define a bean that implements WebMvcTagsContributor to add to the default tags. Similarly, if you're using Spring WebFlux you can define beans that implements WebFluxTagsProvider and WebFluxTagsContributor to take complete control over the tags and contribute additional tags respectively.

Where is the Spring Actuator Controller endpoint and can I call it programmatically with jvm call?

I want to find the actual java class that serves the Spring Actuator endpoint (/actuator).
It's similar to this question in a way, but that person wanted to call it via a network HTTP call. Ideally, I can call it within the JVM to save on the cost of setting up an HTTP connection.
The reason for this is because we have 2 metrics frameworks in our system. We have a legacy metrics framework built on OpenCensus and we migrated to Spring Actuator (Prometheus metrics based on Micrometer). I think the Spring one is better but I didn't realize how much my company built infrastructure around the old one. For example, we leverage internal libraries that use OpenCensus. Infra team is depending on Opencensus-based metrics from our app. So the idea is to try to merge and report both sets of metrics.
I want to create my own metrics endpoint that pulls in data from Opencensus's endpoint and Actuator's endpoint. I could make an HTTP call to each, but I'd rather call them within the JVM to save on resources and reduce latency.
Or perhaps I'm thinking about it wrong. Should I simply be using MeterRegistry.forEachMeter() in my endpoint?
In any case, I thought if I found the Spring Actuator endpoint, I can see an example of how they're doing it and mimic the implementation even if I don't call it directly.
Bonus: I'll need to track down the Opencensus handler that serves its endpoint too and will probably make another post for that, but if you know the answer to that as well, please share!
I figured it out and posting this for anyone else interested.
The key finding: The MeterRegistry that is #Autowired is actually a PrometheusMeterRegistry if you enable the prometheus metrics.
Once you cast it into a PrometheusMeterRegistry, you can call its .scrape() method to return the exact same metrics printout you would when you hit the http endpoint.
I also need to get the same info from OpenCensus and I found a way to do that too.
Here's the snippet of code for getting metrics from both frameworks
Enumeration<MetricFamilySamples> openCensusSamples = CollectorRegistry.defaultRegistry.filteredMetricFamilySamples(ImmutableSet.of());
StringWriter writer = new StringWriter();
TextFormat.write004(writer, openCensusSamples);
String openCensusMetrics = writer.toString();
PrometheusMeterRegistry registry = (PrometheusMeterRegistry) meterRegistry;
String micrometerMetrics = registry.scrape();
return openCensusMetrics.concat(micrometerMetrics);
I found out another interesting way of doing this.
The other answer I gave but it has one issue. It contains duplicate results. When I looked into it, I realized that both OpenCensus and Micrometer were reporting the same result.
Turns out that the PrometheusScrapeEndpoint implementation uses the same CollectorRegistry that OpenCensus does so the both sets of metrics were being added to the same registry.
You just need to make sure to provide these beans
#PostConstruct
public void openCensusStats() {
PrometheusStatsCollector.createAndRegister();
}
#Bean
public CollectorRegistry collectorRegistry() {
return CollectorRegistry.defaultRegistry;
}

Keycloak annotation based Resource configuration

I'm recently working with microservices, developed as Spring Boot applications (v 2.2) and in my company we're using Keycloak as authorization server.
We chose it because we need complex policies, roles and groups, and we also need the User Managed Authorization (UMA) to share resources between users.
We configured Keycloak with a single realm and many clients (one client per microservice).
Now, I understand that I need to explicitly define Resources within Keycloak and this is fine, but the question is: do I really need to duplicate all of them in my microservice's property file?
All the documentation, examples and tutorials end up with the same thing, that is something like:
keycloak.policy-enforcer-config.enforcement-mode=PERMISSIVE
keycloak.policy-enforcer-config.paths[0].name=Car Resource
keycloak.policy-enforcer-config.paths[0].path=/cars/create
keycloak.policy-enforcer-config.paths[0].scopes[0]=car:create
keycloak.policy-enforcer-config.paths[1].path=/cars/{id}
keycloak.policy-enforcer-config.paths[1].methods[0].method=GET
keycloak.policy-enforcer-config.paths[1].methods[0].scopes[0]=car:view-detail
keycloak.policy-enforcer-config.paths[1].methods[1].method=DELETE
keycloak.policy-enforcer-config.paths[1].methods[1].scopes[0]=car:delete
(this second example fits better our case because it also uses different authorization scopes per http method).
In real life each microservice we're developing has dozens of endpoints and define them one by one seems to me a waste of time and a weakness in the code's robustness: we change an endpoint, we need to reconfigure it in both Keycloak and the application properties.
Is there a way to use some kind of annotation at Controller level? Something like the following pseudo-code:
#RestController
#RequestMapping("/foo")
public class MyController {
#GetMapping
#KeycloakPolicy(scope = "foo:view")
public ResponseEntity<String> foo() {
...
}
#PostMapping
#KeycloakPolicy(scope = "bar:create")
public ResponseEntity<String> bar() {
...
}
}
In the end, I developed my own project that provides auto-configuration capabilities to a spring-boot project that needs to work as a resource server.
The project is released under MIT2 license and it's available on my github:
keycloak-resource-autoconf

Using Spring Solr Data or Not for Flexible Requests as Like Backup?

I want to implement an application at Spring that interacts with my current Solr or SolrCloud. I consider of using Spring Data Solr or not. However I think that there is no CloudSolrServer implemented at it yet on the other hand if I just run a query like that:
http://localhost:8983/solr/replication?command=backup
and check whether backup is completed or not(I will do a get request, parse JSON and will see that last backup time is changed or not) How I can integrate it with Spring Data Solr?
I mean is it more meaningful using Spring + Solrj instead of Spring Data Solr at my situation (that is I want to do more flexible things that just CRUD operations on Solr with Spring)?
True, there is no support for CloudSolrServer yet. What you can do is provide you own SolrServerFactory.
public class CloudSolrServerFactory implements SolrServerFactory {
private final CloudSolrServer solrServer;
public CloudSolrServerFactory(String zkHost) throws MalformedURLException{
this.solrServer = new CloudSolrServer(zkHost);
}
#Override
public SolrServer getSolrServer() {
return this.solrServer;
}
#Override
public String getCore() {
return "";
}
}
Next you can add custom behavior to all your repositories as described in Section 1.3 of Spring Data Commons documentation. Have a look at this (not an implementation of your issue, rather general usage of custom repositories) to get the idea of how it might work.
Please feel free to open a feature request as this is definitely something missing Spring Data Solr.

Where to store request specific values in Spring MVC?

I'm using Spring MVC and I want to store request specific values somewhere so that they can be fetched throughout my request context. Say I want to set a value into the context in my Controller (or some sort of handler) and then fetch that value from some other part of the Spring request/response cycle (could be a view, view resolver, interceptor, exception handler, etc)... how would I do that?
My question is:
Does Spring MVC already provide a method to do what I described above?
If Spring doesn't have this functionality, any ideas on the best way to do this (by extending something maybe)?
Thanks!
If you need to pass an object from your controller to view, you can use Spring's ModelMap.
#RequestMapping("/list")
public String list(ModelMap modelMap) {
// ... do foo
modelMap.addAttribute("greeting", "hello");
return viewName;
}
on your view:
<h1>${greeting}</h1>
You could use sessionAttributes.
Session Attributes
I took the latest version of the api (3.1) since you didn't mention your version of spring.

Categories