2

I work with hibernate-jpa-2.1-api

I have an EJB class for busines logic

I have made an @RequestScopded EntityManager that is injected in the EJB and called in the save method, there is no error but even no entry in the database. The funny thing is that the hibernate sequence number is increased in the DB correctly but the insert of the entity is not called, I dont even see the insert statement for the entity in the logs.

if I call

em.flush()

after

em.persist()

I get an error that tells there is no transaction in progress.

I have othere save metods for other entities organised the same way and are working correctly. I have also tryed to inject the EntityManager in the EJB as @PersistenceContect and in that case it is working, but I wonder why in this specific case the requesed scoped EM is not working and in other it does.

Here is my code:

1.) the Entity

@Entity
@Table(name = "CONSULTATION")
public class Consultation implements java.io.Serializable {

private static final long serialVersionUID = 2989793280017282405L;
private long idConsulation;
private DomainExpert domainExpert;
private Date date;
private Long hours;
private String description;
private PayedResource payedResource;
private Integer version;

public Consultation() {
}

public Consultation(long idConsulation, DomainExpert domainExpert) {
    this.idConsulation = idConsulation;
    this.domainExpert = domainExpert;
}

public Consultation(long idConsulation, DomainExpert domainExpert, Date date, Long hours) {
    this.idConsulation = idConsulation;
    this.domainExpert = domainExpert;
    this.date = date;
    this.hours = hours;
}

@Id
@TableGenerator(name = "ID_CONSULATION", table = "hibernate_sequence", pkColumnName = "SEQUENCE_NAME", valueColumnName = "NEXT_VAL", pkColumnValue = "SEQ_ID_CONSULATION", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.TABLE, generator = "ID_CONSULATION")
@Column(name = "ID_CONSULATION", unique = true, nullable = false)
public long getIdConsulation() {
    return this.idConsulation;
}

public void setIdConsulation(long idConsulation) {
    this.idConsulation = idConsulation;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ID_DOMAIN_EXPERT", nullable = false)
public DomainExpert getDomainExpert() {
    return this.domainExpert;
}

public void setDomainExpert(DomainExpert domainExpert) {
    this.domainExpert = domainExpert;
}

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "DATE", length = 19, nullable = false)
public Date getDate() {
    return this.date;
}

public void setDate(Date date) {
    this.date = date;
}

@Column(name = "HOURS", length = 20, nullable = false)
public Long getHours() {
    return this.hours;
}

public void setHours(Long hours) {
    this.hours = hours;
}

@Column(name = "DESCRIPTION", length = 500)
public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

@Version
@Column(name = "VERSION", nullable = false)
public Integer getVersion() {
    return this.version;
}

public void setVersion(Integer version) {
    this.version = version;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ID_PAYED_RESOURCE", nullable = false)
public PayedResource getPayedResource() {
    return this.payedResource;
}

public void setPayedResource(PayedResource payedResource) {
    this.payedResource = payedResource;
}

}

2.) the EJB

@Stateless
public class DomainExpertHandler {

    @Inject
    private EntityManager em;

    public void saveConsultation(Consultation consultation) {
       if (consultation.getIdConsulation() > 0) {
         em.merge(consultation);
       } else {
         em.persist(consultation);
       }
    }
}

3.) The bean that generates the @requestscoped EM

public class Resources {

    @PersistenceUnit
    EntityManagerFactory emf;

    @Produces
    @RequestScoped
    public EntityManager createEntityManager() {
        return emf.createEntityManager();
    }

    protected void closeEntityManager(@Disposes EntityManager entityManager) {

        if (entityManager.isOpen()) {
            entityManager.close();
        }
    }


}

4.) my persistence.xml

<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="cloudflow" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>java:jboss/datasources/cloudflow</jta-data-source>
        <properties>
         <!-- Properties for Hibernate -->
         <property name="hibernate.jdbc.batch_size" value="50"/>  
         <property name="hibernate.show_sql" value="false" />
         <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />  
        </properties>
   </persistence-unit>

</persistence>
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
simonC
  • 4,101
  • 10
  • 50
  • 78
  • did you try to add `@TransactionAttribute(TransactionAttributeType.REQUIRED)` above the save method ? – Gab Aug 05 '15 at 14:29
  • @Gab yes I have tried but with the same problem...it looks like there is no transaction or that the em is not asociated with a transaction in that moment – simonC Aug 05 '15 at 14:31
  • 2
    I don't see you actually starting or committing a transaction anywhere on your manually created EntityManager. Quite possibly you should let the container inject a container managed EntityManager into your producer class, and not an EntityManagerFactory. – Gimby Aug 05 '15 at 14:31
  • @Gimby I have used the example here for request scoped EM http://piotrnowicki.com/2012/11/types-of-entitymanagers-application-managed-entitymanager/ it is working correctly in other beans but this one seem have some problem – simonC Aug 05 '15 at 14:42
  • @simonC did you read the text about exactly your problem in the link? `Notice the BeanA being a non-transactional resource. Also note that we injected and invoked some operation on the EntityManager (this makes the injection to be actually performed.) Now if the BeanB is transactional and also injects and uses EntityManager – we’ll end with a non-transactional EntityManager that will not throw any exception and will not save any changes to the database.` where `BeanA` is your `DomainExpertHandler ` – dognose Aug 05 '15 at 14:50
  • DomainExpertHandler is an EJB so it should not be a non-transactional resource – simonC Aug 05 '15 at 14:57
  • @BalusC I agree with you, but the class does make sense - it is the CDI way of making an EntityManager injectable using CDI annotations. Of course then you need to understand that you still need to let the container inject a managed entity manager into it, basically as ErwanC explains it. – Gimby Aug 05 '15 at 15:44
  • maybe I missed the point here, I tried with RequestScoped EM to avoid some Lazy exceptions during the render repsonse phase in JSF, maybe there are better aproaches to this, I have fowm taht if I put em.joinTransaction() in saveConsultation method then it works otherwise the EM is not asociated woth a transaction – simonC Aug 06 '15 at 07:13

1 Answers1

0

May you manually define the transaction ?

EntityTransaction trans = em.getTransaction();
    trans.begin();
    //etc....

If not may you try

@PersistenceContext(name="cloudflow")
    EntityManager em;

and see this answer

Community
  • 1
  • 1
Erwan C.
  • 709
  • 5
  • 18
  • no i cann not i get "A JTA EntityManager cannot use getTransaction()" but anyway there yhould be the EJB that handles the transaction to avoid handling it by hand – simonC Aug 05 '15 at 14:39
  • I know, PersistenceContext injectet em is working but I want RecuestScoped EM whic is created by Resources calss mentioned in the question – simonC Aug 05 '15 at 15:02