java WildFly:具有@Transactional、@Stateless的EntityManager没有事务

new9mtju  于 2023-02-07  发布在  Java
关注(0)|答案(1)|浏览(172)

我目前在WildFly 25上的普通Java EE应用程序中遇到了一个奇怪的问题,我没有找到根本原因。我一直在为一些客户使用类似的配置,代码从未出现过任何问题。我知道要使事务工作,我需要正确地注入所涉及的一切。我使用@Stateless注解,并在需要它的方法上使用@Transactional注解。但是我从来没有遇到过这样的问题,我只是没有得到任何事务,而且我现在有点迷路了。数据源也是用JTA配置的,设置为true
我的存储库:

@Stateless
public class DocumentImportLogRepository{
    
    @PersistenceContext(unitName = "AktenimportPU")
    EntityManager em;
    
    public <T> Object find(Class<T> entityClass, Object primaryKey)
    {
        return em.find(entityClass, primaryKey);
    }
    
    public void persist(Object object)
    {
        em.persist(object);
    }
    
    public void forcePersist(Object object)
    {
        em.persist(object);
        em.flush();
    }
    
    public void merge(Object object)
    {
        em.merge(object);
    }
    
    public void forceMerge(Object object)
    {
        em.merge(object);
        em.flush();
    }

    public void remove(Object object)
    {
        em.remove(object);
    }

在以下服务类中调用:

@Stateless
public class DocumentImportService 

[...]
    @Inject
    DocumentImportLogRepository importLogRepo;

来自几种方法,均源自:

@Transactional
public void doImport()
{
    [...]
    readInputFolder(Config.DOCUMENT_IMPORT_FOLDER);
    prepareImport(importLogRepo.getByState(State.PARSED), getPersonalakten());
    performArchive(importLogRepo.getByState(State.PREPARED));
    performArchiveMove(importLogRepo.getByState(State.ARCHIVED));
    [...]
}

其由控制器触发:

@Named("StartController")
@ApplicationScoped
public class StartController implements Serializable {

    
    @Inject
    private transient DocumentImportService importService;
    
    [...]
    
    @Transactional
    @TransactionTimeout(value=120, unit = TimeUnit.MINUTES)
    public void performTask(Task task)
    {
        [...]

            switch(task)
            {
                case Personalaktenimport:
                    importService.doImport();
                    break;
            }

        [...]
            
    }

实际方法调用失败:

@Transactional
public void readInputFolder(Path inputFolder) throws IOException
{
    [...] importLogRepo.forcePersist(entry); [...]
}

但有例外:

javax.ejb.EJBTransactionRolledbackException: WFLYJPA0060: Transaction is required to perform this operation (either use a transaction or extended persistence context

persistence.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
   <persistence-unit name="AktenimportPU">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
      <jta-data-source>java:jboss/datasources/Aktenimport</jta-data-source>
      <properties>
         <property name="hibernate.hbm2ddl.auto" value="none"/>
         <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>
         <property name="hibernate.jdbc.time_zone" value="Europe/Berlin"/>
         
      </properties>
   </persistence-unit>
      
</persistence>
qvsjd97n

qvsjd97n1#

我终于找到了导致这个错误的原因:
我之前并没有真正阅读异常,因为我认为它们只是输入中常见的错误,但是,是的,我捕获了几个异常,然而,javax.validation.ValidationException不是其中之一,错误在于实体有一个字段BARCODE,其类型是枚举BARCODE_TYPE,其中包含一组预定义值。我的意图是让它遇到错误,但继续导入未知类型,然而,如果出现该异常,则似乎将事务设置为应用程序无法从中恢复的错误状态。删除枚举字段上的@NotNull注解确实消除了错误。

相关问题