I have following problem. I have a Vaadin/Spring application. All the business logic and data come from a different system and my application is using REST service clients for accessing these data. I have a lot of components, where I need these service clients.
I have a singleton class (kind of helper), that can provide beans from the Spring context. I would like to have my service client beans in this context, too, and just call getBean(beanId) on my helper class in my components. However, they should be first initialized after the user logs into the application (or even better, when they are first accessed). I don't want to create objects of my service clients in each component I need them and I also don't want to pass those objects through component constructors or methods.
Could someone point me the right directions???
The default Spring configuration is for Eager Initialization - i.e. singletons are initialized as the ApplicationContext is started, by defining the spring beans with Lazy Initialization. That way way, they should only be initialized when requested.
Related
I have copied a sample Spring Boot SPA. I want to understand, what happens if multiple people use the web page via the URL. Does Java create an instance of the web application per call? Memory resources are not shared, right, i.e. if there is a list object appended to, each user sees their own list?
The default scope for a spring-boot bean is a singleton. Assuming your bean is not managing state you should be fine with the default behavior:
https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch04s04.html
4.4.1 The singleton scope
When a bean is a singleton, only one shared instance of the bean will be managed, and all requests for beans with
an id or ids matching that bean definition will result in that one
specific bean instance being returned by the Spring container.
To put it another way, when you define a bean definition and it is
scoped as a singleton, then the Spring IoC container will create
exactly one instance of the object defined by that bean definition.
This single instance will be stored in a cache of such singleton
beans, and all subsequent requests and references for that named bean
will result in the cached object being returned.
Now if you are using a bean that's stateful and want a new bean used per request, you can define the scope of that bean to be prototype:
4.4.2 The prototype scope
The non-singleton, prototype scope of bean deployment results in the creation of a new bean instance every time a
request for that specific bean is made (that is, it is injected into
another bean or it is requested via a programmatic getBean() method
call on the container). As a rule of thumb, you should use the
prototype scope for all beans that are stateful, while the singleton
scope should be used for stateless beans.
Spring resources like #Service and #Repository and #RestController are stateless singletons. Only a single instance is created to serve the application.
Your implementation of the list at scope level will determine whether or not it is shared. If you define the List in the Controller, as in your example, then every user will have access to the same list. You can use multiple browsers to see that the list is shared. Based on the example, this is fine, as getting "all" should really mean getting all.
If you wanted each user to have their own list, you would have to implement some sort of Session or back-end process to associate each individual user with their own list.
This isn't shared-nothing like PHP or Rails. Java is so slow starting up that firing up a new instance of the application for every request isn't an option.
Check out the spring-boot sample application source code, there's a main method on the SpringbootJQueryAjaxClientApplication class, like this:
public static void main(String[] args) {
SpringApplication.run(SpringBootJQueryAjaxClientApplication.class, args);
}
this is the main method like for any Java program, what happens here is it starts the self-hosted servlet container and installs the application into it, then waits for http requests.
It is one process, where every request is served by a thread, so memory is shared. Spring components like com.javasampleapproach.jqueryajax.controller.RestWebController (scoped as singleton by default) are instantiated once in the web application, and every request calls methods on the same instance.
I want to store a particular variable (String or Object) in application context in spring boot application. But I don't want to use an xml or properties file for storing it.
There will be a function which will store the data in application context. I should be able to retrieve it, modify it, delete it or add more data.
Basically I want to store data in application context after its initialization has been done.
If you create a class and put #Configuration annotation over it, and declare some beans with #Bean annotation, they become application managed beans.
#Configuration
public class ConfigurationClass {
#Bean("myString")
public String getString() {
return "Hello World";
}
}
Then anywhere from your code you can call AnnotationConfigWebApplicationContext.getBean("myString") to get your bean.
Now there could be concurrency issues (as mentioned by davidxxx ). For that you can use SimpleThreadScope. Look at this link to learn how to register it with application context and where to place that annotation (or google it).
Or if you don't want to deal with that, then a #Scope("request") should help. The bean with #Scope("request") would be created for every new incoming request thus it’s thread safety is guaranteed since it’s created every time a new request comes in.
As a general way, you should avoid creating stateful services.
Storing application data in the server memory makes it harder to be resilient, autonomous but also distributed and scalable.
Besides, Spring Beans are not designed to be stateful.
If you do it, you may have race conditions without the required synchronization.
About your need, if you want really to have a stateful service at startup, create your own singleton instance and synchronize the methods that should be thread safe.
Then access it from anywhere.
Maybe I'm not using the right terminology and that's why i can't find an answer, but I want to know how can I take information from a database to create beans that I can inject into the application?
Here's an example, rather than having this coded in a configuration file, I would like to possibly loop some values stored in a database and build these beans based on that:
#Bean
public CronTriggerFactoryBean cronTriggerFactoryBean() {
CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
factory.setJobDetail(jobDetailFactoryBean().getObject());
factory.setStartDelay(3000);
factory.setCronExpression("0 0/2 * 1/1 * ? *");
return factory;
}
How can I build beans like this and have them become a part of the application?
There are probably multiple ways how to achieve that, but all of them are pretty complex with a lots of pitfalls. I would say that in your example you should not create triggers as separate beans but rather have a single service to manage your schedules (and leave it out of Spring).
The thing with Spring is, that it is not designed to act as a dynamic container (like OSGi for example). This means that for example #Autowired dependencies are initialized during context startup and stays the same till the application context is destroyed.
However it is possible to construct bean definitions on the fly during initialization. Best place would be BeanFactoryPostProcessor. But this would be called during context initialization. This means you will have no other beans available (like EntityManager, DataSource, ...).
Another possibility is to somehow take advantage of context hierarchy. You can create and destroy application contexts on-the-fly. However implementing that would require deeper knowledge of Spring's internals.
Question for others: not sure if it is possible to reference initialized beans from parent context during child context initialization.
After you load the necessary bean properties from Database , use BeanDefinitionBuilder. You can refer this link
I am using Guice in a project. Since it is the first time, I am wondering about how to keep and pass around state, i.e. objects that contain some user input or long lived objects that are needed elsewhere (not where they were injected the first time).
For instance, my application has a Server which the user can start and stop. Furthermore, the user can enter some data which leads to state that needs to be preserved in memory.
At the moment I see two possibilities:
have a Context class with scope #Singleton and some references to other classes that keep my state and offer me certain functionality.
The Context class would give me access to the Server instance, to user data, other services etc.
The instances of the Context may be injected by Guice.
Thus, if I want to stop my server, I would require the Context as a dependency (and not the server).
This goes a bit against the recommendation on the Guice website (inject direct dependencies instead of accessing the "real" dependency with chained getters).
annotate all classes with #Singleton that should exist only once and are injected in several other classes. As a consequence, I would have only a singleton server, somewhere a class with the user data, etc.
The singleton pattern (GoF) is said to be bad design. Thus, I am wondering whether I should minimize the use of #Singleton or whether this is a different story using Guice respectively dependency injection in general.
Are there any other possibilities or a better approach?
I think most of your questions is related to Dependency Injection Paradigm. first of all Using DI doesn't mean every managed bean should be Singleton. The managed beans have their own life cycle. they can be instantiated on every access / request / session or being singleton.
The other thing you should be care about is with DI we usually wire-up our main application design. you should think of your domain objects and their relations instead of DI(Guice/Spring).
for instance in your case if you need a Service Object in a bean so you have the relationship between these two classes and no need to to have a relation to Context!
if data inserted by different users are visible to all users so make the service singleton in your application. if the states of Server bean for each user are different so make the scope of bean Session to allow every user have his own Server bean.
I am new to CDI. While reading, I am always encountering contextual objects, non contextual objects. What does they mean?
For example the below link
http://docs.jboss.org/weld/reference/latest/en-US/html/beanscdi.html#d0e881
Message-driven and entity beans are by nature non-contextual objects
and may not be injected into other objects
The context of a CDI framework is basically a big map of objects*. You can add objects to the context or make the CDI framework create objects from your service classes by using any CDI configuration method (spring xml beans/annotations like #Component/#Service).
Once you have the context you can get objects from it: (Spring: getBean(name))
Now you can configure dependencies between the objects/beans in the context, and the CDI will make sure any object you get from the context will have its dependencies set. This is the dependency injection part.
Non-contextual objects are simply not added to the context and the CDI framework does not know about them. Usually only service classes are part of the CDI context.
* Not really a map though, objects can be accessed by name, by type and other ways. The default is you get the same object each time you ask by the same name (singleton), although you may configure the CDI to create a new object each time you ask (prototype).
A context in CDI is some span during execution of your program when contextual objects can be used.
It defines when CDI container creates, destroys and how it links instances of those objects together.
Non-contextual objects are those that are not tied to any CDI context.
MDBs are one example, they are managed by EJB container and not intended to be used as ordinary objects.
Entities come and go as you interact with a DB via JPA, so they also cannot be tied to a context.
Another example is any object whose instances you create manually.