{"id":871,"date":"2012-01-02T10:22:00","date_gmt":"2012-01-02T10:22:00","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/2012\/10\/zk-web-framework-thoughts.html"},"modified":"2012-10-21T22:52:44","modified_gmt":"2012-10-21T22:52:44","slug":"zk-web-framework-thoughts","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html","title":{"rendered":"ZK Web Framework Thoughts"},"content":{"rendered":"<div dir=\"ltr\" style=\"text-align: left\">I\u2019ve been asked several times to present some of my opinions about <a href=\"http:\/\/www.zkoss.org\/\">ZK<\/a>. So, based of my experience of 4 years as a ZK user, here\u2019s some thoughts:<\/p>\n<p><span class=\"Apple-style-span\" style=\"font-size: large\"><strong>Overall developer experience, the community and documentation<\/strong><\/span><\/p>\n<p><strong>\u201cIt just works\u201d<\/strong><\/p>\n<p>Most of the stuff that ZK offers works very well, and the functionality is usually very intuitive to use if you have developed any desktop Java applications before. In 2007 I did a comparison of RIA technologies that included Echo2, ZK, GWT, OpenLaszlo and Flex. Echo2 and OpenLaszlo felt incomplete and buggy and didn\u2019t seem to have proper Maven artifacts anywhere. GWT seemed more of a technical experiment than a good platform to build on. Flex was dropped because some important Maven artifacts were missing and Flash was an unrealistic requirement for the application. On the other hand, ZK felt the most \u201cnatural\u201d and I was able to quickly get productive with it. During my 4 year long journey with ZK, I\u2019ve gotten plenty of those \u201cwow\u201d moments when I\u2019ve learned more and more of ZK and improved my architectural understanding of the framework.<\/p>\n<p>Nowadays I\u2019ve got a pretty good understanding of what in ZK works, what doesn\u2019t, and what has problems and what doesn\u2019t. But still, after gaining all this good and bad insight, I consider ZK to be a very impressive product out of the box. The downside of this is of course the fact that the framework hides a lot of things from newcomers in order to be easy to use, and <i>some of these things will bite you later on<\/i>, especially if your application has lots of users.<\/p>\n<p><strong>It\u2019s very, very, very flexible<\/strong><\/p>\n<p>ZK is very flexible and has plenty of integrations. Do you want use declarative markup to build component trees? Use ZUL files. Do you want to stick to plain Java? Use richlets. You can also integrate JSP, JSF, Spring, and use plenty of languages in zscript. The core framework is also pretty flexible and you can override a lot of stuff if you run into problems.<\/p>\n<p>The downside is that there are very many ways of doing things correctly, and even more ways of screwing up. Flexibility itself is not a negative point, but I think that the ZK documentation doesn\u2019t guide users enough towards the best practices of ZK. What are the best practices anyway? Many tutorials use zscript, but the docs also recommend to avoid it due to performance reasons.<\/p>\n<p><strong>The forum is quite active<\/strong><\/p>\n<p>I think that the ZK forum is one of the best places to learn about ZK. It\u2019s pretty active and the threads vary from beginner level to deep technical stuff. I read the forums myself almost every day and sometimes help people with their problems. There\u2019s one thing that troubles me a bit: the English language in the forums isn\u2019t usually very good and people often ask too broad questions. I know, it\u2019s not fair to criticize the writings of non-native English speakers, especially when I\u2019m not a native speaker myself. Regardless, I think that such a barrier exists. For example, take 5 random threads from the ZK forum and Spring Web forum.<\/p>\n<p>The threads in the Spring forums are typically more detailed and focused instead of \u201c<i>I\u2019m a newbie and I need to create application x with tons of features, please tell me how to do everything<\/i>\u201d-type threads you see in the ZK forums and people clearly spend some time formulating good and detailed questions. You\u2019ll see that you have to spend a bit more time in the ZK forum in order to understand the threads. It\u2019s not anybody\u2019s fault or anything, nor a bad thing, this is just an observation. Unfortunately for me it means that some of my limited time I have for the ZK community is spent just trying to understand what people are saying. Usually I answer a thread only when I know the answer right away, or if the thread concerns some deep technical stuff.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p><strong>There\u2019s plenty of documentation<\/strong><\/p>\n<p>In the past the ZK documentation was scattered, out of date and some of the more important stuff was completely missing. In the recent years the docs have improved a lot, and there\u2019s now separate comprehensive references for <a href=\"http:\/\/books.zkoss.org\/wiki\/ZK_Configuration_Reference\">ZK configuration<\/a>, <a href=\"http:\/\/books.zkoss.org\/wiki\/ZK_Client-side_Reference\">client-side ZK<\/a>, and <a href=\"http:\/\/books.zkoss.org\/wiki\/ZK_Style_Guide\">styling<\/a>. I think the documentation is today very good, and most basic questions can be easily answered by reading the docs.<\/p>\n<p>As I mentioned above, ZK has a tendency to \u201cjust work\u201d. The overall technical quality is impressive and on par with most Java web frameworks, but I believe there are some parts of ZK that are less impressive.<\/p>\n<p><span class=\"Apple-style-span\" style=\"font-size: large\"><strong>Stuck on Java 1.4<\/strong><\/span><\/p>\n<p>ZK is built with Java 1.4, which greatly limits the flexibility of their API and internal code quality<\/p>\n<p><strong>Negative effects on ZK internal code<\/strong><\/p>\n<ul>\n<li>ThreadLocals not removed with remove() <i>(calling set(null) does prevent leaking the contained object but does not properly remove a ThreadLocal)!<\/i><\/li>\n<li>Lots of custom synchronization code where simple java.util.concurrent data structures or objects would work (ConcurrentHashMap, Semaphore, Atomic*, etc)<\/li>\n<li>StringBuffer is used where StringBuilder would be appropriate<\/li>\n<\/ul>\n<p><strong>No annotations<\/strong><\/p>\n<p>Personally I\u2019m not a fan of annotation-heavy frameworks because annotations are an extralinquistic feature and usually you end up annotations with string-based values that have no type safety. However, I know that some people would be overjoyed to have an API based on them.<\/p>\n<p><strong>No enums<\/strong><\/p>\n<p>There are many places in the ZK API where proper enums would be much better than the hacks that are used at the moment. The worst offender is Messagebox. Just look at this signature:<\/p>\n<pre class=\"brush: java\">public static int show(String message,\r\n                       String title,\r\n                       int buttons,\r\n                       java.lang.String icon,\r\n                       int focus)<\/pre>\n<p>Ugh..the magic integers remind me of SWT (which is a great library with an awful API). Let\u2019s imagine an alternative version with enums and generics:<\/p>\n<pre class=\"brush: java\">public static Messagebox.Button show(String message,\r\n                       String title,\r\n                       Set&lt;Messagebox.Button&gt; buttons,\r\n                       Messagebox.Icon icon,\r\n                       Messagebox.Button focus)<\/pre>\n<p>Much, much better and more typesafe. No more bitwise OR magic. I could code this in 10 minutes into ZK if it would use Java 1.5.<\/p>\n<p><strong>No generics<\/strong><\/p>\n<p>This is the worst part of being stuck on Java 1.4.<\/p>\n<p>I\u2019ll just list some of the places where I\u2019d like to see generics:<\/p>\n<p>Collection values in API signatures<\/p>\n<p>Example in org.zkoss.zk.ui.util.Initiator:<\/p>\n<pre class=\"brush: java\">void doInit(Page page, Map args);<\/pre>\n<p>vs<\/p>\n<pre class=\"brush: java\">void doInit(Page page, Map&lt;String, Object&gt; args);<\/pre>\n<p>Example in org.zkoss.zk.ui.Component:<\/p>\n<pre class=\"brush: java\">List getChildren();<\/pre>\n<p>vs<\/p>\n<pre class=\"brush: java\">List&lt;Component&gt; getChildren();<\/pre>\n<p>Collection-like classes<\/p>\n<p>Example in ListModel:<\/p>\n<pre class=\"brush: java\">public interface ListModel {\r\n  ...\r\n  Object getElementAt(int index);\r\n  ...\r\n}<\/pre>\n<p>vs<\/p>\n<pre class=\"brush: java\">public interface ListModel&lt;T&gt; {\r\n  ...\r\n  T getElementAt(int index);\r\n  ...\r\n}<\/pre>\n<p>All ListModel* classes should also be generic (most extend java.util.Collection).<br \/>\norg.zkoss.zk.ui.event.EventListener<\/p>\n<pre class=\"brush: java\">public interface EventListener {\r\n  public void onEvent(Event event);\r\n}<\/pre>\n<p>vs<\/p>\n<pre class=\"brush: java\">public interface EventListener&lt;T extends Event&gt; {\r\n  public void onEvent(T event);\r\n}<\/pre>\n<p>org.zkoss.zk.ui.util.GenericAutowireComposer<\/p>\n<pre class=\"brush: java\">public class GenericAutowireComposer {\r\n  protected Component self;\r\n  ...\r\n}<\/pre>\n<p>vs<\/p>\n<pre class=\"brush: java\">public class GenericAutowireComposer&lt;T extends Component&gt; {\r\n  protected T self;\r\n  ...\r\n}<\/pre>\n<p>All *Renderer classes<br \/>\nExample in org.zkoss.zul.RowRenderer:<\/p>\n<pre class=\"brush: java\">public interface RowRenderer {\r\n  void render(Row row, Object data);\r\n}<\/pre>\n<p>vs<\/p>\n<pre class=\"brush: java\">public interface RowRenderer&lt;T&gt; {\r\n  void render(Row row, T data);\r\n}<\/pre>\n<p><span class=\"Apple-style-span\" style=\"font-size: large\"><strong>Unimpressive server push implementations<\/strong><\/span><\/p>\n<p>The default PollingServerPush has latency and will absolutely kill your application server if there are many active users. CometServerPush is better, but it does not use non-blocking IO and will block servlet threads in your servlet container. Let\u2019s put this into perspective:<\/p>\n<p>Tomcat 7.0 default configuration sets connector max threads to 200. This means that if you have 200 comet-enabled desktops, Tomcat will stop responding to other requests because all the threads are in use by comet. If the implementation used Servlet 3.0 or container-specific async APIs instead, you could run Tomcat even with one thread. It would of course be slow but it would not stop working!<br \/>\nAlso, CometServerPush requires ZK EE so regular users are stuck with PollingServerPush. I\u2019d say that\u2019s a pretty big limitation considering how server push is marketed. However, it\u2019s not surprising: proper non-blocking comet is hard to implement and requires non-blocking components in all parts of the pathway from the browser to the servlet code.<\/p>\n<p><strong><span class=\"Apple-style-span\" style=\"font-size: large\">Zscript<\/span><\/strong><\/p>\n<p>I don\u2019t like zscript. It might have been a good feature many years ago, but I believe that today it should not be used at all. Why, oh why would someone want to replace typesafe compiled Java code with non-typechecked zscript mixed with ZUL templates?<\/p>\n<ul>\n<li>\u201cI can use Python\/Ruby\/\u2026\u201d. This might be a valid point for some people but you\u2019ll end up with unmaintainable code mangled inside ZUL templates<\/li>\n<li>\u201cChanges are visible when you save the file\u201d. True, but I would never sacrifice so much just for this feature. And besides, you can get a similar effect with <a href=\"http:\/\/www.zeroturnaround.com\/jrebel\">JRebel<\/a>.<\/li>\n<\/ul>\n<p>So, if you put \u201cJava code\u201d (=BeanShell code) in zscript, you might want to rethink that.<\/p>\n<p><strong><span class=\"Apple-style-span\" style=\"font-size: large\">Reliance on reflection<\/span><\/strong><\/p>\n<p>Many useful features rely on reflection, which limits what things the compiler can check for you. This is very typical thing in many Java libraries\/frameworks, so it\u2019s not really a ZK-specific thing. As a Scala user I can see how the limitations of Java have guided most frameworks to the path of reflection\/annotations. Reflection cannot always be avoided but I think it\u2019s a bad sign if most of the useful features rely on reflection. Here are some features in ZK that use reflection:<\/p>\n<ul>\n<li>Any kind of event listening that does not use component.addEventListener. This includes any classes that extend GenericEventListener (such as all ZK-provided Composer classes except MultiComposer)<\/li>\n<li>Data binding<\/li>\n<li>EL expressions in ZUL templates<\/li>\n<\/ul>\n<p><strong><i>Reference: <\/i><\/strong><a href=\"http:\/\/jawsy.fi\/blog\/2011\/09\/08\/thoughts-about-the-zk-web-framework-overall-experience\/\">Thoughts about the ZK Web Framework: Overall experience<\/a>&nbsp; &amp;&nbsp;<a href=\"http:\/\/jawsy.fi\/blog\/2011\/09\/27\/thoughts-about-the-zk-web-framework-technical-stuff\/\">Thoughts about the ZK Web Framework: Technical stuff<\/a>&nbsp;from our <a href=\"http:\/\/www.javacodegeeks.com\/p\/jcg.html\">JCG partner<\/a>&nbsp;Joonas Javanainen at the&nbsp;<a href=\"http:\/\/jawsy.fi\/blog\/\">Jawsy Solutions technical blog <\/a><\/p>\n<p><strong><i>Related Articles :<\/i><\/strong><\/p>\n<ul>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2010\/06\/getting-started-smartgwt-gwt-interfaces.html\">Getting Started with SmartGWT for awesome GWT interfaces<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2011\/01\/advanced-smartgwt-tutorial-part-1.html\">Advanced SmartGWT Tutorial, Part 1<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2010\/12\/securing-gwt-apps-with-spring-security.html\">Securing GWT apps with Spring Security<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2010\/09\/gwt-ejb3-maven-jboss-51-integration.html\">GWT EJB3 Maven JBoss 5.1 integration tutorial<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2011\/04\/spring-mvc3-hibernate-crud-sample.html\">Spring MVC3 Hibernate CRUD Sample Application<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2011\/02\/spring-mvc-development-tutorial.html\">Spring MVC Development &#8211; Quick Tutorial<\/a><\/li>\n<\/ul>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>I\u2019ve been asked several times to present some of my opinions about ZK. So, based of my experience of 4 years as a ZK user, here\u2019s some thoughts: Overall developer experience, the community and documentation \u201cIt just works\u201d Most of the stuff that ZK offers works very well, and the functionality is usually very intuitive &hellip;<\/p>\n","protected":false},"author":111,"featured_media":257,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[351],"class_list":["post-871","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-zk"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>ZK Web Framework Thoughts - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"I\u2019ve been asked several times to present some of my opinions about ZK. So, based of my experience of 4 years as a ZK user, here\u2019s some thoughts: Overall\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"ZK Web Framework Thoughts - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"I\u2019ve been asked several times to present some of my opinions about ZK. So, based of my experience of 4 years as a ZK user, here\u2019s some thoughts: Overall\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2012-01-02T10:22:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2012-10-21T22:52:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/zk-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Joonas Javanainen\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@http:\/\/twitter.com\/Gekkio\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Joonas Javanainen\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html\"},\"author\":{\"name\":\"Joonas Javanainen\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/11d056970ee9a1b348d9d320e9a2ca7f\"},\"headline\":\"ZK Web Framework Thoughts\",\"datePublished\":\"2012-01-02T10:22:00+00:00\",\"dateModified\":\"2012-10-21T22:52:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html\"},\"wordCount\":1571,\"commentCount\":4,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/zk-logo.jpg\",\"keywords\":[\"ZK\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html\",\"name\":\"ZK Web Framework Thoughts - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/zk-logo.jpg\",\"datePublished\":\"2012-01-02T10:22:00+00:00\",\"dateModified\":\"2012-10-21T22:52:44+00:00\",\"description\":\"I\u2019ve been asked several times to present some of my opinions about ZK. So, based of my experience of 4 years as a ZK user, here\u2019s some thoughts: Overall\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/zk-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/zk-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/01\\\/zk-web-framework-thoughts.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"ZK Web Framework Thoughts\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/11d056970ee9a1b348d9d320e9a2ca7f\",\"name\":\"Joonas Javanainen\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/340875a23855972753a4340fae766e867777945e028a4809a525f2952ba16607?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/340875a23855972753a4340fae766e867777945e028a4809a525f2952ba16607?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/340875a23855972753a4340fae766e867777945e028a4809a525f2952ba16607?s=96&d=mm&r=g\",\"caption\":\"Joonas Javanainen\"},\"description\":\"Joonas is a passionate software developer from Finland. He has worked on a multitude of problem domains, and focuses professionally on functional programming and JVM-based technologies.\",\"sameAs\":[\"http:\\\/\\\/gekkio.fi\\\/blog\\\/\",\"http:\\\/\\\/fi.linkedin.com\\\/in\\\/gekkio\\\/\",\"https:\\\/\\\/x.com\\\/http:\\\/\\\/twitter.com\\\/Gekkio\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/Joonas-Javanainen\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"ZK Web Framework Thoughts - Java Code Geeks","description":"I\u2019ve been asked several times to present some of my opinions about ZK. So, based of my experience of 4 years as a ZK user, here\u2019s some thoughts: Overall","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html","og_locale":"en_US","og_type":"article","og_title":"ZK Web Framework Thoughts - Java Code Geeks","og_description":"I\u2019ve been asked several times to present some of my opinions about ZK. So, based of my experience of 4 years as a ZK user, here\u2019s some thoughts: Overall","og_url":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2012-01-02T10:22:00+00:00","article_modified_time":"2012-10-21T22:52:44+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/zk-logo.jpg","type":"image\/jpeg"}],"author":"Joonas Javanainen","twitter_card":"summary_large_image","twitter_creator":"@http:\/\/twitter.com\/Gekkio","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Joonas Javanainen","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html"},"author":{"name":"Joonas Javanainen","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/11d056970ee9a1b348d9d320e9a2ca7f"},"headline":"ZK Web Framework Thoughts","datePublished":"2012-01-02T10:22:00+00:00","dateModified":"2012-10-21T22:52:44+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html"},"wordCount":1571,"commentCount":4,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/zk-logo.jpg","keywords":["ZK"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html","url":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html","name":"ZK Web Framework Thoughts - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/zk-logo.jpg","datePublished":"2012-01-02T10:22:00+00:00","dateModified":"2012-10-21T22:52:44+00:00","description":"I\u2019ve been asked several times to present some of my opinions about ZK. So, based of my experience of 4 years as a ZK user, here\u2019s some thoughts: Overall","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/zk-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/zk-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2012\/01\/zk-web-framework-thoughts.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"ZK Web Framework Thoughts"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/11d056970ee9a1b348d9d320e9a2ca7f","name":"Joonas Javanainen","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/340875a23855972753a4340fae766e867777945e028a4809a525f2952ba16607?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/340875a23855972753a4340fae766e867777945e028a4809a525f2952ba16607?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/340875a23855972753a4340fae766e867777945e028a4809a525f2952ba16607?s=96&d=mm&r=g","caption":"Joonas Javanainen"},"description":"Joonas is a passionate software developer from Finland. He has worked on a multitude of problem domains, and focuses professionally on functional programming and JVM-based technologies.","sameAs":["http:\/\/gekkio.fi\/blog\/","http:\/\/fi.linkedin.com\/in\/gekkio\/","https:\/\/x.com\/http:\/\/twitter.com\/Gekkio"],"url":"https:\/\/www.javacodegeeks.com\/author\/Joonas-Javanainen"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/871","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/111"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=871"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/871\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/257"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=871"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=871"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=871"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}