You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Create a Lock annotation that is functionally equivalent to the EJB Lock annotation but is more general in scope and therefore can be used more generally across the platform.
Other specification that might want to use this annotation, and also have XML (like web.xml) may also desire to have an XML equivalent.
If the annotation were the same as EJB, except with a different package... i.e. so only supporting 2 options:
@Lock(LockType.READ)
@Lock(LockType.WRITE)
With a default of WRITE, then perhaps the EJB spec could just allow applications to use the EJB version and new concurrency version interchangeably, then the above specific EJB XML could be left alone; no need to support two different ways in XML.
I assume the EJB specification would be allowed to consume the new annotation and :
limit use to only specific bean types (i.e only singleton)
ignore the annotation if present on an unsupported bean type, or interface
ignore the annotation if the module XML file contains metadata-complete="true"
use the same inheritance and override rules currently in the EJB specification
I haven't thought too much on how other specs consume the api. As a first instance I think it would be good for it to behave similar to the EJB annotations so that they can be used interchangeably with the advantage that it brings the equivalent EJB functionality to CDI beans.
I assume the EJB specification would be allowed to consume the new annotation
I don't think we should update EJB anymore, and just leave it be.
At most we can define a kind of subset of EJB lite that consists of a set of annotations and extensions that lets EJB be implemented via CDI. This new annotation would then automatically apply to these 'EJB' beans (which are actually CDI beans then).
While omni-beans is an interesting exercise to demonstrate how closely CDI has come to replicating EJB functionality, any product that ships the EJB API classes would be required to pass the EJB TCK, and would therefore be an EJB implementation (even if that is backed by a CDI implementation under the covers).
While we could update the EJB specification to define a new EJB Extra Lite, I think that would generally result in confusion with people wondering why they would want to use the new EJB Extra Lite vs just CDI. Or, are there still some remaining EJB exclusive capabilities that CDI really doesn't want?
The purpose of my prior comment was to:
Identify some of the things EJB did with the @lock annotation for consideration. I agree that providing an XML equivalent should not be done.... just some of the baggage that comes along with EJB, which makes EJB undesirable.
Note that some users might assume they could just use (or may accidentally use) the new @lock annotation with EJB. I think the original intent for Java EE was to have the ManagedBeans spec at the core, then CDI as an extension to that, and finally EJB as an extension to CDI. I'd prefer we strive to have only one bean model in Jakarta EE, which is CDI, and work toward completely eliminating ManagedBeans and EJB. So, while we might not update the EJB specification for this, it may be worth updating the Platform spec (or whatever spec contains the new @lock annotation) to specifically indicate it does not apply to either the Managed Beans or EJB specifications. Otherwise we could potentially end up with some EJB implementation providers supporting in and some not.
Managed beans has been removed from the platform, and CDI no longer depends on it.
Still, there's a slew of remaining usage or references to this managed beans spec. For instance, Servlets are still managed beans, and REST still mentions managed beans in its spec document as well.
I would like to propose still adding the Lock annotation for the 3.1 release. Don't go overboard yet with new features, but standardise what we done and understood through the years:
I think that would generally result in confusion with people wondering why they would want to use the new EJB Extra Lite vs just CDI.
Compatibility with existing code mostly. We're (seemingly?) not yet ready to drop EJB completely from the profiles, probably because of the large body of existing code.
are there still some remaining EJB exclusive capabilities that CDI really doesn't want?
Most things in EJB Lite could be done by features in other specs, though most would land in Concurrency I think, and a few in Security. Transactions has already absorbed the EJB features, and Interceptors have already been split out. I don't think CDI itself (CDI core) wants any of those higher level features.
EJB Ultra / Extra Lite being based on CDI by spec definition, and not just as an implementation detail, might make a lot of things a lot easier and consistent in the platform, and make a level of legacy EJB support trivial to add to other platform such as Tomcat and Quarkus.
I would like to propose still adding the Lock annotation for the 3.1 release. Don't go overboard yet with new features, but standardise what we done and understood through the years:
My vote is that we are too late in the Jakarta EE 11 release cycle for it to be a good idea to add more features. I would recommend that we look into adding it early on in 3.2. The focus for 3.1 should be on getting an RC1 built and ensure we have at least one compatible implementation passing the TCK by the approaching deadline for component specification release review. It should be noted that if Open Liberty is needed to be the compatible implementation, our schedules are such that the RC1 will be needed by March 20 (around 1 week from now), in order to have a publicly available downloadable beta that can be used to pass the TCK by the component specification deadline. If Glassfish can be used instead, maybe their schedules will allow some additional weeks of time, but it seems to me like we are inviting unnecessary risk if we choose to add anything new at this point in the schedule.
My vote is that we are too late in the Jakarta EE 11 release cycle for it to be a good idea to add more features
I was indeed thinking about whether it would be too late or not. Concurrency is a bit later in the release waves, so theoretically there is some time, but let's look at it for 3.2 then.
If we allow configuring a timeout, it would be optional to configure and would otherwise not time out. If we are basing this on ReadWriteLock and its provided implementation, ReentrantReadWriteLock, then the options for waiting mechanism are the Fair mode or Non-fair mode.
I think this is more than fine. After all, the EJB locking functionality is pretty minimal. The Quarkus design also appears pretty simple.
@njr-11 It looks good. I also hope there is a configurable provider to allow developers to use custom storage, such as Redis. When the application is scaled horizontally, all instances can share a central storage.
@njr-11 It looks good. I also hope there is a configurable provider to allow developers to use custom storage, such as Redis. When the application is scaled horizontally, all instances can share a central storage.
Before we can even get to the topic of the possibility of applying a Lock across multiple servers like that, I would like to first figure out what the scope of a Lock is within a single server.
The CDI beans with methods to which Lock is applied will themselves have a scope, such as ApplicationScoped, RequestScoped, and so forth. In a single server, is the intention to have the locking happen at the bean instance level? Or at the annotated class/method level? If the former, are we planning to allow Lock to be used on CDI beans at all scopes, or limiting to a subset such as only ApplicationScoped and Singleton? Whichever way we end up choosing, I worry that if users make opposite assumptions about the scope of Lock, they will end up coding their applications incorrectly without realizing it.
The primary intended use was indeed just application scoped beans and singletons, essentially at the instance level. However, it would be good to keep it as broadly applicable as possible.
I would suggest looking at what OmniServices and Quarkus is doing already (I think both just leave it open to users where they can apply @lock but provide some sort of guidance).
Java/Jakarta EE typically has left cluster-level concerns to vendors. I would just stick to standardizing single server behavior.
The primary intended use was indeed just application scoped beans and singletons, essentially at the instance level. However, it would be good to keep it as broadly applicable as possible.
Thanks - that's good. It eliminates the ambiguity which would be the source of user errors related to scope if we limit to ApplicationScoped and Singleton, so I would definitely favor that. I would say wait until someone presents a good use case why they need Lock at another scope before opening it up further.
I would suggest looking at what OmniServices and Quarkus is doing already
Maybe a good start is to just donate what OmniServices did to Concurro in terms of implementation, and donate the associated annotation as a draft to the Concurrency API. We can then take it from there (if the end-result is something totally different then that's of course fine, but it would probably be good to have a start)
Pooled (called maxconcurrency in another issue) was done by me and @janbeernink but mainly Jan. I asked before if it was okay to transfer that one, but when I'm actually about to transfer that I'll ask again.
Very cool. Obviously I would very much like to see both @lock and @MaxConcurrency become reality finally after so many years. I implemented both myself in Resin back in the EE 6 days, but sadly I am not in a position to donate it now.
We left one thing out of the Lock specification; a thread that holds a read lock and (perhaps through some other bean) again reaches the interceptor that takes care of the lock for a write lock.
Since the lock won't upgrade, this will deadlock / timeout today.
It's fairly easy to solve, as an implementation can just check the readers before attempting to
acquire a write lock.
I agree. We should define one way or the other what must happen. Otherwise implementations will differ.
We have not implemented this yet, but an obvious choice would be using Java's ReentrantReadWriteLock. However, ReentrantReadWriteLock does NOT permit upgrading locks from READ to WRITE.
The Lock annotation from Jakarta Enterprise Beans also does not support upgrading from READ to WRITE. It defines IllegalLoopbackException to be raised when this is attempted. This is per section 4.8.5.1, which states:
If a loopback call occurs on a singleton session bean that holds a read lock on the same thread (but does not also hold a write lock on the same thread):
If the target of the loopback call is a read method, the call must proceed immediately, without releasing the original Read lock.
If the target of the loopback call is a write method, the jakarta.ejb.IllegalLoopbackException must be thrown to the caller.
Given that neither of the above support lock upgrade, I have to wonder whether there is sufficient demand for it. I can see it being useful in 2 scenarios:
when the invoking thread is the only thread currently holding a read lock on the bean, or,
when it can be guaranteed that all other threads that have a read lock plan to release their read locks without attempting to upgrade.
As soon as you have 2 threads that both want to upgrade read locks on the bean to write locks, you have deadlock again.
I'm leaning toward saying that we should take an approach similar to Jakarta Enterprise Beans where we detect and fail fast rather then deadlocking.
Activity
tkburroughs commentedon May 6, 2021
Should an XML equivalent also be defined? Or would that be left to the discretion of the specifications that choose to support it?
For example, the EJB specification supports the following XML equivalent of the annotation in ejb-jar.xml:
Other specification that might want to use this annotation, and also have XML (like web.xml) may also desire to have an XML equivalent.
If the annotation were the same as EJB, except with a different package... i.e. so only supporting 2 options:
With a default of WRITE, then perhaps the EJB spec could just allow applications to use the EJB version and new concurrency version interchangeably, then the above specific EJB XML could be left alone; no need to support two different ways in XML.
I assume the EJB specification would be allowed to consume the new annotation and :
metadata-complete="true"smillidge commentedon Oct 4, 2021
I haven't thought too much on how other specs consume the api. As a first instance I think it would be good for it to behave similar to the EJB annotations so that they can be used interchangeably with the advantage that it brings the equivalent EJB functionality to CDI beans.
hantsy commentedon May 25, 2023
The lock is available in a distributed env? When the application is scaled horizontally, all instances can share a central storage.
If possible to allow developers to expose a custom
LockRegistryand the@Lockannotation can specify a lock name and backend lock registry?It provides a programmatic API instead of the
@Lockannotation.It provides a Pool concept, like Kotlin Semaphore,https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-semaphore/
arjantijms commentedon May 26, 2023
Let's not do that.
I don't think we should update EJB anymore, and just leave it be.
At most we can define a kind of subset of EJB lite that consists of a set of annotations and extensions that lets EJB be implemented via CDI. This new annotation would then automatically apply to these 'EJB' beans (which are actually CDI beans then).
See https://github.com/OmniFish-EE/omni-beans for a prototype of that idea.
tkburroughs commentedon May 26, 2023
While omni-beans is an interesting exercise to demonstrate how closely CDI has come to replicating EJB functionality, any product that ships the EJB API classes would be required to pass the EJB TCK, and would therefore be an EJB implementation (even if that is backed by a CDI implementation under the covers).
While we could update the EJB specification to define a new EJB Extra Lite, I think that would generally result in confusion with people wondering why they would want to use the new EJB Extra Lite vs just CDI. Or, are there still some remaining EJB exclusive capabilities that CDI really doesn't want?
The purpose of my prior comment was to:
Identify some of the things EJB did with the @lock annotation for consideration. I agree that providing an XML equivalent should not be done.... just some of the baggage that comes along with EJB, which makes EJB undesirable.
Note that some users might assume they could just use (or may accidentally use) the new @lock annotation with EJB. I think the original intent for Java EE was to have the ManagedBeans spec at the core, then CDI as an extension to that, and finally EJB as an extension to CDI. I'd prefer we strive to have only one bean model in Jakarta EE, which is CDI, and work toward completely eliminating ManagedBeans and EJB. So, while we might not update the EJB specification for this, it may be worth updating the Platform spec (or whatever spec contains the new @lock annotation) to specifically indicate it does not apply to either the Managed Beans or EJB specifications. Otherwise we could potentially end up with some EJB implementation providers supporting in and some not.
m-reza-rahman commentedon May 29, 2023
XML is really not needed. We should try not to bother with EJB/managed beans any more and just stick to CDI as much as possible.
arjantijms commentedon May 31, 2023
Managed beans has been removed from the platform, and CDI no longer depends on it.
Still, there's a slew of remaining usage or references to this managed beans spec. For instance, Servlets are still managed beans, and REST still mentions managed beans in its spec document as well.
arjantijms commentedon Mar 11, 2024
I would like to propose still adding the Lock annotation for the 3.1 release. Don't go overboard yet with new features, but standardise what we done and understood through the years:
arjantijms commentedon Mar 11, 2024
Compatibility with existing code mostly. We're (seemingly?) not yet ready to drop EJB completely from the profiles, probably because of the large body of existing code.
Most things in EJB Lite could be done by features in other specs, though most would land in Concurrency I think, and a few in Security. Transactions has already absorbed the EJB features, and Interceptors have already been split out. I don't think CDI itself (CDI core) wants any of those higher level features.
EJB Ultra / Extra Lite being based on CDI by spec definition, and not just as an implementation detail, might make a lot of things a lot easier and consistent in the platform, and make a level of legacy EJB support trivial to add to other platform such as Tomcat and Quarkus.
njr-11 commentedon Mar 11, 2024
My vote is that we are too late in the Jakarta EE 11 release cycle for it to be a good idea to add more features. I would recommend that we look into adding it early on in 3.2. The focus for 3.1 should be on getting an RC1 built and ensure we have at least one compatible implementation passing the TCK by the approaching deadline for component specification release review. It should be noted that if Open Liberty is needed to be the compatible implementation, our schedules are such that the RC1 will be needed by March 20 (around 1 week from now), in order to have a publicly available downloadable beta that can be used to pass the TCK by the component specification deadline. If Glassfish can be used instead, maybe their schedules will allow some additional weeks of time, but it seems to me like we are inviting unnecessary risk if we choose to add anything new at this point in the schedule.
arjantijms commentedon Mar 11, 2024
I was indeed thinking about whether it would be too late or not. Concurrency is a bit later in the release waves, so theoretically there is some time, but let's look at it for 3.2 then.
7 remaining items
m-reza-rahman commentedon Jan 21, 2025
I think this is more than fine. After all, the EJB locking functionality is pretty minimal. The Quarkus design also appears pretty simple.
hantsy commentedon Jan 22, 2025
@njr-11 It looks good. I also hope there is a configurable
providerto allow developers to use custom storage, such as Redis. When the application is scaled horizontally, all instances can share a central storage.njr-11 commentedon Jan 22, 2025
Before we can even get to the topic of the possibility of applying a Lock across multiple servers like that, I would like to first figure out what the scope of a Lock is within a single server.
The CDI beans with methods to which Lock is applied will themselves have a scope, such as
ApplicationScoped,RequestScoped, and so forth. In a single server, is the intention to have the locking happen at the bean instance level? Or at the annotated class/method level? If the former, are we planning to allow Lock to be used on CDI beans at all scopes, or limiting to a subset such as onlyApplicationScopedandSingleton? Whichever way we end up choosing, I worry that if users make opposite assumptions about the scope of Lock, they will end up coding their applications incorrectly without realizing it.m-reza-rahman commentedon Jan 22, 2025
The primary intended use was indeed just application scoped beans and singletons, essentially at the instance level. However, it would be good to keep it as broadly applicable as possible.
I would suggest looking at what OmniServices and Quarkus is doing already (I think both just leave it open to users where they can apply @lock but provide some sort of guidance).
Java/Jakarta EE typically has left cluster-level concerns to vendors. I would just stick to standardizing single server behavior.
njr-11 commentedon Jan 22, 2025
Thanks - that's good. It eliminates the ambiguity which would be the source of user errors related to scope if we limit to ApplicationScoped and Singleton, so I would definitely favor that. I would say wait until someone presents a good use case why they need Lock at another scope before opening it up further.
m-reza-rahman commentedon Jan 22, 2025
That's fine. I would leave the possibility open for the future. There may be use cases I have not yet encountered.
arjantijms commentedon Jan 27, 2025
Maybe a good start is to just donate what OmniServices did to Concurro in terms of implementation, and donate the associated annotation as a draft to the Concurrency API. We can then take it from there (if the end-result is something totally different then that's of course fine, but it would probably be good to have a start)
m-reza-rahman commentedon Jan 27, 2025
Who does the donation? You or someone else? These look to be the contributors other than yourself: @janbeernink and @BalusC.
arjantijms commentedon Jan 27, 2025
Lock was exclusively done by me: https://github.com/omnifaces/omniservices/commits/develop/src/main/java/org/omnifaces/services/lock
Pooled (called maxconcurrency in another issue) was done by me and @janbeernink but mainly Jan. I asked before if it was okay to transfer that one, but when I'm actually about to transfer that I'll ask again.
m-reza-rahman commentedon Jan 28, 2025
Very cool. Obviously I would very much like to see both @lock and @MaxConcurrency become reality finally after so many years. I implemented both myself in Resin back in the EE 6 days, but sadly I am not in a position to donate it now.
janbeernink commentedon Jan 28, 2025
From my side, I'm perfectly happy if my work on the Pooled annotation is contributed.
arjantijms commentedon Jul 9, 2026
We left one thing out of the Lock specification; a thread that holds a read lock and (perhaps through some other bean) again reaches the interceptor that takes care of the lock for a write lock.
Since the lock won't upgrade, this will deadlock / timeout today.
It's fairly easy to solve, as an implementation can just check the readers before attempting to
acquire a write lock.
We do have to define this behaviour in the spec.
njr-11 commentedon Jul 10, 2026
I agree. We should define one way or the other what must happen. Otherwise implementations will differ.
We have not implemented this yet, but an obvious choice would be using Java's ReentrantReadWriteLock. However, ReentrantReadWriteLock does NOT permit upgrading locks from READ to WRITE.
The
Lockannotation from Jakarta Enterprise Beans also does not support upgrading from READ to WRITE. It defines IllegalLoopbackException to be raised when this is attempted. This is per section 4.8.5.1, which states:Given that neither of the above support lock upgrade, I have to wonder whether there is sufficient demand for it. I can see it being useful in 2 scenarios:
As soon as you have 2 threads that both want to upgrade read locks on the bean to write locks, you have deadlock again.
I'm leaning toward saying that we should take an approach similar to Jakarta Enterprise Beans where we detect and fail fast rather then deadlocking.
One place we need to update is here,
concurrency/api/src/main/java/jakarta/enterprise/concurrent/Lock.java
Lines 67 to 68 in ce8c26e
That Javadoc has incorrect language and needs updates regardless because it mistakenly says that a "method" ... "is" ... "held".
arjantijms commentedon Jul 11, 2026
I was also leaning towards that. It's the most straightforward solution and more or less the accepted industry way today.
njr-11 commentedon Jul 13, 2026
Excellent! I update the Javadoc accordingly in PR #899