<?xml version="1.0" encoding="utf-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">
<title>Lance Andersen&apos;s Blog</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/" />
<modified>2008-01-16T19:40:04Z</modified>
<tagline></tagline>
<id>tag:weblogs.java.net,2008:/blog/lancea/161</id>
<generator url="http://www.movabletype.org/" version="3.01D">Movable Type</generator>
<copyright>Copyright (c) 2008, lancea</copyright>
<entry>
<title>Welcome MySQL!</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2008/01/welcome_mysql.html" />
<modified>2008-01-16T19:40:04Z</modified>
<issued>2008-01-16T08:36:14Z</issued>
<id>tag:weblogs.java.net,2008:/blog/lancea/161.9000</id>
<created>2008-01-16T08:36:14Z</created>
<summary type="text/plain"> As you have probably have heard by now, MySQL is becoming the lastet member of the Sun family. Jonathan&apos;s blog discusses this exciting event in detail. I am looking forward to this new adventure as i have had nothing...</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>

<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[<p>
As you have probably have heard by now,  <a href="http://www.mysql.com/">MySQL</a> is becoming the lastet member of the Sun family.  <a href="http://blogs.sun.com/jonathan/entry/winds_of_change_are_blowing">Jonathan's blog</a> discusses this exciting event in detail.
</p><p>
I am looking forward to this new adventure as i have had nothing but positive experiences when working with the MySQL engineering team.
</p><p>
See the following <a href="http://blogs.mysql.com/kaj/2008/01/16/sun-acquires-mysql/">blog on the acquisition</a> from the MySQL community.
</p>
<!-- technorati tags start --><p style="text-align:right;font-size:10px;">Technorati Tags: <a href="http://www.technorati.com/tag/databases" rel="tag">databases</a>, <a href="http://www.technorati.com/tag/mysql" rel="tag">mysql</a></p><!-- technorati tags end -->]]>

</content>
</entry>
<entry>
<title>Updated list of JDBC drivers supporting JDBC 4.0</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2007/09/updated_list_of.html" />
<modified>2007-09-18T21:44:51Z</modified>
<issued>2007-09-18T21:44:42Z</issued>
<id>tag:weblogs.java.net,2007:/blog/lancea/161.8272</id>
<created>2007-09-18T21:44:42Z</created>
<summary type="text/plain">More JDBC 4.0 drivers are available including recent offerings from Oracle and MySQL.</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>J2EE</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[The following is the current list of available JDBC 4.0 drivers:
<p>

<ul>
<li> <a href="http://db.apache.org/derby/derby_downloads.html">Java DB/Apache Derby</a>
<li> <a href="http://mysql.org/downloads/connector/j/5.1.html">MYSQL Connector/J 5.1</a>
<li><a href="http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/htdocs/jdbc_111060.html">Oracle 11g</a>
<li><a href="http://inetsoftware.de">inet software</a> for Microsoft SQL Server(Merlia  driver) and for Oracle (Oranxo driver).
<li><a href="http://www.aveconnect.com/default.htm">Atinav aveConnect 4.0 </a> for Microsoft SQL Server
 <li><a href="http://www.datadirect.com/products/jdbc/release_highlights/index.ssp">DataDirect 3.7</a> has also introduced some JDBC 4.0 features
</ul>
<p>

]]>

</content>
</entry>
<entry>
<title>Java DB upgraded in Glassfish V2</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2007/09/java_db_upgrade_1.html" />
<modified>2007-09-17T17:30:01Z</modified>
<issued>2007-09-17T16:25:07Z</issued>
<id>tag:weblogs.java.net,2007:/blog/lancea/161.8254</id>
<created>2007-09-17T16:25:07Z</created>
<summary type="text/plain">Glassfish V2 includes a new release of Java DB which incorporates many new features and bug fixes.</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>J2EE</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[Java DB, Sun's supported distribution of Apache Derby, has been upgraded from Java DB 10.1.3.1 which was bundled with Glassfish V1, to Java DB 10.2.2.
<p>

The new release of Java DB includes many new features and improvements including:
<p>
<ul>
<li>JDBC 4.0 Support
<li><a href="http://issues.apache.org/jira/secure/attachment/12322522/onlinebackup2.html">Improved on-line backup support</a>
<li><a href="http://issues.apache.org/jira/secure/attachment/12324156/writeup-v4.html">Support for Scrollable and Updatable ResultSets</a>
<li><a href="http://issues.apache.org/jira/secure/attachment/12338762/grantRevokeSpec_v5.html">Grant and Revoke Support</a>
<li>a $JAVADB_HOME/bin directory with easier to use scripts for Java DB utilities.
</ul>
<p>

You can find the complete list of <a href="http://db.apache.org/derby/releases/release-10.2.1.6.html#Release%20Overview">new features</a> in Java DB 10.2.2 <a href="http://db.apache.org/derby/releases/release-10.2.1.6.html#Release%20Overview">here</a>.
<p>

For more information on Java DB, check out the following resources:

<ul>
<li>Glassfish <a href="https://glassfish.dev.java.net/javaee5/javadb/">Java DB home page</a>
<li>Java DB <a href="http://developers.sun.com/javadb/">Home page</a>
<li>Java DB <a href="http://developers.sun.com/javadb/reference/docs/index.jsp">documentation</a>
<li>Java DB <a href="http://developers.sun.com/javadb/support/">support offerings</a>
</ul>
<p>

Glassfish v2 is now available for <a href="https://glassfish.dev.java.net/downloads/v2-b58g.html">download</a>.]]>

</content>
</entry>
<entry>
<title>Using Java Web Start with the Java Persistence API</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2007/06/using_java_web.html" />
<modified>2007-06-15T17:02:42Z</modified>
<issued>2007-06-15T17:02:36Z</issued>
<id>tag:weblogs.java.net,2007:/blog/lancea/161.7577</id>
<created>2007-06-15T17:02:36Z</created>
<summary type="text/plain">Ever try to use the Java Persistence API with Java Web Start successfully?  If not read on...</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>J2EE</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Untitled Document</title>
<style type="text/css">
<!--
.style1 {color: #FF0000}
-->
</style>
</head>

<body>
I created a  simple Java Persistence API application using Toplink Essentials which runs like a champ from NetBeans and from the 
command line.  So I figure, great, I will spice up the example a little more and use Java Web Start (yes I am a rookie to Java Web Start, so be gentle!) and I whip up a simple jnlp file <strong>JPAWebStart.bad.jnlp</strong>:
<p>
<table border="1" cellpadding="10" cellspacing="0" width="67%" >
<tr><td>
<pre style="color: darkblue;">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE jnlp PUBLIC "-//Sun Microsystems, Inc.//DTD JNLP 1.5//EN" "http://www.netbeans.org/jnlp/DTD/jnlp.dtd"&gt;
&lt;jnlp codebase="file:///C:/Netbeans/JPAWebStart" href="JPAWebStart.bad.jnlp"&gt;
   &lt;information&gt;
    &lt;title&gt;JPAWebStart fail&lt;/title&gt;
    &lt;vendor&gt;Company, Inc.&lt/vendor&gt;
    &lthomepage href="homepage.html"/&gt;
    &lt;description&gt; &lt/description&gt;
    &lt;icon href="default"/&gt;
    &lt;offline-allowed/&gt;
    &lt;shortcut online="true"/&gt;
  &lt;/information&gt;
  &lt;resources&gt;
    &lt;j2se href="http://java.sun.com/products/autodl/j2se" version="1.6+"/&gt;
  &lt;/resources&gt;
  &lt;resources&gt;
    &lt;jar download="eager" href="dist/JPAWebStart.jar" main="false"/&gt;
  &lt;/resources&gt; 
  &lt;resources&gt;
    &lt;jar download="eager" href="dist/lib/toplink-essentials.jar" main="false" version=""/&gt;
  &lt;/resources&gt;
  &lt;resources&gt;
    &lt;jar download="eager" href="dist/lib/derby.jar" main="false" version=""/&gt;
&lt;/resources&gt;
  &lt;application-desc main-class="demo.ui.JPAWebStartDemo"/&gt;
&lt;/jnlp&gt;
</pre>
</td></tr>
</table>
<p>&nbsp;</p>
<p>Ok, off I go to run my application:
</p>
<table border="1" cellpadding="10" cellspacing="0" width="67%" >
<tr><td>
<pre style="color: darkblue;">
javaws JPAWebStart.bad.jnlp
</pre>
</td></tr>
</table>

<p>And low and behold, I get the following error:
</p>
<p>&nbsp;</p>
<table border="1" cellpadding="10" cellspacing="0" width="67%" >
<tr><td>
<pre style="color: darkblue;">
Exception in thread "AWT-EventQueue-0" 
javax.persistence.PersistenceException: No Persistence provider for EntityManager named JPAWebStartPU
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:89)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60)
	at demo.ContactImpl$1.run(ContactImpl.java:37)
	at java.security.AccessController.doPrivileged(Native Method)
	at demo.ContactImpl.<init>(ContactImpl.java:34)
	at demo.ContactFactory.getInstance(ContactFactory.java:28)
	at demo.ContactTableModel.<init>(ContactTableModel.java:34)
	at demo.ui.JPAWebStartDemo.initComponents(JPAWebStartDemo.java:134)
	at demo.ui.JPAWebStartDemo.<init>(JPAWebStartDemo.java:23)
	at demo.ui.JPAWebStartDemo$7.run(JPAWebStartDemo.java:304)
	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)
</pre>
</td></tr>
</table>
<p>
Why is my Persistence provider not found when I can run the application fine as a standalone application from the command line or from NetBeans?
<p>
The error message is misleading as the issue turns out to be due to  the sandbox environment that Java Web Start uses to protect users from untrusted applications.
<p>
So where do we go from here?  Well, we will create two jnlp files, one to start our application, the other which contains the classes which require more access then the sandbox allows.  The jar files contained in the second jnlp, which is referenced from our first jnlp file, will enable access to the system and all jar files listed as resources  will be signed.
<p>
Here is the new JNLP file, <strong>JPAWebStart.jnlp</strong>, used to launch my application:
<p>
<table border="1" cellpadding="10" cellspacing="0" width="67%" >
<tr><td>
<pre style="color: darkblue;">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE jnlp PUBLIC "-//Sun Microsystems, Inc.//DTD JNLP 1.5//EN" "http://www.netbeans.org/jnlp/DTD/jnlp.dtd"&gt;
&lt;jnlp codebase="file:///C:/Netbeans/JPAWebStart" href="JPAWebStart.jnlp"&gt;
   &lt;information&gt;
    &lt;title&gt;JPAWebStart Demo&lt;/title&gt;
    &lt;vendor&gt;Company, Inc.&lt/vendor&gt;
    &lthomepage href="homepage.html"/&gt;
    &lt;description&gt; &lt/description&gt;
    &lt;icon href="default"/&gt;
    &lt;offline-allowed/&gt;
    &lt;shortcut online="true"/&gt;
  &lt;/information&gt;
  &lt;resources&gt;
    &lt;j2se href="http://java.sun.com/products/autodl/j2se" version="1.6+"/&gt;
  &lt;/resources&gt;
    &lt;resources&gt;<font color="red">
    &lt;jar download="eager" href="dist/JPAWebStartMain.jar" main="false"/&gt;
  &lt;/resources&gt;
  &lt;resources&gt;
    &lt;extension href="JPAPermissions.jnlp" name="jpa"/&gt;
  &lt;/resources&gt;
  &lt;application-desc main-class="demo.main.JPADemo"/&gt;</font>
&lt;/jnlp&gt;
</pre>
</td></tr>
</table>
<p>
I made the following changes to  JPAWebStart.jnlp:
<ul><li>Start the application via a new program which resides in the jar JPAWebStartMain.jar
  <li>Use the extension element to reference the JPAPermissions.jnlp which contains the jars that needed to be signed as well as grant the access beyond what is allowed by the sandbox
  </li>
</ul>
<p>
Here is the<strong> JPAPermissions.jnlp</strong> which contains all of the signed jars and enables the extra security access:
<p>
<table border="1" cellpadding="10" cellspacing="0" width="67%" >
<tr><td>
<pre style="color: darkblue;">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE jnlp PUBLIC "-//Sun Microsystems, Inc.//DTD JNLP 1.5//EN" "http://www.netbeans.org/jnlp/DTD/jnlp.dtd"&gt;
&lt;jnlp codebase="file:///C:/Netbeans/JPAWebStart" href="JPAPermissions.jnlp"&gt;
   &lt;information&gt;
    &lt;title&gt;JPAPermissions&lt;/title&gt;
    &lt;vendor&gt;Company, Inc.&lt/vendor&gt;
    &lthomepage href="homepage.html"/&gt;
    &lt;description&gt; &lt/description&gt;
    &lt;icon href="default"/&gt;
    &lt;offline-allowed/&gt;
    &lt;shortcut online="true"/&gt;
  &lt;/information&gt;<font color="red">
   &lt;security&gt;
      &lt;all-permissions/&gt;
   &lt;/security&gt;</font>
  &lt;resources&gt;
    &lt;jar download="eager" href="dist/lib/toplink-essentials.jar" main="false" version=""/&gt;
  &lt;/resources&gt;
  &lt;resources&gt;
    &lt;jar download="eager" href="dist/lib/derby.jar" main="false" version=""/&gt;
  &lt;/resources&gt;
  &lt;resources&gt;
    &lt;jar download="eager" href="dist/JPAWebStart.jar" main="false"/&gt;
  &lt;/resources&gt; 
  &lt;component-desc/&gt;
&lt;/jnlp&gt;</pre>
</td></tr>
</table>
<p>
Next, we need to sign the jars.  To do this I added a -post-jar target to the default build.xml in my NetBeans project:
<p>
<table border="1" cellpadding="10" cellspacing="0" width="67%" >
<tr><td>
<pre style="color: darkblue;">
    &lt;target name="-post-jar"&gt;
        &lt;property name="key-alias" value="jpawebstart"\&gt;
        &lt;property name="keystore.password" value="foobar"\&gt;
        &lt;property name="keystore.location" value="dist/keystore"\&gt;
        &lt;delete file="${keystore.location}"\&gt;
        &lt;genkey alias="${key-alias}" keystore="${keystore.location}" storepass="${keystore.password}" validity="3650" dname="CN=jpawebstart, OU=jpawestart, O=net, C=US"\&gt;
        
        &lt;signjar jar="dist/JPAWebStart.jar"  alias="${key-alias}" keystore="${keystore.location}" storepass="${keystore.password}"\&gt;
        &lt;signjar jar="dist/lib/derby.jar" alias="${key-alias}" keystore="${keystore.location}" storepass="${keystore.password}"\&gt;
        &lt;signjar jar="dist/lib/toplink-essentials.jar"  alias="${key-alias}" keystore="${keystore.location}" storepass="${keystore.password}"\&gt;
        
        &lt;jar destfile="dist/JPAWebStartMain.jar" 
             basedir="build/classes"
             includes="demo/main/**"
             manifest="MANIFEST_MAIN.MF"
         \&gt;
    &lt;/target&gt;
</pre>
</td></tr>
</table>
<p>
One other addition to the -post-jar target is the creation of the jar file that is referenced in JPAWebStart.jnlp.  Why am I doing it here you ask?  Well, it was easier then overriding all of the default targets for building the application that NetBeans provides (if someone has an alternative suggestion, let me know).
<p>
<h3>About the JPAWebStart sample application</h3>

<p>The sample application demonstrates the use of the Java Persistence API from Java SE,  using Swing, Java DB and Java Web Start:</p>
<p>When the application is started the main screen is shown:</p>
<p><img src="http://weblogs.java.net/blog/lancea/archive/ContactMain.JPG" width="650" height="554"> </p>
<p>There are no contacts in the database when the application is started. To add contacts to the database, you would select the Contacts menu item, &quot;Add Contact&quot;</p>
<p><img src="http://weblogs.java.net/blog/lancea/archive/AddContact.JPG" width="650" height="554"></p>
<p> and the following form will be opened: </p>
<p><img src="http://weblogs.java.net/blog/lancea/archive/ContactDialog.png" width="438" height="349">
<p>
The main entry point to the application is the JPADemo class.  JPADemo is packaged in the jar JPAWebStartMain.jar and its sole purpose is to start the rest of the application which requires more permissions than the sandbox allows:
<p>
<table border="1" cellpadding="10" cellspacing="0" width="35%" >
<tr><td>
<pre style="color: darkblue;">
package demo.main;
import demo.ui.JPAWebStartDemo;
public class JPADemo {
    
    /** Creates a new instance of JPADemo */
    public JPADemo() {
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
       java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new JPAWebStartDemo().setVisible(true);
            }
        });
    }
    
}
</pre>
</td></tr>
</table>
<p>
<p>As this is a simple demo, there is only one Entity used by the application, Contact:
<p>
<table border="1" cellpadding="10" cellspacing="0" width="35%" >
<tr><td>
<pre style="color: darkblue;">
package demo.entity;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Entity class Contact
 * 
 */

@Entity
@Table(name="Contacts")
public class Contact implements Serializable {

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

    private String firstName;
    private String lastName;
    private String phone;
    
    /**
     * Creates a new instance of Contact
     */
    public Contact() {
    }

    /**
     * Creates a new instance of Contact
     */
    public Contact(String firstName, String lastName, String phone) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.phone = phone;
    }
    /**
     * Gets the id of this Contact.
     * 
     * @return the id
     */
    public Long getId() {
        return this.id;
    }

    /**
     * Sets the id of this Contact to the specified value.
     * 
     * @param id the new id
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * Returns a hash code value for the object.  This implementation computes 
     * a hash code value based on the id fields in this object.
     * @return a hash code value for this object.
     */
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (this.id != null ? this.id.hashCode() : 0);
        return hash;
    }

    /**
     * Determines whether another object is equal to this TestPerson.  The result is 
     * <code>true</code> if and only if the argument is not null and is a TestPerson object that 
     * has the same id field values as this object.
     * 
     * @param object the reference object with which to compare
     * @return <code>true</code> if this object is the same as the argument;
     * <code>false</code> otherwise.
     */
    @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 Contact)) {
            return false;
        }
        Contact other = (Contact)object;
        if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) return false;
        return true;
    }

    /**
     * Returns a string representation of the object.  This implementation constructs 
     * that representation based on the id fields.
     * @return a string representation of the object.
     */
    @Override
    public String toString() {
        return "entity.Contact[id=" + id + "], firstName= " + firstName + ", lastName= " + lastName + ", phone= " + phone;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }  
    
}
 </pre>
</td></tr>
</table>
<p>To persist a new Contact, the addContact() method  of ContactImpl is called: 
<p>
<table border="1" cellpadding="10" cellspacing="0" width="35%" >
<tr><td>
<pre style="color: darkblue;">
public void addContact(Contact contact) {
        try{
            em = emf.createEntityManager();
            em.getTransaction().begin();
            em.persist(contact);
            em.getTransaction().commit();
            System.out.println("row created");
            
        } finally {
            em.close();
        }
    }
</pre>
</td></tr>
</table>

<p>Because this application is strictly a Java SE application and not running inside of a container, the application must do the following:</p>
<ul>
  <li> Explicitly create an EntityManagerFactory by calling <strong>Persistence.createEntityManagerFactory()</strong></li>
  <p>
<table width="37%" height="73" border="1" cellpadding="10" cellspacing="0" >
<tr><td>
<pre style="color: darkblue;">
  emf = Persistence.createEntityManagerFactory("JPAWebStartPU"); 
</pre>
</td></tr>
</table>       
  <p>&nbsp;</p>
  <li>Create an application managed EntityManager by calling the method <strong>createEntityManager() </strong>on an EntityManagerFactory instance in each method as an EntityManager is lightweight and not thread safe </li>
  <li>Explicitly control the transaction (this is a Resource-Local Transaction). The application must acquire an instance of EntityTransaction and then call the methods <strong>begin()</strong>, <strong>commit()</strong> and <strong>rollback()</strong> as needed. </li>
  <li>Close the EntityManger by calling the <strong>close()</strong> method. It is recommended that this is done in a finally block to guarantee that the EntityManager is closed. </li>
</ul>
<p>One other thing to note is that in order to run TopLink Essentials with Java Web Start, you must <strong>enable privileges</strong> for the call to Peristence.createEntityManagerFactory which is done in the ContactImpl constructor:  </p>
<ul>
  <p>
  <table width="37%" height="73" border="1" cellpadding="10" cellspacing="0" >
    <tr>
      <td><pre style="color: darkblue;">public ContactImpl() {
        
        <span class="style1">emf = (EntityManagerFactory ) AccessController.doPrivileged(
                new PrivilegedAction() {
            public Object run() {
                return Persistence.createEntityManagerFactory("JPAWebStartPU");
            }
        }
        );</span>
    }</pre>
      </td>
    </tr>
  </table>
</ul>
<p>&nbsp;</p>
<p>If you do not enable privileges for Peristence.createEntityManagerFactory, then you will encounter the following Exception:</p>
<table border="1" cellpadding="10" cellspacing="0" width="67%" >
  <tr>
    <td><pre style="color: darkblue;">----------------------------------------------------<br>Exception in thread &quot;AWT-EventQueue-0&quot; java.security.AccessControlException: access denied (java.util.PropertyPermission toplink.logging.level read)<br>	at java.security.AccessControlContext.checkPermission(Unknown Source)<br>	at java.security.AccessController.checkPermission(Unknown Source)<br>	at java.lang.SecurityManager.checkPermission(Unknown Source)<br>	at java.lang.SecurityManager.checkPropertyAccess(Unknown Source)<br>	at java.lang.System.getProperty(Unknown Source)<br>	at oracle.toplink.essentials.internal.ejb.cmp3.JavaSECMPInitializer.getTopLinkLoggingLevel(JavaSECMPInitializer.java:99)<br>	at oracle.toplink.essentials.internal.ejb.cmp3.JavaSECMPInitializer.initializeFromMain(JavaSECMPInitializer.java:272)<br>	at oracle.toplink.essentials.internal.ejb.cmp3.JavaSECMPInitializer.getJavaSECMPInitializer(JavaSECMPInitializer.java:80)<br>	at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.createEntityManagerFactory(EntityManagerFactoryProvider.java:118)<br>	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)<br>	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60)<br>	at demo.ContactImpl.&lt;init&gt;(ContactImpl.java:42)<br>	at demo.ContactFactory.getInstance(ContactFactory.java:28)<br>	at demo.ContactTableModel.&lt;init&gt;(ContactTableModel.java:34)<br>	at demo.ui.JPAWebStartDemo.initComponents(JPAWebStartDemo.java:134)<br>	at demo.ui.JPAWebStartDemo.&lt;init&gt;(JPAWebStartDemo.java:23)<br>	at demo.main.JPADemo$1.run(JPADemo.java:30)<br>	at java.awt.event.InvocationEvent.dispatch(Unknown Source)<br>	at java.awt.EventQueue.dispatchEvent(Unknown Source)<br>	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)<br>	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)<br>	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)<br>	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)<br>	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)<br>	at java.awt.EventDispatchThread.run(Unknown Source</pre>
    </td>
  </tr>
</table>
<p>When we configure the persistence.xml we will need to indicate that we are using <strong>a Resource-Local Transaction</strong></p>
<table width="37%" height="73" border="1" cellpadding="10" cellspacing="0" >
    <tr>
      <td>
	  <pre style="color: darkblue;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;persistence version="1.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_1_0.xsd"&gt;
  &lt;persistence-unit name="JPAWebStartPU" <span class="style1">transaction-type="RESOURCE_LOCAL"</span>&gt;
    &lt;provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider&lt;/provider&gt;
    &lt;class>demo.entity.Contact&lt;/class&gt;
    &lt;properties&gt;
      &lt;property name="toplink.jdbc.url" value="jdbc:derby:testDB;create=true"/&gt;
      &lt;property name="toplink.jdbc.user" value="APP"/&gt;
      &lt;property name="toplink.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/&gt;
      &lt;property name="toplink.jdbc.password" value="APP"/&gt;
      &lt;property name="toplink.ddl-generation" value="drop-and-create-tables"/&gt;
      &lt;property name="toplink.logging.level" value="FINE"/&gt;
    &lt;/properties&gt;
  &lt;/persistence-unit&gt;
&lt;/persistence&gt;
 </pre>
      </td>
    </tr>
</table>
</ul>
<p>&nbsp;</p>
<p>After adding  a few contacts, you can then query the database allowing for the rows to either be deleted or modified:</p>
<p><img src="http://weblogs.java.net/blog/lancea/archive/JPAWebStart.PNG" width="510" height="446"> </p>

<p>The application provides an implementation of the JTable TableModel interface, ContactTableModel, which is used to manage the display and modification of the rows within the JTable. </p>
<table border="1" cellpadding="10" cellspacing="0" width="35%" >
<tr><td>
<pre style="color: darkblue;">    
package demo;

import demo.entity.Contact;
import java.util.ArrayList;
import java.util.List;
import javax.swing.table.AbstractTableModel;
/*
 * ContactTableModel.java
 *
 * Created on May 23, 2007, 4:59 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

/**
 *
 * @author Owner
 */
public class ContactTableModel extends AbstractTableModel {
    
    private  List<String> columnNames;
    private List<Contact> contacts;
    private Contacts contactImpl;
    
    private final int FIRSTNAME = 0;
    private final int LASTNAME = 1;
    private final int PHONE = 2;
    
    /**
     * Creates a new instance of ContactTableModel
     */
    public ContactTableModel() {
        
        contacts = new ArrayList<Contact>();
        contactImpl = ContactFactory.getInstance(ContactFactory.ConfigApi.USE_JPA);
        columnNames = new ArrayList<String>();
        columnNames.add( "FIRST NAME");
        columnNames.add( "LAST NAME");
        columnNames.add( "PHONE NUMBER");
        
    }
    
    /*
     * Return the Column name for the current column
     */
    public String getColumnName(int column) {
        return columnNames.get(column);
        
    }
    
    /*
     * Return the number of Rows in our table
     */
    public int getRowCount() {
        return contacts.size();
    }
    
    /**
     * Return the number of Columns in our table
     */
    public int getColumnCount() {
        return columnNames.size();
    }
    
    /**
     * Allow all columns to be updatable
     * @param  row Row number in the JTable
     * @param  col Column number for the row in the JTable
     */
    public boolean isCellEditable(int row, int col) {
        // All columns are edititable
        return true;
        
    }
    
    /**
     * Return the column value for the specified  columnIndex and rowIndex.
     * @param  rowIndex Row number in the JTable
     * @param  columnIndex Column number for the row in the JTable
     */
    public Object getValueAt(int rowIndex, int columnIndex) {
        String result = null;
        if (contacts.size() != 0) {
            Contact c = contacts.get(rowIndex);
            
            switch( columnIndex) {
                case FIRSTNAME:
                    result = c.getFirstName();
                    break;
                case LASTNAME:
                    result = c.getLastName();
                    break;
                case PHONE:
                    result = c.getPhone();
                    break;
            }
            
        }
        return result;
    }
    
    /**
     * Sets the column value specified at columnIndex and rowIndex to value.
     * @param  value New value for the column
     * @param  rowIndex Row number in the JTable
     * @param  columnIndex Column number for the row in the JTable
     */
    public void setValueAt(Object value, int rowIndex, int columnIndex) {
        
        System.out.println("Setting value at " + rowIndex + "," + columnIndex
                + " to " + value + " (an instance of " + value.getClass() + ")");
        
        Contact c = contacts.get(rowIndex);
        String result = null;
        switch( columnIndex) {
            case FIRSTNAME:
                c.setFirstName((String) value);
                break;
            case LASTNAME:
                c.setLastName((String) value);
                break;
            case PHONE:
                c.setPhone((String) value);
                break;
        }
        
        contacts.set(rowIndex, c);
        fireTableCellUpdated(rowIndex, columnIndex);
    }
    
    /**
     * Add a new contact
     * @param p  A new Contact(entity)
     * 
     */
    public void addContact(Contact p) {
        if (p != null) {
            contactImpl.addContact(p);
        } else {
            System.out.println("No row to persist");
        }
    }
    /**
     * Query the database for Contacts using the criteria specified
     * @param firstName  First name of the contact
     * @param lastName   Last name of the contact
     * @param phone      Phone number of the contact
     * @return           The number of rows that matched the selection criteria
     */
    public int executeQuery(String firstName, String lastName, String phone) {
        System.out.println("first=" + firstName + "- last ="+ lastName + "- phone=" + phone +"-");
        contacts= contactImpl.executeQuery( firstName,  lastName,  phone);
        
        if (contacts.size() != 0 ) {
            fireTableDataChanged();
        }
        return contacts.size();
    }
    /**
     * Utility method which is just used for debugging
     */
    public Contact getRow(int row ) {
        return contacts.get(row);
    }
    
    /**
     * Delete the selected row from the JTable and database
     * @param selectedRow  The row number displayed in the JTable to delete from the database
     */
    public void deleteContact(int selectedRow) {
        contactImpl.removeContact(contacts.get(selectedRow));
        contacts.remove(selectedRow);
        fireTableRowsDeleted(selectedRow, selectedRow);
        
    }
    /**
     * Update the selected row in the JTable and database
     * @param selectedRow  The row number displayed in the JTable to update in the database
     */
    public void updateContact(int selectedRow) {
        contactImpl.updateContact(contacts.get(selectedRow));
    }
    
}
</pre>
</td></tr>
</table>
<p>The ContactTableModel invokes the static factory <strong>ContactFactory.getInstance()</strong> to obtain an instance of ContactImpl which in our example is implemented using the Java Persistence API. This factory allows for providing  additional implementations for accessing the database such as JDBC.</p>
<table border="1" cellpadding="10" cellspacing="0" width="35%" >
<tr><td>
<pre style="color: darkblue;"> 
contactImpl = ContactFactory.getInstance(ContactFactory.ConfigApi.USE_JPA);
</pre>
</td></tr>
</table>
<p>When a query is submitted, it is built as a dynamic query.  Normally you will find the use of Named queries more efficient.  However, sometimes you will find you need to use a dynamic query based 
  on the number of parameters that might be optional.
</p>
<p>
<table border="1" cellpadding="10" cellspacing="0" width="35%" >
<tr><td>
<pre style="color: darkblue;"> 
    public List<Contact> executeQuery(String firstName, String lastName, String phone) {
        Query q = null;
        List<Contact> result = null;
        boolean paramSpecified = false;
        StringBuffer buf = new StringBuffer("Select c from Contact c where ");
        String query = null;        
        
        if (!firstName.equals(EMPTYSTRING)) {
            paramSpecified = true;
            buf.append("upper(c.firstName) like :firstName and ");
        }
        if (!lastName.equals(EMPTYSTRING)) {
            paramSpecified = true;
            buf.append("upper(c.lastName) like :lastName and ");
        }
        if (!phone.equals(EMPTYSTRING)) {
            paramSpecified = true;
            buf.append("upper(c.phone) like :phone and ");
        } 
        
        // If there are parameters specified, then remove the last "and" otherwise
        // remove "where" from the end of the query.
        if (paramSpecified) {
            query = buf.substring(0, buf.length() - " and".length());
        } else {
            query = buf.substring(0, buf.length() - " where ".length());
        }
        System.out.println("Query is \"" + query + "\"");
        
        try {
            em = emf.createEntityManager();
            q = em.createQuery(query);
            
            if (!firstName.equals(EMPTYSTRING)) {
                q = q.setParameter("firstName", "%"+firstName.toUpperCase()+"%");
            }
            if (!lastName.equals(EMPTYSTRING)) {
                q = q.setParameter("lastName", "%"+lastName.toUpperCase()+"%");
            }
            if (!phone.equals(EMPTYSTRING)) {
                q = q.setParameter("phone", "%"+ phone.toUpperCase()+"%");
            }
            
            result = q.getResultList();
            System.out.println("rows returned=" + result.size());
        } finally {
            em.close();
        }        
        return result;
    }      
</pre>
</td></tr>
</table>
<p>All of the rows that are displayed in the JTable are <strong>detached</strong> and must be <strong>managed</strong> by the persistence context prior to committing the transaction. This is accomplished by calling the EntityManager method<strong> merge() </strong>prior to committing the transaction:</p>
<table border="1" cellpadding="10" cellspacing="0" width="35%" >
<tr><td>
<pre style="color: darkblue;">    
    /**
     * Remove a contact to the database.  The contact that is
     * passed in, needs to be merged prior to removing.
     * @param  contact  The Contact to remove
     */
    public void removeContact(Contact contact) {
        try {
            if(contact  != null) {
                em = emf.createEntityManager();
                em.getTransaction().begin();
                <span class="style1">Contact mergedContact = em.merge(contact);</span>
                <span class="style1">em.remove(mergedContact);</span>
                em.getTransaction().commit();
                System.out.println("row removed");
            }
        } finally {
            em.close();
        }       
        
    }
	
     /**
     * Update a contact in the database.  The contact that is
     * passed in, needs to be merged prior to the update.
     * @param  contact  The Contact to update
     */
    public void updateContact(Contact contact) {
        try {
            em = emf.createEntityManager();
            em.getTransaction().begin();
            <span class="style1">em.merge(contact);</span>
            em.getTransaction().commit();
            System.out.println("row :" + contact + " updated");
            
        } finally {
            em.close();
        }        
    }    
</pre>
</td>
</tr>
</table>

<p>
<h3>Configuring  the JPAWebStart application</h3>
<p>The following steps are needed to configure the JPAWebStart application:</p>
<ul>
  <li>The JPAWebStart application requires <a href="http://java.sun.com/javase/downloads/index.jsp">Java SE 6</a>. </li>
  <li>Download the <a href="http://weblogs.java.net/blog/lancea/archive/JPAWebStart.zip">JPAWebStart Application</a></li>
  <li>Optionally download and install <a href="http://www.netbeans.info/downloads/index.php">NetBeans</a> </li>
  <li>Optionally install the NetBeans Java Web Start plugin from the Update Center: NetBeans Update Center Beta </li>
  <li>Install <a href="http://developers.sun.com/javadb/downloads/index.jsp">Java DB</a> and update the NetBeans project properties to specify the location of the<a href="http://developers.sun.com/javadb/downloads/index.jsp"> Java DB embedded JDBC driver</a>. </li>
</ul>
<blockquote>
  <p><img src="http://weblogs.java.net/blog/lancea/archive/Properties.png" width="622" height="188"> </p>
</blockquote>
<p>&nbsp;</p>
<ul>
  <li>If you are going to run the JPAWebStart application using the javaws command, then you need to modify the <strong>jnlp</strong> elements in the files <strong>JPAWebStart.jnlp</strong> and <strong>JPAPermissions.jnlp</strong> files specifying the correct codebase:</li>
</ul>
<ul>
  <table border="1" cellpadding="10" cellspacing="0" width="35%" >
    <tr>
      <td><pre style="color: darkblue;">   
&lt;jnlp codebase=<span class="style1">"file:///C:/Netbeans/JPAWebStart"</span> href="http://weblogs.java.net/blog/lancea/archive/JPAWebStart.jnlp"&gt;
  </pre>
      </td>
    </tr>
  </table>
  <p>For, example if you are on unix and installed  JPAWebStart in /tmp, you would modify the jnlp element in <strong>JPAWebStart.jnlp</strong> and <strong>JPAPermissions.jnlp</strong> to be: </p>
</ul>
<ul>
  <table border="1" cellpadding="10" cellspacing="0" width="35%" >
    <tr>
      <td><pre style="color: darkblue;">   
&lt;jnlp codebase=<span class="style1">"file:///tmp/JPAWebStart"</span> href="JPAWebStart.jnlp"&gt;
  </pre>
      </td>
    </tr>
  </table>
</ul>
<h3>Running the JPAWebStart application</h3>
<p>You can run the JPAWebStart application using Java Web Start in multiple ways:</p>
<ul>
  <li>Using the <strong>javaws</strong> command</li>
</ul>
<ul>
  <table border="1" cellpadding="10" cellspacing="0" width="35%" >
    <tr>
      <td><pre style="color: darkblue;">   
javaws JPAWebStart.jnlp</pre>
      </td>
    </tr>
  </table>
</ul>
<ul>
  <li>Running using the NetBeans Java Web Start plugin: </li>
</ul>
<p><img src="http://weblogs.java.net/blog/lancea/archive/RunViaWebStart.JPG" width="650" height="710"> </p>
<h3>&nbsp;</h3>
<ul>
  <li>Deploying and then running from a web browser using  the NetBeans Java Web Start plugin:</li>
</ul>
<blockquote>
  <p>	<img src="http://weblogs.java.net/blog/lancea/archive/DeployWebStart.JPG" width="650" height="687"></p>
</blockquote>
<p>&nbsp;</p>
<ul>
  <ul>
    <ul>
      <li>After the application deploys, a web browser will be launched allowing you to start the JPAWebStart application:</li>
    </ul>
  </ul>
  <blockquote>
    <p><img src="http://weblogs.java.net/blog/lancea/archive/StartViaBrowser.JPG" width="772" height="743"> </p>
  </blockquote>
</ul>
<h3>&nbsp;</h3>
<h3>Summary</h3>
<p>This blog provides an overview of how to successfully develop a Java SE application using Java Web Start, Java Persistence API, Swing and NetBeans 5.5. In order to use Java Web Start with the Java Persistence API, you must enable security and sign the jars for the classes which need more access than the Java Web Start sandbox allows.</p>
<p>The following are additional references which you might find useful when developing applications using the technologies demonstrated in this article:  </p>
<ul>
  <li>The <a href="http://jcp.org/en/jsr/detail?id=220">Java Persistence API Specification</a></li>
  <li>The Glassfish Persistence <a href="https://glassfish.dev.java.net/javaee5/persistence/">home page </a></li>
  <li>The Swing Tutorial on<a href="http://java.sun.com/docs/books/tutorial/uiswing/components/table.html"> creating and using JTables</a></li>
  <li>The Java Web Start <a href="http://java.sun.com/javase/6/docs/technotes/guides/javaws/developersguide/contents.html">Developer Guide </a></li>
  <li>The Java DB <a href="http://developers.sun.com/javadb/reference/docs/index.jsp">documentation</a></li>
</ul>
<p>&nbsp;</p>
<p>Special thanks to Mitesh, Markus and Ryan for a quick review, testing and suggestions for the blog.. </p>
<p>&nbsp; </p>
<ul>
  <p>&nbsp;</p>
</ul>
<p>&nbsp;</p>
</body>
</html>
]]>

</content>
</entry>
<entry>
<title>More JDBC 4.0 drivers are now available</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2007/03/more_jdbc_40_dr.html" />
<modified>2007-03-28T21:57:12Z</modified>
<issued>2007-03-28T21:57:05Z</issued>
<id>tag:weblogs.java.net,2007:/blog/lancea/161.6941</id>
<created>2007-03-28T21:57:05Z</created>
<summary type="text/plain">The number of available JDBC 4.0 drivers is continuing to expand.</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>Community: Java Enterprise</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[<a href="http://inetsoftware.de">inet software</a> has released JDBC 4.0 drivers  for Microsoft SQL Server(Merlia  driver) and for Oracle (Oranxo driver).
<p>
<a href="http://www.aveconnect.com/default.htm">Atinav </a>has also release a JDBC 4.0 driver for Microsoft SQL Server (aveConnect 4.0).]]>

</content>
</entry>
<entry>
<title>JDBC 4.0 and Java SE 6 have left the stable</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2006/12/jdbc_40_and_jav.html" />
<modified>2007-09-02T14:06:54Z</modified>
<issued>2006-12-11T17:11:42Z</issued>
<id>tag:weblogs.java.net,2006:/blog/lancea/161.6142</id>
<created>2006-12-11T17:11:42Z</created>
<summary type="text/plain">After a lot of hard work and effort by a many dedicated contributors, JDBC 4.0 and Java SE 6 are now final and have left the barn.</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>J2EE</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[Well, we have made it.  Java SE 6 and JDBC 4.0 are now final and have been released.  It has been an interesting and rewarding adventure!
<p>

Java SE 6 SDK bundles <a href =" http://developers.sun.com/javadb/">Java DB</a> which provides a JDBC 4.0 driver.  I suspect we will see quite a few JDBC 4.0 drivers soon and I will update this blog with the latest info.
<p>


JDBC 4.0 brings many new features such as improved LOB support, SQL XML data type support as well as many clarifications to the previous versions of the JDBC specification.
<p>
I once again, want to thank the members of the JDBC 4.0 expert group for their efforts in making the release of JSR 221 a success.
<p>
Once we catch our breadth, we will be looking at ways to continue to improve JDBC going forward and if you have suggestions, let me know.
<p>
Regards
<p>
Lance]]>

</content>
</entry>
<entry>
<title>JDBC 4.0 completes the Final Approval Ballot</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2006/11/jdbc_40_complet.html" />
<modified>2006-11-07T18:09:57Z</modified>
<issued>2006-11-07T18:07:44Z</issued>
<id>tag:weblogs.java.net,2006:/blog/lancea/161.5886</id>
<created>2006-11-07T18:07:44Z</created>
<summary type="text/plain">JDBC 4.0, JSR 221, has passed the Final Approval Ballot.</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>Community: Java Enterprise</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[JSR 221, JDBC 4.0, has successfully passed the Final Approval Ballot in the JCP Executive committee.  I would like to thank all of the JDBC 4.0 Expert Group members for their efforts on this specification.  JDBC 4.0 is being delivered as part of the Java SE 6 release.
<p>]]>

</content>
</entry>
<entry>
<title>JDBC EoD API Deferred</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2006/10/jdbc_eod_api_de.html" />
<modified>2006-10-05T17:54:23Z</modified>
<issued>2006-10-05T17:53:54Z</issued>
<id>tag:weblogs.java.net,2006:/blog/lancea/161.5687</id>
<created>2006-10-05T17:53:54Z</created>
<summary type="text/plain">We will not be releasing the JDBC EoD API as part of Java SE 6.</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>Community: Java Enterprise</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[As you are all aware, we are in the final end game for releasing Java SE 6 in December 2006.  As part of this process we
are actively testing all areas of Java SE.  During this testing effort we have discovered, much to our dismay,
that the quality of the JDBC EoD Reference Implementation (RI) is not where it should be in order to be released as part of Java SE 6.
<P>
Based on our analysis, we would not be able to stabilize the JDBC EoD RI without slipping the Java SE 6 schedule by at least  8 weeks, which is something that none of us want.
<p>
The JDBC 4.0 Expert Group agrees that we should not delay Java SE 6 for this feature and as of build 101 of Java SE 6, the JDBC EoD RI has been removed.
<P>

I do believe that the proposed features in the JDBC EoD API are useful and we will work toward including an improved version of the API  in Java SE 7. 
<p>]]>

</content>
</entry>
<entry>
<title>JDBC 4.0 PFD is now available</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2006/07/jdbc_40_pfd_is_1.html" />
<modified>2006-07-20T15:12:41Z</modified>
<issued>2006-07-20T15:12:30Z</issued>
<id>tag:weblogs.java.net,2006:/blog/lancea/161.5207</id>
<created>2006-07-20T15:12:30Z</created>
<summary type="text/plain">The JDBC 4.0 PFD is now available for review.</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>Community: Java Enterprise</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[The JDBC 4.0 PFD contains many clarifications to the JDBC spec including the JDBC API docs.  The majority of the changes are reflected in b91 of Java SE 6, Mustang.  Some of the areas of change include:
<p>
<ul>
<li>Revamping the SQLXML interface, <a href="http://weblogs.java.net/blog/lancea/archive/2006/05/jdbc_40_sqlxml.html">which which I blogged about earlier</a>
<li>Improvements to the JDBC compliance chapter which now incorporates the requirements for JDBC drivers in a Java EE environment.  This chapter will be pointed to by future Java EE specs.  This chapter also clarifies which methods must be supported and which methods are optional.  Optional methods that are not supported must throw a SQLFeatureNotSupportedException.

<li>Added the createArrayOf and createStruct to the Connection interface.

<li> getColumns also now indicates whether a column is auto-incremented

<li>Renamed ClientInfoException to SQLClientInfoException

<li>Renamed getFunctionParameters to getFunctionColumns

<li>Added support for system functions to getFunctions and getFunctionColumns

<li>Synced up the DatabaseMetaData methods: getColumns, getProcedures, 
getProcedureColumns, getTables, getTablePrivileges, getSchemas, getUDTS, getAttributes, getFunctions, getFunctionColumns so that the methods match ODBC and include catalog in its ordering 

<li>Added the scalar functions CHAR_LENGTH, CHARACTER_LENGTH, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, EXTRACT, OCTET_LENGTH,
POSITION which where added previously to ODBC

<li>Added methods to PreparedStatement, CallableStatement, ResultSet which do not require a length parameter for stream based methods (these methods are optional for this release)


</ul>


<p>]]>

</content>
</entry>
<entry>
<title>Java DB  provides a great way to try JDBC 4.0  features</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2006/06/java_db_provide_1.html" />
<modified>2006-06-15T18:44:22Z</modified>
<issued>2006-06-15T18:15:05Z</issued>
<id>tag:weblogs.java.net,2006:/blog/lancea/161.5032</id>
<created>2006-06-15T18:15:05Z</created>
<summary type="text/plain">Java DB and Apache Derby community has been working quite diligently to add support for JDBC 4.0 in their upcoming 10.2 alpha release</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>Community: JDK</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[Java DB and Apache Derby have been following the progress of the JDBC 4.0 specification very closely and have implemented many of the JDBC 4.0 features in the 10.2 alpha release.  Rick Hillegas has done a great job of leading the team implementing the JDBC 4.0 features.

<p>
Another key JDBC feature that has been added in the 10.2 release is support for updatable scrollable cursors.
<p>
You can find the latest status regarding the JDBC 4.0 features as well as the rest of the Java DB 10.2 features <a href="http://wiki.apache.org/db-derby/TenTwoSnapshot">here</a>.
<p>

Java DB will be available with Mustang later today (6/15) or tomorrow (6/16) as part of the JDK bundles for build 88, available at <a href="http://download.java.net/jdk6/binaries/">http://download.java.net/jdk6/binaries/</a>
<p>]]>

</content>
</entry>
<entry>
<title>JDBC 4.0  SQLXML Interface</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2006/05/jdbc_40_sqlxml.html" />
<modified>2006-05-03T14:54:13Z</modified>
<issued>2006-05-02T19:09:46Z</issued>
<id>tag:weblogs.java.net,2006:/blog/lancea/161.4627</id>
<created>2006-05-02T19:09:46Z</created>
<summary type="text/plain">JDBC 4.0 has introduced several new features which will be highlighted in blogs over the next few weeks.  Today&apos;s focus is on the SQLXML interface.</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>J2EE</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[Since the public draft of the JDBC spec, the JDBC EG has reworked the SQLXML interface completely providing for more flexibility.  The new version of the interface will be available in the Java SE 6 upcoming beta and should also be available in the current nightly builds.
<p>
 The SQLXML interface provides methods for accessing the XML data in a datasource as a String, a Reader or Writer, or as a Stream. The XML value may also be accessed through a Source or set as a Result, which are used with XML Parser APIs such as DOM, SAX, and StAX, as well as with XSLT transforms and XPath evaluations.
<p>
The revised interface includes the following methods:
<ul>
<li>free - closes the object and releases the resources that it held
<li>getBinaryStream - Retrieves the XML value designated by this SQLXML instance as a stream
<li>getCharacterStream -  Retrieves the XML value designated by this SQLXML instance as a java.io.Reader object
<li>getSource - Returns a Source for reading the XML value designated by this SQLXML instance
<li>getString -  Returns a string representation of the XML value designated by this SQLXML instance
<li>setBinaryStream - Retrieves a stream that can be used to write the XML value that this SQLXML instance represents
<li>setCharacterStream - Retrieves a stream to be used to write the XML value that this SQLXML instance represents
<li>setResult - Returns a Result for setting the XML value designated by this SQLXML instance
<li>setString - Sets the XML value designated by this SQLXML instance to the given String representation
</ul>
<p>

I have included some of the sample code we provided in the SQLXML javadoc:
<p>
 The XML value of the SQLXML instance may be obtained as a BinaryStream using
<p>
<pre>

   SQLXML sqlxml = resultSet.getSQLXML(column);
   InputStream binaryStream = sqlxml.getBinaryStream();
 </pre>

For example, to parse an XML value with a DOM parser:
<p>
<pre>
   DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
   Document result = parser.parse(binaryStream);
 </pre>

or to parse an XML value with a SAX parser to your handler:
<p>
<pre>
   SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
   parser.parse(binaryStream, myHandler);
 </pre>

or to parse an XML value with a StAX parser:
<p>
<pre>
   XMLInputFactory factory = XMLInputFactory.newInstance();
   XMLStreamReader streamReader = factory.createXMLStreamReader(binaryStream);
 </pre>
<p>

Because databases may use an optimized representation for the XML, accessing the value through getSource() and setResult() can lead to improved processing performance without serializing to a stream representation and parsing the XML.
<p>

For example, to obtain a DOM Document Node:
<p>
<pre>

   DOMSource domSource = sqlxml.getSource(DOMSource.class);
   Document document = (Document) domSource.getNode();
 </pre>

To set the value to a DOM Document Node to myNode:
<p>
<pre>

   DOMResult domResult = sqlxml.setResult(DOMResult.class);
   domResult.setNode(myNode);
  </pre>

To send SAX events to your handler:
<p>
<pre>

   SAXSource saxSource = sqlxml.getSource(SAXSource.class);
   XMLReader xmlReader = saxSource.getXMLReader();
   xmlReader.setContentHandler(myHandler);
   xmlReader.parse(saxSource.getInputSource());
 </pre>

To set the result value from SAX events:
<p>
<pre>

   SAXResult saxResult = sqlxml.setResult(SAXResult.class);
   ContentHandler contentHandler = saxResult.getXMLReader().getContentHandler();
   contentHandler.startDocument();
   // set the XML elements and attributes into the result
   contentHandler.endDocument();
  </pre>

To obtain StAX events:
<p>
<pre>

   StAXSource staxSource = sqlxml.getSource(StAXSource.class);
   XMLStreamReader streamReader = staxSource.getXMLStreamReader();
  </pre>

To set the result value from StAX events:
<p>
<pre>

   StAXResult staxResult = sqlxml.getResult(StAXResult.class);
   XMLStreamWriter streamWriter = staxResult.getXMLStreamWriter();
  </pre>

To perform XSLT transformations on the XML value using the XSLT in xsltFile output to file resultFile:
<p>
<pre>

   File xsltFile = new File("a.xslt");
   File myFile = new File("result.xml");
   Transformer xslt = TransformerFactory.newInstance().newTransformer(new StreamSource(xsltFile));
   Source source = sqlxml.getSource(null);
   Result result = new StreamResult(myFile);
   xslt.transform(source, result);
  </pre>

To evaluate an XPath expression on the XML value:
<p>
<pre>

   XPath xpath = XPathFactory.newInstance().newXPath();
   DOMSource domSource = sqlxml.getSource(DOMSource.class);
   Document document = (Document) domSource.getNode();
   String expression = "/foo/@bar";
   String barValue = xpath.evaluate(expression, document);
  </pre>

To set the XML value to be the result of an XSLT transform:
<p>
<pre>

   File sourceFile = new File("source.xml");
   Transformer xslt = TransformerFactory.newInstance().newTransformer(new StreamSource(xsltFile));
   Source streamSource = new StreamSource(sourceFile);
   Result result = sqlxml.setResult(null);
   xslt.transform(streamSource, result);
 </pre>

Any Source can be transformed to a Result using the identity transform specified by calling newTransformer():
<p>
<pre>

   Transformer identity = TransformerFactory.newInstance().newTransformer();
   Source source = sqlxml.getSource(null);
   File myFile = new File("result.xml");
   Result result = new StreamResult(myFile);
   identity.transform(source, result);
  </pre>

To write the contents of a Source to standard output:
<p>
<pre>
   Transformer identity = TransformerFactory.newInstance().newTransformer();
   Source source = sqlxml.getSource(null);
   Result result = new StreamResult(System.out);
   identity.transform(source, result);
  </pre>

To create a DOMSource from a DOMResult:
<p>
<pre>

    DOMSource domSource = new DOMSource(domResult.getNode()); 
  </pre>]]>

</content>
</entry>
<entry>
<title>JDBC 4.0  RowId Interface</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2006/03/jdbc_40_rowid_i.html" />
<modified>2006-03-10T23:39:02Z</modified>
<issued>2006-03-10T23:32:18Z</issued>
<id>tag:weblogs.java.net,2006:/blog/lancea/161.4293</id>
<created>2006-03-10T23:32:18Z</created>
<summary type="text/plain">JDBC 4.0 has introduced several new features which will be highlighted in blogs over the next few weeks.  Today&apos;s focus is on the RowId interface.</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>J2EE</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[The RowID interface was added to JDBC 4.0 in order to support the ROWID datatype which is supported by databases such as Oracle and DB2.  A ROWID may be thought of as the address for a given row within a table and maybe be considered either logical or physical depending on the underlying data source.
<p>

The lifetime of a RowId object may be valid as long as the row is not deleted and the lifetime of the RowId is within the bounds of the lifetime of the RowId's data source.

The DatabaseMetaDataMethod.getRowIdLifetime() can be used to 
determine the lifetime validity of the RowId object.  The return value from this method is a RowIdLifetime enumerated data-type.  Possible values are:

<ul>
<li>ROWID_UNSUPPORTED  - backend does not support RowIds
<li>ROWID_VALID_OTHER - lifetime of the RowId is implementation dependant
<li>ROWID_VALID_TRANSACTION - lifetime of the RowId is within the transaction as long as the row is not deleted
<lI>ROWID_VALID_SESSION - the lifetime of the RowId is as long as the session as long as the row is not deleted
<lI>ROWID_VALID_FOREVER - the lifetime of the RowId is unlimited as long as the row is not deleted
</ul>
<p>

You can obtain a ROWID using the ResultSet.getRowId() method and may use the PreparedStatement.setRowId() to use a RowId in query.
<p>

A RowId object value is typically not portable between data sources and should be considered as specific to the data source when using the set or update method in PreparedStatement and ResultSet objects respectively. It is therefore inadvisable to get a RowId from a ResultSet object with a connection ’Foo’ and then attempt to use the RowId in a unrelated ResultSet object with a connection ’Bar’.
<p>]]>

</content>
</entry>
<entry>
<title>JDBC 4.0  Wrapper Interface</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2006/02/jdbc_40_wrapper.html" />
<modified>2006-02-23T22:46:39Z</modified>
<issued>2006-02-23T22:46:21Z</issued>
<id>tag:weblogs.java.net,2006:/blog/lancea/161.4188</id>
<created>2006-02-23T22:46:21Z</created>
<summary type="text/plain">JDBC 4.0 has introduced several new features which will be highlighted in blogs over the next few weeks.  Today&apos;s focus is on the Wrapper Interface.</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>J2EE</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[The Wrapper interface provides a mechanism for JDBC users to be able to access an instance of a resource which has been wrapped for architectural reasons. This mechanism helps to eliminate the need to use non-standard means to access vendor specific resources.
<p>
The following JDBC interfaces are subinterfaces of the Wrapper interface:
<p>
<ul>
<li> java.sql.Connection
<li>java.sql.DatabaseMetaData
<li>java.sql.ParameterMetaData
<li>java.sql.ResultSet
<li>java.sql.ResultSetMetaData
<li>java.sql.Statement
<li>javax.sql.Datasource
</ul>

<p>

The Wrapper interface consists of two methods:
<p>
<ul>
<li>isWrapperFor - Returns true if this either implements the interface argument or is directly or indirectly a wrapper for an object that does.
<li> unwrap - Returns an object that implements the given interface to allow access to non-standard methods, or standard methods not exposed by the proxy.
</ul>

Here is a simple example of using these new methods:
<p>
<pre>
  Statement stmt = conn.createStatement();
  Class clzz = Class.forName("oracle.jdbc.OracleStatement");
  OracleStatement os;
  if(stmt.isWrapperFor(clzz)) {
     os = stmt.unwrap(clzz);
     os.defineColumnType(1, Types.NUMBER);
  }

</pre>
]]>

</content>
</entry>
<entry>
<title>JDBC 4.0 SQLException Enhancements</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2006/02/jdbc_40_sqlexce.html" />
<modified>2006-02-21T19:58:20Z</modified>
<issued>2006-02-21T19:58:11Z</issued>
<id>tag:weblogs.java.net,2006:/blog/lancea/161.4174</id>
<created>2006-02-21T19:58:11Z</created>
<summary type="text/plain">JDBC 4.0 has introduced several new features which will be highlighted in blogs over the next few weeks.  Today&apos;s focus is on SQLException enhancements.</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>J2EE</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[The following enhancements were made in JDBC 4.0  in order to provide a better developer's experience when dealing with SQLExceptions:

<UL>
<li> Support for causal relationships
<li> For-each loop support
<li> New SQLException sub-classes
</ul>

<h3>Causal Relationship Support</h3>

We have added support for the Java SE chained exception mechanism by adding additional constructors allowing for the cause to be specified.  The cause could be a non-SQLException, it is just what resulted in the SQLException being thrown.
<p>
This feature does not reduce the need for the getSQLException() method  as it is possible for multiple  unique SQLExceptions to be generated (not all DBs do this currently but could going forward and is allowed by the SQL Standard) due to executing a statement on the backend. 
<p>

Your code would look something like the following to process the causal relationships:
<p>
<pre>
catch(SQLException ex) {
     while(ex != null) {
        System.out.println("SQLState:" + ex.getSQLState());
        System.out.println("Error Code:" + ex.getErrorCode());
        System.out.println("Message:" + ex.getMessage());
        Throwable t = ex.getCause();
        while(t != null) {
            System.out.println("Cause:" + t);
            t = t.getCause();
        }
        ex = ex.getNextException();
    }
}

</pre>


<h3>For Each Loop Support</h3>

The SQLException class now implements the Iterable interface providing support for the For each loop feature added in J2SE 5.0.  The navigation of the loop will walk through the SQLException and its cause (if any):
<p>

<pre>

catch(SQLException ex) {
     for(Throwable e : ex ) {
        System.out.println("Error encountered: " + e);
     }
}

</pre>

<h3>Categorization of SQLExceptions</h3>

JDBC 4.0 has introduced two categories of SQLException: SQLTransientException and SQLNonTransientException.  
<p>

A SQLNonTransientException would be thrown in instances where a retry of the same operation would fail unless the cause of the
SQLException is corrected.  The following Exceptions have been added, each extending SQLNonTransientException:
<p>
  
<ul>
<li>SQLFeatureNotSupportedException
<lI>SQLNonTransientConnectionException
<li>SQLDataException
<li>SQLIntegrityConstraintViolationException
<li>SQLInvalidAuthorizationException
<li>SQLSyntaxErrorException
</ul>

<p>
A SQLTransientException will be thrown in situations where a previously failed operation might be able to succeed when the operation is retried without any intervention by application-level functionality. The following Exceptions have been added, each extending SQLTransientException:
<p>
  
<ul>
<lI>SQLTransientConnectionException
<li>SQLTransactionRollbackException
<li>SQLTimeoutException
</ul>
<p>
Please refer to the JDBC specification to see the SQLState Class value code that is associated with the new SQLExceptions.
<p>

<h3>Correct SQLState for a DataTruncation on a write operation</h3>

We have also fixed a long outstanding JDBC bug so that the SQLState of  22001 is now returned for a DataTruncation Exception during a write operation to a data source.
<p>]]>

</content>
</entry>
<entry>
<title>JDBC 4.0 keeps moving forward</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/lancea/archive/2006/02/jdbc_40_keeps_m.html" />
<modified>2006-02-17T17:23:21Z</modified>
<issued>2006-02-17T17:23:08Z</issued>
<id>tag:weblogs.java.net,2006:/blog/lancea/161.4152</id>
<created>2006-02-17T17:23:08Z</created>
<summary type="text/plain">JDBC 4.0, JSR 221, has completed Public Draft, and we are working towards Proposed final draft.  Here is a reminder of the functionality that is part of this release.</summary>
<author>
<name>lancea</name>

<email>Lance.Andersen@Sun.COM</email>
</author>
<dc:subject>J2EE</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/lancea/">
<![CDATA[JDBC 4.0 has just completed public draft review and the EG is working on closing the last few issues.   One of the interfaces that I expect to change signficantly is the SQLXML interface. 

Here is a list of the major features being added to JDBC 4:

<UL>
<LI> ROWID Support
<LI> National Character Set Support
<LI> Additional SQLException sub classes
<LI> Improved Blob/Clob support
<LI> SQL XML support 
<LI> Ease of Development
<LI> Ability to unwrap implementation classes to make use of vendor specific methods
<LI> Auto loading of Driver class implementations
<LI> Connection management enhancements
</ul>
<P>
Some of the features have been enhanced in the current drops of Mustang (part of the specification evolution).
<p>
We have also spent a lot of time trying to clarify and improve the javadoc  method and interface descriptions as well as various sections of the JDBC paper spec that have resulted in some confusion in the past for developers.  We will continue to review and address as many issues that we can prior to the  official release of Mustang.
<P>
As we wind down the spec work, we will also be focusing on addressing as many outstanding JDBC bugs as possible.  
<P>]]>

</content>
</entry>

</feed>