Nico Schertler
Nico Schertler

Reputation: 32587

Persisting entities

I am just getting started with EJB development, so I created a test system that consists of the following three projects:

System overview

Actually, the HelloWorldBeanRemote interface does also exist in the EJBTest project. I haven't found a way to import it from the other project without runtime exceptions.

The EJBTestInterfaces is a plain java project that contains only the remote interface. EJBTest contains the program logic. HelloWorldBean is a session bean. Its constructor sets the created field to the current time. In the sayHello() method it uses an injected PersistenceManager to retrieve the TestEntity with id 0 (or creates it if it does not exist), increments the ´hit` variable and returns it:

@PersistenceContext(name="manager1") 
private EntityManager em;

@Override
public String sayHello() {
    String info;
    if (em == null)
        info = "Entity Manager is null";
    else {
        TestEntity entity;
        try {
            entity = em.find(TestEntity.class, 0);
            entity.setHits(entity.getHits() + 1);
            em.merge(entity);
            info = "Hit entity " + entity.getHits() + " times.";
        } catch(Exception x) {
            entity = new TestEntity();
            em.persist(entity);
            info = "Never used entity bean before.";
        } 
    }
    return "Hello! I was created at " + created.toString() + "<br>" + info;
}

The persistence unit is defined in the persistence.xml as follows:

<persistence>
   <persistence-unit name="manager1">
       <jta-data-source>java:jboss/datasources/AppointmentDS</jta-data-source>
       <jar-file>../EJBTest.jar</jar-file>
       <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
                  <!-- also tried value="validate" -->
       </properties>
   </persistence-unit>
</persistence>

It uses an embedded database defined in the standalone.xml:

<datasource jndi-name="java:jboss/datasources/AppointmentDS" pool-name="AppointmentDS" enabled="true" use-java-context="true">
    <connection-url>jdbc:h2:file:[path to file]</connection-url>
    <driver>h2</driver>
    <security>
        <user-name>sa</user-name>
        <password>sa</password>
    </security>
</datasource>

The servlet basically outputs the return value of sayHello():

doGet(...) {
    //get initial context ...

    bean = (HelloWorldBeanRemote)initialContext.lookup(name);
    output.write(bean.sayHello());
}

If I now call the servlet via a web browser, I get the expected output: The creation date and "Never used entity bean before." If I refresh the page, the creation date does not change, but the hit count increments. I can restart the servlet project without changing this behaviour. The hit count increments steadily.

However, if I restart the EJB project, everything is reset to zero. It is the expected behaviour for the creation date, but the hit count should be read from the database. But it is not.

I can see the created database files in the specified directory and they seem to contain data (I just opened the file in a text editor).

Am I supposed to use the session bean the way I did? I am not sure if I have to close the bean after the request (so the transaction can commit).

How can I make the EJB project read persisted data from the database file?

Upvotes: 0

Views: 66

Answers (2)

Uwe Hehn
Uwe Hehn

Reputation: 11

It might be that H2 resets the DB once you restart your EJB project, that is, when the last connection is gone. Stop your EJB project and connect to the DB to see if the expected data is still there.

Upvotes: 0

Petr Mensik
Petr Mensik

Reputation: 27496

You need to change hibernate.hbm2ddl.auto value from create-drop to validate or some other value. create-drop will delete whole schema when the SessionFactory is closed and recreate it again on open.

Upvotes: 1

Related Questions