Spring Service instance variable in a multi-threaded environment - java

I recently ran into a race condition issue because of declaring an instance variable inside a default scoped (Singleton scope) Service class. The purpose of the instance variable was to make my code more readable and avoid the constant passing of the same variable to different private methods within the Service class. The example goes:
#Service
public class SomeServiceImpl implements SomeService {
private final StatusRepository statusRepository;
private Predicate<Status> statusPredicate;
#Autowired
public SomeServiceImpl(StatusRepository statusRepository) {
this.statusRepository = statusRepository;
}
#Override
public List<Status> getAllowedStatuses(String userId) {
statuses = statusRepository.getAll();
initPredicate();
appendPredicateA();
appendPredicateB();
List<Status> results = statuses.stream()
.filter(statusPredicate)
.collect(Collectors.toList());
return results;
}
private void initPredicate() {
statusPredicate = p -> p.getDefault().equals("default");
}
private void appendPredicateA() {
statusPredicate.and(p -> p.getA().equals("A"));
}
private void appendPredicateB() {
statusPredicate.and(p -> p.getB().equals("B"));
}
}
This is a very simple example of the kind of things I want to achieve. This is clearly not thread-safe because now the service class is stateful. I could simply resolve this by turning the statusPredicate variable into a local variable and have the void methods return the predicate after it has been appended new conditions, but that would become cluttered like this:
#Override
public List<Status> getAllowedStatuses(String userId) {
statuses = statusRepository.getAll();
Predicate<Status> statusPredicate = p -> p.getDefault().equals("default");
statusPredicate = appendPredicateA(statusPredicate);
statusPredicate = appendPredicateB(statusPredicate);
List<Status> results = statuses.stream()
.filter(statusPredicate)
.collect(Collectors.toList());
return results;
}
It'd be constantly calling to modify the variable and return the variable.
I know a few solutions that can resolve this such as adding #RequestScope on the Service class to ensure each request from the HTTP will get a new instance of the
Service object, or use ThreadLocal on the Predicate variable. However, I'm not quite certain what is the best approach and whether declaring an instance variable in a Service class is even okay to begin with. If it is bad to make Service class stateful to begin with, how should I structure my code to make it cleaner and still keeping it stateless?
Please advise! Thanks in advance :D

Spring Service can be stateful and this is why scopes for.
Default scope of Spring Service is Singleton because this is the widest use case. But you shouldn't use mutable local variables.
Simply, try for a stateless design and use scopes to solve the issue only if the class instantiation is fast otherwise TreadLocal will perform better.

Related

What are the tricks to make lazy initialization thread safe and efficiency considering the costs of sychronized keyword?

After reading the lazy initialization of expensive resources in the book around Page 106-108 - functional programming in Java by Venkat Subramaniam, it is found hard to understand the tricks with this code snippet
my understandings:
variable heavy in class Holder is of type Supplier<Heavy>
vs
local class HeavyFactory inside the method createAndCacheHeavy is a sub class extends Supplier
It seems only run once to execute that lambda method and then alter the outer member variable of class Holder.heavy
I am confused about below code the heavy is then later assigned with new reference pointing to the sub class extends Supplier
please if anyone could share hints the tricks here to gain the advantages of author proposed to save performance penalty from synchronized keyword and also taking care of thread safety. It also mentioned virtual proxy pattern. Did I miss out any key info to understand it?
package fpij;
import java.util.function.Supplier;
public class Holder {
//only run once here? before heavy get reassigned to HeavyFactory, the local class to that lambda method?
private Supplier<Heavy> heavy = () -> createAndCacheHeavy();
public Holder() {
System.out.println("Holder created");
}
public Heavy getHeavy() {
//the 2nd time it will call always the HeavyFactory.heavyInstance?
return heavy.get();
}
private synchronized Heavy createAndCacheHeavy() {
//create a local class inside method? Is the real trick/hack here I missed out so it will avoid 2nd time the synchronized penalty?
class HeavyFactory implements Supplier<Heavy> {
private final Heavy heavyInstance = new Heavy();
public Heavy get() { return heavyInstance; }
}
if(!HeavyFactory.class.isInstance(heavy)) {
heavy = new HeavyFactory();
}
return heavy.get();
}
public static void main(final String[] args) {
final Holder holder = new Holder();
System.out.println("deferring heavy creation...");
System.out.println(holder.getHeavy());
System.out.println(holder.getHeavy());
}
}
package fpij;
public class Heavy {
public Heavy() { System.out.println("Heavy created"); }
public String toString() { return "quite heavy"; }
}
If you are really concerned on the cost of synchronized, there a simple way to make it work correctly while keeping the initialization lazy.
It use the property that the classloader ensure synchronization when the class is loaded. It garentee that no other thread will be able to access the class until it is fully loaded. And the class load is actually lazy: it load the class only when the class is actually used from the first time.
If the only feature of class HeavyFactory is to provide the singleton instance, it will be loaded only when the getInstance is called and all will play nicely.
class HeavyFactory {
private static final Heavy heavyInstance = initInstance();
public static Heavy getHeavyInstance() {
return heavyInstance;
}
private static Heavy initInstance() {
heavyInstance = new HeavyInstance();
[...] // Other init stuff
return heavyInstance;
}
}
Edit: The init of complex objects and wiring of dependencies is so common that frameworks like JEE or Spring have implemented ways to do simplify it.
If you use spring for example, you would be able to just declare a given service as a singleton and then declare a dependency on it where you need it. The init would be done when the spring framework initialize in proper order:
// We instruct spring to create a shared instance of heavy
// with #Component annotation
// The instance would be created eagerly at the start of the app.
#Component
public class Heavy {
public Heavy() { System.out.println("Heavy created"); }
public String toString() { return "quite heavy"; }
}
// For the example another service using the Heavy shared instance
#Component
public class ClientDependingOnHeavy {
// We ask spring to fill it automatically the shared instance for us.
#Autowired
private Heavy heavy;
public String foo() {
//So we can use the instance like any object.
System.out.println(heavy.toString());
}
}
Well spring or JEE are quite complex advanced frameworks. For a single case they would not be worth it at all. For a whole application it would make sense. You'd need quite some reading/tutorials to make the second example work if you don't already know them. But in the long run, it may be worth the effort.

Can we have a factory class as spring bean and have a factory method returning multiple spring beans based on the condition?

I want to return multiple spring beans based on the condition in the factory class.
Is this a good practice?
Any better ways to write the following piece of code?.
Any other design patterns suitable here?
Below is the code snippet:
package com.test;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
#Component
public class InstanceFactory {
#Resource(name = "instance1")
private Instance instance1;
#Resource(name = "instance2")
private Instance instance2;
public Instance getService(Condition condition) {
if (condition.one() && condition.two()) {
return instance2;
} else {
return instance1;
}
}
}
It depends on what you want to achieve. Factory Pattern is meant to create objects but what you are returning are objects already create somewhere else (Spring in this case). If you want to create beans that will be managed by Spring there are several ways:
#Conditional(YourConditionImplementation.class): This annotation added on a method of a #Configuration annotated class will allow you to create a bean when the given condition is fullfilled. Example here: https://javapapers.com/spring/spring-conditional-annotation/
You can uses as well BeanFactory to inject the definition of your bean (DefinitionBean) into the container. Example here: https://www.logicbig.com/tutorials/spring-framework/spring-core/bean-definition.html
Now, if you want an object that determine what object of type Instance fits better for some need then your approach is ok, but it is not technically a factory :)
When designing something like that I would face that solution considering two design patterns:
Strategy pattern: In order to replace repetitive if else every time you need to evaluate more instances.
Decorator pattern: Trying to make every condition as configurable as possible. They can be composed (decorated) for one or more predicates.
Considering these two pattens you might achieve something like this:
First, define which conditions will identify a given instance:
public enum InstanceType {
INSTANCE_TYPE_1(Condition::isOne, Condition::isTwo),
INSTANCE_TYPE_2(Condition::isOne, Condition::isThree),
...;
private List<Predicate<Condition>> evaluators;
#SafeVarargs
InstanceType(final Predicate<Condition>... evaluators) {
this.evaluators = Arrays.asList(evaluators);
}
public boolean evaluate(final Condition condition) {
return evaluators.stream().allMatch(it -> it.test(condition));
}
}
Then, you should link every instance implementation to an specific instance type:
#Component
public class InstanceOne implements Instance {
#Override
public InstanceType getType() {
return InstanceType.INSTANCE_TYPE_1;
}
}
Finally, a class to config where defining the relation between types and instances as EnumMap
#Configuration
public class InstanceFactoryConfig {
#Autowired
private List<Instance> instances;
#Bean
public EnumMap<InstanceType, Instance> instancesMap() {
EnumMap<InstanceType, Instance> instanceEnumMap = new EnumMap<>(InstanceType.class);
instances.forEach(i -> instanceEnumMap.put(i.getType(), i));
return instanceEnumMap;
}
}
Thus, you InstanceFactory can be replaced to something like this:
public class InstanceFactory {
#Autowire
private final EnumMap<InstanceType, Instance> instancesMap;
public void getInstance(Condition condition) {
instancesMap.get(getInstanceType(condition)).doSomething();
}
private InstanceType getInstanceType(Condition condition) {
return Arrays.stream(InstancesType.values())
.filter(evaluator -> evaluator.evaluate(condition))
.findFirst().orElseThrow(() -> new RuntimeException("Instance type not found"));
}
}
As you can see, you InstanceFactory is less prone to be modified. This means, every time you need you add a new instance implementation you only need to modify the InstanceType enum. Hope this is helps.
You can use spring existing FactoryBean interface and implement your own logic
It’s one of the best approaches to create beans in spring framework
Here is the link with example :
https://www.baeldung.com/spring-factorybean
See:
Spring Profile
The active profile is set by properties and based on the value you assign to the profile, Spring will load different beans for the same interface.
So it might be exactly what you need.

Dynamic dependency injection for multiple implementations of the same interface with Spring MVC

I am working on a REST API where I have an interface that defines a list of methods which are implemented by 4 different classes, with the possibility of adding many more in the future.
When I receive an HTTP request from the client there is some information included in the URL which will determine which implementation needs to be used.
Within my controller, I would like to have the end-point method contain a switch statement that checks the URL path variable and then uses the appropriate implementation.
I know that I can define and inject the concrete implementations into the controller and then insert which one I would like to use in each particular case in the switch statement, but this doesn't seem very elegant or scalable for 2 reasons:
I now have to instantiate all of the services, even though I only need to use one.
The code seems like it could be much leaner since I am literally calling the same method that is defined in the interface with the same parameters and while in the example it is not really an issue, but in the case that the list of implementations grows ... so does the number of cases and redundant code.
Is there a better solution to solve this type of situation? I am using SpringBoot 2 and JDK 10, ideally, I'd like to implement the most modern solution.
My Current Approach
#RequestMapping(Requests.MY_BASE_API_URL)
public class MyController {
//== FIELDS ==
private final ConcreteServiceImpl1 concreteService1;
private final ConcreteServiceImpl2 concreteService2;
private final ConcreteServiceImpl3 concreteService3;
//== CONSTRUCTORS ==
#Autowired
public MyController(ConcreteServiceImpl1 concreteService1, ConcreteServiceImpl2 concreteService2,
ConcreteServiceImpl3 concreteService3){
this.concreteService1 = concreteService1;
this.concreteService2 = concreteService2;
this.concreteService3 = concreteService3;
}
//== REQUEST MAPPINGS ==
#GetMapping(Requests.SPECIFIC_REQUEST)
public ResponseEntity<?> handleSpecificRequest(#PathVariable String source,
#RequestParam String start,
#RequestParam String end){
source = source.toLowerCase();
if(MyConstants.SOURCES.contains(source)){
switch(source){
case("value1"):
concreteService1.doSomething(start, end);
break;
case("value2"):
concreteService2.doSomething(start, end);
break;
case("value3"):
concreteService3.doSomething(start, end);
break;
}
}else{
//An invalid source path variable was recieved
}
//Return something after additional processing
return null;
}
}
In Spring you can get all implementations of an interface (say T) by injecting a List<T> or a Map<String, T> field. In the second case the names of the beans will become the keys of the map. You could consider this if there are a lot of possible implementations or if they change often. Thanks to it you could add or remove an implementation without changing the controller.
Both injecting a List or a Map have some benefits and drawbacks in this case. If you inject a List you would probably need to add some method to map the name and the implementation. Something like :
interface MyInterface() {
(...)
String name()
}
This way you could transform it to a Map<String, MyInterface>, for example using Streams API. While this would be more explicit, it would polute your interface a bit (why should it be aware that there are multiple implementations?).
When using the Map you should probably name the beans explicitly or even introduce an annotation to follow the principle of least astonishment. If you are naming the beans by using the class name or the method name of the configuration class you could break the app by renaming those (and in effect changing the url), which is usually a safe operation to do.
A simplistic implementation in Spring Boot could look like this:
#SpringBootApplication
public class DynamicDependencyInjectionForMultipleImplementationsApplication {
public static void main(String[] args) {
SpringApplication.run(DynamicDependencyInjectionForMultipleImplementationsApplication.class, args);
}
interface MyInterface {
Object getStuff();
}
class Implementation1 implements MyInterface {
#Override public Object getStuff() {
return "foo";
}
}
class Implementation2 implements MyInterface {
#Override public Object getStuff() {
return "bar";
}
}
#Configuration
class Config {
#Bean("getFoo")
Implementation1 implementation1() {
return new Implementation1();
}
#Bean("getBar")
Implementation2 implementation2() {
return new Implementation2();
}
}
#RestController
class Controller {
private final Map<String, MyInterface> implementations;
Controller(Map<String, MyInterface> implementations) {
this.implementations = implementations;
}
#GetMapping("/run/{beanName}")
Object runSelectedImplementation(#PathVariable String beanName) {
return Optional.ofNullable(implementations.get(beanName))
.orElseThrow(UnknownImplementation::new)
.getStuff();
}
#ResponseStatus(BAD_REQUEST)
class UnknownImplementation extends RuntimeException {
}
}
}
It passes the following tests:
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class DynamicDependencyInjectionForMultipleImplementationsApplicationTests {
#Autowired
private MockMvc mockMvc;
#Test
public void shouldCallImplementation1() throws Exception {
mockMvc.perform(get("/run/getFoo"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("foo")));
}
#Test
public void shouldCallImplementation2() throws Exception {
mockMvc.perform(get("/run/getBar"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("bar")));
}
#Test
public void shouldRejectUnknownImplementations() throws Exception {
mockMvc.perform(get("/run/getSomethingElse"))
.andExpect(status().isBadRequest());
}
}
Regarding two of your doubts :
1. Instantiating the service object should not be an issue as this is one time job and controller gonna need them to serve all type of request.
2. You can use the exact Path mapping to get rid of switch case. For e.g. :
#GetMapping("/specificRequest/value1")
#GetMapping("/specificRequest/value2")
#GetMapping("/specificRequest/value3")
All of the above mapping will be on separate method which would deal with specific source value and invoke respective service method.
Hope this will help to make code more cleaner and elegant.
There is one more option of separating this on service layer and having only one endpoint to serve all types of source but as you said there is different implementation for each source value then it says that source is nothing but a resource for your application and having separate URI/separate method makes the perfect sense here. Few advantages that I see here with this are :
Makes it easy to write the test cases.
Scaling the same without impacting any other source/service.
Your code dealing the each source as separate entity from other sources.
The above approach should be fine when you have limited source values. If you have no control over source value then we need further redesign here by making source value differentiate by one more value like sourceType etc. and then having separate controller for each group type of source.

Spring 4 #Service with #RequestScope

In order to optimize sql request, I've made a service that aggregate other services consumptions to avoid unecessary calls.
(Some pages of my webapp are called millions times by day, so I want to reuse the results of database queries as many times as possible on each request)
The solution I create is this one :
My service has #RequestScope instead of default scope (Singleton)
In MyService
#Service
#RequestScope
public MyService {
private int param;
#Autowired
private OtherService otherService;
#Autowired
private OtherService2 otherService2;
private List<Elements> elements;
private List<OtherElements> otherElements;
public void init(int param) {
this.param = param;
}
public List<Elements> getElements() {
if(this.elements == null) {
//Init elements
this.elements = otherService.getElements(param);
}
return this.elements;
}
public List<OtherElements> getOtherElements() {
if(this.otherElements == null) {
//Init otherElements
this.otherElements = otherService2.getOtherElements(param);
}
return this.otherElements;
}
public String getMainTextPres() {
//Need to use lElements;
List<Elements> elts = this.getElements();
....
return myString;
}
public String getSecondTextPres() {
//Need to use lElements;
List<Elements> elts = this.getElements();
//Also Need to use lElements;
List<OtherElements> otherElts = this.getOtherElements();
....
return myString;
}
}
In my controller :
public class myController {
#Autowired MyService myService;
#RequestMapping...
public ModelAndView myFunction(int param) {
myService.init(param);
String mainTextPres = myService.getMainTextPres();
String secondTextPres = myService.getSecondTextPres();
}
#OtherRequestMapping...
public ModelAndView myFunction(int param) {
myService.init(param);
String secondTextPres = myService.getSecondTextPres();
}
}
Of course, I've simplified my example, because myService use lots of other elements, and i protect the initialization of his members attributes
This method has the advantage of doing lazy loading of the attributes only when I need them.
If somewhere in my project (in same or other controller) I only need the SecondTextPres, then calling "getSecondTextPres" will initialize both lists which is not the case in my example beacuse the first list has been initialized when "getMainTextPres" was called.
My question are :
What do you think of this way of doing things ?
May I have performance issues because I instantiate my service on each request ?
Thanks a lot !
Julien
I think that your idea is not going to fly. I you call the same or different controller this is will be different request - in that case new bean will be created (elements and other elements are empty again).
Have you been thinking about caching? Spring has nice support where you can define cache expiration, etc
It's not quite clear to me what exactly you want to optimise instantiating Service in request scope? If you are bothered about memory foot print, you could easily measure it by JMX or VisualVM.
On the other hand, you could make all Service calls pure, i.e. depending on function parameters and (ofc) database state only and instantiate the Service with default scope as Singleton.
This decision will save you reasonable amount of resources as you will not instantiate possible large object graph on each call and will not require GC to clean the thing after Request is done.
The rule of thumb is to think why exactly you need the specific Class instantiated on every call and if it doesn't keep any state specific to call, make it Singleton.
Speaking about lazy loading, it always helps to think about worst case repeated like 100 times. Will it really save you something comparing to be loaded once and for the whole Container lifetime.

Dependency Injection Java Design Pattern Singleton

I have some serious problems to understand, how to work with Dependency Injection and especially the singleton design pattern in a multithreaded environment.
Lets say i have a class:
public class DependencyOne {
private DependencyTwo dependencyTwo;
private DependencyThree dependencyThree;
private Integer aNumber;
public Foo(Integer aNumber, DependencyTwo dependencyTwo, DependencyThree dependencyThree) {
this.aNumber = aNumber;
this.dependencyTwo = dependencyTwo;
this.dependencyThree = dependencyThree;
}
public doSomething() {
dependencyTwo.doSomethingInDepOne(aNumber, dependencyThree);
}
}
public class DependencyTwo {
private DependencyThree dependencyThree;
private aNumber;
public Foo(Integer aNumber,DependencyThree dependencyThree) {
this.aNumber = aNumber;
this.dependencyThree = dependencyThree;
}
public doSomething() {
dependencyThree.doSomethingInDepOne(aNumber);
}
}
public class Main {
public static void main(String[] args) {
DependencyOne depTwo = new DependencyTwo("foo", "foofooo" .... <- just random config);
DependencyOne depThree = new DependencyThree(1,2,3,4,5,12,3,1235 <- just random config);
DependencyOne depOne = new DependencyOne(123, depTwo, depThree);
depOne.doSomething();
}
}
Now lets imagine, DependencyThree needs to be a singleton for various reasons, e.g. a JPA EntityManagerFactory, Centralized Logging or whatever at a global level, not per thread.
Injector injector = Guice.createInjector(new DependencyThree());
A injector as far as i understand should only be created once.
Now my question, what is the best way to provide access to one instance of the DependencyThree Class.
**
I don't want pass the dependencythree object through all other
classes, to get access of it.
**
At the moment i've just created a global singleton, which returns the instance, when i ask for one.
But some people say, that this is very bad design, (is it?).
How do i use dependency injection, on this setup, or shouldn't i use it at all ? This code is just raped a bit, it usually runs in a multithreaded environment.
Guice provides an #Singleton annotation, but this is per thread and not multihreaded.
How do i implement a global singleton in Guice, which is lazy created ?
#Singleton in Guice means that once an instance of the target class is created, that very same instance is returned for all subsequent injection requests. The injector itself is thread safe and thus can be safely shared among threads.
Now, when does injection happens? Injection happens when you ask Guice to get an instance instead of using the new operator yourself.
You only have to ensure that there are no circular dependencies and that lifetimes of injected objects are clearly defined in such a way that #Singleton instances are created before depending classes and are possibly destryed after. By the way, there's nothing wrong with the singleton concept itself: sometimes you simply have a physical resource that can't be represented by more than on instance. It's the singleton pattern with Java static and lazy loading that it's often criticized because it's somewhat non-trivial to implement and there are safer alternatives (like a dependency injection framework)

Categories

Resources