Wednesday, April 10, 2013

ExtJS debug version: there it is - but useless

This is a follow-up post to my last week's "ExtJS: desperately need a debug version".
A user comment pointed me to the "-dev" version. Apparently there is such a file now containing some lines of error checking (not too many):

See  http://www.diffnow.com/?report=ahx86 for the diff. I compared http://cdn.sencha.io/ext-4.2.0-gpl/ext-debug.js with http://cdn.sencha.io/ext-4.2.0-gpl/ext-dev.js (My Chrome browser crashed a couple of times with these large files at DiffNow and similar online diff tools.)

A download of the latest version 4.2 contains, among many other files:

ext-all.js 1'402 KB
ext-all-debug.js 3'262 KB
ext-all-debug-w-comments.js 6'052 KB
ext-all-dev.js 6'109 KB

So what Sencha needs to do now is to update this page http://www.sencha.com/learn/debugging-ext-js-applications and recommend to include ext-all-dev.js instead of ext-all-debug.js, while keeping ext-all.js for production.

And, does it help?

A couple days forward and I upgraded my app (still in development) from ExtJS 4.1 to 4.2. All seemed fine. There were not too many backward-incompatible changes this time. Plus, I have the dev version now which would alert me of problems right?

A screen using 4.1:

The same screen with 4.2:
<link rel="stylesheet" href="http://cdn.sencha.io/ext-4.2.0-gpl/resources/css/ext-all-gray.css"/>
<script src="http://cdn.sencha.io/ext-4.2.0-gpl/ext-all-dev.js"></script>


The search field on the toolbar is missing. Just gone. Nothing in the console. The grid search extension is from here but that is irrelevant.

Another week passed by, and another case cost me 15 minutes of searching: I've created a new form panel with just one field, copy-pasted from an official example.

{
    fieldLabel: 'My field',
    name: 'myField',
    allowBlank: false
}

Loading it in the browser, but the panel remains empty (except for the button bar). No error or warning output of course. What's wrong? Something with the panel dimensions? The panel has no width or height? (ExtJS developers will know...) Trying all kinds of combinations. Turns out the problem is very, very basic. I forgot to specify what kind of field it is (xtype: 'textfield'). The example had it configured in the parent object as 'defaultType', and I did not copy that. So ext was supposed to render an element to the screen, but it was not informed about what kind of element it is. What does it do? Apparently nothing... How about at least logging a warning?

Conclusion

Nothing has changed for me. Making mistakes or upgrading ExJS means digging.

Thursday, April 4, 2013

ExtJS: desperately need a debug version

Update to this post: there is a debug version.

I missed it when using ExtJS 2, then with ExtJS 3. Now I'm using ExtJS 4 for a new web user interface, and the situation is the same: I desperately need a debug version of ExtJS!

On the plus side: The best web gui toolkit

ExtJS is, in my opinion, the most complete JavaScript library for making desktop-like apps in the browser. It has been there for long time, and is actively developed. It's relatively easy to extend components and develop your own. The community is large, the documentation is OK, and it's possible to create useful, functional, "rich" user interfaces. It's possible to get the job done.

Beware: It's a full time job

The examples look nice, and one could get the idea that it's a quick and easy path to develop your own rich gui. Nah. It's all trial and error F5 style development. It takes a lot of time and effort to get halfway fluent with it. There are many gotchas to learn about.

It sucks the energy out of me

For me, working with ExtJS is no pleasure. It brings a new flow stopper way too often. Why?
  1. The nature of JavaScript.
    JavaScript is not a type safe language. There's no safe refactoring. No compile time confidence. That's a fact, nothing to improve here.
  2. ExtJS performs no checks.
    No input checking (preconditions, assertions), no checks for common errors.
Let's look at an example: "Uncaught TypeError: Object #<object> has no method 'read'"</object>


Aha, some script execution error occurred. Let's check the detail:


Not that helpful. Something internal in ExtJS on line 39145 failed. ExtJS does not catch this one (or any other) and tell me what the real problem is. Nor does the stack trace go back to my userland code.

In this case the problem was that I did not include some data store model prior to using it. My fault. But it doesn't have to be. There are plenty of reasons for such time consuming debugging, just because problems are never detected, and throw at last moment, deep down:
  • Developer error: wrong API use
  • ExtJS bug
  • ExtJS annoyance
  • Old code: upgrading an older app, or copying an older example from the internet

But wait: I'm using "ext-all-debug.js"

Unfortunately, the naming of the ExtJS JavaScript files is, imo, wrong.

JQuery got it right:
The original JS file, with apidoc: http://code.jquery.com/jquery-1.9.1.js
The minified version for production: http://code.jquery.com/jquery-1.9.1.min.js

This has become the standard, and makes perfect sense. The minified file name contains the ".min". And they both contain the version number - this way there's never a web browser having a stale version in the cache.

ExtJS files:
ext-all.js: The minified JS file.
ext-all-debug.js: The original source code, comments stripped. Useless.
ext-all-debug-w-comments.js: The original source code.

What I (and probably every other ExtJS developer) need is a version that contains code with input checking to throw as early as possible, with a meaningful message. You know... common  programming practices... absolutely mandatory for any library code.

Summing it up

As it is now, you have to test every single functionality to be sure it works. Upgrading an app from ExtJS 3 to ExtJS 4 is no fun. Lots of things don't work anymore, but you have to figure out a) which and b) what to change. And the same will be true for version 5, 6 and 7. And any minor upgrade can break things too.

If you have ui tests then at least you will know about some defects early. But you still need to figure out the hard way how to fix them. And writing and maintaining automated ui tests is another full time job.

Please, Sencha, do yourself and every of the 2 million developers a big favor and add error checking to your libraries, and strip it in the "min"-ified production version for equal performance and file size.

Wednesday, April 3, 2013

Java: Replace Apache Commons DBCP

Until recently I used to use the Apache Commons Database Connection Pool in my JDBC Java applications. Then there was an incident, and I had to replace it with c3p0. Here are my reasons.

I never gave it much thought. A db connection pool just manages the connections... handing them out and taking them back. How hard can that be? It's not something I want to spend time on. There's that project from Apache, and I like their HTTP server. So it's probably a safe bet. I thought.

What's the quality of commons-dbcp?

The hottest question about commons-dbcp on stackoverflow is this one: Someone asking whether to use Apache DBCP or C3P0.

The top answer with many agreements says:
DBCP is out of date and not production grade. Some time back we conducted an in-house analysis of the two, creating a test fixture which generated load and concurrency against the two to assess their suitability under real life conditions.
DBCP consistently generated exceptions into our test application and struggled to reach levels of performance which C3P0 was more than capable of handling without any exceptions.
C3P0 also robustly handled DB disconnects and transparent reconnects on resume whereas DBCP never recovered connections if the link was taken out from beneath it. Worse still DBCP was returning Connection objects to the application for which the underlying transport had broken.
Since then we have used C3P0 in 4 major heavy-load consumer web apps and have never looked back.
The post (from 2009) then goes on and says that recently there was some work on  commons-dbcp. Now, 4  years later, what happened in the meantime?

What's the status of  commons-dbcp?

The website was last updated 2.5 years ago.

The last release 1.4 is 3 years old, 1.4.1 is a snapshot.

The website is broken:
  • It has dead links (for example to the official Javadoc). 
  • The logo image on the left doesn't load.
  • And it has character set issues to display the text (those ? signs). 
Maybe these errors are in place when the website url changed from http://commons.apache.org/dbcp/ to the one it redirects to. Anyway, they don't seem to be important to be fixed.

Commons-dbcp is a subversion repo at svn.apache.org (C3P0 is on GitHub).

My issue

The reason why I had to kick commons-dbcp out was that it broke my application. After a couple hours it stopped handing out connections, and all threads were in WAITING state.
org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1104)
After some reading I tried c3p0, run long running high concurrency tests where commons-dbcp choked, and it all worked fine. And after some more reading I was convinced that the problem was solved.

But it works for me...

Maybe it does. Maybe you just don't hit it hard enough yet. And maybe you don't get to see all errors. As reported by others there are issues with commons-dbcp, and it looks like a dead project. Also, Hibernate comes with c3p0, not commons-dbcp.

But dbcp is faster ...

I've seen statistics where one or the other product stands out. Any connection pool is fast enough for me... as long as it keeps doing its main job.

Other alternatives

I did not look into other, newer products because I'm happy with one that has been in use for long time.

Now there's the Apache Tomcat JDBC Connection Pool and this blog post talks about feeling uncomfortable with commons-dbcp and replacing it with tomcat-jdbc.

And there's BoneCP which says how much faster it is than the others. It started in 2009, had no release in 2 years, and is at version v0.7.1.

I want to replace commons-dbcp with c3p0!

Here's what you have to do if you're using Maven and Spring, connecting to MySQL:

1. Replace the commons-jdbc dependency with this:
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.2.1</version>
</dependency>
2. Replace some words in the data source bean:
a) change the class to com.mchange.v2.c3p0.ComboPooledDataSource
b) change the word "driverClassName" to "driverClass"
c) change the word "url" to "jdbcUrl"
d) change the word "username" to "user"

Example:
<bean id="geoDataSource" destroy-method="close" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl"     value="jdbc:mysql://localhost/db"/>
    <property name="user"        value="myUser"/>
    <property name="password"    value="myPassword"/>
</bean>

Conclusions

  1. You might want to consider replacing commons-dbcp also. Maybe with c3p0, it works for me.
  2. Maybe commons-dbcp should be moved to their attic.

Update 2014-03-11
C3P0 is under active development on GitHub, and the author nicely replied to my questions on StackOverflow and on the mailing list within hours. Thumbs up.