Saturday, March 22, 2008

Cebumapia, the Google Gadget

I've always wondered if I could package Cebumapia as a Google Gadget.. After taking a peek at the other Gadget samples, I was determined to build it. The wondering stage is over now..



The gadget uses the Google Maps API to render the map, overlay markers and trigger events when the mouse hovers on markers and when these are clicked. Markers are stored in xml files and fetched using the gadget-specific _IG_FetchXmlContent function.

The Cebumapia gadget code is miniscule - only 200 lines. But then, functionality is trimmed down to the very basic and UI is just as minimalistic. Take out the module header, css and html portions, and you are left with only 100 lines of javascript code.

If you've been wanting to create your own killer gadget and thinking you don't have the time, start now! My advise.. Start with small reliable code and incrementally build on it. Me? I'm planning to add a local news feed.. spruce up the UI for an iPhone-ish look.. or maybe not.

Add the Cebumapia gadget to your iGoogle page..

See the gadget embedded in Blogger template at Cebumapia.

Thursday, March 13, 2008

Testing ZK Ajax Framework with iSeries/AS400 using JDBC

The ZK Ajax Framework standalone zkdemo application has a sample program that uses JDBC to provide database support to an Ajax app. I decided to give it a try using an iSeries datasource. Here's how it was done..

ZK downloads are here.

- Download ZK-quickstart-x.y.z.pdf
- Download and install Tomcat. I used version 5.5 as this was the version referred to in the manual.
- Download zk-demo-x.y.z.zip and extract the package. Copy the zkdemo.war package to the webapps directory of Tomcat (C:\Program Files\Apache Software Foundation\Tomcat 5.5)
- Restart Tomcat and open the url http://localhost:8080/zkdemo/userguide/

Shutdown Tomcat. I copied the ...\webapps\zkdemo directory to ...\webapps\myzk so I can make changes to the sample code without touching the demo application. I then copied ...\webapps\myzk\userguide\dbconnect\jdbc.zul to ...\webapps\myzk\dbconnect\jdbc.zul and modified the submit() function, as follows:


void submit() {
// Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
// DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver());
Class.forName("com.ibm.as400.access.AS400JDBCDriver");
// String url = "jdbc:odbc:Fred";
String mySchema = "REXJUN1";
String myAS400 = "m170pub1.rzkh.de";
String myUserId = "REXJUN";
String myPasswd = "-change-me-";
String url = "jdbc:as400://" + myAS400 + "/" + mySchema;
Connection con = DriverManager.getConnection(url,myUserId, myPasswd);
PreparedStatement stmt = con.prepareStatement("INSERT INTO BASICJDBC values(?, ?)");
//insert what end user entered into database table
stmt.setString(1, id.value);
stmt.setString(2, name.value);
//execute the statement
stmt.executeUpdate();
//commit
con.commit();
//close the jdbc connection
con.close();
}

Add the jt400.jar from JTOpen to the ...\webapps\myzk\WEB-INF\lib directory. This jar file contains the JDBC driver for iSeries.

Restart Tomcat. Opening the url http://localhost:8080/myzk/dbconnect/jdbc.zul should give you this..


A wrong password does not trigger an error and the application seems to hang -- the host system may have requested a password re-entry but the UI failed to render.

Reviewing the file contents shows the successful addition of new records..


ZK also released ZK Mobile 0.8.7 for the mobile platform on November 07, 2007.

Tuesday, March 4, 2008

Gaga over Google Maps

I gotta admit it, I'm hooked on Google Maps, specifically its API. I've seen the maps of Hongkong's MTR system and with it you can practically plan your trips down to the nearest entry and exit points.


Cebu of the Philippines is likewise a destination for many. Although several travel guides featuring Cebu abound on the web, maps are seldom employed to aid those needing directions. With the availability of rooftop-level satellite imagery offered by Google Maps, I decided to overlay Cebu's streets and places of interest with markers. To spice up the pages, I interspersed local info with impressive photos at Panoramio and Flickr courtesy of camera enthusiasts.

Before I forget, let me introduce you to Cebumapia - a Google Map mashup of Cebu's places of interest! And shall I add, always a Work In Progress!


I've started with markers, or should I say.. I planned to use only markers. But as complexity started to evaporate, I found myself twiddling with infowindows and polylines to spruce things up. After the 30th or so marker in place, I realized I barely scratched the surface... so many markers, so little time! I needed an easier way to add and modify map objects without further mangling the html and javascript code of my Blogger template.

Google Docs to the rescue! By migrating the coordinates, waypoints and even descriptions into Google spreadsheets, I can now change map info even without having to log into Blogger. Hmmm... I'm now thinking of letting visitors add their own sites so I don't have to do anything at all!

I've learned a lot of new things already while building this site. Enjoy it as much as I did... or still do.

Wednesday, February 6, 2008

Using Beanshell with the iSeries/AS400 JTOpen JDBC driver

What seemed to be simple and straightforward task is not as what I expected it to be. And I'm referring to making JTOpen JDBC work with Beanshell. Isn't it supposed to be as easy as load and connect? I guess not..

The common method of invoking java.sql.DriverManager to load the JTOpen JDBC drivers for IBM iSeries (erstwhile AS400) doesn't seem to work with Beanshell. The subsequent calls to DriverManager.getConnection result to a message "No suitable driver found..".

The closest clue I got without going thru the code is contained in this post. Sad to say it is in Spanish --- but there's always Babelfish to the rescue. Still, the translation is wanting, but good enough to tell me not to use DriverManager.

Here's an alternative code. Most of the statements were lifted from IBM.


addClassPath ("./jt400.jar");

import java.sql.*;
import java.util.Properties;
import com.ibm.as400.access.AS400;
import com.ibm.as400.access.AS400JDBCDriver;

private Connection connection = null;
private Statement s = null;
private String mySchema = "REXJUN1";
private String myAS400 = "m170pub1.rzkh.de";
private String myUserId = "REXJUN";
private String myPasswd = "--change-me-";

System.out.println("Loading JDBC driver..");
try {
AS400JDBCDriver d = new AS400JDBCDriver();
AS400 o = new AS400(myAS400, myUserId, myPasswd);
Properties p = new Properties();
Connection c = d.connect (o, p, mySchema);
s = c.createStatement();
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
System.exit(0);
}
System.out.println("Setting up connection..");
try {
s.executeUpdate("drop table basicjdbc");
} catch (SQLException e) {
// Do not perform anything if an exception occurred. Assume
// that the problem is that the table that was dropped does not
// exist and that it can be created next.
System.out.println("Table may not have been dropped.");
}
System.out.println("Creating table..");
try {
s.executeUpdate("create table basicjdbc(id int, name char(15))");
s.executeUpdate("insert into basicjdbc values(1, 'Frank Johnson')");
s.executeUpdate("insert into basicjdbc values(2, 'Neil Schwartz')");
s.executeUpdate("insert into basicjdbc values(3, 'Ben Rodman')");
s.executeUpdate("insert into basicjdbc values(4, 'Dan Gloore')");
} catch (SQLException sqle) {
System.out.println("Failure occurred while setting up " +
" for running the test.");
System.out.println("Test will not continue.");
System.exit(0);
}
System.out.println("Dumping table..");
try {
ResultSet rs = s.executeQuery("select * from basicjdbc");
System.out.println("--------------------");
int i = 0;
while (rs.next()) {
System.out.println("| " + rs.getInt(1) + " | " + rs.getString(2) + "|");
i++;
}
System.out.println("--------------------");
System.out.println("There were " + i + " rows returned.");
System.out.println("Output is complete.");
} catch (SQLException e) {
System.out.println("SQLException exception: ");
System.out.println("Message:....." + e.getMessage());
System.out.println("SQLState:...." + e.getSQLState());
System.out.println("Vendor Code:." + e.getErrorCode());
e.printStackTrace();
}
System.out.println("Clean-up..");
try {
if (connection != null)
connection.close();
} catch (Exception e) {
System.out.println("Caught exception: ");
e.printStackTrace();
}

Sunday, February 3, 2008

Sending mail using Gmail SMTP server with Java

This is a companion project of my previous experiment with S/Mime encryption. This script is also based on Beanshell and it's purpose is basically to connect to Gmail SMTP servers and deliver the encrypted payload to the message recipients.

There are several examples off the Internet but, somehow, I had to combine the techniques before I finally pulled this off. I've enabled debug, otherwise this post would not have any image at all!

Here's the debug output..


Here's the script..


addClassPath( "./mail.jar" );
addClassPath( "./activation.jar" );

import java.security.Security;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.Authenticator;
import javax.mail.internet.MimeMessage;

private class SMTPAuthenticator extends javax.mail.Authenticator {
public PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(smtpUsername, smtpPassword);
}
}

public static final String smtpHost = "smtp.gmail.com";
public static final String smtpUsername = "rexjun@gmail.com";
public static final String smtpPassword = "-change-me-";
public static final String smtpPort = "465";

Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
Properties props = new Properties();
props.put("mail.smtp.user", smtpUsername);
props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.port", smtpPort);
props.put("mail.smtp.starttls.enable","true");
props.put("mail.smtps.auth", "true");
props.put("mail.smtp.debug", "true");
props.put("mail.smtp.socketFactory.port", smtpPort);
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
props.put("mail.smtp.ssl","true");

SecurityManager security = System.getSecurityManager();
Authenticator auth = new SMTPAuthenticator();
Session smtpSession = Session.getInstance(props, auth);
smtpSession.setDebug(true);

MimeMessage smtpMessage = new MimeMessage(smtpSession,
new FileInputStream("Encrypted.eml"));
smtpMessage.saveChanges();
smtpMessage.setSentDate(new Date());

Transport tr = smtpSession.getTransport("smtp");
tr.connect(smtpHost, smtpUsername, smtpPassword);
tr.sendMessage(smtpMessage, smtpMessage.getAllRecipients());
tr.close();