在项目 JSF + EJB + CDI + JAX-RS + GlassFish 4.1 的 ManagedBean 中回滚

Rollback in ManagedBean on a project JSF + EJB + CDI + JAX-RS + GlassFish 4.1

我正在开始一个结合 "JSF + EJB + CDI + JAX-RS + GlassFish 4.1"

的项目

看了一些书,做了一些研究,终于把这些技术完美的结合起来了。除了事务控制,一切正常。

为了帮助理解问题,我创建了一个测试项目https://github.com/douglasjunior/TestRollbackJsfEjbCdiRest

问题是:在ManagedBean中,没有运行抛出异常时回滚事务

但 JAX-RS 资源中的相同问题完美运行。

在我的示例中,我试图在数据库中插入重复记录。我应该在哪里收到异常 DuplicatedKey。因此,交易应该被逆转,数据库中不应该插入任何东西。

但是当这在ManagedBean中完成时,异常不会回滚事务。第一条记录已提交。

GenericDao.java

@Stateless
public class GenericDao implements Serializable {

    @PersistenceContext(unitName = "PU")
    private EntityManager em;

    public void persist(Object entity) {
        getEntityManager().persist(entity);
        getEntityManager().flush();
    }
}

User.java

@Entity
@Table(name = "table_user")
@XmlRootElement
public class User extends AbstractEntity<Long> {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(length = 100, unique = true)
    private String someText;

}

TestManagedBean.java(回滚无效)

@Named(value = "testManagedBean")
@ViewScoped
@TransactionManagement(TransactionManagementType.CONTAINER) // I tested also as BEAN
public class TestManagedBean extends AbstractManagedBean {

    @Inject
    private GenericDao dao;

    private User user;

    public TestManagedBean() {
        user = new User();
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRED) // I tested also as REQUIRES_NEW
    public String test() {
        if (user.getSomeText() == null || user.getSomeText().isEmpty()) {
            sendErrorMessage("Text is riquired!");
            return null;
        }
        dao.persist(user);
        User user2 = new User();
        user2.setSomeText(user.getSomeText()); // "someText" is unique on database
        dao.persist(user2); // org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "table_user_sometext_key"
        return null;
    }

    public User getUser() {
        return user;
    }    
}

TestResource.java(回滚正常)

@Path("test")
@Stateless
public class TestResource {

    @Inject
    private GenericDao dao;

    @Context
    private UriInfo context;

    public TestResource() {
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public User getTeste(@QueryParam("someText") String someText) {
        if (someText == null || someText.isEmpty()) {
            throw new WebApplicationException("Text is riquired!", Response.Status.BAD_REQUEST);
        }
        System.out.println("someText: " + someText);
        User user = new User();
        user.setSomeText(someText);
        dao.persist(user);
        User user2 = new User();
        user2.setSomeText(user.getSomeText()); // "someText" is unique on database
        dao.persist(user2); // org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "table_user_sometext_key"
        return user;
    }
}

如下更改您的class:

@Transactional 
public class TestManagedBean extends AbstractManagedBean {

你的方法如下:

@Transactional
public String test() {