{"id":815,"date":"2010-01-05T17:34:05","date_gmt":"2010-01-05T17:34:05","guid":{"rendered":"http:\/\/salientsoft.co.uk\/?p=815"},"modified":"2011-11-17T13:03:33","modified_gmt":"2011-11-17T13:03:33","slug":"java-bean-introspection-and-dynamic-sortingcomparison","status":"publish","type":"post","link":"https:\/\/salientsoft.co.uk\/?p=815","title":{"rendered":"Java Bean Introspection and dynamic Sorting\/Comparison"},"content":{"rendered":"<p>Whilst this can be done with the Reflection API, there are standard APIs that do this for Beans and which are therefore a better choice.<\/p>\n<p><strong>java.beans.beaninfo<\/strong> is a standard API for bean introspection. Better still for many applications is the <strong><a title=\"http:\/\/commons.apache.org\/beanutils\/\" href=\"http:\/\/commons.apache.org\/beanutils\/\">Apache Commons BeanUtils<\/a><\/strong> library.<\/p>\n<p>This provides a really simple interface for many operations. For example, get\/set of simple bean properties dynamically is a single call as in this example :-<\/p>\n<pre>Employee employee = ...;\r\n\u00a0\u00a0\u00a0 String firstName = (String)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 PropertyUtils.getSimpleProperty(employee, \"firstName\");\r\n\u00a0\u00a0\u00a0 String lastName = (String)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 PropertyUtils.getSimpleProperty(employee, \"lastName\");\r\n\u00a0\u00a0\u00a0 ... manipulate the values ...\r\n\u00a0\u00a0\u00a0 PropertyUtils.setSimpleProperty(employee, \"firstName\", firstName);\r\n\u00a0\u00a0\u00a0 PropertyUtils.setSimpleProperty(employee, \"lastName\", lastName);<\/pre>\n<p>One of my requirements was a dynamic sort comparator for use in sorting JSF tables by any column. A static comparator is fast, but messy, as you need to hard code switch statements etc. for the property to be compared. BeanUtils has a better option and can create a dynamic comparator for you as in the following\u00a0code fragment from <strong><a title=\"http:\/\/timothypowell.net\/blog\/?p=105\" href=\"http:\/\/timothypowell.net\/blog\/?p=105\">here<\/a><\/strong> :-<\/p>\n<pre>List tvShows = new ArrayList&lt; WorldsGreatestTVShow&gt;();\r\n    \/\/group (sort) by actor\r\n    BeanComparator actorComparator = new BeanComparator(\"actorName\");\r\n    Collections.sort(tvShows, actorComparator);\r\n    \/\/group (sort) by producer\r\n    BeanComparator producerComparator = new BeanComparator(\"producerName\");\r\n    Collections.sort(tvShows, producerComparator);<\/pre>\n<p>However, there is a performance hit with using this &#8211; one comparison cited 16ms using a hard coded static comparator, compared to 400ms using the BeanUtils BeanComparator. Always one to strive for perfection, I said to myself &#8220;why can&#8217;t I have both&#8221; &#8211; i.e. a dynamically created comparator for no effort but which performs as well as a static one? Well, after a bit of searching I found one in the form of the <a title=\"http:\/\/cojen.sourceforge.net\/\" href=\"http:\/\/cojen.sourceforge.net\/\"><strong>Cojen Project<\/strong><\/a><strong>.<\/strong> This is a project aimed at supporting dynamic bytecode generation and disassembly. However, the project also provides a number of powerful utility classes which use the bytecode generation to create fast dynamic Bean Comparators with the same peformance as a statically coded comparator, perform fast Bean Property Introspection, and fast Pattern Matching.<\/p>\n<p>Here is an example\u00a0comparator which orders threads by name, thread group name, and reverse\u00a0priority\u00a0:-<\/p>\n<pre> Comparator c = BeanComparator.forClass(Thread.class)\r\n     .orderBy(\"name\")\r\n     .orderBy(\"threadGroup.name\")\r\n     .orderBy(\"-priority\");<\/pre>\n<p>I particularly love the fact that the customising methods e.g. <strong>orderBy<\/strong> return\u00a0the comparator\u00a0instance so that you can chain them together as above. Sorting by multiple properties is supported as the above example shows. All the generated objects are fully serializable. I\u00a0\u00a0also love the fact that\u00a0you can prefix a property name with a minus sign to reverse the comparison order for that orderBy, which is great for toggling column sort orders with JSF etc.\u00a0 A brief test had it working correctly in no time, and it does indeed appear to be just as fast as a static comparator and very flexible. In future, I would make <strong>Cojen<\/strong> my first port of call for bean pattern matching \/ introspection \/ comparison without hesitation, and then look at <strong>Apache Commons BeanUtils<\/strong> only if <strong>Cojen<\/strong> couldn&#8217;t do what I needed, then failing that <strong>java.beans.beaninfo<\/strong> or finally the raw <strong>reflection<\/strong> API.<\/p>\n<p><strong>I really can have my cake and eat it!<\/strong> <strong><a title=\"http:\/\/headrush.typepad.com\/creating_passionate_users\/2006\/11\/two_simple_word.html\" href=\"http:\/\/headrush.typepad.com\/creating_passionate_users\/2006\/11\/two_simple_word.html\">Sex on a stick!<\/a><\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Whilst this can be done with the Reflection API, there are standard APIs that do this for Beans and which are therefore a better choice. java.beans.beaninfo is a standard API for bean introspection. Better still for many applications is the Apache Commons BeanUtils library. This provides a really simple interface for many operations. For example, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[7],"tags":[100,96,98,99,181,97,16],"_links":{"self":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/815"}],"collection":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=815"}],"version-history":[{"count":13,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/815\/revisions"}],"predecessor-version":[{"id":1572,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/815\/revisions\/1572"}],"wp:attachment":[{"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=815"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=815"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/salientsoft.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=815"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}