Thursday, March 04, 2004


OC4J 10.0.3 Developer Preview 2 - J2EE 1.4 Compatible

Finally, it's out the door ... a lot of folks here at Oracle worked awfully hard to get it out.  About 17,900 or so Sun CTS tests passed along with our own massive regression suites - with the last two weeks filled with "squashing" the last bugs.  A lot of folks pretty happy it's done.   Check it out: 

http://otn.oracle.com/tech/java/oc4j/1003/content_preview.html

We have a variety of exit criteria and an obvious one is, are all the demos working including Sun's Adventure Builder application? We were feeling pretty good because we've had Adventure Builder .9x running since sometime around Christmas but then somewhere around mid-February we noticed that Adventure Builder 1.0 was out.  Same UI but architecturally a completely different application using all sorts of interesting features of J2EE 1.4.

A little bit of panic that close to release but OC4J came through with flying colors.  Debu Panda, the EJB PM on OC4J and general all round J2EE wizard, did a lot of the last minute "squashing" on that one including sending back a bunch of fixes to Sun (Steve Button, another of my teammates [who I believe reads J2EE specifications for entertainment :-) ] talks about one issue here).  The how-to for this, which for all intents and purposes is "ant deploy" with lots of words around it, should be available early next week.  

Nice to see the value proposition of J2EE illustrated but it would have been nicer if Sun had put it out a little earlier than exactly when we were getting down to the last minutes of our our release!



comment []
10:23:42 PM    

Links Updated - Brian Duff and Gerard Davidson

These two guys I think are having too much fun on the JDev team - Aspect Oriented Programming in JDeveloper from Gerard and topics all over the place like Tiger and the Magic of Synth   from Brian.  Fixed their links into my blogroll - check them out, they are doing cool stuff. 



comment []
10:11:44 PM    

Oracle Lite from OC4J

Another break from blogging but I am back.   I've had a slew of side projects going on one of which has been getting a partner going with Oracle Lite so they could embed it into their product.   The other, coming up in another blog and eventually more official writeup for OTN is using Lomboz with Eclipse for OC4J. 

Anyway, because I know close to zero about Oracle Lite I became a customer of Oracle rather than a know-it-all about my particular area.

I had two requirements:

1. A light footprint database that ran on Windows and Linux.  Despite the 358 megabyte download on Windows and 256 megabyte download on Linux, the actual footprint of the Oracle Lite runtime on Windows is about 1.2 megabytes and on Linux about 3 megabytes. 

The reason for this size mismatch is that Oracle Lite really consists of a whole slew of features, one of which is a lightweight database for a ton of different form factor mobile devices as well as mainstream OS's like Windows and Linux.  This download has native kits for all sorts of mobile platforms, synchronization technology, queuing stuff, something called Branch Office etc etc. 

All I wanted was the database, as small as possible on Windows and Linux.

2.  It had to be accessible from servlets and EJB's on OC4J from a JDBC driver - thus my involvement as an OC4J PM.  

The first challenge was getting the big download to a minimum size.  The next was figuring out how the concept of a database listener on Oracle Lite worked.  And the last, the easiest for me, was hooking it up to OC4J.

Now that I have it going it is very slick and easy to use - but I have to admit, I did have some challenges getting here.  This is the purpose of this writeup - for my own record!  So here goes:

1. Download the zip file.  I chose the latest 5.0.2 release. Run the installer, on Windows setup.exe; on Linux runInstaller, and do a custom install.  On Windows install the Windows SDK.  This reduces the 358 megabyte footprint to about 38 megabytes.

2. Now you're ready to build your minimal distribution.  Here is the set of files you need - copy them into your new Oracle Lite distribution/runtime directory:

   createdb.exe

   msql.dll

   msql.exe - 'sqlplus' of Oracle Lite

   msql.jar

   OLAD2040.DLL

   OLADCL2040.DLL

   OLITE40.JAR (thin JDBC driver)

   olite40.msb

   oljdbc40.dll

   olobj40.dll

   OLOD2040.DLL

   olsv2040.exe ('tns listener' of Oracle Lite)

   olsql40.dll

 

3. You will have from the install a file polite.ini in the directory c:\windows or c:\winnt.  Edit it to point to your working directory and one of the Olite message file:

 

[All Databases]

DatabaseID=502

DataDirectory=c:\olite

NLS_LOCALE=ENGLISH

MessageFile=c:\olite\OLITE40.MSB

DBCharEncoding=Native

 

4. You are now ready to create a Oracle Lite database:

 

>c:\olite\createdb.exe mikedb c:\olite\mikedb.odb

 

5. Next make sure you have the ODBC registry entries for OLite.  Here is the screen shots of mine which I manually entered - first the node Software->ODBC->ODBCINST.INI->Oracle Lite 40 ODBC Driver:

and second the node Software->ODBC->ODBCINST.INI->ODBC Drivers->Oracle Lite 40 ODBC Driver:

 

6. On Windows, Oracle Lite uses ODBC, even if you come in through thin, type 4 JDBC, the Oracle Lite equivalent to Oracle mothership tnslsnr, converts those JDBC calls into ODBC calls - at least as I understand it.  So, we need to go into the Microsoft ODBC administrator and create a datasource for mikedb.odb.  You will find you have from the SDK install a user datasource called POLite ... you can alter that one or create a new one.  Here are my properties:

 

Datasource Name: mikedb

Data Description: Oracle Lite 40 Data Source

Database: mikedb

Default Isolation Level: Read Committed
AutoCommit: Off

Default Cursor Type: Static

Here is a picture of from the Microsoft ODBC tool: 

7. Now so you can handle incoming thin JDBC calls from your Servlet running on OC4J, start up the Oracle Lite listener - this is the part that had me stymied for a while:

>c:\olite\olsv2040.exe /debug  /wdir=c:\olite

 

In debug mode, above, errors will be output to the file olsv.log.  This listener can also be more usefully installed as a service using the command:

 

>c:\olite\olsv2040.exe /install

 

This service listens on port 100 for JDBC calls to data sources defined in the Microsoft ODBC Administrator.

 

One of the tricks with this is two things need to available on the path and classpath:

 

a.  <JDK_HOME>\jre\bin\server\jvm.dll has to be on the path

b. OLITE40.jar has to be on the classpath

 

8. Now you need to populate that database with something. Here is how to do scott/tiger:

 

>c:\olite\msql system/manager@jdbc:polite4@127.0.0.1:100:mikedb

 

SQL> CREATE USER SCOTT IDENTIFIED BY TIGER;
SQL> GRANT DDL TO SCOTT;

SQL> GRANT ADMIN TO SCOTT;

SQL> GRANT RESOURCE TO SCOTT;

SQL> COMMIT;

SQL> EXIT;

 

>c:olitemsql scott/tiger@jdbc:polite4@127.0.0.1:100:mikedb

 

SQL>CREATE TABLE DEPT (DEPTNO NUMBER(2) NOT NULL,DNAME CHAR(14),LOC CHAR(13),CONSTRAINT DEPT_PRIMARY_KEY PRIMARY KEY (DEPTNO));

SQL>INSERT INTO DEPT VALUES (10,'ACCOUNTING','NEW YORK');
SQL>INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS');
SQL>INSERT INTO DEPT VALUES (30,'SALES','CHICAGO');
SQL>INSERT INTO DEPT VALUES (40,'OPERATIONS','BOSTON');


SQL>CREATE TABLE EMP (EMPNO NUMBER(4) NOT NULL,ENAME CHAR(10),JOB CHAR(9),MGR NUMBER(4) CONSTRAINT EMP_SELF_KEY REFERENCES EMP (EMPNO),HIREDATE DATE,SAL NUMBER(7,2),COMM NUMBER(7,2),DEPTNO NUMBER(2) NOT NULL,CONSTRAINT EMP_FOREIGN_KEY FOREIGN KEY (DEPTNO) REFERENCES DEPT (DEPTNO),CONSTRAINT EMP_PRIMARY_KEY PRIMARY KEY (EMPNO));

SQL>INSERT INTO EMP VALUES (7839,'KING','PRESIDENT',NULL,'17-NOV-81',5000,NULL,10);
SQL>INSERT INTO EMP VALUES (7698,'BLAKE','MANAGER',7839,'1-MAY-81',2850,NULL,30);
SQL>INSERT INTO EMP VALUES (7782,'CLARK','MANAGER',7839,'9-JUN-81',2450,NULL,10);
SQL>INSERT INTO EMP VALUES (7566,'JONES','MANAGER',7839,'2-APR-81',2975,NULL,20);
SQL>INSERT INTO EMP VALUES (7654,'MARTIN','SALESMAN',7698,'28-SEP-81',1250,1400,30);
SQL>INSERT INTO EMP VALUES (7499,'ALLEN','SALESMAN',7698,'20-FEB-81',1600,300,30);
SQL>INSERT INTO EMP VALUES (7844,'TURNER','SALESMAN',7698,'8-SEP-81',1500,0,30);
SQL>INSERT INTO EMP VALUES (7900,'JAMES','CLERK',7698,'3-DEC-81',950,NULL,30);
SQL>INSERT INTO EMP VALUES (7521,'WARD','SALESMAN',7698,'22-FEB-81',1250,500,30);
SQL>INSERT INTO EMP VALUES (7902,'FORD','ANALYST',7566,'3-DEC-81',3000,NULL,20);
SQL>INSERT INTO EMP VALUES (7369,'SMITH','CLERK',7902,'17-DEC-80',800,NULL,20);
SQL>INSERT INTO EMP VALUES (7788,'SCOTT','ANALYST',7566,'09-DEC-82',3000,NULL,20);
SQL>INSERT INTO EMP VALUES (7876,'ADAMS','CLERK',7788,'12-JAN-83',1100,NULL,20);
SQL>INSERT INTO EMP VALUES (7934,'MILLER','CLERK',7782,'23-JAN-82',1300,NULL,10);
SQL>COMMIT;
SQL>EXIT;

9. Now we are ready to hook up OC4J.  Edit your:

<oc4j_home>\j2ee\home\config\data-sources.xml

 

and add the following datasource:

 

            <data-source

           class="com.evermind.sql.DriverManagerDataSource"

           name="OracleLiteDS"

           location="jdbc/OracleLiteCoreDS"

           xa-location="jdbc/xa/OracleLiteXADS"

           ejb-location="jdbc/OracleLiteDS"

           connection-driver="oracle.lite.poljdbc.POLJDBCDriver"

           username="scott"

           password="tiger"

           url="jdbc:polite4@127.0.0.1:100:mikedb"

           inactivity-timeout="30"

       />

 

10. Now we have to make the Oracle Lite thin JDBC driver available for OC4J to be aware of.  Copy the olite40.jar file to:

<oc4j_home>\j2ee\home\applib

 

and then edit the file:

 

<oc4j_home>\j2ee\home\config\application.xml

 

and add the line:

<library path="../applib/olite40.jar"/>

11. Now fire up OC4J (java -jar oc4j.jar) and you are ready to deploy a servlet.

12. I will assume folks know how to write and package servlets as wars etc.  The main trick is is to make sure that you look it up correctly.  The last piece of this blog is a trivial sample servlet querying the emp table [1].

And that is that.  Recorded for posterity.  Am also working on the Linux piece but it looks pretty much the same sans ODBC.  Would be even cooler if it were native Java but we'll have to check out statement of directions and the like to see what those guys are actually up to in that space!

[1]

package hr;

import java.rmi.RemoteException;

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.PrintWriter;

import java.io.IOException;

 

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.sql.DataSource;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.PreparedStatement;

import java.sql.Connection;

 

import oracle.lite.poljdbc.*;

 

public class query extends HttpServlet

{

  private static final String CONTENT_TYPE = "text/html;

charset=windows-1252";

 

  private Connection conn = null;

  private PreparedStatement ps = null;

  private static final String dsName = "jdbc/OracleLiteDS";

 

  public void init(ServletConfig config) throws ServletException

  {

    super.init(config);

  }

 

  public void doGet(HttpServletRequest request, HttpServletResponse

response) throws ServletException, IOException

  {

    response.setContentType(CONTENT_TYPE);

    PrintWriter out = response.getWriter();

   

    String salary = "";

    try {

      conn = getConnection(dsName);

      ps = conn.prepareStatement("SELECT SAL FROM EMP WHERE ENAME = ?");

      ps.setString(1, "TURNER");

      ps.executeQuery();

      ResultSet rs = ps.getResultSet();

      if (rs.next()) {

        salary = new String(rs.getBigDecimal(1).toString());

      }

    } catch (SQLException e) {

    throw new RemoteException(e.getMessage());

    }

   

   

    out.println("<html>");

    out.println("<head><title>query</title></head>");

    out.println("<body>");

    out.println("<p>Turner's salary is: " + salary + "</p>");

    out.println("</body></html>");

    out.close();

  }

 

  private Connection getConnection(String dsName)

       throws SQLException, RemoteException

  {

    DataSource ds = getDataSource(dsName);

    return ds.getConnection();

  }

 

  private DataSource getDataSource(String dsName)

       throws RemoteException

  {

    DataSource ds = null;

    try {

      Context ic = new InitialContext();

      ds = (DataSource) ic.lookup(dsName);

    } catch (NamingException e) {

      e.printStackTrace();

      throw new RemoteException(e.getMessage());

    }

    return ds;

  }

 

}




comment []
9:28:28 PM