« March 2007 »
SunMonTueWedThuFriSat
1
3
4
5
6
7
8
9
11
12
13
14
15
16
17
19
20
21
22
23
24
25
26
27
28
29
30
     
       
Today
XML

Blog::Navigation

GetJava Download Button
Get the Source
Personal Blog

Blog::Referers

Today's Page Hits: 499

Powered by Roller Weblogger.
« Previous month (Feb 2007) | Main | Next month (Apr 2007) »
20070418 Wednesday April 18, 2007

Desktop scripting applications with NetBeans 5.5

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...



( Apr 18 2007, 07:42:59 PM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

20070410 Tuesday April 10, 2007

SML subset for TEDI?

I came across "Do we need a new kind of schema language?" from Tim Bray's blog. After reading it, I can't resist this: why not use a subset of Standard ML for this purpose?

In the above, we have every type expression except for function types! (IMO, it is not a big list!). Annotations for bindings may be specified in SML comments [this needs more thought].



The example in James Clark's page

 { url: String, width: Integer?, height: Integer?, title: String }
 
would become the following in SML:

 { url: string, width: Maybe int, height: Maybe int, title: string }

where Maybe is

  datatype 'a Maybe = Just of 'a | Nothing

Pros:
  • We can have parametric types and module system - may be useful, for defining larger, generic schema.
  • Tuples, Lists, Records could be mapped to parametrized classes (like in Scala, Java etc.) or native data types in scripting languages.
  • sum-of-product types can be translated as classes (like case classes in Scala)
  • Type expressions are proper set of one particular language - at least few people would feel at home :-) JSON is proper subset of JavaScript object literals, functional folks could have their turn :-). BTW, I am okay with Haskell as well. Personally, I've played with SML little bit more :-)
  • If we want to have schema specified default values of various elements of data, we can include proper subset of value definitions in SML.



( Apr 10 2007, 07:40:43 PM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

20070402 Monday April 02, 2007

Retrieving .class files from a Java core dump

In my last blog entry, I explained how to retrieve .class files from a running Java application. How about retrieving .class files from a Java core dump? You may have got a core dump from JVM due to

  • a bug in some JNI code [you may want to run your application with the -Xcheck:jni flag during development]
  • a bug in JVM. You got core dump and hs_err_pid<NNN> file [which you can decode online!]
  • or you may have forced core dump by a tool such as gcore

When you debug native core dumps, you may have asked your customer for the matching shared objects [or DLLs]. This is because text (a.k.a "code") pages are not dumped into core dump in most operating systems [although you could configure any page to be dumped into core on Solaris 10+]

In JVM, the equivalent of "text" section is the JVM internal data structures created by parsing the loaded .class files. Such data structures are stored in an area of the Java heap called "permanent generation". Because the Java heap is included into the core dumps, it should be possible to access these from Java core dumps. If so, how about reconstructing .class files from core dumps? As it turns out, there is already a tool to do exactly that!

HotSpot Serviceability Agent (SA) is a postmortem/snapshot debugger for HotSpot Java Virtual Machine. SA has a number of tools that are not bundled with JDK/JRE. But, now that HotSpot JVM is a open source, you can look/modify/build HotSpot SA. HotSpot SA lives under the $HOTSPOT/agent directory. There are tools under $HOTSPOT/agent/make directory. To use the SA tools, you need to build SA. There is a gnumake file for SA under $HOTSPOT/agent/make directory. HotSpot SA uses Mozilla Rhino JavaScript engine to implement certain features:

After building HotSpot SA, you can run any of the tools under $HOTSPOT/agent/make. There are shell scripts the SA tools - jcoreproc.sh is the tool to retrieve .class files from core dumps. There is another tool called clhsdbproc.sh that supports dbx/gdb like command line interface. This tool supports dumpclass command to retrieve .class files from core dump. There is some documentation of SA tools under $HOTSPOT/agent/doc directory. Happy core dump debugging!



( Apr 02 2007, 09:07:54 PM IST ) Permalink del.icio.us | furl | simpy | slashdot | technorati | digg

Copyright (C) 2005, A. Sundararajan's Weblog