<document>
  <header>
    <product>resin-ee</product>
    <title>Field-based Persistent Objects</title>
        <description>
          <p>Amber's persistence supports a field-based relational model: each
Java field represents a database column.  The tutorial
shows the configuration, classes, and client code for a single-table entity. </p>
        </description>
    <type>tutorial</type>
    <tutorial-startpage>basic</tutorial-startpage>
  </header>

  <body>
    <summary/>

<section title="Overview">

<p>Amber provides a Java model for a relational database,
following the Java Persistence standard.</p>

<p>A typical project starts planning with the
relational database schema and matching the Java model to that schema.
This data-driven approach contrasts with a transparent persistent
object approach which starts with Java classes and then tries to
create storage to match the Java model, an approach more typical
of object-oriented databases.  While the transparent persistence model
may be appropriate for some applications, the persistence specification
wisely leaves
transparent persistence to other products and specifications, and
concentrates on the relational database model.</p>

<p>In a way, Amber simply provides an extension
to SQL queries, returning fully-populated Java objects instead of
just returning primitive values like Strings.  That somewhat
understates Amber's capabilities since the Java objects are live,
updating the database in a object-oriented fashion, and also provides
caching.  Still, viewing Amber as a SQL extension supporting
relations and objects is a good starting model.</p> 

<p>The tutorial uses "entity" to mean a persistent object.
Amber's entities are far simpler than the "EntityBean" of EJB 2.1.</p>

</section>

<section title="Files in this tutorial">
<deftable>
<tr><td><viewfile-link file="WEB-INF/resin-web.xml"/>
    <td>resin-web.xml configuration
<tr><td><viewfile-link file="WEB-INF/classes/META-INF/persistence.xml"/>
    <td>persistence.xml configuration
<tr><td><viewfile-link file="WEB-INF/classes/example/Course.java"/>
    <td>The course bean
<tr><td><viewfile-link file="WEB-INF/classes/example/CourseServlet.java"/>
    <td>The course servlet
</deftable>
</section>

<section title="Database Model">

<p>The tutorial's design begins with its database model.  The
table is a collection of school courses, each with an assigned teacher.
The table has an integer primary key "id" and two string data fields, "course"
and "teacher".</p>

<example title="course.sql">
CREATE TABLE amber_basic_courses (
  id INTEGER PRIMARY KEY auto_increment,

  course VARCHAR(250),
  teacher VARCHAR(250)
);

INSERT INTO amber_basic_courses VALUES('Potions', 'Severus Snape');
INSERT INTO amber_basic_courses VALUES('Transfiguration', 'Minerva McGonagall');
</example>

<p>To judge the complexity of Amber, it's useful to compare the Amber
Java model to the simplest possible Java model.  The simple model
has a single class, <code>Course</code>, for the table and three fields for the
table's columns.</p>

<example title="Minimal Java model">
package example;

public class Course {
  private int id;
  private String course;
  private String teacher;
}
</example>

<p>The minimal class is missing any description of its intended use as a
persistent object, information needed for maintainable code.
In theory, a persistent object tool could use the minimal class
automatically, but without more information, the source doesn't
properly describe the class behavior.  Fortunately, the JDK 1.5
metadata annotations can describe the persistence information in
a maintainable, self-documenting way.</p>

<p>Of course, those annotations might have default values and should
be overridable by an optional XML configuration file, but it's
necessary to annotate the intended function of the entity in the Java
source itself to properly document and validate the Java code.</p>

</section>

<section title="Overview">

<p>To find and enhance a persistent Java bean, Amber follows the following
procedure.

<ol>
<li>&lt;ejb-server> in the resin-web.xml configures Amber to start looking for persistence.xml in the classpath.
<li>The persistence.xml in WEB-INF/classes/META-INF tells Amber to create a persistence-unit named "example".
<li>The "example" persistence-unit contains a class example.CourseBean
<li>Amber enhances example.CourseBean as a persistent object.
</ol>

<p>By the end of initialization time, Amber has enhanced CourseBean and
made it available to the application in the persistence-unit "example".</p>

<p>A servlet will then lookup the CourseBean with the following procedure:</p>

<ol>
<li>Obtain an EntityManager for the persistence unit from JNDI either directly as java:comp/env/persistence/PersistenceContext/example, or using the @PersistenceUnit injection annotation.
<li>Use the EntityManager to find the instance of the bean.
</ol>

</section>

<section title="Persistent Object Implementation">

<p>The minimal Java class needs the following annotations to
produce a maintainable persistent object:</p>

<ul>
<li>A annotation to mark the class as persistent.
<li>An annotation naming the relational table for the class.
<li>An annotation to mark the primary key and any auto-generation
capability.
<li>Annotations to mark each persistent field.
<li>Annotations naming the columns for the table.
</ul>

<p>The following code shows the Amber annotations for the course
entity.  As a quick comparison with the minimal Java class shows,
Amber is close to the simplest possible implementation of the
Java model which provides the necessary annotations in the list.</p>


<example title="Course.java">
package example;

import javax.persistence.*;

<a href="amber|amber-table.xtp#@Entity">@Entity</a>
<a href="amber|amber-table.xtp#@Table">@Table</a>(name="amber_basic_course")
public class Course {
  <a href="amber|amber-table.xtp#@Id">@Id</a>
  <a href="amber|amber-table.xtp#@Column">@Column</a>(name="id")
  <a href="amber|amber-table.xtp#@GeneratedValue">@GeneratedValue</a>
  private int _id;

  <a href="amber|amber-table.xtp#@Basic">@Basic</a>
  <a href="amber|amber-table.xtp#@Column">@Column</a>(name="course")
  private String _course;

  <a href="amber|amber-table.xtp#@Basic">@Basic</a>
  <a href="amber|amber-table.xtp#@Column">@Column</a>(name="teacher")
  private String _teacher;

  public String course()
  {
    return _course;
  }

  public String teacher()
  {
    return _teacher;
  }
}
</example>

<p>The example uses the <code>course()</code>
and <code>teacher()</code> methods to emphasize that the
field accesses to _course and _teacher are live, i.e. they
read and write the database values directly.  (Under the covers, Amber
uses bytecode enhancement to make this work.)</p>

<section title="@Entity - marking the class as persistent">

<p>Course uses the @Entity to mark the Java class as a field-based
persistent object.</p>

<example>
@javax.persistence.Entity
</example>

<p><a href="amber|amber-table.xtp#@Entity">@javax.persistence.Entity</a> declares
a Java class as an entity bean.</p>

<p>Since the @Id annotation marks a field, the
bean's fields are persistent, as in JDO.  Unlike JDO, only
the bean itself or its children may access the fields.  Other classes
must use the bean's methods, like getters or setters, to
indirectly access the fields.</p>

<p>If the @Id annotation had marked a property method,
the methods would be enhanced. </p>

</section>

<section title="@Table - naming the table">

<p><a href="amber|amber-table.xtp#@Table">@javax.persistence.Table</a> specifies
the SQL database table name to be used.  If <code>@Table</code> is
unspecified, Amber will use the class name as the table name.</p>

<example>
@javax.persistence.Table(name="amber_basic_course")
</example>

</section>

<section title="@Id - marking the primary key">

<p>The <a href="amber|amber-table.xtp#@Id">@Id</a> attribute marks the
bean's primary key.  The <code>EntityManager.find</code> method
looks up a bean instance with the primary key, and relations use
the primary key to link beans together.</p>

<example>
@Id
@Column(name="id")
@GeneratedValue
private int _id;
</example>

<p>The optional <code>@GeneratedValue</code> specifies automatic
generation of primary keys when beans are created.  The default
strategy <code>AUTO</code> generates primary keys depending on the database.
Postgres, for example, will use a SEQUENCE, while Resin's built-in
database will use an auto_increment IDENTITY.</p>

<p>The optional <a
href="amber|amber-table.xtp#@Column">@Column</a> annotation specifies the
SQL column name.  The default SQL column for an @Id is
the property name.</p>

</section>

<section title="@Basic - marking a persistent field">

<p>The <a href="amber|amber-table.xtp#@Basic">@Basic</a> attribute
marks a basic data column like a string or integer or double.</p>

<example>
@Basic 
@Column (name="course")
private String _course;
</example>

</section>

<section title="@Column - naming the column">

<p>The optional <a href="amber|amber-table.xtp#@Column">@Column</a>
annotation specifies SQL column name.
For a @Basic field, the
default column name is the field name.</p>

</section>

<section title="Under the covers: bytecode enhancement">

<p>Amber processes the bean's class to implement field-enhancement.
In practice, this means replacing setting a field with a Resin setter
and getting a field with an Amber getter.</p>

<example>
public String course()
{
  return _course;
}
</example>

<p>For example, Resin would process the above method and produce
something like:</p>

<example>
public String course()
{
  return __caucho_get_course();
}
</example>

</section>

</section>

<section title="Client Servlet">

<p>The client servlet queries the database for all courses and lists
them.  It uses the <code>EntityManager</code> API to create a
<code>Query</code> and uses the <code>Query</code> to obtain the results.</p>


<example title="CourseServlet.java">
public class CourseServlet extends HttpServlet {
  @PersistenceUnit(name="example")
  private EntityManager _manager;

  public void service(HttpServletRequest req, HttpServletResponse res)
    throws java.io.IOException, ServletException
  {
    PrintWriter out = res.getWriter();

    res.setContentType("text/html");

    out.println("&lt;h3>Course Details&lt;/h3>");

    Query query = _manager.createQuery("SELECT o FROM Course o");
    
    for (Course course : (List&lt;Course>) query.listResults()) {
      out.println("course: " + course.course() + "&lt;br>");
      out.println("teacher: " + course.teacher() + "&lt;br>");
      out.println("&lt;br>");
    }
  }
}
</example>
<results>
<h3>Course Details</h3>
course: Potions
instructor: Severus Snape

course: Transfiguration
instructor: Minerva McGonagall
</results>

<section title="EntityManager">

<p><code>EntityManager</code> is the primary interface for
finding, querying, adding and deleting persistent beans.  It is stored
in JNDI at java:comp/env/persistence/PersistenceContext/example.</p>

<example>
@PersistenceContext(name="example")
</example>

<p>The example uses dependency injection to configure the entity
manager.</p>

<example title="web.xml configuration">
&lt;servlet servlet-name="basic" servlet-class="example.CourseServlet">
&lt;/servlet>
</example>

</section>

<section title="Query">

<p><code>Query</code> acts like a <code>PreparedStatement</code> in
JDBC.  It saves a parsed SQL query and allows for parameters.</p>

<example>
Query query = _manager.createQuery("SELECT o FROM Course o");
</example>

<p>The SQL used for EJB 3.0 is an enhanced database SQL.  The query
can return objects directly ("SELECT&nbsp;o") and it can traverse
relations ("o.next.data").  In most other respects, it can be thought
of as regular SQL.</p>

<example>
List list = query.listResults();
</example>

<p>The query returns its values with <code>listResults()</code>.
Queries which return a single value can
use <code>getSingleResult()</code>.</p>

</section>

</section>

<section title="Resin Configuration">

<p>The Resin configuration is fairly straightforward.  Resin needs to
start the ejb-server, configure the JDBC data-source, and list the
beans that will be used.</p>

<example title='WEB-INF/resin-web.xml'>
&lt;web-app>
  &lt;!-- server configuration -->
  &lt;ejb-server data-source="jdbc/resin"/>

  &lt;servlet servlet-name="basic" servlet-class="example.CourseServlet"/>

  &lt;servlet-mapping url-pattern="/basic" servlet-name="basic"/>
&lt;/web-app>
</example>

<p>The &lt;ejb-server> configures Amber support.</p>

</section>

<section title="persistence.xml">

<p>The persistence.xml lives in META-INF/persistence.xml.  Since
we're developing in WEB-INF/classes, the file will be in
WEB-INF/classes/persistence.xml.</p>

<example title='WEB-INF/classes/META-INF/persistence.xml'>
&lt;persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
  &lt;persistence-unit name="example">
    &lt;class>example.CourseBean&lt;/class>

    &lt;exclude-unlisted-classes/>
  &lt;/persistence-unit>
&lt;/persistence>
</example>

</section>

  </body>
</document>
