I'm creating a small game where I would like to have a game room and a bunch of games in the game room. This would be a spring boot application. So I was thinking of starting the GameRoom at the start of the application. Then whenever a new game is created, I will add it to the list of games in the game roon. Is is a good idea? Or are there any potential pitfalls.
public class GameRoon{
private static GameRoom instance = null;
List<Game> games = new ArrayList();
private GameRoom() {}
public static GameRoom getIsntance() {
if(instance == null) {
instance = new GameRoom();
}
return instance;
}
}
The above is my unfinished singleton.. I have 2 questions.
1. Is it a good idea to start this during spring-boot start up?
2. Is it better to use singleton like this in spring-boot or is there a better way to do it
Singletons are highly debated and you will always find reasons for using it and for not.
In my opinion if your class responsibility is to hold a state (think of a registry with some data) which is shared within the application I don't see any problem. It is clear that you share the data and must be sure to govern concurrent access.
The main drawback of Singleton is testing: you have a global state but ideally during unit testing you want to test some code without relying on the singleton class (instead a mock). You can still solve this thanks to Spring: define the GameRoom as Spring bean (default scope is Singleton) which is injected like any other bean. This allows to mock it during unit testing, even if underneath there is a singleton behavior.
Related
I am wondering what is the current best practice as to the use of factory pattern within the context of Spring framework in using dependency injection. My wonder arises about whether the factory pattern is still relevant nowadays in light of the use of Spring dependency injection. I did some searching and see some past discussion (Dependency Injection vs Factory Pattern) but seem there is different view.
I see in some real life project in using a Map to hold all the beans and rely on autowiring to create those beans. When the bean is needed, it get it via the map using the key.
public abstract class Service {
//some methods
}
#Component
public class serviceA extends Service {
//implementation
}
#Component
public class serviceB extends Service {
//implementation
}
Map<String, Service> services;
But I see there is some difference among the two approaches.
Using the above method, all beans are created on application start up and the creation of object is handled by the framework. It also implies there is only one bean for each type.
While for factory pattern, the factory class creates the object on request. And it can create a new object for each request.
I think a deeper question may be, when Spring framework is used in a project, should it be strived to not create any object inside a class, which means the factory pattern ( or any creational design patterns?) should not be used, as Spring is supposed to be the central handler of the objects dependency ?
The answer to this question can be really deep and broad, I'll try to provide some points that hopefully will help.
First off, spring stores its beans (singletons) in the ApplicationContext. Essentially this is the map you're talking about. In a nutshell, it allows getting the bean by name, type, etc.
ApplicationContext, while being a really important concept, is not the whole Spring, in fact Spring framework allows much more flexibility:
You say, using a map implies that all the beans will be created at the beginning of the application and there is one instance of the bean.
Spring has a concept of Lazy beans, basically supporting a concept of beans being actually created only when they're required for the first time, so Spring supports the "delayed" beans initialization
Spring also allows more than one instance of a bean per type. So this map is more "advanced". For example you can create more than one implementation of the interface and use declare both as beans. As long as you provide enough information about what bean should be injected to the class that might use them (for example with a help of qualifiers suppored in spring), you're good to go. In addition, there are features in spring IoC container that allow injecting all registered implementations of an interface into a list:
interface Foo {}
#Component
class FooImpl1 implements Foo {}
#Component
class FooImpl2 implements Foo {}
class Client {
#Autowired
List<Foo> allFoos;
}
Now you say:
While for factory pattern, the factory class creates the object on request. And it can create a new object for each request.
Actually Spring can create objects per request. Not all beans have to be singletons, in general spring has a concept of scopes for this purposes.
For example, scope prototype means that Spring will create a bean upon each usage. In particular one interesting usage that spring supports in variety of ways is Injecting prototype bean into singleton. Some solutions use exactly like a factory (read about annotation #Lookup others rely on auto-generated proxy in runtime (like javax.inject.Provider). Prototype scope beans are not held in the application context, so here again spring goes beyond a simple map abstraction.
Last feature that you haven't mentioned is that sometimes even for singletons the initialization can be a little bit more complicated then calling a constructor with Parameters. Spring can address that by using Java Configurations:
#Configuration
public class MyConfig {
public SomeComplicatedObject foo(#Value("...") config, Bar bar) {
SomeComplicatedObject obj = new SomeComplicatedObject() // lets pretend this object is from some thirdparty, it only has no-op constructor, and you can't place spring annotations on it (basically you can't change it):
obj.setConfig(config);
obj.setBar(bar);
return obj;
}
}
The method foo here initializes the object SomeComplicatedObject and returns it. This can be used instead of factories to integrate "legacy" code (well, java configurations go way beyond this, but its out of scope for this question).
So bottom line, you Spring as an IoC container can provide many different ways to deal with object creation, in particular it can do everything that factory design pattern offers.
Now, I would like to also refer to your last sentense:
I think a deeper question may be, when Spring framework is used in a project, should it be strived to not create any object inside a class, which means the factory pattern ( or any creational design patterns?) should not be used, as Spring is supposed to be the central handler of the objects dependency ?
Indeed you don't have to use Factory Pattern when using Spring, since (as I hopefully have convinced you) provides everything that factory can do and more.
Also I agree that spring is supposed to be the central handler of the objects dependency (unless there are also parts of the application which are written in a different manner so you have to support both :) )
I don't think we should avoid using "new" altogether, not everything should/can be a bean, but I do see (from my subjective experience, so this is arguable) that you use it much less leaving the creation of most of the objects to Spring.
Should we avoid a usage of any creation design pattern? I don't think so, sometimes you can opt for implementing "builder" design pattern for example, its also a creational pattern but spring doesn't provide a similar abstraction.
I think if your project uses Spring framework you should use it. Although it depends on your project design e.g. You may use creational patterns along side with Spring IoC. e.g when you have abstraction layers not framework dependant (agnostic code)
interface ServiceFactory {
Service create(String type);
}
#Component
class SpringServiceFactory implements ServiceFactory {
#Autowired private ApplicationContext context;
Service create(String type) {
return context.getBean(type)
}
}
I use Factory pattern as well when I refactor legacy not unit testable code which also uses Spring Framework in order to implement unit tests.
// legacy service impossible to mock
class LegacyApiClient implements Closeable {...}
#Component
class LegacyApiClientFactory {
LegacyApiClient create(String endpoint) {
return new LegacyApiClient(endpoint);
}
}
#Component
class OtherService {
private final String endpoint
private final LegacyApiClientFactory factory;
OtherService(#Value("${post.endpoint}") String endpoint,
LegacyApiClientFactory factory) {...}
void doCall {
try (LegacyApiClient client = factory.create(endpoint)) {
client.postSomething();
}
}
}
....
// a random unit test
LegacyApiClient client = mock(LegacyApiClient.class)
LegacyApiClientFactory factory = mock(LegacyApiClientFactory.class)
OtherService service = new OtherService("http://scxsc", factory);
when(factory.create(any())).thenReturn(client)
service.doCall()
....
I've learned a lot recently about Spring and one thing i think i might be misunderstanding is the #Autowired annotation, especially when using it in constructors. You see, the app i'm developing is a service so basically EVERYTHING is initialized within a constructor. The only actual user-driven events that happen are buttons that restart certain modules of the service. This is my main method :
ConfigurableApplicationContext ctx = new SpringApplicationBuilder(MDHIS_Service.class)
.headless(false).web(false).run(args);
java.awt.EventQueue.invokeLater(() ->
{
MDHIS_Service frame = ctx.getBean(MDHIS_Service.class);
frame.setSize(1024, 768);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
This is the constructor of my main class, where basically everything happens. I have omitted the calls to the methods initializing each module to shorten it :
#Autowired
public MDHIS_Service(GlobalParamService globalParamService, LogEntryService logentryService, InterfaceService interfaceService,
ConnectionService connectionService, OutboundMessageService outboundMessageService, OutboundMessageHistoryService outboundMessageHistoryService,
InboundMessageService inboundMessageService, FacilityService facilityService, ModuleStatusService moduleStatusService,
SequenceService sequenceService)
{
this.globalParamService = globalParamService;
this.logEntryService = logentryService;
this.interfaceService = interfaceService;
this.connectionService = connectionService;
this.outboundMessageService = outboundMessageService;
this.outboundMessageHistoryService = outboundMessageHistoryService;
this.inboundMessageService = inboundMessageService;
this.facilityService = facilityService;
this.moduleStatusService = moduleStatusService;
this.sequenceService = sequenceService;
}
My main class has a private final global variable for each service. Each module is a separate thread and i'm finding myself having to pass those variables to the constructor of each module which in term stores them into it own private final variables. The way i'm doing things right now #Autowired is pretty much useless since i'm having to pass the instance around. Is there a way to better use #Autowired? This service is used as the backend for a large web app and i find myself making much better use of the annotation in there. I did a lot of research on this topic and i did try the #PostContruct annotation but all i ever got was null services.
Any help would be appreciated.
Thanks!
I figured out my problem, and it was a pretty dumb one. First off, i had not annotated my main class with #Component so Spring never bothered to inject the dependencies in it. Secondly, I did not realize that a method annotated with #PostContruct would run by itself after the constructor runs WITHOUT NEEDING TO EXPLICITELY BE CALLED!
I moved all my initialization code to an init method annotated with #PostConstruct and annotated my main class with #Component, everything is working now!
You typicall don't have to use a constructor + #Autorwired, you can directly use autowired on fields and spring would fill the dependencies for you:
#Component
public class MDHIS_Service {
#Autowired
private GlobalParamService globalParamService;
}
What is important to understand is that for spring to work, you must let it create the objects for you, and not calling the constructors explicitely. It would then fill the dependencies as needed. This is done by declaring the service as a component (for example with the #Component annotation) and never create the service yourself but getting them from dependency injection.
The first object you start with has to have been created by spring and returned by the application context.
What you gain in exchange is that you don't have to forwared everything explicitely. A sub-sub-sub service quite distant from the root of the application can depend on anything it has visibility without you having to forward the reference all the way.
I would advise to take a look a the spring reference documentation, it quite detailled and complete:
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#spring-core
Edit: I'll try to clarify a bit with an example... What do the init code of the various service actually does ?
Maybe it set the dependencies. Then just autowire them:
#Component
MySubService {
#Autowired MySubSubService mySubSubService;
}
Maybe it does some more thing than setting fields so you can add on top an init method that do it and this init method can eventually call the other services.
#Component
MySubService {
#Autowired MySubSubService mySubSubService;
#PostConstruct
public void init() {
//Init code that may use mySubSubService.
}
}
You don't have to declare a constructor and forward dependencies yourself, sprint does it for you.
The only case where you'd have problem is if finally you need some parameters that are not dependency to the init method. But even in that case you could do it from you main code. That's actually what you did with the main service calling the various setters rather than messing with the constructor to set theses values.
I like to add Spring to my Scala projects for educational purposes. But I do not understand the advantage of Spring Scala to decouple components.
I have created a simple configuration:
import org.springframework.scala.context.function.FunctionalConfiguration
class Configuration extends FunctionalConfiguration {
bean() {
new Service()
}
}
and a simple service:
class Service {
def method = "Bonjour tout le monde!"
}
and then an application which uses both:
import org.springframework.scala.context.function.FunctionalConfigApplicationContext
object Application extends App {
implicit val context = FunctionalConfigApplicationContext(classOf[Configuration])
val service = context.getBean(classOf[Service])
println(service.method)
}
This is just my interpretation and implementation of the Spring Scala examples.
My application still has knowledge of the Service class. I could just write:
val service = new Service() // instead of asking for a Bean which has classname Service
println(service.method)
with the same effect.
Am I missing something?
This does decouple your use of the Service from the instantiation of it. E.g. if in the future Service changes to depend on some other InnerService, or has some initialization that can't be done in the constructor for some reason but needs to happen in a method call before it's used (.connectToDatabase() or some such), or if you wanted to replace the Service with a mock one for testing, then you can do this without changing these two lines of code:
val service = context.getBean(classOf[Service])
println(service.method)
If you program to an interface rather than implementation, e.g.
trait IService {
def method: String
}
class Service extends IService...
val service = context.getBean(classOf[IService])
then you also make it easy to swap out the Service for a different implementation, though given the extra lines of code I probably wouldn't bother doing this until I actually had more than one implementation.
I'm not sure that Spring carries its own weight (it's a very large and complex library), particularly in Scala with its more concise constructor syntax. But whether you use Spring or not, it's worth separating the construction of your dependencies and "wiring up" of your application from their actual use. IMO a class Foo that uses Service should accept it, explicitly via its constructor, class Foo(service: Service), and leave the construction/initialization of Service to a class/or function dedicated to that.
I am reading the 《Spring in Action》, and it says "singleton beans in Spring often don't maintain state because they're usually shared among multiple threads", but in my opinion, a bean in Spring is a POJO, so how can it not maintain state?
I am reading the 《Spring in Action》, and it says "singleton beans in
Spring often don't maintain state because they're usually shared among
multiple threads", but in my opinion, a bean in Spring is a POJO, so
how can it not maintain state?
Yes, it's better for a Spring/Singleton to not have a state (of course it can uses other Spring/Singletons [also them without a state]) so you can call its methods from different threads without worring about they could messed up its state (it doesn't have one :-)).
Let's think about a calculator that stores its intermediate results inside an internal stack, what can happen if two threads try to calculate something at the same time?
A Spring/Singleton is annotated (and if it's not it's just like it would be) and lives inside the spring context , it's not a POJO.
If you want to have a Spring/Bean with a state you have to use the scope "prototype", with this kind of scope every time you get a bean you will get a difference instance.
Sorry for the bad english
The book is implying that the state of a bean may not be trustworthy at a given point in time due to manipulation of its state by another thread. If multiple threads are accessing the same instance of a bean you cannot be sure of what state changes have occurred on the bean prior to using it. Since Spring uses Singletons by default there is only one instance of a bean. If multiple threads hit the bean at the same time there could be issues with the state of the bean.
So your correct that the beans will maintain state, however the state may be unreliable due to modifications from other threads.
In a typical web application, you have multiple threads (one per request) and all the requests are using the same beans. In a typical layered application, they will uses a Controller which uses then a Service which uses then a Repository. All of these beans should be singletons without any state. Otherwise you will have bugs due to concurrency (e.g. one thread modifies data in a singleton while another thread do the same).
I think that your misunderstanding comes from saying that bean in Spring are POJO. Most of Spring beans are stateless beans which I would not describe as POJO.
A Spring bean is considered a POJO in the sense that it does not need to adhere to special requirements (implement certain interfaces, extend particular class, be specific in some way, etc.) to be used with Spring.
Depending on the requirements a Spring bean might need to maintain, and operate on, its state.
It also depends on the requirements to consider if the Spring bean should be a singleton or not.
If a singleton Spring bean is maintaining its own state, proper safeguards must be taken to ensure correct concurrent access/modification.
Confusion comes from a general pattern used in enterprise applications where Spring beans are used to implement bulk of the system logic, and support operations.
In these scenarios, generally its a good practice to not have any state in the Spring bean itself, and just be an extension of the Value Object/Data Transfer Object that contain actual state.
Since these Spring beans are not going to maintain their own state, they are almost always created as singletons.
SomeClass, SomeOtherClass and Situation are all POJO in below code.
SomeClass and SomeOtherClass are Spring beans but Situation is not, which is a DTO.
class SomeClass {
private int x; // not restricted
public void handleSituation(Situation s) {
// may or may not use/modify SomeClass state represented by 'x'
// one approach is to provide all required information through parameters
}
}
class SomeOtherClass {
#Autowired
private SomeClass sc;
public void process() {
// gets called from another object
Situation z = new Situation();
sc.handleSituation(z);
// other processing
}
}
<!-- default scope = singleton -->
<bean id="someClassBean" class="SomeClass"/>
<bean id="someOtherClassBean" class="SomeOtherClass">
<property name="someClass" ref="someClassBean"/>
</bean>
This is a slight variation from pure OOP in which above would be coded similar to following.
class SomeOtherClass {
public void process() {
// gets called from another object
Situation z = new Situation();
z.handle();
// other processing
}
}
I have a number of Grails Services that are singleton Spring beans, not prototypes.
Is there any way to retrieve a prototype instance (fully injected with any dependencies) of what is normally a singleton bean?
I'd like this for testing purposes so that I can mess with the prototype instance (potentially changing it's metaClass to mock things out) without the risk of forgetting to clean up after any changes I make to the instance and having them leak into other tests.
I've been playing around with this a little bit and haven't had any luck. I've tried doing something like this:
def ctx = grailsApplication.mainContext
ctx.registerPrototype("foo", MyService)
I'm then able to ask Spring for an instance of MyService
def myServicePrototype = ctx.getBean("foo")
and it does give a new instance every time, but none of the instances have had their properties autowired up so they're all null. I'm guessing theres some way to create a BeanDefinition and feed it to the BeanFactory with some of the autowire stuff that I must be missing turned on.
I'm hoping to come up with some generic solution that doesn't force me to explicitly annotate the target services in any way.
Is there any way to directly ask the Spring applicationContext for a prototype version of what's normally a singleton?
Figured out how to do it using the Grails BeanBuilder to create a temporary ApplicationContext that has the main app context as a parent. This won't work if any unusual wiring/spring configuration has been done to the service, but that's not normally the case with Grails services, so seems like a good default pattern:
// this works in the grails console where grailsApplication is in the binding,
// need to inject in other situations
import org.springframework.context.ApplicationContext
import grails.spring.BeanBuilder
import com.example.service.MyService
def getPrototypeInstanceOf(Class clazz) {
BeanBuilder beanBuilder = new BeanBuilder(grailsApplication.mainContext)
String beanName = "prototype${clazz.name}"
beanBuilder.beans {
"$beanName"(clazz) { bean ->
bean.autowire = 'byName'
}
}
ApplicationContext applicationContext = beanBuilder.createApplicationContext()
return applicationContext.getBean(beanName)
}
def prototypeService = getPrototypeInstanceOf(MyService)
def singletonService = grailsApplication.mainContext.getBean("myService")
assert singletonService != prototypeService
assert singletonService.injectedService == prototypeService.injectedService
If it is only for testing purposes and there are no conflicting dependencies (e.g. some beans that must only be singltons), then you can just create your Spring context twice.
EDIT: Another aproach could be that you define a factory interface for your singleton service and provide 2 implementations of that factory interface: 1 for singleton only and second for having multiple instances depending on your testing situation.