ninjaframework / ninja

Ninja is a full stack web framework for Java. Rock solid, fast and super productive.
http://www.ninjaframework.org
Apache License 2.0
1.91k stars 520 forks source link

@Transactional not working with @Schedule #417

Open jnye opened 9 years ago

jnye commented 9 years ago

Using version 5.2.1 the following throws an exception. I've not tested earlier versions.

package services;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.persist.Transactional;
import ninja.scheduler.Schedule;

import javax.persistence.EntityManager;
import java.util.concurrent.TimeUnit;

/*
    In Module.java:
        bind(TestScheduledAction.class);
*/
@Singleton
public class TestScheduledAction {

    @Inject
    private Provider<EntityManager> entityManagerProvider;

    @Schedule(initialDelay = 0, delay = 60, timeUnit = TimeUnit.SECONDS)
    public void run() {
        doSomething();
    }

    @Transactional
    private void doSomething() {
        if (!entityManagerProvider.get().getTransaction().isActive()) {
            throw new RuntimeException("No transaction active!");
        }
    }

}

Also, if I place @Transactional on the run method the scheduler never calls it.

jnye commented 9 years ago

As a work around you can split the @Schedule class and the @Transactional class and it will work.

package services;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import ninja.scheduler.Schedule;

import java.util.concurrent.TimeUnit;

@Singleton
public class TestScheduledAction {

    @Inject
    private TestAction testAction;

    @Schedule(initialDelay = 0, delay = 60, timeUnit = TimeUnit.SECONDS)
    public void run() {
        testAction.doSomething();
    }

}
package services;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.persist.Transactional;

import javax.persistence.EntityManager;

@Singleton
public class TestAction {

    @Inject
    private Provider<EntityManager> entityManagerProvider;

    @Transactional
    public void doSomething() {
        if (!entityManagerProvider.get().getTransaction().isActive()) {
            throw new RuntimeException("No transaction active!");
        }
    }

}
ThinkHuang commented 5 years ago

I meet the same question, someone would help us?

rrarrarra commented 5 years ago

@Transactional does not work on private methods afaik.