Tuesday, March 22, 2011

Zend Server for IBM iSeries platform does not support multiple persistent connection to DB2

_
_
Edit: This post's content may only apply to i5/OS V5R4 without latest PTF. Please refer to comments for detailed info.

Persistent connection in PHP has its advantage and disadvantage. According to my observation about creating DB2 connection on i5/OS, time used to set up connection via normal connection and persistent connection can be 50 ~ 100 times different. However, persistent connection has its disadvantage as well. Some php programmer even call it evil. Also, it might not be worthy to take risk from persistent connection if the access traffic is not so high.

In a brief way to describe, the causer for persistent connection has disadvantage is that PHP itself is a stateless script language and database connection is usually stateful. That is, php script's life time only exists from the request coming and request end. Meanwhile, database connection will hold some state like table lock, user defined variables etc. So, the problem will occur when a php script use a persistent connection as a fresh new connection and it is not. PHP persistent does not support a kind of "private" connection, which will be used by one user session only. This kind private connection implementation can be found in easyComm i5 toolkit.

Back to what I observed recently. I find that Zend Server (ver 5.0.4) for IBM i5/OS V5R4 does not supports having multiple persistent connection in one request to php scripts. Below is a simple testing code. When you run it, you can see that the output Current Schema is not ALWAYS as what you specified in db2 connection string. I guess the hash function used Zend Server for resource manager may has some problem. Or, DB2 extension has a bug if it does not intend to support only one persistent connection in one PHP script request.

Change the db2_pconnect to db2_connect to see different output. You need to run this script many times to see that you can not ALWAYS get the right schema as your current schema. Most likely, you need to take 5 minutes to 10 minutes break during the testing and see the wrong result to come out.


<?php 

$sysStr = 'select CURRENT SCHEMA from SYSIBM.SYSDUMMY1 ';

$params = array(
 'username' => 'accountNameOne', 
 'password' => 'accountPwdOne',
 'dbname' => '*LOCAL', 
 'driver_options' => array('i5_lib' => 'libraryOne')
);
$connOne = db2_pconnect($params['dbname'], $params['username'], 
$params['password'], $params['driver_options']);
$sysStmt = db2_prepare($connOne, $sysStr);
db2_execute($sysStmt);
$returnObj = db2_fetch_object($sysStmt);
var_dump($returnObj);

$params2 = array(
 'username' => 'accountNameTwo', 
 'password' => 'accountPwdTwo', 
 'dbname' => '*LOCAL', 
 'driver_options' => array('i5_lib' => 'libraryTwo')
);
$connTwo = db2_pconnect($params2['dbname'], $params2['username'], 
$params2['password'], $params2['driver_options']);
$sysStmt2 = db2_prepare($connTwo, $sysStr);
db2_execute($sysStmt2);
$returnObj2 = db2_fetch_object($sysStmt2);
var_dump($returnObj2);

Sunday, March 20, 2011

Which format is for RESTful service, JSON or XML?

I was facing question about what format I need to use for my RESTful Web service. Some persons said they want JSON. Their reason is very simple, compared with XML, JSON is more compact. Therefore, it can save bandwidth. This sounds reasonable. But, it is not an insightful and completed thought. My points are here,

1) The RESTful web service may not be consumed by JavaScript code. Most likely, it will be consumed by other languages like Java, PHP, ASP .Net etc.

2) The size of data is not only concern for the system. Encoding and decoding performance should be considered too.

3) XML parser has been developed and improved for years. JSON parse engine newer than XML.

4) I saw Zend Framework JSON encode and decode functions are pure PHP code. It's performance needs to be investigated.

5) More importantly, one of reasons for me to chose RESTful is that the service going to be implemented is more about sharing resource than about exposing RPC functions. Concept about Resource need to be always with people who design and implements RESTful Web Service. When we talk about resource, we should not forget that the Internet is invented to share resource among people. Furthermore, hyperlink is invented to be key feature of the Internet. Hyperlink feature makes the Internet to be called as Web though HTTP protocol is not the only thing used to transfer data over the Internet.

We have hypertext, hypermedia etc. Now, we have RESTful Web service. Will we have something like hyper-RESTful? Obviously, the answer will be YES. In fact, this should be one of major reasons for us to use XML as output format as we have XLink in XML already. Below is one sample output of RESTful Web service in XML format.

CUSTOMER
INVOICE
ITEM
PRODUCT

As we can see, this output is not a simple one "page" of XML document. It contains hyperlinks to other resources, which could be another RESTful Web service. With this in mind, RESTful designer can borrow methodology of creating Web site to design and "expanding" their RESTful service. That is, we do not need to develop a dedicated service, which will do every thing by itself and it wont share resource with other service. One RESTful web service could be implemented as a piece of "page". Then, another RESTful web service can be composed by using multiple RESTful web service. This architecture will give RESTful Web service more flexibility in terms of deployment and network optimizing.

Won't we lost this great hyperlink feature, which is nature for the Internet if we use JSON? I think 1) JSON may not give whole system better performance if we consider not only data size but also encoding/decoding speed and memory usage. 2) XML will give us great feature of hyplelink from the Web. XLink is just the technique from XML world.

Below is a picture linked from a blog post Native JSON Support is Required.
It is an article written and experiment made in 2007. Now, the things has been different as modern browsers have native JSON support already. However, it is still helpful to remind people who know JSON has more compact size than XML and missed other important factors in the system.

JSON or XML? I think there are different answers for different software system. However, it is thoughtless to assert JSON is better than XML just because of the uncompressed data size. Back to the topic, I will say it is good to use XML as output format of RESTful when the service is not consumed by JavaScript running in Web browser. Of course, it won't be difficult to make RESTful service to be configurable to output XML or JSON.

Wednesday, March 16, 2011

buit-in datatype supported by DB2 for i5/OS and MySQL

To complete one of my work, I need to know list of data type supported by RDBMS. So, I wrote a simple Java application to fetch it. Below is java code and output.

Db2MetaData.java using jt400.jar. (This is just a quick work)
package jia.blog.db2;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Yiyu Jia
 */
public class Db2MetaData {
   Connection conn = null;
   DatabaseMetaData dmd = null;

    public Db2MetaData() {
     
    }

  public void openConnection () {

      try {                  
          String url = "jdbc:as400://172.0.0.1"; //change ip address
          DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver());
          conn = DriverManager.getConnection(url, "accountName", "password");
      }
    catch (Exception e) {
         Logger.getLogger(Db2MetaData.class.getName()).log(Level.SEVERE, null, e);
       }
  }  

 
  public void closeConnection () {

    if (conn != null) {
       try {
           conn.close();           
           System.out.println("Connection closed");
           }
       catch(SQLException e) {
          Logger.getLogger(Db2MetaData.class.getName()).log(Level.SEVERE, null, e);
          }
       }
  }  


    public void displayMaxConnection() {
        try {
            DatabaseMetaData metadata = conn.getMetaData();
            int maxConnection = metadata.getMaxConnections();
            System.out.println("Maximum Connection = " + maxConnection);
        } catch (SQLException ex) {
            Logger.getLogger(Db2MetaData.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public void displayTypeInfo() {
        try {
            DatabaseMetaData metadata = conn.getMetaData();
            ResultSet resultSet = metadata.getTypeInfo();
            while (resultSet.next()) {
                String typeName = resultSet.getString("TYPE_NAME");
                System.out.println(typeName);
            }
            resultSet.close();
        } catch (SQLException ex) {
            Logger.getLogger(Db2MetaData.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

  public static void main(String args[])  {
      Db2MetaData db2Meta = new Db2MetaData();
      db2Meta.openConnection();
      db2Meta.displayMaxConnection();
      db2Meta.displayTypeInfo();
      db2Meta.closeConnection();
  }

}

Supported data type printed by JDBC
DB2 i5 R6V1 MySQL 5.5.8

CHAR
CHAR() FOR BIT DATA
GRAPHIC
LONG VARGRAPHIC
LONG VARCHAR FOR BIT DATA
VARCHAR
VARCHAR() FOR BIT DATA
VARGRAPHIC
DATE
TIMESTAMP
TIME

DECIMAL
DOUBLE
FLOAT
INTEGER
NUMERIC
REAL
SMALLINT
BIGINT
ROWID
DECFLOAT
DATALINK
BLOB
CLOB
DBCLOB

BIT
BOOL
TINYINT
TINYINT UNSIGNED
BIGINT
BIGINT UNSIGNED
LONG VARBINARY
MEDIUMBLOB
LONGBLOB
BLOB
TINYBLOB
VARBINARY
BINARY
LONG VARCHAR
MEDIUMTEXT
LONGTEXT
TEXT
TINYTEXT
CHAR
NUMERIC
DECIMAL
INTEGER
INTEGER UNSIGNED
INT
INT UNSIGNED
MEDIUMINT
MEDIUMINT UNSIGNED
SMALLINT
SMALLINT UNSIGNED
FLOAT
DOUBLE
DOUBLE PRECISION
REAL
VARCHAR
ENUM
SET
DATE
TIME
DATETIME
TIMESTAMP
Below is a picture linked from IBM web site. It listed out built-in data type supported by DB2 for i5/OS RvV4.source
Here are links for DB2 data type to jdbc data type mapping and MySQL data type to JDBC data type mapping

Sunday, March 13, 2011

install and configure Zend server Java Bridge on Linux

As far as I know, there are two active PHP-Java bridge projects. One is PHP/Java Bridge hosted on SourceForge. The other is Java bridge coming with Zend Server and Zend Server CE for linux and IBM i. It is clear that sourceForge PHP/Java bridge is based on SOAP web service. But, this make me feel it is not useful so much as it is not difficult for a PHP programmer to write SOAP client to call a SOAP service written in Java. I guess Zend Java bridge is implemented in client/server architecture too as its configuration parameters include a TCP/IP port number. I thought Zend Java Bridge is written based on JNI technology. However, it seems not true.

Anyway, the mystification of Zend Java Bridge attracts me to give it a shot. Here are simple steps about how to install and configure Zend Java Bridge.

1) Following post Installing Zend server CE on Fedora 14 and fix YUM update to install Zend Server CE on Fedora 14.

2) Running command yum search java-bridge to have output similar as below.

[root@jiaFedora14 yyjia]# yum search java-bridge
Loaded plugins: langpacks, presto, refresh-packagekit
Adding en_US to language list
updates/pkgtags | 56 kB 00:00
======================================================================== Matched: java-bridge =========================================================================
php-5.2-java-bridge-zend-server.x86_64 : Zend Java bridge
php-5.3-java-bridge-zend-server.x86_64 : Zend Java bridge
[root@jiaFedora14 yyjia]#


3) call command yum install php-5.3-java-bridge-zend-server to install Zend Java Bridge as I installed php 5.3 version on my machine.

4) call command /usr/local/zend/etc/rc.d/06jb stop and command /usr/local/zend/etc/rc.d/06jb start to start Zend Java Bridge if it is necessary. Or you can enable/disable Zend Java Bridge from Zend Server admin Web page.

5) compile following Java code into a .jar file, say jia.jar and add put it into directory /usr/local/zend/bin.

SystemPropertyList.java
package jia.blog.util.lang;

import java.util.Properties;

/**
 *
 * @author Yiyu Jia
 */
public class SystemPropertyList {

    public static Properties listSystemProperties(){
         return System.getProperties();
    }
}


6) open file /usr/local/zend/etc/watchdog-jb.ini and add jia.jar file into the CLASSPATH.

7) put below PHP code into directory, where Zend server executes php file. For example, /var/www/html.

javaInfo.php
<?php
$javaEnv = new Java("jia.blog.util.lang.SystemPropertyList");
$out = $javaEnv->listSystemProperties();
?>

List of JVM System Properties

<?php foreach($out as $key => $value) { ?> <?php } ?>
<?php echo $key; ?> <?php echo $value; ?>

8) open web browser and access php code, for example http://localhost/javaEnv.php. If you can see the list of Java system properties, it is done. Enjoy it. This Java system properties is very important for Java programmer to create java app running in Zend Java Bridge.

Note: it seems that Zend Java Bridge does not support Java class hot deployment. So, you may need to restart Java Bridge every time after you modified your java classes.

Thursday, March 10, 2011

Implementing Singleton pattern in Java and PHP shows different "static" modifers between Java and PHP

This is a quick note about the difference between Java "static" modifier and PHP "static" modifier. I investigated the different "static" modifiers in Java and PHP (static variable in PHP vs static variable in Java). Here is a quick notes that shows more difference. It is about "synchronized" and multi-threaded safe coding. Java programmer have to pay extra attention when static variables are used. However, this is not problem in PHP. It does not mean PHP is better than Java. It is just because PHP does not natively support multi-thread.

The following are two singleton pattern implementations in Java and PHP respectively. Listing both of them here can clearly show the difference between Java and PHP static variables.

Java Singleton pattern
/**
 * @author Yiyu Jia
 */
public class DBConnectionFactory {
   
    // static means there will be only one instance in one JVM.
    private static DBConnectionFactory m_connFactory = new DBConnectionFactory();

    // private means this class can not be created by "new" operator outside it.
    private DBConnectionFactory() {
        //connManagerList = new ConcurrentHashMap();
    }
    
    public static DBConnectionFactory getInstance() {

        return m_connFactory;

    }


}

To have better understand about Java memory management, singleton pattern, we can refer to this article and links inside it.



PHP singleton pattern
/**
  * @author Yiyu Jia
  */
class JiaLog
{ 
    private static $_instance;   
    private $logger;
    
    // declaring constructor to be private function.
    private function __construct() 
    {       
     $writer = new Zend_Log_Writer_Stream('path/to/logfile');     
     $this->logger = new Zend_Log($writer);     
    }

    //public static function is the way allowed to get instance
    public static function getJiaLog() 
    {
        if (!isset(self::$_instance)) {
            $c = __CLASS__;
            self::$_instance = new $c;
        }
        return self::$_instance;  
    }
    
   
    public function info($str)
    {
        $this->logger->log($str, Zend_Log::INFO);
    }   

    // Prevent users to clone the instance
    public function __clone()
    {
     trigger_error('Clone is not allowed.', E_USER_ERROR);
    }
}

Sunday, March 6, 2011

Installing Zend server CE on Fedora 14 and fix YUM update

Install Zend Server CE on Fedora 14 (SElinux diabled) is pretty easy. Here are key steps,

1) With root account privilege, go to directory /etc/yum.repos.d and create a file named as anyName.repo. The content of file is as below,


[Zend]
name=Zend Server
baseurl=http://repos.zend.com/zend-server/rpm/$basearch
enabled=1
gpgcheck=0

[Zend_noarch]
name=Zend Server - noarch
baseurl=http://repos.zend.com/zend-server/rpm/noarch
enabled=1
gpgcheck=0


2) With root privilege, running below command,
yum install zend-server-php-5.3

3) After running step 2, Zend server is installed. However, you may run into error when you run yum update. The error message is as below,

Fatal Python error: pycurl: libcurl link-time version is older than compile-time version.

To solve this, we need to do two more things to correct the system.

  1. modify file /etc/ld.so.conf.d/zend_server.conf to have below content,

    cat /etc/ld.so.conf.d/zend_server.conf
    /usr/lib64
    /usr/local/zend/lib


  2. run linux command ldconfig to build correct symbolic links.

Tuesday, March 1, 2011

A war to occupy Internet user's Web browser

Do you see the strange characters "%20" in below HTML fragment? It represents white space. I have to put white space there. why? Because google uses iframe to redirect my browser to its igoogle application portal if I happen to have an alive log on session with google. So, google definitely does not want to live as part of other web application. It wants to be always on the top. This is an evidence to determine this. I am not saying I do not like google. I like google. I just speak out one thing I observed.


So above HTML snippet is a popular way for Web developer to include eternal web site into a Div area. This redirecting can be prevent if I add iFrame redirect event listener and block the redirect. However, this way has to popup a dialogue and ask user to choose "cancel" button to stay in current page. However, it is ugly to ask user to do this!

I have not found a way to silently block this kind actions from google web site. I do not know how many portal web site do this. But, I am really aware that a war about occupying Web browser screen is quietly going on! Probably, Web community need to define new rule to prevent this from happening? Then, developers can have more freedom to build their creative work.