Given: simple JSF webapp (no Seam), having JSF beans calling few EJB's which in turn load and persist JPA entities. What I want to is to use #Singleton annotation for ejb's and inject EntityManager instead of EntityManagerFactory:
#Singleton
public class MyEJB {
#PersistenceContext(unitName = PERSISTENCE_UNIT_NAME)
protected EntityManager em; // not EntityManagerFactory
}
Spec says that #Singleton is thread-safe, supports concurrency and transaction attributes which (from my pov) makes it safe for calling from JSF beans. I expect also performance benefits because of EntityManager not being recreated for each call and it's internal caching abilities.
My main concern here is create/update operations on JPA entities in the situation when I have several singletons and, as a result, the same count of long-living EntityManagers.
What happens if one singleton updates an JPA instance and how these
changes are populated to other singletons?
As I'm not able to close entity manager, do I need to flush it upon
each entity update?
Would it be better if these few singletons will share the same entity
manager?
I saw only few examples of such design. Why? Are there any serious
drawbacks?
Many thanks in advance!
I expect also performance benefits because of EntityManager not being recreated for each call and it's internal caching abilities.
You might save some memory using singletons, but using it everywhere in your app could make it actually slower, because as there's only one EJB to serve all the concurrent requests by various users of your app, the container locks access to the EJB and when it's busy serving a request it cannot be serving another request. However this can be alleviated to some degree using lock types (i.e. #Lock(WRITE) and #Lock(READ)).
Singletons are useful for times when you want to execute a piece of code periodically using EJB timers, or to update a cache periodically, etc.
What happens if one singleton updates an JPA instance and how these changes are populated to other singletons?
Shouldn't be any different to the way non-singleton EJBs behave.
As I'm not able to close entity manager, do I need to flush it upon each entity update?
If you use CMT, no. At the end of each transaction everything will be flushed automatically.
Would it be better if these few singletons will share the same entity manager?
Looks like premature optimization to me. Just let the container inject the EM for you.
I saw only few examples of such design. Why? Are there any serious drawbacks?
Already explained.
There is one thing I want to mention regarding changing LockType of Singleton EJBs. While in general it sounds like a good idea, you should remember that resources such as EntityManger are NOT thread-safe, so appropriate concurrent access control should be provided. You can annotate methods that access non-thread-safe resources with #Lock(WRITE), but if almost all interface methods of your Singleton EJB access such resources, you will have almost the same situation as with fully write locked one. Alternative is to use Bean Concurrency Management with manual fine-grained synchronization, but it's also questionable decision.
Because of this in general I prefer Stateless EJBs over Singleton and use latter in specific cases.
Related
I read a lot of documents and articles about DBcontext in Efcore and its lifetime, however, I have some questions.
Based on this link "https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/" the best lifetime of DBcontext and default lifetime of AddDbContext is scope, but there is a contradiction in the two below sentences on this document.
"DbContext is not thread-safe. Do not share contexts between
threads. Make sure to await all async calls before continuing to use
the context instance."
on the other hand, it was mentioned too,
"Dbcontext is safe from concurrent access issues in most
ASP.NET Core applications because there is only one thread executing
each client request at a given time, and because each request gets
a separate dependency injection scope (and therefore a separate
DbContext instance)."
I was confused about whether registering DBcontext as a scoped service is thread-safe or not?
What are the problems of registering DBcontext as a singleton service in detail?
In addition, I read some docs that prohibit registering singleton DbContext, however, AddDbContextPool makes to register singleton DBcontext.
so there are some questions about the Dbcontextpool.
what are the impacts of using the DbContextPool instead of the DbContext?
when we should use it and what should be considered when we use contextPool?
DbContextPool is thread-safe?
Has it memory issues because of storing a number of dbset instances throughout the application's lifetime?
change-tracking or any parts of the ef would be failed or not in the DB context pool?
One DbContext per web request... why?
.NET Entity Framework and transactions
I understand why you think the language in the Microsoft documents is confusing. I'll unravel it for you:
"DbContext is not thread-safe." This statement means that it's not safe to access a DbContext from multiple threads in parallel. The stack overflow answers you already referenced, explain this.
"Do not share contexts between threads." This statement is confusing, because asynchronous (async/await) operations have the tendency to run across multiple threads, although never in parallel. A simpler statement would be: "do not share contexts between web requests," because a single web request typically runs a single unit of work and although it might run its code asynchronously, it typically doesn't run its code in parallel.
"Dbcontext is safe from concurrent access issues in most ASP.NET Core applications": This text is a bit misleading, because it might make the reader believe that DbContext instances are thread-safe, but they aren't. What the writers mean to say here is that, with the default configuration (i.e. using AddDbContext<T>(), ASP.NET Core ensures that each request gets its own DbContext instance, making it, therefore, "safe from concurrent access" by default.
1 I was confused about whether registering DBcontext as a scoped service is thread-safe or not?
DbContext instances are by themselves not thread-safe, which is why you should register them as Scoped, because that would prevent them from being accessed from multiple requests, which would make their use thread-safe.
2 What are the problems of registering DBcontext as a singleton service in detail?
This is already described in detail in this answer, which you already referenced. I think that answer goes into a lot of detail, which I won't repeat here.
In addition, I read some docs that prohibit registering singleton DbContext, however, AddDbContextPool makes to register singleton DBcontext. so there are some questions about the Dbcontextpool.
The DbContext pooling feature is very different from registering DbContext as singleton, because:
The pooling mechanism ensures that parallel requests get their own DbContext instance.
Therefore, multiple DbContext instances exist with pooling, while only a single instance for the whole application exists when using the Singleton lifestyle.
Using the singleton lifestyle, therefore, ensures that one single instance is reused, which causes the myriad of problems laid out (again) here.
The pooling mechanism ensures that, when a DI scope ends, the DbContext is 'cleaned' and brought back to the pool, so it can be reused by a new request.
what are the impacts of using the DbContextPool instead of the DbContext?
More information about this is given in this document.
when we should use it and what should be considered when we use contextPool?
When your application requires the performance benefits that it brings. This is something you might want to benchmark before deciding to add it.
DbContextPool is thread-safe?
Yes, in the same way as registering a DbContext as Scoped is thread-safe; in case you accidentally hold on to a DbContext instance inside an object that is reused accross requests, this guarantee is broken. You have to take good care of Scoped objects to prevent them from becoming Captive Dependencies.
Has it memory issues because of storing a number of dbset instances throughout the application's lifetime?
The memory penalty will hardly ever be noticable. The so-called first-level cache is cleared for every DbContext that is brought back to the pool after a request ends. This is to prevent the DbContext from becoming stale and to prevent memory issues.
change-tracking or any parts of the ef would be failed or not in the DB context pool?
No, it doesn't. For the most part, making your DbContext pooled is something that only requires infrastructural changes (changes to the application's startup path) and is for the most part transparent to the rest of your application. But again, make sure to read this to familiar yourself with the consequences of using DbContext pooling.
Is there a difference using a singleton class and an application scoped managed bean to hold application data?
I need to lookup certain JNDI ressources such as remote bean interfaces and therefore I wrote myself a singleton to cache my references and only allow single references. (ServiceLocator)
I opened my website in two different browsers and that singleton got only initialized once. So I assume its application scope?
Any other benefits of a application scope managed bean then being able to access its properties in jsf?
Singletons are not unit testable nor abstractable nor extendable. Singletons are also unnecessarily complex to reliably create and maintain if your sole purpose is to have application scoped data (at least, if you really want a fullworthy singleton for it for some reason -most starters don't even exactly understand what a singleton is supposed to be).
"Just create one" like an application scoped managed bean is much simpler to develop, test and maintain. JSF as framework will guarantee that only one instance will be created and reused during web application's lifetime.
See also:
Singleton vs Just Create one
How to choose the right bean scope?
In a Message-Driven Bean am I restricted to the same rules of Session Beans (EJB3 or EJB3.1), i.e:
use the java.lang.reflect Java Reflection API to access information unavailable by way of the security rules of the Java runtime environment
read or write nonfinal static fields
use this to refer to the instance in a method parameter or result
access packages (and classes) that are otherwise made unavailable by the rules of Java programming language
define a class in a package
use the java.awt package to create a user interface
create or modify class loaders and security managers
redirect input, output, and error streams
obtain security policy information for a code source
access or modify the security configuration objects
create or manage threads
use thread synchronization primitives to synchronize access with other enterprise bean instances
stop the Java virtual machine
load a native library
listen on, accept connections on, or multicast from a network socket
change socket factories in java.net.Socket or java.net.ServerSocket, or change the stream handler factory of java.net.URL.
directly read or write a file descriptor
create, modify, or delete files in the filesystem
use the subclass and object substitution features of the Java serialization protocol
It is always a good idea not to create threads manually (ExecutorService seems fine in some cases though).
Actually MDBs are very often used to address this limitation: instead of creating a separate thread, send some task object (put something like MyJob extends Serializable in ObjectMessage) into the queue and let it be executed in MDB thread pool. This approach is much more heavyweight but scales very well and you don't have to manage any threads manually. In this scenario JMS is just a fancy way of running jobs asynchronously.
These EJB restrictions are typically not hard restrictions. In fact, they're not caveats on making your EJBs work properly, they're more like advisories on how to make your EJBs portable across EJB containers.
From time to time, some very fussy EJB container providers (cough.... WebSphere... cough) will actually enforce these restrictions through java security policies, but I would say about half of those restrictions are routinely ignored ( I mean just using log4j in your MDB potentially violates about 30% of them).
Violating the the other 70% probably indicates some architectural or design problem.
So, can you call System.exit() in an MDB ? The answer is yes, but only once... :)
It sounds like, in your case, you need some of these restrictions to reign in potentially misbehaving plugins. I don't know if MDBs are going to get you out of that problem. I suppose it depends on how much you trust the third party developers, but rather than use the invocation based models in EJB, I would install the components as JMX ModelMBeans. You can use the java security model to limit what they can do, but I suppose that would defeat the purpose.
Perhaps using some run (or load) time AOP byte code engineering, you could rewrite all requests for threads to be redirected to a per component thread factory that you allocate and limits the threads that can be created. Because you don't want to stop them from doing whatever it is that they do, you just don't want them to take down the whole server when they crash/stall/misbehave.
Interesting problem.
I've been developing my first Java EE app, which has a number of JPA entity classes, each of which have a corresponding EJB class for dealing with the business logic. What I've done is changed one of those beans from Stateless to SessionScoped, so I can use it to allow a user to work their way through a series of form fields, all of which are rendered on a JSF form.
However, I'm starting to think this is clearly wrong, as I'm doing things like implementing methods such as "submitStep1" and "goBackToStep2" in my EJB. These methods set indicators which are used by render elements of various tags on the JSF page, so they are clearly "presentation logic".
My question is, how should I re-structure my code? I'm thinking that I should just have one SessionScoped (or should that be stateful?) bean, which deals with the presentation logic of my JSF page, and is able to use all the other ejbs (and by extension my JPA classes). This bean would be in the presentation-tier level of my app, meaning my business logic tier wouldn't need any Session Scoped Session Beans.
Now this all makes sense to me, and is what I am probably going to do. However the reason for my question is that on my JSF xhtml pages I use JSF EL tags a lot to refer to EJB content. Are there any JPA-related pitfalls I need to watch out for when writing presentation tier classes?
I know my question is pretty vague, and not really related to a specific example. And although I've found quite a lot out about Stateful v Stateless beans on this and other sites I just want to know my intended structure is the best one.
Why don't you use backing beans for presentation purpose, as they are intended for it, and you can easyly configure its scope, and leave the EJBs to business tier?
When using entities directly on the presentation tier, you should be aware of the transaction scope, specially regarding lazy relationships. That is, normally it is used one transaction per request, what will mean that amongst different requests, the entities will become detached, so you will need to reatach them to be able to load lazy relationships. You could use a filter that does it automatically each request or handle it by hand. You could also keep the same transaction during different requests but a long transaction is normally not a good idea, specially if there are updates/creations in the DB during this transacion.
I've got a large multi-threaded webapp in which I am passing in jdbcTemplates into DAO classes via constructor injection. Is this a multi-threading risk? Should I be passing in just the datasource instead?
Spring IOC runs in only 1 thread on start up so threading issues are not an issue there. Spring will not publish the DAO as a bean (to be retrieved from elsewhere) until it is completely constructed.
There is no risk of multithreading, you can safely pass jdbcTemplate into DAO classes.
In every query execution method, it essentially talks to the injected datasource and does not use any state which could lead to any side effect.