X

Sundararajan's Weblog

  • Java
    April 18, 2007

Desktop scripting applications with NetBeans 5.5

Guest Author

How about developing desktop Java applications using scripting, XML and database with
NetBeans? This afternoon I played with scripting using NetBeans 5.5.
Before proceeding further, I will describe the devepment environment:

In addition, I've CVS checked out the following java.net projects:

I started with a simple Java program project. Added a script file
with the name "hello.js" to the project:


I added the following code using the JavaScript editor:

JavaScript editor supports syntax highlighting etc. The "importPackage" built-in function imports a Java package to script."importClass"
imports a specific Java class. Everything above is straight forward -- except may
be the listener for the button. JavaScript engine takes care of wrapping the supplied JavaScript function to ActionListener interface. Also, JavaScript engines supports
JavaBean convention so that we can write f.visible = true instead of
f.setVisible(true).

I added the following code to the main class:


package helloscript;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class Main {
public static void main(String[] args) throws Exception {
// create manager
ScriptEngineManager m = new ScriptEngineManager();
// create javascript script engine
ScriptEngine js = m.getEngineByName("javascript");
// evaluate "hello.js"
InputStream strm = Main.class.getResourceAsStream("/hello.js");
Reader r = new InputStreamReader(strm);
js.eval(r);
}
}

Note that NetBeans copies "hello.js" to build/classes directory
and packages it into dist/HelloScript.jar as well. So, the above
getResourceAsStream works as expected. When running the project,
I got this:


Now, how about throwing some database access and XML? I'm too lazy to use JDBC
API directly. I wanted to try out the persistence API. So, I
followed the steps below to generate entity classes from the sample database [shipped with
NetBeans enterprise pack? I've no idea, as long as it works... :-) ]. You probably
know this already: You do not need to use Java EE to use the persistence API.
You can use it within Java SE

Password is also "app". Don't forget to choose "Remember password during this session" option!

I added all tables from the sample db and I just selected package name to be "helloscript".

Created "persistence unit" as suggested!

Now, I need to add Java code to fetch all "Customer" instances from DB. So, I added
the following to Main.java:


package helloscript;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class Main {
public static void main(String[] args) throws Exception {
// create JavaScript engine
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine js = m.getEngineByName("javascript");
// Create Entity manager factory - "HelloScriptPU"
// is the name given when creating persistence unit
EntityManagerFactory emf = Persistence.createEntityManagerFactory("HelloScriptPU");
// create Entity manager
EntityManager em = emf.createEntityManager();
// select all Customer instances
Query q = em.createQuery("SELECT c FROM Customer c");
// get the result list (of Customers)
List l = q.getResultList();
// expose the Customer list to script
// as a global variable by the name "customers"
js.put("customers", l);
// now evaluate script -- the script may use
// "customers" variable
InputStream strm = Main.class.getResourceAsStream("/hello.js");
Reader r = new InputStreamReader(strm);
js.eval(r);
}
}


Now, I added logic to display the customer list in the JavaScript code:


Again, I've used JavaBean convention support to access Customer name and
email -- so that I wrote c.name and c.email instead
of calling c.getName() and c.getEmail() on the entity
instances. I used JEditorPane to display the generated HTML table
inside the JFrame. When I ran the above code. I got the following
error:

Exception in thread "main" Local Exception Stack:
Exception [TOPLINK-4003] (Oracle TopLink Essentials - 2006.8 (Build 060830)): oracle.toplink.essentials.exceptions.DatabaseException
Exception Description: Configuration error. Class [org.apache.derby.jdbc.ClientDriver] not found.
at oracle.toplink.essentials.exceptions.DatabaseException.configurationErrorClassNotFound(DatabaseException.java:86)
at oracle.toplink.essentials.sessions.DefaultConnector.loadDriver(DefaultConnector.java:168)
at oracle.toplink.essentials.sessions.DefaultConnector.connect(DefaultConnector.java:83)
at oracle.toplink.essentials.sessions.DatasourceLogin.connectToDatasource(DatasourceLogin.java:170)
at oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.loginAndDetectDatasource(DatabaseSessionImpl.java:537)
at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:180)
at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:230)
at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:78)
at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:113)
at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:107)
at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:76)
at helloscript.Main.main(Main.java:20)
Java Result: 1

Seems like persistence runtime did not find the driver classes. I added
derbyclient.jar from $JDK/db/lib directory to the project's "Libraries".

After that, it ran as expected!

But, I mentioned XML. Where is it? Well, I generated (X)HTML for table :-) How
about using E4X? (easier interface to work with XML).
Although Mozilla Rhino JavaScript
supports E4X, the bundled version in JDK 6 does not support E4X. Rhino's E4X
implementation depends on Apache XML Beans.
We do have a jsr-223 script engine for "full" Rhino with E4X support in the
http://scripting.dev.java.net
project. I added js-engine.jar
from this project, js.jar [Rhino jar - either download it from Mozilla site or
from CVS workspace of scripting project] and xmlbeans.jar
[which I got from the Phobos project $PHOBOS/phobos/dist/lib/xmlbeans.jar] to the
project:

Then, I modified the "hello.js" script to use E4X:

Note that the HTML table generation does not involve strings. I use E4X
to generate it -- I've expressions inside { } for the 'dynamic' portions of
the (X)HTML. Also, in the Java code, I made a
small change:


ScriptEngine js = m.getEngineByName("rhino-nonjdk");

Note that I used "rhino-jdk" as the engine name instead of "javascript" so that
the manager would choose the jsr-223 engine that is bundled with JDK 6. Without
this, it would choose the not bundled jsr-223 engine in rt.jar. With the change
above, E4X works! I learned a bit about NetBeans 5.5 JavaScript support,
persistence API and E4X. Hmm..., some day I need to try out the bleeding edge stuff in
NetBeans 6
...

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.