EJB lite, JPA, DataSource embedded in java application

This post demonstrates how to put EJB lite, JPA, DataSource together in a standalone java application, using standard JavaEE 6 API in GlassFish. The application source consists of 4 files: persistence.xml, JPA entity, no-interface EJB, and main class.

Transaction is managed by embeddable EJB container. The persistence unit is backed by an application-scoped JTA DataSource declared with annotation on EJB class. No need to package or deploy anything. Client and server pieces are all in a single JVM.

classes/META-INF/persistence.xml :
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" 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">
<persistence-unit name="test_pu" transaction-type="JTA">
<jta-data-source>java:app/jdbc/test</jta-data-source>
<properties>
<property name="eclipselink.ddl-generation" value="create-tables"/>
<property name="eclipselink.logging.level" value="FINE"/>
</properties>
</persistence-unit>
</persistence>
JPA entity Employee:
package test;
import javax.persistence.*;

@Entity
public class Employee implements java.io.Serializable {
private static final long serialVersionUID = 1L;

@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Basic private String name;

public Long getId() {
return id;
}

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

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Employee)) {
return false;
}
Employee other = (Employee) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override public String toString() {
return "Employee id=" + id + ", name=" + name;
}
}
No-interface stateless EJB:
package test;
import javax.ejb.Stateless;
import javax.persistence.*;
import javax.annotation.sql.DataSourceDefinition;

@Stateless
@DataSourceDefinition(
name="java:app/jdbc/test",
className="com.mysql.jdbc.jdbc2.optional.MysqlDataSource",
user="root",
password="root",
databaseName="test",
serverName="localhost",
portNumber=3306 )
public class TestBean {
@PersistenceContext private EntityManager em;

public void addEmployee(String[] names) {
for(String name : names) {
Employee e = new Employee();
e.setName(name);
em.persist(e);
}
}
}
main class:
package test;
import javax.ejb.embeddable.EJBContainer;
import javax.naming.*;

public class Client {
public static void main(String[] args) throws Exception {
EJBContainer container = EJBContainer.createEJBContainer();
Context namingContext = container.getContext();
TestBean testBean = (TestBean) namingContext.lookup("java:global/classes/TestBean");
testBean.addEmployee(args); //need to pass in employee names from command line
container.close();
}
}
To compile from project directory:
$ javac -cp "classes:$GLASSFISH_HOME/lib/embedded/glassfish-embedded-static-shell.jar" classes/test/*java
Start mysqld, and run the app:
cd /usr/local/mysql-5.1.32; sudo bin/mysqld_safe --user root
java -cp "classes:$GLASSFISH_HOME/lib/embedded/glassfish-embedded-static-shell.jar:$HOME/mysql-connector-java-5.1.5-bin.jar" test.Client Jon Jane
Verify entities are successfully created by running mysql:
mysql> select * from EMPLOYEE;
+----+------+
| ID | NAME |
+----+------+
| 1 | Jon |
| 2 | Jane |
+----+------+
2 rows in set (0.00 sec)
If you are wondering why the jar is named xxx-static-shell.jar, I guess "static" means it's not OSGi bundle, and "shell" means it's a wrapper for all the other GlassFish jars.

Followers

Pageviews Last 7 Days