This post is simply a summary of a simple proof of concept. It shows how to:
- create a stateless EJB3 bean
- persist an entity using JPA with Hibernate as a JPA provider
- configure JPA to use a datastore defined on Glassfish (uses pre-installed java/__default datastore, which uses pre-installed Derby/JavaDB)
Entity
@Entity
public class Book implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String title;
private float price;
public Book() {
super();
}
...
}
Here, I have annotated the property, rather than the getter (not shown for brevity), since it feels more intuitive to me. I don't know if there is any advantage/difference of one vs the other other than my personal preference. The "@GeneratedValue(...)" annotation for primary key in JPA entity definition is not optional, as I expected. Using just the "@Id" annotation results in the primary key being not set (set to 0).EJB Bean
The interface:
@Remote
public interface BookManager {
public abstract int addBook(Book book);
public abstract Book find(int bookId);
}
And the bean implementation:
@Stateless(name="BookManager", mappedName = "ejb/BookManagerJNDI")
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class BookManagerImpl implements BookManager {
// Dependency injection of Entity Manager for
// the given persistence unit
@PersistenceContext(unitName="pu1") EntityManager em;
public int addBook(Book book) {
// Transitions new instances to managed. On the
// next flush or commit, the newly persisted
// instances will be inserted into the datastore.
em.persist(book);
return book.getId();
}
@Override
public Book find(int bookId) {
return em.find(Book.class, bookId);
}
}
The annotation @Stateless with the mappedName make the bean to get registered with JNDI. The
TransactionAttributeType.REQUIRED tells the container to wrap each method in the class with a transaction. JPA SetupThe persistence.xml file (put it into META-INF folder under src folder so it will be deployed onto the server)
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="pu1">
<!-- Persistence provider -->
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/__default</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
The "hibernate." prefix in persistence.xml file is not optional when adding properties of the JPA provider (Hibernate in this case). They are ignored without it, without a warning.
Glassfish Setup
Nothing other than installing the Hibernate component using the Glassfish console.
Unit Tests
The unit test:
try {
InitialContext ctx = new InitialContext();
BookManager bean = (BookManager) ctx.lookup("ejb/BookManagerJNDI");
Book book = new Book("Chocolate Rain", 25.10f);
int bookId = bean.addBook(book );
book = null;
book = bean.find(bookId);
Assert.assertEquals("Chocolate Rain", book.getTitle());
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Assert.fail("Failed. Exception thrown.");
}
A Few Notes
- Can JPA be used to create and index? Yes and no. Not in general. But it provides a limited capability. To create a unique constrain on a table, use @UniqueConstraint(columnNames={"EMP_BDAY", "EMP_NAME"})
- How to specify the character column type length? Use @Column(length=50).
- What the client can understand about the remote exception, in case the EJB bean fails? The remote exception is wrapped in a EJBException and returned to the client. For example, if the password for the DB is incorrect, the org.hibernate.exception.GenericJDBCException will be returned with a message "Cannot open connection" (when Hibernate is used as JPA provider).
A few things to try in the next proof of concept:
- test the rollback function, if second of two persistence operations failed when both are in the same method of the BookManager class.
- do a parent/child relationship.

1 comment:
thanks for this good post
Post a Comment