I have a very positive experience with Click Framework. It’s very easy to create something without to fight with some abstraction level. Most things I ever have used in Click are very fluent and reasonable. For those who prefer tight ORM integration the Apache Cayenne is being supported and integrated very well. With a new ClickIDE version the new application setup, that combines Click + Cayenne + Spring, is quite easy. I can honestly encourage anyone to try it as it is very nice to develop with. I have to mention also that Click is very fast in production.
And final note, what I really like about Click, are the logging levels. As a developer one can easily setup Click logging level. Using this, on server console, you get helpful info, not just some secret java messages. Here is an example of what you can see in lowest logging level when Click is processing the request. It’s a mix of Click and Apache Cayenne logging info. Its many lines but you can see what Click is doing in details.
###################################################################x
[Click] [debug] GET
http://localhost:8080/extjs_user_management/auth/register.htm
[Click] [trace] invoked: Register.<>
[Click] [trace] invoked: Register.onSecurityCheck() : true
INFO - --- will run 1 query.
INFO - Opening connection: jdbc:postgresql://localhost:5432/extjs_auth
Login: postgres
Password: *******
INFO - +++ Connecting: SUCCESS.
INFO - --- transaction started.
INFO - Detected and installed adapter: org.apache.cayenne.dba.postgres.PostgresAdapter
INFO - SELECT t0.description, t0.name, t0.id FROM Role t0 ORDER BY t0.name - prepared in 110 ms.
INFO - === returned 4 rows. - took 688 ms.
INFO - +++ transaction committed.
[Click] [trace] invoked: Register.onInit()
[Click] [trace] invoked: 'form' Form.onInit()
[Click] [trace] invoked: 'form' Form.onProcess() : true
[Click] [trace] invoked: Register.onGet()
[Click] [trace] invoked: Register.onRender()
[Click] [trace] invoked: 'form' Form.onRender()
[Click] [info ] renderTemplate: /auth/register.htm,layouts/layout_logged.htm - 125 ms
[Click] [trace] invoked: 'form' Form.onDestroy()
[Click] [trace] invoked: Register.onDestroy()
[Click] [info ] handleRequest: /auth/register.htm - 1344 ms
[Click] [debug] POST
http://localhost:8080/extjs_user_management/auth/register.htm
[Click] [trace] request param: email=df at df dot cz
[Click] [trace] request param: firstname=David
[Click] [trace] request param: form_name=form
[Click] [trace] request param: lastname=Marko
[Click] [trace] request param: login=password
[Click] [trace] request param: ok= Zaregistrovat
[Click] [trace] request param: password=password
[Click] [trace] invoked: Register.<>
[Click] [trace] invoked: Register.onSecurityCheck() : true
INFO - --- will run 1 query.
INFO - --- transaction started.
INFO - SELECT t0.description, t0.name, t0.id FROM Role t0 ORDER BY t0.name
INFO - === returned 4 rows. - took 0 ms.
INFO - +++ transaction committed.
[Click] [trace] invoked: Register.onInit()
[Click] [trace] invoked: 'form' Form.onInit()
[Click] [debug] Form -> Contact.firstname : David
[Click] [debug] Form -> Contact.lastname : Marko
[Click] [debug] Form -> Contact.email : df at df dot cz
[Click] [debug] Form -> Contact.login : password
[Click] [debug] Form -> Contact.password : password
INFO - --- transaction started.
INFO - INSERT INTO Contact (email, enabled, firstname, id, lastname, login, password, phone) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
INFO - [batch bind: 1->email:'df at df dot cz', 2->enabled:NULL, 3->firstname:'David', 4->id:260, 5->lastname:'Marko', 6->login:'password', 7->password:'password', 8->phone:NULL]
INFO - === updated 1 row.
[Click] [trace] invoked: 'form' Form.onProcess() : true
[Click] [trace] invoked: Register.onPost()
[Click] [trace] invoked: Register.onRender()
[Click] [trace] invoked: 'form' Form.onRender()
[Click] [info ] renderTemplate: /auth/register.htm,layouts/layout_logged.htm - 15 ms
[Click] [trace] invoked: 'form' Form.onDestroy()
[Click] [trace] invoked: Register.onDestroy()
[Click] [info ] handleRequest: /auth/register.htm - 875 ms###################################################################