Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Monday, October 20, 2008

KnowledgeTree integration using Apache Camel

What the hump is Apache Camel?

Camel is a Spring-based Integration Framework that implements routing and mediation rules using a Java-based Domain Specific Language (DSL or Fluent API), via a Spring-based XML configuration files or via Scala DSL.

The upcoming version 1.5 release includes a tutorial using Axis 1.4 with Camel. I used this example as a springboard to craft a document publisher to KnowledgeTree document management system via it's Axis-based web services.

The basic document publisher picks up an XML file, uploads it to KnowledgeTree using Apache HttpClient, and invokes KnowledgeTree's add_document webservice to include the file into the document repository. Here is the associated routing rule:

from("file:src/data?delete=true").process(ktDocUploader).to("file://target/test?noop=true");

Once the document-uploader function is implemented, the power and versatility of Camel as a routing and mediation framework comes into play. Camel supports a wide array of components allowing for more points of integration. In the above example, the File endpoint can easily be changed to FTP, SMTP, or JMS messaging without affecting the Processor code.

Route interceptors can be used to insert simple tasks like logging or complex ones like payload inspection for conditional application of logic.

intercept(xpath("/person[@user='rexjun']")).to("log:VIP").proceed();

A delivery failure is handled automatically by the Dead Letter Channel processor. I wanted failed deliveries to be deposited to another folder and this rule was implemented by a single line of code:

errorHandler(deadLetterChannel("file://target/errors"));

Aside from the Dead Letter Channel processor, Camel supports most of the Enterprise Integration Patterns and lends itself as a component of the Apache ServiceMix ESB project.

Sunday, July 20, 2008

Using KnowledgeTree SOAP Services from Java apps

I'm making a front-end to KnowledgeTree using the ZK Ajax framework so I eventually dipped my fingers into KT's web service integration from a Java app. My previous SOAP projects involved a Tcl client and a Google gadget using the javascript/php combo.

KnowledgeTree's wiki article on Web Service integration using Java has been most helpful. Since I'm doing my development work on Windows, I've adapted the procedures slightly. And since ZK uses the Beanshell interpreter to execute the Java code, I also modified the tester client application accordingly.

What's needed:

The proxy classes were generated using the WSDL2Java utility provided by the Apache Axis. I'm providing the packaged ktws.jar available for download here. To generate the proxy classes yourself, you would need the Java Compiler and not just the JRE. Here's the batch file to generate the jar package.

set CP=axis-1_4/lib/axis.jar;axis-1_4/lib/commons-discovery-0.2.jar
set CP=%CP%;axis-1_4/lib/commons-logging-1.0.4.jar;axis-1_4/lib/jaxrpc.jar
set CP=%CP%;axis-1_4/lib/log4j-1.2.8.jar;axis-1_4/lib/saaj.jar
set CP=%CP%;axis-1_4/lib/wsdl4j-1.5.1.jar
java -cp %CP% org.apache.axis.wsdl.WSDL2Java -c T1 -p com.pipoltek.ktws http://docs.pipoltek.com/ktwebservice/webservice.php?wsdl
"%JAVA_HOME%\bin\javac" -d . -classpath %CP% com/pipoltek/ktws/*.java
"%JAVA_HOME%\bin\jar" cvf ktws.jar .\com\pipoltek\ktws\*.class

Here's the Beanshell script to execute a login via SOAP.

/*
filename: ktsoaptest.bsh
to run, type from the command-line:
java -cp bsh-2.0b4.jar bsh.Interpreter ktsoaptest.bsh
*/

// add axis classes
addClassPath ("./axis-1_4/lib/axis.jar");
addClassPath ("./axis-1_4/lib/axis-ant.jar");
addClassPath ("./axis-1_4/lib/jaxrpc.jar");
addClassPath ("./axis-1_4/lib/commons-logging-1.0.4.jar");
addClassPath ("./axis-1_4/lib/commons-discovery-0.2.jar");
addClassPath ("./axis-1_4/lib/log4j-1.2.8.jar");
addClassPath ("./axis-1_4/lib/wsdl4j-1.5.1.jar");
addClassPath ("./axis-1_4/lib/saaj.jar");

// knowledgetree proxy classes
addClassPath ("./ktws.jar");

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

import com.pipoltek.ktws.KnowledgeTreeBindingStub;
import com.pipoltek.ktws.Kt_response;
import com.pipoltek.ktws.Kt_folder_contents;
import com.pipoltek.ktws.Kt_workflow_transitions_response;
import org.apache.axis.client.Service;
import java.net.URL;
import com.pipoltek.ktws.Kt_folder_item;

URL url = new URL("http://kt352c.pipoltek.com/ktwebservice/webservice.php");

KnowledgeTreeBindingStub stub = new KnowledgeTreeBindingStub(url, new Service());

System.out.println("Logging into KnowledgeTree");
Kt_response response = stub.login("rexjun","cabanilla","127.0.0.1");

int status_code=response.getStatus_code();
String session;
if (status_code == 0) {
session = response.getMessage();
System.out.println("Session: " + session);
} else {
System.out.println("Status Code: " + status_code);
System.out.println("Session: " + response.getMessage());
return;
}

I'll be using this piece of code to invoke SOAP services from my ZK app. More on this later..

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.

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();