CoroutineContext best practices in a Spring application - spring

I would like to understand what are the best practices on how to use kotlin coroutines in a Spring server application, specifically about the CoroutineContext.
Let's say I have a Controller like this:
#Controller
class ProductController {
#Autowired
lateinit var productRepository: ProductRepository
#Autowired
lateinit var mapper: ProductDtoMapper
#GetMapping("/")
suspend fun getProduct(): ProductDTO {
val product = productRepository.getFirst()
val productDTO = mapper.mapToDto(product)
return productDto
}
}
Then my Repository is like:
#Repository
class ProductRepository(private val productService: ProductService) {
suspend fun getFirst(): Product = withContext(Dispatchers.IO) {
return productService.get()
}
}
I noticed that the code inside the getProduct function is executed in a CoroutineContext that is Unconfined, which means that in the example above, after productRepository.getFirst() returns, the execution resumes in the same thread defined in the ProductRepository.getFirst method.
Now, in this specific example probably this doesn't matter but I was thinking that with the application growing, this might cause some problems.
For example, let's say that the ProductService is doing some operations that is blocking the thread: in this case I could decide to create a fixed number of threads to limit the amount of threads to handle this kind of operation. The code might look to something like this:
#Repository
class ProductRepository(private val productService: ProductService) {
private val dispatcher = Executors.newFixedThreadPool(10).asCoroutineDispatcher()
suspend fun getFirst(): Product = withContext(dispatcher) {
return productService.get()
}
}
So, as stated above, after productRepository.getFirst() returns, the execution resumes in the same thread defined in the ProductRepository.getFirst method.
That means that also the mapping in ProductController will be executed in the same thread, and if this is also a blocking operation the thread will continue to execute operations that was not suppose to execute.
I come from Android and this kind of behavior is not recommended, since it might end up executing code that is doing cpu intensive operations in the main thread and this will be blocking the ui.
So, back to the server application, I would define the CoroutineContext that I want to use in the ProductController so I will be sure that the code after productRepository.getFirst() will be executed in the same context that I decided to be. It would look to something like this:
#Controller
class ProductController {
// other code
#GetMapping("/")
suspend fun getProduct(): ProductDTO = withContext(Dispatchers.Default) {
val product = productRepository.getFirst()
val productDTO = mapper.mapToDto(product)
return productDto
}
}
In this way I found way more easier mentally track the context in which the code is executed.
So my questions are:
Is it fine to use this Unconfined context?
Might this behavior be a problem when need to scale the application?
What is a good practice for this case?
If I wrote something wrong or my question is not clear let me know.

Related

Using Service methods inside Utils class [Spring and Kotlin]

I have faced a well-known scenarios whereby I really need to move a number of utilities private functions (that should not have been there in the first place) from my Service class to a utility class. My question is around using service methods in a utility class. I have attempted at the following refactoring:
class Utils(
val serviceIneed : ServiceIneed) {
companion object {
private val someMapper = ObjectMapperConfig.mapper
}
fun someUtility(): ResponseEntity<Any> {
// lots of stuff
return serviceIneed.someFunction()
}
}
Then this is the other service where I need to use the method I have moved to the newly created utility class:
class anotherService(
private val serviceIneed: ServiceIneed
) {
fun someMethod() {
// lots of things happening
val utilityUsage = Utils(serviceIneed).someUtility()
}
}
Is this the correct way to go about this? Can you recommend any approach on refactoring service classes in a way that only service-oriented methods and not helper ones remain in my Service class?
Thank you

Spring HATEOAS custom controller - enable converting URI to entity

This is an example of what I would like to achieve:
#RepositoryRestController
#RequestMapping("/users")
public class UserController {
#Autowired
private UserRepository userRepository;
#Autowired
private TaskRepository taskRepository;
#PostMapping("/addCompletedTask")
public void addCompletedTask(User user, Task task) {
user.getCompletedTasks().add(task);
task.incrementCompletedBy();
userRepository.save(user);
taskRepository.save(task);
}
}
Then I would make a request like this:
POST http://localhost:8080/api/users/addCompletedTask
{
"user": "http://localhost:8080/api/db/users/59fa19bfd58dcf25e82082b2",
"task": "http://localhost:8080/api/db/tasks/59fa19bfd58dcf22d2322312"
}
I tried to wrap arguments to the method with Resource<User>, add #RequestBody, nothing works, everything is null.
I don't know if it's possible, but I've seen examples of people writing code like this, so maybe I'm missing something (here for example). Or maybe is there some way to do that through the repository in one call? I can add a task in one call, and increment counter in another, but that requires two calls from the client. Also I'm pretty sure I will encounter another situation similiar to this, so if there is a solution that would be great.

Spring framework and java like Object collectors In Scala

In Spring framework and Java world, there is an interesting object collector pattern that I use.
For example consider below -
public interface Calculator {
SomeOutput calculate(SomeInput input);
}
#Component
public class CalImpl1 implements Calculator {
public SomeOutput calculate(SomeInput input){
//some implementation
}
}
#Component
public class CalImpl2 implements Calculator {
public SomeOutput calculate(SomeInput input){
//some implementation
}
}
Now this can easily injected in another class using Spring DI
#Component
public class Main {
//This line collects all to implementors of this and set it here.
#Autowired
public List<Calculator> calculators;
//other methods
}
Now problem is I am not sure how same thing can be achieved in scala. I have done some search and found cake pattern (http://loicdescotte.github.io/posts/scala-di/) used in scala but that didn't seem to achieve same thing as object collectors like above. I also want to follow open close principle which I think gets violated in cake pattern but using object collectors I can easily achieve it.
is there a way achieve same object collectors like implementation in scala?
There are templates in lighbend activator that illustration using spring DI on Play, Akka and Scala applications. Please see this: https://www.lightbend.com/activator/templates#filter:spring
I haven't used Spring as DI, I usually use Guice (explicitly used because it's default on play framework 2) and Implicits parameters both as a compilation DI.
Sample:
class B
class X(x: Int)(implicit c: B)
//DI - mostly define in main method/application
implicit val c: B = new B
val x = new X(2)
Explicitly using java.util.List worked for me. This is not the prettiest solution but it shows that it basically works. Haven't tried that but implementing a corresponding PropertyEditor you could stick with the Scala types.
trait Calculator {
def calculate(input: SomeInput) : SomeOutput
}
#Component
class CalImpl1 extends Calculator {
override def calculate(input: SomeInput): SomeOutput = ...
}
#Component
class CalImpl2 extends Calculator {
override def calculate(input: SomeInput): SomeOutput = ...
}
#Component
class Main #Autowired()(calculators: java.util.List[Calculator]) {
// or inject field if constructor injection is not desired
// #Autowired
// var calculators: java.util.List[Calculator] = _
}
object Main {
def main(args: Array[String]) = {
val ctx = new AnnotationConfigApplicationContext("your package name here")
val main = ctx.getBean(classOf[Main])
// calculators should now be wired in the returned instance
}
}

Spring cache #Cacheable method ignored when called from within the same class

I'm trying to call a #Cacheable method from within the same class:
#Cacheable(value = "defaultCache", key = "#id")
public Person findPerson(int id) {
return getSession().getPerson(id);
}
public List<Person> findPersons(int[] ids) {
List<Person> list = new ArrayList<Person>();
for (int id : ids) {
list.add(findPerson(id));
}
return list;
}
and hoping that the results from findPersons are cached as well, but the #Cacheable annotation is ignored, and findPerson method got executed everytime.
Am I doing something wrong here, or this is intended?
This is because of the way proxies are created for handling caching, transaction related functionality in Spring. This is a very good reference of how Spring handles it - Transactions, Caching and AOP: understanding proxy usage in Spring
In short, a self call bypasses the dynamic proxy and any cross cutting concern like caching, transaction etc which is part of the dynamic proxies logic is also bypassed.
The fix is to use AspectJ compile time or load time weaving.
Here is what I do for small projects with only marginal usage of method calls within the same class. In-code documentation is strongly advidsed, as it may look strage to colleagues. But its easy to test, simple, quick to achieve and spares me the full blown AspectJ instrumentation. However, for more heavy usage I'd advice the AspectJ solution.
#Service
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
class PersonDao {
private final PersonDao _personDao;
#Autowired
public PersonDao(PersonDao personDao) {
_personDao = personDao;
}
#Cacheable(value = "defaultCache", key = "#id")
public Person findPerson(int id) {
return getSession().getPerson(id);
}
public List<Person> findPersons(int[] ids) {
List<Person> list = new ArrayList<Person>();
for (int id : ids) {
list.add(_personDao.findPerson(id));
}
return list;
}
}
For anyone using the Grails Spring Cache plugin, a workaround is described in the documentation. I had this issue on a grails app, but unfortunately the accepted answer seems to be unusable for Grails. The solution is ugly, IMHO, but it works.
The example code demonstrates it well:
class ExampleService {
def grailsApplication
def nonCachedMethod() {
grailsApplication.mainContext.exampleService.cachedMethod()
}
#Cacheable('cachedMethodCache')
def cachedMethod() {
// do some expensive stuff
}
}
Simply replace exampleService.cachedMethod() with your own service and method.

How to Produce prototype objects from singleton? (Design help needed)

I'm relatively new to Spring and I've got myself dug in a hole. I'm trying to model motor cars. Each model has it's own builder object, and I have a BuilderFactory that returns the correct builder based upon user selection from a web-app.
So I'm looking for suggestions on how to approach this problem where I need to create a number of individual vehicles, but I don't know what type of vehicle I'm going to need until run-time, and each vehicle needs to be unique to the user.
What I've got at the moment is shown below. The problem I have at the moment is that because the individual builders are singletons so are the individual vehicles. I need them
to be prototypes. I know it all looks pretty horrible so I'm sure there must be a better way of doing this.
The top level from the web-app looks like;
Vehicle vehicle = vehicleBuilderFactory.getBuilder(platform).build();
My vehicleBuilderFactory looks like this;
#Service
public class VehicleBuilderFactory {
#Autowired
Discovery3Builder discovery3Builder;
#Autowired
Discovery4Builder discovery4Builder;
// Lots of #Autowired statements here.
#Autowired
FreeLander2010Builder freeLander2010Builder;
public VehicleBuilder getBuilder(Platform platform) {
switch (platform.getId()) {
case 1: return discovery3Builder;
case 2: return discovery4Builder;
// Lots of case statements here
case 44: return freeLander2010Builder;
default: return null;
}
}
}
which itself looks pretty horrible. Each individual builder looks like;
#Service
public class DefenderBuilder implements VehicleBuilder {
#Autowired
Defender defender;
// Loads of Defender specific setters ommitted
#Override
public Vehicle build() {
return defender;
}
}
and finally the individual vehicle
#Service
#Scope("prototype")
public class Defender extends Vehicle {
}
The main problem now, is that because the builders are singletons, so are the vehicles, and
I need them to be prototypes, because User A's Defender is different to user B's Defender.
You can use Spring's ObjectFactory to have it service up prototype scoped beans from a singleton scoped bean. The usage is pretty straightforward:
#Component
class DefenderBuilder implement VechicleBuilder {
#Autowired
ObjectFactory<Defender> defenderFactory;
Defender build() {
return defenderFactory.getObject()
}
}
#Component
#Scope("prototype")
class Defender {
}
This returns a new Defender on each call to defenderFactory.getObject()
Without reading too much into the detail you say you want to produce Prototype beans from a singleton possibly with a look up in the IoC container.
Section 3.4.6.1 Lookup method injection of the Spring documentation describes how this can be done without losing the Inversion of Control i.e. without your beans knowing about the bean store.
I have made use of the ServiceLocatorFactoryBean to solve a similar problem before. The class level Javadoc is excellent and contains some clear examples.
Two things:
1) You can use proxy in order to hold narrower scope from wider scope(e.g prototype from singleton)
All you need is to define the prototype component with the relevant scope and proxyMode
You can read about scoped proxy here.
2) Another thing that I have noticed is that you plan to use multiple autowired annotation.
note that you can use autowire on a list of interface and it will autowire all components that implements this interface as discussed here.
Moreover you can add a platform id to the VehicleBuilder interface and then generate a map in the constructor e.g:
Map<Integer, VehicleBuilder> vehicleBuilders;
#Autowired
public VehicleBuilderFactory(List<VehicleBuilder> vehicleBuilders) {
this.vehicleBuilders = vehicleBuilders.stream()
.collect(Collectors(x -> x.getPlatformId(), x -> x));
}
in that way you can avoid the switch case.

Resources