[Red Hat JIRA] (CDI-414) Support for "self" injection or intercepted self invocation
by nimo stephan (Jira)
[ https://issues.redhat.com/browse/CDI-414?page=com.atlassian.jira.plugin.s... ]
nimo stephan edited comment on CDI-414 at 1/4/21 10:20 AM:
-----------------------------------------------------------
I have the same problem.
For example:
{code:java}
@Singleton
public class Bean1 {
@PersistenceContext
private EntityManager em;
@Resource
private ManagedScheduledExecutorService scheduler;
@PostConstruct
private postConstruct(){
// with this, no transaction is created within callNewTransaction
scheduler.scheduleWithFixedDelay(this::callNewTransaction, 0, 5, TimeUnit.SECONDS);
// with this, a new transaction is created within callNewTransaction
// scheduler.scheduleWithFixedDelay(bean2::callNewTransaction, 0, 5, TimeUnit.SECONDS);
}
// No transaction is created within the method because it is within the same class
// Workaround: Put this method into another Bean2, inject this bean into Bean1
@Transactional(Transactional.TxType.REQUIRES_NEW)
@Interceptors(BeanInterceptor.class)
public void callNewTransaction(User user) {
// should always be done within a new transaction
user.setLastLoginTime(LocalDateTime.now());
em.merge();
}
}{code}
A good solution would be a new Annotation (which elminates the need to create an artifical class only to deserve the need of the actual limitation), for example:
{code:java}
@Proxy // eliminates the need to put it into another class
@Transactional(Transactional.TxType.REQUIRES_NEW)
@Interceptors(BeanInterceptor.class)
public void callNewTransaction(User user) {
// should always be done within a new transaction
user.setLastLoginTime(LocalDateTime.now());
em.merge();
}{code}
Another solution would be to provide a programmatic way to define @Transactional within the code, for example (something like Spring TransactionTemplate):
{code:java}
public void callNewTransaction(User user) {
var transaction = EJB.createTransactional(Transactional.TxType.REQUIRES_NEW);
transaction(()->
// should always be done within a new transaction user.setLastLoginTime(LocalDateTime.now()); em.merge();
}}
{code}
was (Author: nimo22):
I have the same problem.
For example:
{code:java}
@Singleton
public class Bean1 {
@PersistenceContext
private EntityManager em;
@Resource
private ManagedScheduledExecutorService scheduler;
@PostConstruct
private postConstruct(){
// with this, no transaction is created within callNewTransaction
scheduler.scheduleWithFixedDelay(this::callNewTransaction, 0, 5, TimeUnit.SECONDS);
// with this, a new transaction is created within callNewTransaction
// scheduler.scheduleWithFixedDelay(bean2::callNewTransaction, 0, 5, TimeUnit.SECONDS);
}
// No transaction is created within the method because it is within the same class
// Workaround: Put this method into another Bean2, inject this bean into Bean1
@Transactional(Transactional.TxType.REQUIRES_NEW)
@Interceptors(BeanInterceptor.class)
public void callNewTransaction(User user) {
// should always be done within a new transaction
user.setLastLoginTime(LocalDateTime.now());
em.merge();
}
}{code}
A good solution would be a new Annotation (which elminates the need to create an artifical class only to deserve the need of the actual limitation), for example:
{code:java}
@Interleave // eliminates the need to put it into another class
@Transactional(Transactional.TxType.REQUIRES_NEW)
@Interceptors(BeanInterceptor.class)
public void callNewTransaction(User user) {
// should always be done within a new transaction
user.setLastLoginTime(LocalDateTime.now());
em.merge();
}{code}
> Support for "self" injection or intercepted self invocation
> -----------------------------------------------------------
>
> Key: CDI-414
> URL: https://issues.redhat.com/browse/CDI-414
> Project: CDI Specification Issues
> Issue Type: Bug
> Components: Resolution
> Reporter: Arjan Tijms
> Priority: Minor
> Fix For: 2.1 (Discussion)
>
>
> Many features of CDI and EJB work by means of a proxy that intercepts calls and adds 'aspects'. In Java it's however not possible to decorate the {{this}} pointer, so methods called on the same bean instance from within a method in the bean do not get their 'aspects' applied.
> This is a well known limitation, but in EJB it's possible to work around this by injecting a bean into itself. E.g.
> {code}
> @Stateless
> public class Foo {
> @EJB
> private Foo self;
> // ...
> }
> {code}
> Also see http://adam-bien.com/roller/abien/entry/how_to_self_invoke_ejb
> Unfortunately using CDI and {{@Inject}} this doesn't work. Weld for instance fails the deployment and logs:
> {noformat}
> WELD-001443 Pseudo scoped bean has circular dependencies.
> {noformat}
> See also: http://adam-bien.com/roller/abien/entry/inject_vs_ejb
> Although there are workarounds, it would be great if {{@Inject}} in combination with CDI could support self injection as well.
> With that projects migrating from {{@EJB}} to {{@Inject}} can do so more easily and the capability can be convenient for new projects as well (e.g. calling two separate {{@Transactional}} methods from a single method without being required to create a new bean).
--
This message was sent by Atlassian Jira
(v8.13.1#813001)
3 years, 11 months
[Red Hat JIRA] (CDI-414) Support for "self" injection or intercepted self invocation
by nimo stephan (Jira)
[ https://issues.redhat.com/browse/CDI-414?page=com.atlassian.jira.plugin.s... ]
nimo stephan commented on CDI-414:
----------------------------------
I have the same problem.
For example:
{code:java}
@Singleton
public class Bean1 {
@PersistenceContext
private EntityManager em;
@Resource
private ManagedScheduledExecutorService scheduler;
@PostConstruct
private postConstruct(){
// with this, no transaction is created within callNewTransaction
scheduler.scheduleWithFixedDelay(this::callNewTransaction, 0, 5, TimeUnit.SECONDS);
// with this, a new transaction is created within callNewTransaction
// scheduler.scheduleWithFixedDelay(bean2::callNewTransaction, 0, 5, TimeUnit.SECONDS);
}
// No transaction is created within the method because it is within the same class
// Workaround: Put this method into another Bean2, inject this bean into Bean1
@Transactional(Transactional.TxType.REQUIRES_NEW)
@Interceptors(BeanInterceptor.class)
public void callNewTransaction(User user) {
// should always be done within a new transaction
user.setLastLoginTime(LocalDateTime.now());
em.merge();
}
}{code}
A good solution would be a new Annotation (which elminates the need to create an artifical class only to deserve the need of the actual limitation), for example:
{code:java}
@Interleave // eliminates the need to put it into another class
@Transactional(Transactional.TxType.REQUIRES_NEW)
@Interceptors(BeanInterceptor.class)
public void callNewTransaction(User user) {
// should always be done within a new transaction
user.setLastLoginTime(LocalDateTime.now());
em.merge();
}{code}
> Support for "self" injection or intercepted self invocation
> -----------------------------------------------------------
>
> Key: CDI-414
> URL: https://issues.redhat.com/browse/CDI-414
> Project: CDI Specification Issues
> Issue Type: Bug
> Components: Resolution
> Reporter: Arjan Tijms
> Priority: Minor
> Fix For: 2.1 (Discussion)
>
>
> Many features of CDI and EJB work by means of a proxy that intercepts calls and adds 'aspects'. In Java it's however not possible to decorate the {{this}} pointer, so methods called on the same bean instance from within a method in the bean do not get their 'aspects' applied.
> This is a well known limitation, but in EJB it's possible to work around this by injecting a bean into itself. E.g.
> {code}
> @Stateless
> public class Foo {
> @EJB
> private Foo self;
> // ...
> }
> {code}
> Also see http://adam-bien.com/roller/abien/entry/how_to_self_invoke_ejb
> Unfortunately using CDI and {{@Inject}} this doesn't work. Weld for instance fails the deployment and logs:
> {noformat}
> WELD-001443 Pseudo scoped bean has circular dependencies.
> {noformat}
> See also: http://adam-bien.com/roller/abien/entry/inject_vs_ejb
> Although there are workarounds, it would be great if {{@Inject}} in combination with CDI could support self injection as well.
> With that projects migrating from {{@EJB}} to {{@Inject}} can do so more easily and the capability can be convenient for new projects as well (e.g. calling two separate {{@Transactional}} methods from a single method without being required to create a new bean).
--
This message was sent by Atlassian Jira
(v8.13.1#813001)
3 years, 11 months