I don't quite know how to explain the situation, I will try to be as clear as possible.
I am currently writing a web-application, using Spring to manage the beans. Obviously, more than one people will use this application. Each user has a set of data related to himself. My problem comes with some poor design I introduced when I just entered the development field. Here is the case:
#Component
public class ServiceClass implements IService {
#Autowired
private Dependency firstDependency;
#Autowired
private UsefulObject secondDependency;
private DataSet dataSet; // THIS LINE IS IMPORTANT
public void entryPoint(String arg1, int arg2, Structure arg3) {
/* Query data from a database specific from the project (not SQL
oriented. I absolutely need this information to keep going. */
dataSet = gatherDataSet(String ar1);
/* Treat the data */
subMethodOne(arg1);
subMethodTwo(arg2);
subMethodThree(arg3);
}
private subMethodOne(String arg1) {
// Do some things with arg1, whatever
subSubMethod(arg1);
}
private subSubMethod(String arg1) {
/* Use the DataSet previously gathered */
dataSet.whateverDoing();
}
... // Functions calling sub-methods, using the DataSet;
As every user would have a different dataSet, I thought it would be good to call it at the beginning of every call to my service. In the same way, as is it used very deep in the call hierarchy, I thought it would be a good idea to store it as an attribute.
The problem I encounter is that, when two users are going through this service nearly simultaneously, I have a cross-data issue. The following happens:
First user comes in, calls gatherDataSet.
Second user comes in, calls gatherDataSet. First user is still treating !
First user still uses the dataSet object, which was overrid by Second user.
Basically, the data first user makes use of become false, because he uses data from the second user, which came in short after him.
My questions are the following:
Are there design pattern / methods to avoid this kind of behavior ?
Can you configure Spring so that he uses two instances fo two users (and so on), to avoid this kinf od problems ?
Bonus: (Kind of unrelated) How to implement a very large data mapper ?
Object member variables (fields) are stored on the heap along with the object. Therefore, if two threads call a method on the same object instance and this method updates object member variables, the method is not thread safe.
However, If a resource is created, used and disposed within the control of the same thread, and never escapes the control of this thread, the use of that resource is thread safe.
With this in mind, change your design. https://books.google.co.in/books?isbn=0132702258 is a must read book for coming up with good java based software design
More stackoverflow links: Why are local variables thread safe in Java , Instance methods and thread-safety of instance variables
Spring promotes singleton pattern and (it is the default bean scope). Spring configuration for having two service class objects for two different users is called prototype bean scoping, but should be avoided as far as possible.
Consider the usage of in-memory Map or an external no-sql datastore or an external relational database
Can you configure Spring so that he uses two instances fo two users (and so on), to avoid this kinf od problems ?
You already mentioned correctly, that the design decisions you took are flawed. But to answer your specific question, which should get your use-case to work correctly, but at a impact to performance cost:
You can set spring beans to various scopes (relevant for your usecase: prototype / request or session), which will modify when spring beans get instanced. The default behaviour is one bean per spring container (singleton), hence the concurrency issues. See https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch04s04.html
The easiest solution is simply to not store the dataset in a class field.
Instead, store the dataset in a local variable and pass it as an argument to other functions, this way there will not be any concurrency problems, as each call stack will have it's own instance.
Example:
public void entryPoint(String arg1, int arg2, Structure arg3) {
// Store the dataset in a local variable, avoiding concurrency problems
Dataset dataSet = gatherDataSet(String ar1);
// Treat the data passing dataset as an argument
subMethodOne(arg1, dataset);
subMethodTwo(arg2, dataset);
subMethodThree(arg3, dataset);
}
Use synchronized modifier for it.
As "Synchronization plays a key role in applications where multiple threads tend to share the same resources, especially if these resources must keep some kind of sensitive state where manipulations done by multiple threads at the same time could lead the resource to become in an inconsistent state."
public void someMethod() {
synchronized (object) {
// A thread that is executing this code section
// has acquired object intrinsic lock.
// Only a single thread may execute this
// code section at a given time.
}
}
Related
I'm translating an application based on REST using Spring Framework. Now I need to translate some responses based on the language of the request. For example:
/get-me-an-answer/?lang=es Spanish
/get-me-an-answer/?lang=en English
/get-me-an-answer/?lang=fr French
I have the variable language_code as a static variable in a class named Translang
class Translang {
...
public static String language_code = null;
...
}
The problem is with multithreading, when a new request come will change the language and if another previous request is executing can probably answer in the language modified and not in the original language it requested.
That's the reason of my question: How can I have a global variable in Spring per request to avoid this problem?
Seems that ThreadLocal is what you are looking for as per request is performed by a separate thread.
This class provides thread-local variables. These variables differ
from their normal counterparts in that each thread that accesses one
(via its get or set method) has its own, independently initialized
copy of the variable. ThreadLocal instances are typically private
static fields in classes that wish to associate state with a thread
(e.g., a user ID or Transaction ID).
I would suggest to implement a context that navigates throw the flow of your request, so with this, you will pass this context among the entire transaction, once you have that domain element, you need to create a new one by each request that you receive. Currently your class is not thread safe, this can be fixed also changing the scope of your bean.
I found several resources to help me with this issue, but I can't seem to mix all the ingredients in order to suit my needs.
I want to "lock" a Cat (or even several) from being petted by other users, if a petting of it (or them) is already in progress. I also want to provide a feedback to the caller, telling him who called the API before him.
#Local
#Singleton // or #Stateful?
public class CatPetterBean_Local implements CatBean_Facade
{
/**
* Key - The ID of the Cat
*/
final private ConcurrentHashMap<Integer, User> pettingState = new ConcurrentHashMap<>();
#TransactionAttribute(TransactionAttributeType.REQUIRED)
#Override
public GzipROWithMsg<Object> pet(final ImmutableSet<Integer> catIds)
{
checkIfTheyAreBeingPetted_AndThrowRuntimeExec(catIds);
<...>
// After petting, they will be saved by the caller bean (e.g. CatPetterBeanImpl)
}
<...>
}
Petting takes a while
Cats retain a state in the DB: ALREADY_PETTED and NOT_PETTED. Once it is already pat, it cannot be petted again. I even thought of loading the Cat from the DB and checking its state on-the-fly, but I think it's more network traffic that way.
How can I take advantage of notions like synchronized keywords, #Lock annotations
No, I am not using Spring
No, This isn't a webapp
Yes, I do lack EE knowledge. I'm asking this question in a process of fast learning.
EJB Singletons have under the hood a locking mechanism, by default, all bean methods are serialized via write locks.
The default concurrency model on EJB Singletons is: #ConcurrencyManagement(ConcurrencyManagementType.CONTAINER), this is the default, no need to annotate the singleton with this. When Container Concurrency Management is in play as I said before every method is write locked. If you want finer control over singleton methods you can annotate them with #Lock(LockType.READ) which means that the method can be accessed concurrently while no one holds a write lock on the bean, or #Lock(LockType.WRITE) giving exclusive access to the current thread.
Alternatively, you can use Bean concurrency management. In this case, you should annotate your singleton class with: #ConcurrencyManagement(ConcurrencyManagementType.BEAN).
In this case, you use synchronized and other Java concurrency goodies. For most of my needs Container Managed concurrency was more than enough.
Another remark to the above code fragment is that #Local doesn't seem appropriate, my guess is that CatBean_Facade should be annotated with #Local.
I'm back to building my Managed-Bean of a hashMap. ( Creating a HashMap of type <String , Object> ) I have defined a class
public class AppProperties {
private String appRepID;
private String helpRepID;
private String ruleRepID;
private String filePath;
private Vector formNames;
private Database appDB;
// all the getters and setters
}
The managed bean will create an Application Scope variable of the hashMap. In the constructor of the Bean I build the the values for each Application (the key) by collecting all the info from a number of different places. The repIDs are pretty straight forward. My question/concern is it wise to store the appBD in the Application Scope variable. I have read that one should never store a Notes Object in a Scoped Variable would that be an issue here? Secondly, if that is the case I could add a method to the AppProperties that would open the DatabaseByReplicaID when ever the method to get the Application Database is called, which adds a fair bit of overhead to the process as the database object will get called many many time in the life cycle of the application.
Right, you shouldn't store Notes objects in scope variables and properties of beans.
Because They are not serializable (a must for certain scopes) and they will be recycled between lifecycles. More precisely, since they are based on C-handles, XSP engine creates Notes objects between request-response cycle and when response written back to the user, they are all going to be recycled. Trying to keep them in the memory will make them 'toxic' for your server.
You can define a method in your bean (like GetHelpDb()), create and return it whenever you need. It's not a huge performance cost. Because Domino server implements caching for databases. When you open a database over and over again will not generate additional disk I/O.
The best practice for interacting with Notes data in such situation would be caching. I frequently use this approach in my applications. You might get values in a single method, cache them into HashMap(s) and get them from the map when you need. Using getter method, you may also check a time-based value to handle time-outs.
In this link: http://code.google.com/p/ehcache-spring-annotations/wiki/UsingCacheable
they say:
When the above POJO is defined as a bean in a Spring IoC container, the bean instance can be made 'cacheable' by adding merely one line of XML configuration.
Without using a caching framework, I would just declare Weather and List as static and that would have taken care of caching.
So my question is that if I want to just have the Weather and List<Location> to be cached, then why would I cache the entire DAO?
Also behind the scenes, does the annotation #Cacheable turn Weather and List<Location> into static variables?
This is the code in question:
public interface WeatherDao {
public Weather getWeather(String zipCode);
public List<Location> findLocations(String locationSearch);
}
public class DefaultWeatherDao implements WeatherDao {
#Cacheable(cacheName="weatherCache")
public Weather getWeather(String zipCode) {
//Some Code
}
#Cacheable(cacheName="locationSearchCache")
public List<Location> findLocations(String locationSearch) {
//Some Code
}
}
I don't quite understand your points about static variables. In essence there is a map from zipCode to Weather and similar from locationSearch to List<Location>. This map can come from a database, file, external API, etc.
Do you want to create a map with all possible arguments as keys and corresponding values? Sure, you can, but it has several drawbacks:
you put a lot of pressure on your heap. In many cases the amount of data might never fit into memory, or even on your disk (think: caching Google search engine by storing every possible search query and list of hits)
most likely you won't use most of the keys, ever. Why store them in memory?
what about eviction? I bet these methods tend to return different weather for the same ZIP code over the time...
Since I don't fully understand your arguments, let me explain briefly what happens behind the scenes when getWeather() is called:
transparent proxy intercepts getWeather() call and looks up weatherCache
in that cache it uses zipCode argument as cache key
if such entry exists (of type Weather) it is returned immediately
if the above is not the case, control is delegated to the real getWeather() method. It can call some API, run database query or do some lengthy computations
the result of getWeather() is placed in the weatherCache for future reference.
No static is involved here.
BTW Spring 3.1 introduced caching abstraction layer that probably makes this Google Code project obsolete. It looks the same and allows seamless integration with different cache implementations.
I am asking very generic question and the answer can vary from requirement to requirement, but for "general" or "rule of thumb", can we say the following is a good design rule:
The classes to be cached (static/reference data) should be designed as
immutable, with exceptions reasoned.
What could be design/performance issues with the above statement, if this is not true?
#JohnB has a good answer about the underlying data.
If, however, the question is referring to the immutability of the cached classes themselves (which are holding the data in the cache), then the answer is that mutable classes can cause thread-safety issues if the instances of the classes are referenced by multiple threads (as can often happen with data shared via a cache). Additionally, "accidental" modification of the data may occur, where a shared instance is unintentionally modified (because the modifying code did not know that the data was shared).
This is because of what a cache does, which is hold data rather than retrieving it from the data source again. For example, you query the database for a value then put it in a memory-based cache so you don't have to query the DB again. However, if the value in the DB can change then the value in the cache will be out of date and your application will be using the wrong data.
Therefore, caching is best if the data cannot change during the live of the application. If the data can change, then a strategy must be developed to regularly check to see if the data has changed.
What jtahlborn is explaining in other words : an immutable class will provide methods to obtain "static" data.
If your class is immutable, you will NOT have setters except the parameters in the constructor.
Take care making this : immutable classes are not made to be used only once, it would result in a performance loss, since copies of inner attributes have to be done each time you access the get... methods.
Example :
class MyImmutableThing {
private final String myProperty;
MyImmutableThing(String myProperty) {
this.myProperty = myProperty;
}
String obtainMyProperty() {
return myProperty;
}
// note there is no mean to modify the myProperty value : the original value remains ;)
// That's it !
}