Consider this Jersey REST endpoint annotated for Dropwizard metrics:
#GET
#Path("/widgets/{id}")
#Produces("application/json")
#Timed(name="widgets.read", absolute=true)
public Response getWidget(#PathParam("id") String id) { .... }
The library is creating named timers per url: /widgets/foo, /widgets/bar, etc. This is probably desirable in many cases. However, in my scenario, I have over 60 million widgets and this behavior is consuming a significant portion of my heap. I'd rather that the library track at the less granular /widget level. Is there a way to accomplish this with the native metric annotations or do I need to roll my own using the core API?
It turns out that it wasn't Dropwizard at fault, but the SpringBoot MetricFilter. It can be disabled via:
-Dendpoints.metrics.filter.enabled=false
or
#SpringBootApplication(exclude=MetricFilterAutoConfiguration.class)
Related
I'm trying to migrate my Servlet-based application to Webflux and got stuck with session management. I've been using Spring session with Jdbc implementation (backed by PostgreSQL) for a while and my config looks like this:
#Configuration
#EnableSpringHttpSession
public static class SessionConfig {
#Bean
public MapSessionRepository sessionRepository() {
return new MapSessionRepository(new ConcurrentHashMap<>());
}
}
Now, as I understood documentation correctly, servlet-based HttpSession has been replaced with WebSession and I need to provide configuration like the following:
#Configuration
#EnableSpringWebSession
public class SessionConfig {
#Bean
public ReactiveSessionRepository sessionRepository() {
return ???
}
}
But I could not find any support for relational databases as there are only 2 implementations of org.springframework.session.ReactiveSessionRepository (from "org.springframework.session:spring-session-core:2.2.2.RELEASE"):
Basic one - ReactiveMapSessionRepository
Redis-based one - ReactiveRedisSessionRepository
but unfortunately, they do not satisfy my requirement.
I also could not find any notes neither for "org.springframework.session:spring-session-jdbc" support for WebSessions, nor for new R2DBC.
Is it possible to back WebSessions by relational database (e.g. Postgres) and if it is, how can I achieve this (which implementation should I use)? I know there are some issues with non-blocking operations support for relational databases but I wonder if I missed something and it's still possible.
Thanks in advance
You are correct that Spring Session does not provide a JDBC implementation of ReactiveSessionRepository, since JDBC is of a blocking nature.
When building a reactive web application, currently only Redis and MongoDB can be auto-configured.
If it's necessary for you to use JDBC with WebFlux, it is possible to back WebSession by relational database, by configuring a custom implementation of ReactiveSessionRepository.
First, make sure you consider whether WebFlux is a good fit for your use case.
From the Spring Framework documentation:
If you have blocking persistence APIs (JPA, JDBC), or networking APIs to use, then Spring MVC is the best choice for common architectures at least. It is technically feasible with both Reactor and RxJava to perform blocking calls on a separate thread but you wouldn’t be making the most of a non-blocking web stack.
If you do implement a custom ReactiveSessionRepository, you may find this section of the Spring Session docs useful.
I want to introduce DI to our application.
In our application, we have some generic parameters that are passed through the entire
application, mostly via constructor parameters.
For example the parameter region limits all actions to a geographic region. This parameter is gathered from user input at runtime and thereby not known at the composition root.
How should I create classes that are always limited to work on one region?
I know that I could use the factory pattern. In this case I would need to pass the DIC into the factory, which is (as far as I know) an anti-pattern.
The factory pattern is certainly NOT an anti-pattern when working with DI, even though you will see the number of factories decrease when you apply DI correctly.
Still in your situation a factory might not be the best approach. Typically you should prevent letting the object graph depend on runtime data and you should separate the need for that request specific data from the composition of your services.
In your case it would probably be easy to have some sort of IRegionContext or IRegionManager abstraction that allows to to get the region for the current request. This IRegionContext itself is a service, but contains a method that can be called by the application after the object graph is contructed:
public interface IRegionContext
{
Region CurrentRegion { get; }
}
Application types can depend on the IRegionContext and in the composition root of your web application you can have a special AspNetRegionContext implementation that allows retrieving the region based on the current request.
I am currently in the process of moving business logic from a controller method to a service, when I fell down the rabbit hole of grails services. I have the following method in my service:
Job closeJobOpportunity(Job op, Employee res) {
op.chosenOne = res
op.requisitionCanceledDate = new Date()
if(!op.chosenOne || !op.hrEffectiveDate){
return null
}
else if(StringUtils.isEmpty(op.chosenOne.id)){
return null
}
return op
}
I started thinking about the different ways this method could cause synchronization problems(because of grails making the service a singleton), and noticed the grails documentation mentions that business logic should be put in the service as long as you don't store the state.
At the risk of sounding ignorant or not well informed, can someone simply provide the differences between stateful and stateless services in Grails? Is the above method stateful? Should it then be surrounded by try catch in the controller?
The difference between stateful and stateless in a Grails service (or any other instance of a class for that matter) is determined by if the instance itself holds any state.
First, it's difficult to say if your Service in your example is stateless or not, but the interaction you have there in that particular method doesn't indicate that you are doing anything stateful with the service itself. That would lead me to believe that the service is going to be stateless.
Let me give you an example of a stateful service and explain why it's stateful.
class MyStatefulService {
Long someNumber
String someString
void doSomething(Long addMe) {
someNumber += addMe
}
void updateSomething(String newValue) {
someString = newValue
}
}
As you can see the above service has two properties. If this service is created as a singleton then all calls to it will use the same single instance. As you can see the two methods on the service effect the properties, or state, of the service. This means, in it's current form, you can't be sure that the state doesn't change while a particular thread is executing a method or methods of the service. Making it unreliable, in it's current form. While this is a very simple example it does demonstrate what makes a service stateful.
It's okay for services to have properties, and often they do. They can be references to other services or even configuration values. The key concept is to make sure they don't change state (there is always exceptions to this, but they are the edge cases).
It's entirely possible to rewrite the service to be stateful, synchronized and such to avoid the pitfalls of multiple threads accessing and modifying the state, but it's not something you should aim to do. Stateless services are simpler, cleaner, easier to test, easier to debug, and more lightweight.
In short, make your services stateless and save yourself the headaches.
I agree with the above answer that specifically details stateful vs stateless services. I'd also agree with the process of moving business logic out of the controller layer and avoiding the "fat controller" anti-pattern. However, to answer a slightly different, perhaps implied question, I wouldn't necessary jump to stuffing everything in the service layer.
It does depend on the complexity of your app. In the short term business logic at the service layer is appealing, but I feel like longer term it leads to procedural thinking and code that is hard to extend or reuse. If you're thinking about where actual business logic should live I'd encourage taking 30 minutes and watching this talk.
https://skillsmatter.com/skillscasts/4037-all-hail-the-command-object-are-stateless-services-the-only-way
What would be the syntax for memoizing a service method that is side-effect free and only does lookups? Would the memo persist from session to session or would it be kindof purposeless in the web world? Are there some examples of good places to use .memoize() in a grails app?
class DetermineStuffService{
def figureThisOut(def whatever){
//look up all sorts of stuff and do some heavy side-effect free processing
return nastyHashmap
}
}
So in a controller can I somehow call DetermineStuffService.figureThisOut(someRandomObject) and take advantage of .memoize()?
One problem with this is that memoize() only works on closures. Closures are objects, so if you store one in your service, it is "state".
A better way of caching services in grails is with the Spring Cache plugin. Then to cache the result of a service method, just annotate the method with #Cacheable. It has support for multiple caches, automatically flushing, and caching controller output as well.
We have a pretty common architecture:
Database
Repository Layer
Business Objects
Services Layer - serves DTOs to the client
Web Layer (MVC)
We've got a number of common paths to resources, in particular images and podcasts (Ex. http://media.mysite.com/podcasts/). I want to create a static utility class with properties:
MySite.Utils.ImagePathUri
MySite.Utils.PodcastsPathUri
etc
My question is: Where do you put uri paths? Into which project does this utility class go?
Initially, it seemed a no-brainer: the web layer. It's a web site. I should be able to change the urls of a site without the other layers knowing about it.
Everything was fine, but, . . . then one day one of my services needed to provide a SyndicationFeed type. The SyndicationFeed needs a full URI, not just a partial file name. But the services shouldn't have access to full paths. Or should they?
I've debated with myself several things, but can't come up with a firm position:
Move the paths to the services layer. That tightly couples the web layer to the services layer, but maybe that's ok, since they're pretty tightly coupled to begin with.
Move the paths to the business objects or repos. I don't like this, but if I'm open to putting it into the services layer, I have to at least consider it.
Don't use SyndicationFeed inside of services layer, but use it only in the web layer. Solves the issue, but it seems like SyndicationFeed should belong in a services layer.
Discard SyndicationFeed. Any SyndicationFeed can more easily be created in MVC with a PartialView that generates the appropriate XML without having to mess with the bloated abstractions like ElementExtensions. I like this one, but we're using SyndicationFeed in a number of places, so that one will take the most explaining to do.
Provide a fake uri to the syndication feed in the services layer and then change it in the web layer. Can you say hack?
Put the full path in the database. That sounds ok at first, but then I realize that it breaks as soon as you have a dynamically generated image.
Some other solution that doesn't occur to me.
What are your thoughts? Where do you put utility classes for web resources (images, podcasts, etc)? And if you say "web layer", what's your take on the SyndicationFeed issue?
UPDATE
At the end of the day, I decided to scrap the SyndicationFeed class, which negated the need for including the path to the file in the service and repository layers. However, the problem still comes up elsewhere and using DI and, in particular, an IoC like Ninject makes perfect sense. So does wrapping together these into a common interface.
SyndicationFeed, View engines and why Declarative does Declarative better
I ditched the SyndicationFeed and instead created the XML that I needed using Razor. Not only is it much easier to create, but it's 1000% more readable. I've come around to the opinion that using imperative code (C#, VB, etc.) to create XML is just harder than it ought to be. XML is declarative, not imperative.
Instead, I've now decided that declarative syntax of View Engines (e.g. Razor) is much easier to work with than imperative languages.
I feel your pain. I too had a similar situation that I resolved by passing the uri to my repository layer, from my web layer.
My project uses Ninject for binding, and since I was already passing the connection string to the repository with Ninject, it was a simple matter to pass my path string as well.
My repository then massages the path string and populates the necessary properties in my business object.
Is this proper? I do not know, but it works for now. I am not completely happy with the solution, but I have not yet had a chance attempt an improvemnt.
Would love to hear how others have dealt with this.
Facing a similar situation I felt the best way to approach it was to define a configuration interface that resulted in an object at the top most layer. Each layer in between would refine the interface with more specific properties and operations:
public interface IWebConfiguration
{
string RootImageUri { get; }
}
the service would layer would add the things needed by itself:
public interface IServicesConfiguration
{
string SyndicationFeedUri { get; }
}
public interface IDatabaseConfiguration
{
string ConnectionString { get; }
}
In the end I had the web tier implement the specific object that wired up all of the interfaces. Ugly? Perhaps. I will admit there was calls to isa in there and some casting.
However, I was able to then pass to each layer a strongly typed interface. In my opinion it was better than having a series of calls to get plain old string from a config file. Also, because each property was specific to a layer and the aggregate object was being passed around I only had to load the configuration once.