2017-03-31 1 views
1

Ich habe Java EE-Projekt, wo ich eine injizierte JTA EntityManager in der Methode verwenden möchte. EntityManager.persist schlägt aufgrund javax.persistence.TransactionRequiredException fehl. Es ist erfolgreich, wenn es über eine EJB-Instanz aufgerufen wird, die in eine von JSF verwaltete Bean injiziert wird. Manuelles Starten einer Transaktion mit @Resource UserTransaction und UserTransaction.begin/commit oder EntityManager.getTransaction.begin/commit, weil es ein JTA EntityManager ist.Warum erhalte ich eine TransactionRequiredException in der @ PostConstruct-Methode in JTA EJB?

Die EJB-Schnittstelle

@Local 
public interface UserService extends Serializable { 

    public void saveUser(AUser user); 
} 

@Entity 
public class AUser implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue 
    private Long id; 
    private String username; 

    public AUser() { 
    } 

    public AUser(String username) { 
     this.username = username; 
    } 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public String getUsername() { 
     return username; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

Die EJB Implementierung:

@Stateless 
public class DefaultUserService implements UserService { 
    private static final long serialVersionUID = 1L; 
    @PersistenceContext 
    private EntityManager entityManager; 

    public DefaultUserService() { 
    } 

    @PostConstruct 
    private void init() { 
     AUser user = new AUser("initUser"); 
     saveUser(user); 
    } 

    @Override 
    public void saveUser(AUser user) { 
     entityManager.persist(user); 
    } 
} 

persistence.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> 
    <persistence-unit name="richtercloud_javaee-persist-in-postconstruct-jar_jar_1.0-SNAPSHOTPU" transaction-type="JTA"> 
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> 
    <jta-data-source>jdbc/example1</jta-data-source> 
    <class>richtercloud.javaee.persist.in.postconstruct.jar.entities.AUser</class> 
    <properties> 
     <property name="eclipselink.target-database" value="Derby"/> 
     <!-- necessary in order to avoid syntax errors --> 
     <property name="javax.persistence.schema-generation.database.action" value="create"/> 
     <property name="eclipselink.ddl-generation" value="create-or-extend-tables"/> 
     <property name="eclipselink.target-server" value="Glassfish"/> 
     <!-- avoid non-severe NullPointerException being logged in GlasFish 
      <ref>https://java.net/jira/browse/GLASSFISH-21468f</ref>--> 
    </properties> 
    </persistence-unit> 
</persistence> 

ich nicht wusste, wie die jdbc/example1 Datenquelle zur Verfügung zu stellen (es Glassfish ist 4.1 JDBC-Ressource basierend auf einem JDBC-Verbindungspool, der sich auf einen Derby bezieht d atabase mit Netzwerktreiber). Alles andere ist verfügbar unter https://github.com/krichter722/javaee-persist-in-postconstruct.

Ich las Persisting in @PostConstruct: javax.persistence.TransactionRequiredException, die das Beispiel eines einfachen EntityManager.persist Anruf in @PostConstruct und http://www.tikalk.com/java/doing-transactional-work-spring-service-using-postconstruct-method/, die auf Frühling bezieht sich übersteigt, die ich nicht verwenden. Ich habe keine Aussage gefunden, dass sich @PersistenceContext EntityManager in anders verhält.

Antwort

1

§8.6.2 der EJB-3.2-Spezifikation besagt:

Der Ausdruck „ein nicht spezifizierte Transaktionskontext“ in der EJB-Spezifikation verwendet wird, um die Fälle zu beziehen, in denen die EJB-Architektur nicht vollständig die nicht definiert Transaktionssemantik einer Ausführung einer Enterprise-Bean-Methode.
Dies umfasst die folgenden Fälle:
...
• Die Ausführung einer Callback-Methode PostConstruct oder PreDestroy einer Stateless Session Bean mit containergesteuerter Transaktionsdemarkation.

Eine alternative Lösung besteht möglicherweise darin, die javax.persistence.sql-load-script-source-Eigenschaft in Ihrer Datei persistence.xml anzugeben. Es zeigt auf ein SQL-Skript, das Ihre Datenbank vorlädt. Dies kann eine in Ihre Anwendung eingebettete Ressource oder eine Datei-URL sein.

3

Es kann nicht garantiert werden, dass @PostConstruct und @PreDestroy Teil der Transaktion sind. Daher sollten keine DB-Operationen in der PostConstruct-Methode und der PreDestroy-Methode ausgeführt werden.

Verwandte Themen