Thursday, July 28, 2011

how Ext JS 4 deals with postprocessors and preprocessors?

I looked into source code of Ext.ClassManager recently. But, I found that I can not understand it. Actually, I think it is a bug?

According to the signature of Ext.ClassManager.create function, It seems that developer can pass in postprocessors in configuration data. However, I think the postprocessors in configuration data will overwrite ClassManager's default postProcessors.

I put sample code to show what happen once we apply "||" operator to two JavaScript arrays. I cited the source code as below and add several lines comments there. Similar things happen to preprocessors in Class.js .

code snippet to show || operator on JavaScript arrays

The output of above code is:
Array is:
0
1
Another array is:
2
3
4
Now, let's see what happens in ClassManager.js: Code snippet cited from ClassManager.js
return new Class(data, function() {
                //If I pass in data having postprocessors,
                //all default postprocessors is going to ignored? 
                var postprocessorStack = data.postprocessors || manager.defaultPostprocessors,
                    registeredPostprocessors = manager.postprocessors,
                    index = 0,
                    postprocessors = [],
                    postprocessor, postprocessors, process, i, ln;

                delete data.postprocessors;

                //if my data has just one postprocessor, 
                //doesn't postprocessorStack.length only equal to 1?  
                for (i = 0, ln = postprocessorStack.length; i < ln; i++) {
                    postprocessor = postprocessorStack[i];

                    if (typeof postprocessor === 'string') {
                        postprocessor = registeredPostprocessors[postprocessor];

                        if (!postprocessor.always) {
                            if (data[postprocessor.name] !== undefined) {
                                postprocessors.push(postprocessor.fn);
                            }
                        }
                        else {
                            postprocessors.push(postprocessor.fn);
                        }
                    }
                    else {
                        postprocessors.push(postprocessor);
                    }
                }

                process = function(clsName, cls, clsData) {
                    postprocessor = postprocessors[index++];

                    if (!postprocessor) {
                        manager.set(className, cls);

                        Ext.Loader.historyPush(className);

                        if (createdFn) {
                            createdFn.call(cls, cls);
                        }

                        return;
                    }

                    if (postprocessor.call(this, clsName, cls, clsData, process) !== false) {
                        process.apply(this, arguments);
                    }
                };

                process.call(manager, className, this, data);
            }

I reported a bug here to see if I am right or it is just because I do not understand the code. Please feel free to make comments below if I am wrong.

Thursday, July 7, 2011

Java memory leak caused by String object

For some reason, I recall that Java String can easily cause memory leak. Since it has not been fixed in JVM, I write this note to keep it in mind. Next time, I will write down C/C++ and C# memory leak on pocket PC, which I was experienced.

We all know that Java has garbage collector, which automatically release memory of object if there is refernece points to it any more. However, something strange from String class happens in at least Sun and IBM's JVM. String is definietly frequently used Object in Java program. So, it will be significant if its function causes memory leak. The souce of the issue is from substring function of String class in JVM implementations from Sun and IBM at least. Speak in simple way, substring() function will not create a new String object having its own memory block and return it. It will only create a String object, which points to part of original String object. Therefore, the memory block occupied by original String object will be refered by new sub String object too. This will cause siginificant memory leak problem if original String is very long and the sub String object will be used outside scope where original String object residents. Below figure gives a clear view of this statement.


To workaround this issue, we can use new operator to force the sub String object has its own memory block. In fact, this is reported as a bug in Sun microsystem. But, it has low priority and has not been fixed. There is an interesting discussion about Java memory leak here: Creating a memory leak with Java

Friday, July 1, 2011

ExtJS 4 REST proxy and Zend framework Zend_Rest_Route are incompatible.

I noticed a very strange thing when I worked on Ext JS 4 v4.0.2 and Zend Framework. I find that every time when Ext JS grid sends new created Record to the server through its REST proxy, the POST method was teated as PUT method in Zend_Rest_Route. This cause troublesome because my code have to know if the incoming record a new one for insert or exsiting one for update. Otherwise, I have to use some UPSERT SQL statement to UPDATE or INSERT record into Database table. Unfortunately, I use DB2 for i5/OS V5R4, which does not have built-in UPSERT command and it even does nor support MERGE statement.

I do not want to walkaround this by doing SELECT first and judging if the code need to run INSERT or UPDATE statement. So, I traced the Ext JS 4 code and Zend Framework 1.11 code. I found that these two are not compatiable. I am not sure if we can say it is BUG as this wont happen if either side change their code. Or, both side can change the code to avoid the confilicaton if we say bugs are from both sides.

The key for this issue is that Ext JS 4 append record's id at the end of base URL, which points to RESTful service. Below is a psuedo POST URL create by Ext JS 4 REST proxy. I highlight the unexpected friend in red color.

http://hostname/yourRestServiceURI/yourRecordId/?dc=randomNum


We understand that adding record id as part of URI can allow server side script easily find it. But, why this design is implemented in a general SDK like Ext JS? Especially, I do not see good reason for a POST request to have it as record in POST are suppoe not to have been existing on server side. Therefore, the ID of the new record might not have been generated if it will be generated on the server side only.

In Ext JS 4 source code \src\data\proxyRest.js, we can see what happens,
/**
     * Specialized version of buildUrl that incorporates the {@link #appendId} and {@link #format} options into the
     * generated url. Override this to provide further customizations, but remember to call the superclass buildUrl
     * so that additional parameters like the cache buster string are appended
     */
    buildUrl: function(request) {
        var me        = this,
            operation = request.operation,
            records   = operation.records || [],
            record    = records[0],
            format    = me.format,
            url       = me.getUrl(request),
            id        = record ? record.getId() : operation.id;
        
        if (me.appendId && id) {
            if (!url.match(/\/$/)) {
                url += '/';
            }
            
            url += id; //Why add ID here even for POST? Yiyu Jia
        }
        
        if (format) {
            if (!url.match(/\.$/)) {
                url += '.';
            }
            
            url += format;
        }
        
        request.url = url;
        
        return me.callParent(arguments);
    }
}

Now, people will ask why adding id in URL cause the problem in Zend Framework? Well, let's trace Zend Framework code now.

On Zend Framework API document about Zend_Rest_Route, we can see Zend clearly described their design how RESTful URI should looks like,
Zend_Rest_Route Behavior
MethodURIModule_Controller::action
GET/product/ratings/Product_RatingsController::indexAction()
GET/product/ratings/:idProduct_RatingsController::getAction()
POST/product/ratingsProduct_RatingsController::postAction()
PUT/product/ratings/:idProduct_RatingsController::putAction()
DELETE/product/ratings/:idProduct_RatingsController::deleteAction()
POST/product/ratings/:id?_method=PUTProduct_RatingsController::putAction()
POST/product/ratings/:id?_method=DELETEProduct_RatingsController::deleteAction()

As we can see, Zend Framework does not expect any thing attached to method URI when PHP programmer intend to use POST method. In Zend_Rest_Route source code, we can see a case switch statement as below. You will see when the POST method will be "magically" routed to PUT method if pathElementCount is larger than zero.

switch( $values[$this->_actionKey] ){
                    case 'post':
                        if ($pathElementCount > 0) {
                            $values[$this->_actionKey] = 'put';
                        } else {
                            $values[$this->_actionKey] = 'post';
                        }
                        break;
                    case 'put':
                        $values[$this->_actionKey] = 'put';
                        break;
                }


But, where is the $pathElementCount set? In the same source code file, we can see below statement,

//Store path count for method mapping
$pathElementCount = count($path);

So, where is value of $path populated? Still, in the same source code, there is a function call match. Part of it is cited as below.

/**
     * Matches a user submitted request. Assigns and returns an array of variables
     * on a successful match.
     *
     * If a request object is registered, it uses its setModuleName(),
     * setControllerName(), and setActionName() accessors to set those values.
     * Always returns the values as an array.
     *
     * @param Zend_Controller_Request_Http $request Request used to match against this routing ruleset
     * @return array An array of assigned values or a false on a mismatch
     */
    public function match($request, $partial = false)
    {
        if (!$request instanceof Zend_Controller_Request_Http) {
            $request = $this->_front->getRequest();
        }
        $this->_request = $request;
        $this->_setRequestKeys();

        $path   = $request->getPathInfo();
        $params = $request->getParams();
        $values = array();
        $path   = trim($path, self::URI_DELIMITER);

Ok, now, it is not the end of code tracing yet. Where is the getPathInfo() function? It is in Zend_Controller_Request_Http. The following code citation will show us that getPathInfo() eeturns everything between the BaseUrl and QueryString and deos something special.

/**
     * Returns everything between the BaseUrl and QueryString.
     * This value is calculated instead of reading PATH_INFO
     * directly from $_SERVER due to cross-platform differences.
     *
     * @return string
     */
    public function getPathInfo()
    {
        if (empty($this->_pathInfo)) {
            $this->setPathInfo();
        }

        return $this->_pathInfo;
    }

/**
     * Set the PATH_INFO string
     *
     * @param string|null $pathInfo
     * @return Zend_Controller_Request_Http
     */
    public function setPathInfo($pathInfo = null)
    {
        if ($pathInfo === null) {
            $baseUrl = $this->getBaseUrl(); // this actually calls setBaseUrl() & setRequestUri()
            $baseUrlRaw = $this->getBaseUrl(false);
            $baseUrlEncoded = urlencode($baseUrlRaw);
        
            if (null === ($requestUri = $this->getRequestUri())) {
                return $this;
            }
        
            // Remove the query string from REQUEST_URI
            if ($pos = strpos($requestUri, '?')) {
                $requestUri = substr($requestUri, 0, $pos);
            }
            
            if (!empty($baseUrl) || !empty($baseUrlRaw)) {
                if (strpos($requestUri, $baseUrl) === 0) {
                    $pathInfo = substr($requestUri, strlen($baseUrl));
                } elseif (strpos($requestUri, $baseUrlRaw) === 0) {
                    $pathInfo = substr($requestUri, strlen($baseUrlRaw));
                } elseif (strpos($requestUri, $baseUrlEncoded) === 0) {
                    $pathInfo = substr($requestUri, strlen($baseUrlEncoded));
                } else {
                    $pathInfo = $requestUri;
                }
            } else {
                $pathInfo = $requestUri;
            }
        
        }

        $this->_pathInfo = (string) $pathInfo;
        return $this;
    }

So, what is the conclusion? The conclusion is that both Ext JS and Zend framework has their own design of RESTful URI pattern. Unfortunately, they are not compatible with each other. They are too nice to do more than developer expected. As libraries vendor, they maybe should do less sometimes in order to make their library as general as possible. Ext JS, as a pure client side JavaScript library, should not guide server side script designer how to implement RESTful Web service. Zend Framework, as a pure server side script library, should not make design for client side application either. In fact, RESTful Web service is a set of guide lines for developer to make scalable application over HTTP methods. But, it does not define how the URI pattern must be.