I want to create a simple webapp that
- allow remote clients to track some data in a send request.
- save all tracking in a lightweight database
- return all tracking for get
About the database, I would like
- put your location in my webapp properties file (and use this location for hibernate.location.url set in persistence.xml file)
- that the database is created using a schema and table, if they do not already exist.
- use existing database and schema and table and data if they exist
So, I created a maven project with
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.my.tracker</groupId> <artifactId>tracker-webapp</artifactId> <version>0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <hibernate.version>4.3.8.Final</hibernate.version> <h2.version>1.4.185</h2.version> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-eclipse-plugin</artifactId> <version>2.9</version> <configuration> <downloadSources>true</downloadSources> <downloadJavadocs>false</downloadJavadocs> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>${h2.version}</version> </dependency> </dependencies> </project>
Src / main / resources / META-INF / persistence.xml
<?xml version="1.0" encoding="UTF-8" ?> <persistence 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_1_0.xsd" version="1.0"> <persistence-unit name="thePersistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>org.my.tracker.Event</class> <properties> <property name="connection.driver_class" value="org.h2.Driver"/> <property name="hibernate.connection.url" value="jdbc:h2:./db/repository"/> <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/> <property name="hibernate.hbm2ddl.auto" value="create"/> <property name="hibernate.show_sql" value="true" /> </properties> </persistence-unit> </persistence>
SRC / Main / WebApp / WEB-INF / web.xml
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <servlet> <servlet-name>orc-event</servlet-name> <servlet-class>org.my.tracker.EventServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>orc-event</servlet-name> <url-pattern>/event/*</url-pattern> </servlet-mapping> </web-app>
Src / home / java / org / mine / tracker / EventServlet.java
package org.my.tracker; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.Gson; public class EventServlet extends HttpServlet { private static final Logger LOGGER = LoggerFactory.getLogger(EventServlet.class); private static final long serialVersionUID = 1L; public static final String HTML_START="<html><body>"; public static final String HTML_END="</body></html>"; private static EntityManager manager; static { EntityManagerFactory factory = Persistence.createEntityManagerFactory("thePersistenceUnit"); manager = factory.createEntityManager(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); try { manager.getTransaction().begin(); @SuppressWarnings("unchecked") List<Event> events = manager.createQuery("from Event").getResultList(); Gson gson = new Gson(); out.print(gson.toJson(events)); manager.getTransaction().commit(); } catch (Exception e) { manager.getTransaction().rollback(); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String body = (String)request.getParameter("body"); if (null != body) { try { manager.getTransaction().begin(); Event event = new Event(); event.setBody(body); manager.persist(event); manager.getTransaction().commit(); } catch (Exception e) { manager.getTransaction().rollback(); } } else { LOGGER.error("null body, cannot track"); } } }
Src / home / java / org / mine / tracker / Event.java
package org.my.tracker; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Event { @Id @GeneratedValue private Integer id; private String body; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } }
Well, thanks to all these powerful tools, it is simple and works pretty well, except that I couldn’t
See how to set my db location through a property (is it possible only through setting tomcat server.xml (which I cannot do for it doesn’t belong to me) or spring (which is a pretty weak reason to add several spring to my project for only 1 injection of properties ...),
(and 3.) every time I launch my webapp, my database is empty. Of course you will tell me since I put the "create" value in persistence.xml
<property name="hibernate.hbm2ddl.auto" value="create"/>
Well, I could put
- create-drop: the same result as "create" in my case (which is expected, for "drop" means a lot like "keep everything on off": D)
- none: but then the database is not created the first time you deploy webapp
- validate: it’s good that I can restore my content when webapp reloads, but like no one, first, if it does not exist, the database schema and table are not created, and my webapp cannot work with it :)
So, I would like, if possible, to keep everything as simple as they are above, is this possible?
If there is no other way to write a sql script to initialize my db only if it does not exist, I would appreciate if you would give some code or some kind of hint, because I am not relevant in this field.
Edit
So, as I added one comment, actually the “update” is the value I was looking for. Work like a charm.
I did not find any other way than spring to pass variables instead of constant values. But, hey, this is quite common in such an area :) (and spring its orm layer too)