Create a single instance of HashMap in Java throughout the session - java

I am working on a project wherein I need to store a set of keys and values throughout the session of the program execution. Meaning when the server is up, I want to have a map which stores data and is same for multiple requests made in that session.
So for creating this map, should I make a static Map or create a singleton bean for it and use autowiring? Which is better?
I used the static map, but noticed that even after stopping the server and running it again, the map instance was having values from previous session, instead it should have been null in the beginning of the request. The objects were not getting destroyed properly.
Does this behavior is improved if I'll use beans?

You have to define what is a Session.
Usually, in a Web project, a Session is related to an HTTP Session. These are managed in Spring by #Scope(value = WebApplicationContext.SCOPE_SESSION). The Bean will have a proxy, managing the instances of your Service automatically.
In this case, you do not want to use a Static Map. Indeed, a static object is global to your program, and only one instance will exist at any time, like a Singleton.
If you define a Session as the start and end of your server process, then fine.
So for creating this map, should I make a static Map or create a singleton bean for it and use autowiring?
This is close to the same thing. The only difference is how it will be instantiated. A static Map will be created by the JVM as soon as your Class is loaded. A Singleton Bean will be created by Spring at the first use.
The main advantage of the Bean, in your case, is the Inversion of Control for your Unit Tests.
I used the static map, but noticed that even after stopping the server and running it again, the map instance was having values from previous session
Usually, an object will lose its data when the server is closed, unless your Map has been Serialized by the server and stored in a session file on the disk. Maybe you should try to move your static Map to its own Class.
Does this behavior is improved if I'll use beans?
No, the behavior will be the same.
Don't forget that, as a singleton, your Map must be synchronized with Collections.synchronizedMap(). Otherwise, you will have surprises when using it.

Related

SpringBoot Single Page Application Concurrency

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.

Is there a way to store java variable/object in application context without xml or properties file

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.

Xpages: managedBean is constantly "losing" global Domino Session object

I'm in the process of building a managedBean for an Xpages application. Currently the bean is registered in faces-config at view scope because I need it to re-initialize on every page load (see below). The bean's constructor initializes several class variables whose values are referenced all over the entire class's code. One of those variables is a Domino session object, another example is the current document datasource:
private Session session;
private DominoDocument ds;
Both are initialized within the constructor as
session=DominoUtils.getCurrentSession();
ds=(DominoDocument) resolveVariable(dsName);
(resolveVariable is an internal helper method; don't think I need to explain that here)
Apart from the constructor and the various helper methods there are also some other public methods within the same class that are called on button clicks. Most of those additional methods make use of the same document datasource, as well as the current session object.
What's happening is that my additional methods can access and use the global datasource object (ds) but if they try to access the global session object an error is thrown; further down the stack trace I find what seems to cause the error:
NotesException: Object has been removed or recycled
There's no recycling at all in my code right now, the session object must get lost somewhere on the way.
As a workaround I started passing the session object from SSJS into each method as in
public void testMethod(Session s){
System.out.println("my name is " + s.getEffectiveUserName());
}
Which is working fine. But why is it that the bean object keeps forgetting the global session while it can remember all the other objects and variables?
BTW: I tried to bind my managedBean to a session scope but that doesn't help at all. And yes, I even restarted the entire server after making that change...
All Domino objects coming from the runtime are recycled at the end of every request. If you want to access any of them, you should re-fetch them from the environment when they're needed and not store references within your mean (you could use transient refs, but you wouldn't gain much). So the quick fix is to replace each use of the session in your class with that DominoUtils.getCurrentSession() call.

Can I define a non final static field in ejb 3.1 singleton

According to EJB specs, non final static fields are not allowed. Is this still the case for an EJB 3.1 stateless session bean defined as singleton?
Just to make things clearer and to prevent question like why you want to do it:
I have a situation where I need an EJB to start working on server start-up ,do some DB related work and only when it is done it will signal all other components in the system that they can start their work.
This EJB will also be defined with timer, so it will start every few minutes and thus, if it failed the first time it will try again until it succeeds, or until someone notices there is a problem. Once succeeded, the flag will be changed and all other components (timer EJB's) can kick in.
So I have a Singleton EJB and I need it to hold a static (global) flag that all other components/EJBs can refer to.
Non-final static fields are still prohibited as you'll run into problems as soon as you try to cluster your application. EJB singletons are only singletons on the server instance they are running on. If you have two server instances you could have two versions of the singleton with different values in your static field.
If you need a global flag, better to store it in the database.
Note that a class is one-to-many with a singleton EJB definition. In other words:
<session>
<ejb-name>TestA</ejb-name>
<ejb-class>org.example.SingletonBean</ejb-class>
</session>
<session>
<ejb-name>TestB</ejb-name>
<ejb-class>org.example.SingletonBean</ejb-class>
</session>
In this example, there will be multiple instances of the SingletonBean class, one for the TestA EJB and another for the TestB EJB. Given this use case and the propensity for the EJB programming model to try to protect the programmer (for better or worse), it seems reasonable to keep the restriction on static fields.
Given that the container is managing the single instance of the singleton EJB, you might as well store your global state as an instance variable in the singleton anyway. Inject the singleton into your other beans, and they can all access the shared state through member variables. That's the point of singleton EJBs anyway.

Singleton Object Created for each Request

I want to create a singleton object whose scope is basically only the request. This will be used to collect the errors and we need to send error whenever we send the response back.
Can anyone provide pointers toward this thing?
I am also using spring.
I tried using Spring container singleton object scope session or request but still my object is holding values from the earlier request
I am using this error object with AspectJ. Will that may cause problem on static binding?
how about
//sync this code
if(request.getAttribute("someKey") == null){
// create object and set it
}
If you set the Object life cycle in the Spring container to be per request then it should only exist for that HttpRequest.
Generally for direct injection containers like Spring when you set the object life cycle or object scope to be per request then it should create an new instance of the object for each http request that it recieves.
If it is not doing this then I would assume that it is more than likely something to do with your configuration.
Singleton is the defualt for the spring container when creating beans I think so you have to specifically set the object scope to per request.
Bean Scopes
http://static.springsource.org/spring/docs/2.5.x/reference/beans.html
I'm not sure that singleton is what you want here - if two requests arrived concurrently they would share the singleton object, and their errors will get mixed up.
Is it possible to create an object to hold the errors and put that in to a ThreadLocal object. The scope of the object will be constrained by the request, and access to it in the ThreadLocal object is easily achieved from within your application without having to pass a refernce to the object around.
You can use ThreadLocal.

Categories