<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-servlet</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-persist</artifactId>
<version>4.0</version>
</dependency>
</dependencies>
Lean example of Tomcat 8 + Guice 4 + EclipseLink 2.6.0
TweetPosted on Tuesday Aug 04, 2015 at 07:26PM in Technology
I wrote a Lean example of Tomcat 8 + Guice 4 in previous entry. this time, I’ll try JPA(EclipseLink) integration with automatic transaction management.
The entire project which based on Maven can be obtained from My GitHub repository.
Prerequisites
For database connection, we’ll use a DataSource which is defined on Tomcat server. to define a Embedded Derby DataSource, This entry would help.
Dependencies
web.xml
No changes against previous entry except addition of resource-ref element.
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- taken from https://github.com/google/guice/wiki/Servlets -->
<listener>
<listener-class>guice.tomcat.MyGuiceServletConfig</listener-class>
</listener>
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<resource-ref>
<res-ref-name>jdbc/derby</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
META-INF/persistence.xml
If you don’t want to use a DataSource on Tomcat, specify the connection information in javax.persistence.jdbc.* properties instead of non-jta-data-source.
<?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="myJpaUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<non-jta-data-source>java:comp/env/jdbc/derby</non-jta-data-source>
<class>guice.tomcat.MyEntity</class>
<properties>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.level.sql" value="FINE"/>
</properties>
</persistence-unit>
</persistence>
MyGuiceServletConfig.java
The last two statements will take care of JPA integration.
public class MyGuiceServletConfig extends GuiceServletContextListener {
@Override
protected Injector getInjector() {
return Guice.createInjector(new ServletModule() {
@Override
protected void configureServlets() {
serve("/*").with(MyServlet.class);
bind(MyService.class).to(MyServiceImpl.class);
install(new JpaPersistModule("myJpaUnit"));
filter("/*").through(PersistFilter.class);
}
});
}
}
MyEntity.java
This is a very simple JPA entity which keeps only generated id and ts (a timestamp).
@Entity
@NamedQuery(name = "MyEntity.findAll", query = "SELECT e FROM MyEntity e ORDER BY e.id DESC")
public class MyEntity implements Serializable {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date ts;
... accessors are omitted
Service class
MyService.java
public interface MyService {
void save(MyEntity e);
List<MyEntity> findAll();
}
MyServiceImpl.java
Note that you need to annotate a method with @com.google.inject.persist.Transactional if you need a transaction on it.
public class MyServiceImpl implements MyService {
// Transactions doesn't start if EntityManager is directly injected via @Inject.
// I have no idea why...
// According to https://github.com/google/guice/wiki/JPA,
// "Note that if you make MyService a @Singleton, then you should inject Provider<EntityManager> instead."
@Inject
private Provider<EntityManager> emp;
@Override
// @javax.transaction.Transactional is not supported yet. https://github.com/google/guice/issues/797
@com.google.inject.persist.Transactional
public void save(MyEntity e) {
EntityManager em = emp.get();
em.persist(e);
}
@Override
public List<MyEntity> findAll() {
return emp.get().createNamedQuery("MyEntity.findAll", MyEntity.class).getResultList();
}
}
MyServlet.java
This servlet saves a MyEntity with current timestamp, then fetches all of rows and returns them to the client on every request.
@javax.inject.Singleton
public class MyServlet extends HttpServlet {
@javax.inject.Inject
private MyService myService;
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
MyEntity myEntity = new MyEntity();
myEntity.setTs(new Date());
myService.save(myEntity);
PrintWriter writer = resp.getWriter();
writer.write("<html><body><ul>");
for(MyEntity e : myService.findAll()){
writer.write("<li>");
writer.write(e.toString());
writer.write("</li>");
}
writer.write("</ul></body></html>");
}
}
Test run
A row will be saved on every request as follows:
Tags: eclipselink guice jpa tomcat