Friday Oct 26, 2012

Removal of the JDBC-ODBC Bridge from Java SE 8 JDK

Starting with Java SE 8, the JDBC-ODBC Bridge will no longer be included with the JDK. The JDBC-ODBC Bridge has always been considered transitional and a non-supported product[1] that was only provided with select JDK bundles and not included with the JRE.

The JDBC-ODBC bridge provides limited support for JDBC 2.0 and does not support more recent versions of the JDBC specification.

I would recommend that you use a JDBC driver provided by the vendor of your database or a commercial JDBC Driver instead of the JDBC-ODBC Bridge.

[1]http://docs.oracle.com/javase/7/docs/technotes/guides/jdbc/bridge.html.

Sunday Dec 13, 2009

Generating the JPA 2.0 Static MetaModel classes using Eclipselink 2.0 and Netbeans 6.8 for your Entity Classes

Eclipselink 2.0 includes an annotation processor for generating the static metamodel classes from your Entity classes for use with the Criteria API which is one of the new features in JPA 2.0.

Here is an example of generating the metamodel classes from the command line using the Eclipselink annotation processor:


javac -processor org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor -sourcepath src -d src -classpath /ace2_apps/eclipselink/jlib/eclipselink.jar:.:/ace2_apps/eclipselink/jlib/jpa/javax.persistence_2.0.0.v200911271158.jar -proc:only -Aeclipselink.persistencexml=src/META-INF/persistence.xml src/demo/\*.java
Note: Creating the metadata factory ...
Note: Building metadata class for round element: demo.Item
Note: Building metadata class for round element: demo.Order
Note: Found Option : eclipselink.persistencexml, with value: src/META-INF/persistence.xml
Note: File was not found: META-INF/orm.xml
Note: File was not found: META-INF/eclipselink-orm.xml
Note: Found Option : eclipselink.persistencexml, with value: src/META-INF/persistence.xml
Note: File was not found: META-INF/orm.xml
Note: File was not found: META-INF/eclipselink-orm.xml
warning: The following options were not recognized by any processor: '[eclipselink.persistencexml]'


In the above example, the metamodel classes demo.Item_.java and demo.Order_.java were generated and placed in the demo directory where the Entity classes reside.


Netbeans 6.8 has recently been released which provides support for many Java EE 6 features. Unfortunately, there is no support for generating the metamodel classes at this time.


However, it is easy to update your project to provide this support following these steps:


1. Add the following target to your projects build.xml file:

<target name="generate-MetaModel" depends="init">
<property name="metaPackage" value="metamodel"/>
<delete>
<fileset dir="${src.dir}" includes="\*\*/\*_.java"/>
</delete>
<echo message="Generating MetaData "/>
<javac srcdir="${src.dir}" verbose="false"
destdir="${src.dir}"
excludes="demo/\*\*"
classpath="${javac.classpath}">
<compilerarg line=" -processor org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor" />
<compilerarg line=" -proc:only" compiler="javac1.6" />

</javac>

</target>

A couple of notes about the target above:

  • Each time you want to regenerate the metamodel classes, you must delete the previous ones or you will receive an error.
  • The target excludes running the annotation processor against the directory that has the code which references the metamodel classes (demo in the target) otherwise you will see some errors yet the metamodel classes will still be generated.

Once you have added the target to the build.xml, you will want to add a menu option to make it easier to invoke the target. You can do this by:

1. Right clicking on the name of the target and "Create Shortcut"


CreateMenuItem.JPG

2. Indicate that you are adding a "Menu Item"


Wizard1.JPG

3. Select "Refactor" for where to add the Menu Item.


Wizard2.JPG

Now you are ready to use the new target which you can access from the refactor menu:


ShowMenuItem.JPG

The Netbeans project, CriteriaStaticMetaModelDemo, provides a simple set of examples on how to use the Criteria AP. The queries that are provided access the metamodel dynamically and statically as well as demonstrate String based navigation.

The code for using the Static MetaModel example looks like:

private void staticMetaModel() {
System.out.println("\*\*\*Running Static MetaModel Example\*\*\*\*\*");

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<League> cq = cb.createQuery(League.class);
Root<League> league = cq.from(League.class);
cq.select(league);
ParameterExpression<Gender> genderType =
cb.parameter(Gender.class, "gender");

cq.where(cb.equal(league.get(League_.gender), genderType));

TypedQuery<League> tq = em.createQuery(cq);
tq.setParameter(genderType, Gender.Mixed);
List<League> rs = tq.getResultList();
displayLeagues(rs);

CriteriaQuery<String> cq2 = cb.createQuery(String.class);
Root<Team> team = cq2.from(Team.class);
cq2.select(team.get(Team_.name)).where(cb.like(team.get(Team_.name), "Longfellow%"));
TypedQuery tq2 = em.createQuery(cq2);
List<String> teamNames = tq2.getResultList();
displayTeamNames(teamNames);
}


The example creates two queries using the Criteria API. The first query will select all leagues whose gender is equal to "Mixed". Gender is a Enum.

The 2nd query will return all teams whose name begins with "Longfellow".

The static metamodel classes are generated by appending an "_" to the name of the entity. In the example above, League_ and Team_ are the static metamodel classes that were generated for the entities League and Team.

Both queries are quite trivial but show how you can create strongly typed queries using the static metamodel.


For more information on JPA 2.0:

[1] JPA 2.0 Specification

[2]Eclipselink MetaModel Annotation Processor Documentation

[3] CriteriaStaticMetaModelDemo

Thursday Dec 10, 2009

Introducing the DataSourceDefinition Annotation

One of the many cool new features in Java EE 6, is support for the DataSourceDefinition annotation.

The DataSourceDefinition annotation provides a way to define a DataSource and register it with JNDI. The annotation provided annotation elements for the commonly used DataSource properties. Additional standard and vendor specific properties may also be specified.

So let us look at an example:

@DataSourceDefinition(name = "java:global/MyApp/myDS",
className = "org.apache.derby.jdbc.ClientDataSource",
portNumber = 1527,
serverName = "localhost",
databaseName = "testDB",
user = "lance",
password = "secret",
properties = {"createDatabase=create"}) )

The data source will be registered using the value specified in the name element and can be defined in any valid Java EE name space, determining the accessibility of the data source from other components.

The properties element is used to specify less frequently used standard DataSource properties as well as vendor-specified properties using the format :

{"property1=value", "property2=value" ...}

Using the newly defined DataSource is as simple as:

  @Resource(lookup = "java:global/MyApp/myDS")
  private DataSource ds;

You can also define multiple DataSources using the DataSourceDefinitions annotation:

@DataSourceDefinitions({
  @DataSourceDefinition(name = "java:global/MyApp/myDS",
  className = "org.apache.derby.jdbc.ClientDataSource",
  portNumber = 1527,
  serverName = "localhost",
  databaseName = "testDB21",
  user = "lance",
  password = "secret",
  properties = {"createDatabase=create"}),
  @DataSourceDefinition(name = "java:global/MyApp/myDS2",
  className = "com.mysql.jdbc.jdbc2.optional.MysqlDataSource",
  portNumber = 3306,
  serverName = "localhost",
  databaseName = "dogDB",
  user = "luckyDog",
  password = "shhh",
  properties = {"pedantic=true"})
})

So let's look at a simple web application, DataSourceDefWebApp, which utilizes the DataSourceDefinition. The application is provided as a NetBeans project that was created with NetBeans 6.8.

The application when deployed, will create a DataSource for Java DB.

When you go to run the application, you will need to make sure that you have the Java DB client JDBC driver accessible to your appserver, which it will be for Glassfish V3 and the Java DB server started.

To run the application after you have deployed it, go to the following URL using your favorite browser:

http://<host>:<port>/DataSourceDefWebApp

When you first run the application, you will see the following menu. Select the menu option "Initialize the Database", to create the Java DB database and create two initial contacts.

AdminMenu.JPG

After initializing the database you can select "Add a Contact" to add a new contact to your database.

AddContact.JPG

When you click the "Add Contact", button you will be taken to the displayContacts page.

DisplayDerby.JPG ,  

The application defines the DataSource in the DataSourceDefServlet:

@DataSourceDefinition(name = "java:global/MyApp/myDS",
className = "org.apache.derby.jdbc.ClientDataSource",
portNumber = 1527,
serverName = "localhost",
databaseName = "testDB",
user = "lance",
password = "secret",
properties = {"createDatabase=create"})
@WebServlet(name = "DataSourceDefServlet", urlPatterns = {"/DataSourceDefServlet", "/displayContacts", "/addContact", "/initDB"})
public class DataSourceDefServlet extends HttpServlet {private ServletContext context;
@Resource(lookup = "java:global/MyApp/myDS")
private DataSource ds;


The DataSourceDefinition annotation is specified above the class declaration. The Resource annotation is then used specifying the JNDI name that was defined in DataSourceDefinition.

The Stateless Session bean, DemoBean, also uses the Resource annotation to access the same DataSource via:

@Resource(lookup = "java:global/MyApp/myDS")
private DataSource ds;

You can also override the settings that you have specified in the DataSourceDefinition annotation by adding the data-source element to your web.xml. For example, in order to use a MySQL database instead of Java DB, you can create a web.xml and add the following (remember to adjust the properties as necessary):

<data-source>
<description>DataSource for MySQL</description>
<name>java:global/MyApp/myDS</name>
<class-name>com.mysql.jdbc.jdbc2.optional.MysqlDataSource</class-name>
<server-name>localhost</server-name>
<port-number>3306</port-number>
<database-name>testDB</database-name>
<user>lance</user>
<password>secret</password>
<property>
<name>x</name>
<value>y</value>
</property>
<property>
<name>y</name>
<value>x</value>
</property>
<login-timeout>500</login-timeout>
<transactional>false</transactional>
<isolation-level>TRANSACTION_READ_COMMITTED</isolation-level>
<initial-pool-size>2</initial-pool-size>
<max-pool-size>5</max-pool-size>
<min-pool-size>1</min-pool-size>
<max-idle-time>500</max-idle-time>
<max-statements>100</max-statements>
</data-source>

In the top level directory of the DataSourceDefinitionWebApp, you will find a web.xml that you can move to the web/WEB-INF folder of the project. Adjust the properties for the data-source to correctly point to your MySQL database, then rebuild and deploy.

When you go to display the data, you will notice that the the output from displayContacts indicates thatthe database that is being used in MySQL

OverrideWithMysql.JPG

The DataSourceDefinition annotation is a simple yet powerful addition to Java EE 6. Enjoy!


References:


Wednesday Dec 03, 2008

MySQL Connector/C++ 1.0.1 Alpha Released offering a JDBC API for MySQL C++ developers

The MySQL Connector/C++ Connector project has successfully reached its first major milestone by releasing its Alpha version. The Connector provides a C++ implementation modeled after JDBC. This allows developers who have worked with JDBC to quickly take advantage of this Connector minimizing the learning curve. The current release provides support for many of the methods found in the following JDBC interfaces:
  • java.sql.Connection
  • java.sql.DatabaseMetaData
  • java.sql.Driver
  • java.sql.PreparedStatement
  • java.sql.ResultSet
  • java.sql.ResultsetMetaData
  • java.sql.Savepoint
  • java.sql.Statement
Examples of using MySQL Connector/C++

Here is an example which connects to a MySQL Server, creates a table and then inserts a row into the table

      sql::mysql::MySQL_Driver \*driver;
      sql::Connection \*con;
      sql::Statement \*stmt

       driver = sql::mysql::get_mysql_driver_instance();
       con = driver->connect("tcp://localhost:3306", "user", "password");

       stmt = con->createStatement();
       stmt->executeUpdate("DROP TABLE IF EXISTS CONTACTS");
       stmt->executeUpdate("CREATE TABLE CONTACTS(ID INT NOT NULL AUTO_INCREMENT, FNAME VARCHAR(25), LNAME VARCHAR(25), PHONE VARCHAR(12))");
       stmt->executeUpdate("INSERT INTO CONTACTS( FNAME, LNAME, PHONE) VALUES ('Bruce', 'Wayne', '555 555-5555')");

       delete stmt;
       delete con;
This example uses a PreparedStatement to insert a couple of rows
        sql::mysql::MySQL_Driver \*driver;
        sql::Connection \*con;
        sql::PreparedStatement \*pstmt
        driver = sql::mysql::get_mysql_driver_instance();
        con = driver->connect("tcp://localhost:3306", "user", "password");
               
        pstmt = con->prepareStatement("INSERT INTO CONTACTS( FNAME, LNAME, PHONE) VALUES ( ?, ?, ?)");
        
        pstmt->setString(1, "Dick");
        pstmt->setString(2, "Grayson");
        pstmt->setString(3, "222 222-2222");
        pstmt->executeUpdate();
        
        pstmt->setString(1, "Clark");
        pstmt->setString(2, "Kent");
        pstmt->setString(3, "333 333-3333");
        pstmt->executeUpdate();
        
        delete pstmt;
        delete con;
This example uses a uses a PreparedSatement to execute a query and then process a ResultSet. Notice that you can reference the columns via an ordinal or a column name
        sql::mysql::MySQL_Driver \*driver;
        sql::Connection \*con;
        sql::PreparedStatement \*pstmt;
        sql::ResultSet \*rs;

        driver = sql::mysql::get_mysql_driver_instance();
        con = driver->connect("tcp://localhost:3306", "user", "password");
               
        pstmt = con->prepareStatement("SELECT \* FROM CONTACTS WHERE ID= ?");      
        pstmt->setInt(1, 2);     
        rs= pstmt->executeQuery();

        while (rs->next()) {  
           cout << "ID = "  << rs->getInt(0);
           cout <<", First Name = '"  <<rs->getString("FNAME")  << "'";
           cout <<", Last Name = '"  <<rs->getString("LNAME")  << "'";
           cout <<", Phone = '"  <<rs->getString(3)  << "'"  << endl;

        }

        delete rs;                  
        delete pstmt;
        delete con;
As you can see from the above examples, the MySQL Connector/C++ connector provides a simple API modeled on JDBC for accessing your MySQL data. The MySQL Connector/C++ connector is being used today by MySQL Workbench and the MySQL/OpenOffice.org Connector. We hope you give it a go and let us know what you think. For more information on MySQL Connector/C++, please refer to the following sites:

Technorati Tags: , ,

Wednesday Nov 05, 2008

Moving Tomcat Toplink Apps to Glassfish v3 Prelude

With Glassfish V3 and Netbeans 6.5, it is easy to move applications which run on Tomcat using Toplink/EclipseLink to Glassfish v3 Prelude. The sample application contained in the zip file JPAWeb_TC6_Toplink-4.zip, is a simple web app using JSTL, Servlet, JSP and TopLink Essentials to store contact information into a MySQL database.

To Deploy and run the application on Tomcat, you need place a copy of the MySQL JDBC driver in $TOMCAT_HOME/lib and have a MySQL database which is accessible and that you have permissions to create tables in. The application uses JNDI to access a Data Source defined on Tomcat (in our case via the context.xml). This requires you to use specify the Toplink property toplink.session.customizer in your persistence.xml indicating that a SessionCustomizer will be used so that the lookup type on the JNDI connector will be a STRING_LOOKUP instead of Composite :

 
<?xml version="1.0" encoding="UTF-8"?>
<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">
  <persistence-unit name="JPAContactJNDIPU" transaction-type="RESOURCE_LOCAL">
    <provider>oracle.toplink.essentials.PersistenceProvider</provider>
 <non-jta-data-source>java:comp/env/jdbc/mysqlTestDB</non-jta-data-source>
    <class>demo.entity.Contact</class>
    <properties>
      <property name="toplink.session.customizer" value="demo.JNDITopLinkSessionCustomizer"/>
      <property name="toplink.logging.level" value="FINE"/>
    </properties>
  </persistence-unit>
</persistence>

The code for JNDITopLinkSessionCustomizer is:

package demo;

import javax.naming.Context;
import javax.naming.InitialContext;
import oracle.toplink.essentials.jndi.JNDIConnector;
import oracle.toplink.essentials.sessions.Session;
import oracle.toplink.essentials.tools.sessionconfiguration.SessionCustomizer;


/\*\*
\*
\* @author Owner
\*/
public class JNDITopLinkSessionCustomizer implements SessionCustomizer {

  /\*\*
   \* Get a dataSource connection and set it on the session with lookupType=STRING_LOOKUP
   \*/
  public void customize(Session session) throws Exception {
      JNDIConnector connector = null;
             Context context = null;
      try {
          context = new InitialContext();
          if (null == context) {
              throw new Exception("JNDIEclipseLinkSessionCustomizer: Context is null");
          }
          connector = (JNDIConnector) session.getLogin().getConnector(); // possible CCE
          // Change from Composite to String_Lookup
          connector.setLookupType(JNDIConnector.STRING_LOOKUP);
      } catch (Exception e) {
          e.printStackTrace();
      }
  }
}
You will also have to modify the context.xml to point to your database:

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/JPAWeb_TC6_Toplink_To_V3">
<Resource auth="Container" driverClassName="com.mysql.jdbc.Driver" maxActive="100" maxIdle="30" maxWait="10000" name="jdbc/mysqlTestDB" password="bar" type="javax.sql.DataSource" url="jdbc:mysql://localhost:3306/mysqltest?autoReconnect=true" username="foo"/>
</Context>
You can now deploy the application using Netbeans to Tomcat and enter some simple data.

Deploytc-1

Run Tc-1

Moving the Application to Glassfish v3 Prelude

Moving the application from Tomcat to Glassfish v3 Prelude is very easy to do:

1. Make a copy of the application in Netbeans by right clicking on the project and selecting copy(call the copy of the project JPAWeb_TC6_Toplink_To_V3).

Copyproject-3

2. Under the project properties, indicate that you are going to deploy to Glassfish V3 Prelude:

Preludeprops-2

3. Add a JNDI Resource Entry to the sun-web.xml:

Sun-Web-1

4. Place the MySQL JDBC driver in $GLASSFISH_V3_HOME/glassfish/domains/domain1/lib.ext

5. Start Glassfish V3 Prelude and add a Connection Pool which points to your MySQL server and database

Connpool-1

Connpool2

5. Add JDBC Resource which uses the Connection Pool

Jdbc Resource-2

6. Deploy the application to Glassfish v3 Prelude

Deployv3-1

7. Run the application deployed on Glassfish

Run V3-1

Migrating from Toplink to Eclipselink It is very easy to change your application to run with EclipseLink.

1. Add the EclipseLink library to your Netbean's project and remove the Toplink Library

Eclipselibrary-1

2. Change your persistence.xml to use EclipseLink (note: that the Design view of persistence.xml will allow you to change Persistence Provider, however it currently does not modify the property names when going from Toplink to Eclipselink ):

<?xml version="1.0" encoding="UTF-8"?>
<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">
  <persistence-unit name="JPAContactJNDIPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
 <non-jta-data-source>java:comp/env/jdbc/mysqlTestDB</non-jta-data-source>
    <class>demo.entity.Contact</class>
    <properties>
      <property name="eclipselink.session.customizer" value="demo.JNDIEclipseLinkSessionCustomizer"/>
      <property name="eclipselink.logging.level" value="FINE"/>
    </properties>
  </persistence-unit>
</persistence>

3. You will need to change the imports for your SessionCustomizer since EclipseLink is being used (note I changed the name of the class for clarity) JNDIEclipseLinkSessionCustomizer :


package demo;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.eclipse.persistence.config.SessionCustomizer;
import org.eclipse.persistence.sessions.JNDIConnector;
import org.eclipse.persistence.sessions.Session;
/\*\*
\*
\* @author Owner
\*/
public class JNDIEclipseLinkSessionCustomizer implements SessionCustomizer {

  /\*\*
   \* Get a dataSource connection and set it on the session with lookupType=STRING_LOOKUP
   \*/
  public void customize(Session session) throws Exception {
      JNDIConnector connector = null;
             Context context = null;
      try {
          context = new InitialContext();
          if (null == context) {
              throw new Exception("JNDIEclipseLinkSessionCustomizer: Context is null");
          }
          connector = (JNDIConnector) session.getLogin().getConnector(); // possible CCE
          // Change from Composite to String_Lookup
          connector.setLookupType(JNDIConnector.STRING_LOOKUP);
      } catch (Exception e) {
          e.printStackTrace();
      }
  }
}

You can now run and deploy the application using EclipseLink for your persistence provider.

Doing a little more clean up if you are only going to run on Glassfish v3 Prelude

If you are just going to run on Glassfish v3 Prelude, you can make a few additional minor tweaks to your application:

1. Simplify your persistence.xml by removing the eclipselink.session.customizer (only needed for JNDI look ups on Tomcat) and simplifying your non-jta-datasource entry (you must specify java:comp/env/ when using Tomcat):

<?xml version="1.0" encoding="UTF-8"?>
<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">
  <persistence-unit name="JPAContactJNDIPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
 <non-jta-data-source>jdbc/mysqlTestDB</non-jta-data-source>
    <class>demo.entity.Contact</class>
    <properties>
      <property name="eclipselink.logging.level" value="FINE"/>
    </properties>
  </persistence-unit>
</persistence>


2. Streamline your context.xml entry to omit the Will ignore everything from DBCP properties so it would just look like:

<Resource
name="jdbc/mysqlTestDB"
auth="Container"
type="javax.sql.DataSource"/>

Technorati Tags: ,

About

user12629431

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
Bookmarks