{"id":822,"date":"2006-07-20T04:02:58","date_gmt":"2006-07-20T08:02:58","guid":{"rendered":"http:\/\/wordpress.cephas.net\/?p=822"},"modified":"2006-07-20T04:02:58","modified_gmt":"2006-07-20T08:02:58","slug":"fluentinterface","status":"publish","type":"post","link":"https:\/\/cephas.net\/blog\/2006\/07\/20\/fluentinterface\/","title":{"rendered":"FluentInterface"},"content":{"rendered":"<p>A couple of weeks ago on the <a href=\"https:\/\/dwr.dev.java.net\/servlets\/SummarizeList?listName=users\">DWR users list<\/a>, in the context of needing to wire up DWR without using an XML file, <a href=\"http:\/\/getahead.ltd.uk\/blog\/joe\">Joe Walker<\/a> pointed to <a href=\"http:\/\/www.martinfowler.com\/bliki\/FluentInterface.html\">a blog posting<\/a> by <a href=\"http:\/\/www.martinfowler.com\/\">Martin Fowler<\/a>. In it, Martin discusses an interface style called a &#8216;fluent interface&#8217;. It&#8217;s a little difficult to describe in words (so check it out in action on above mentioned blog post) but I think <a href=\"http:\/\/www.bofh.org.uk\/\">Piers Cawley<\/a> <a href=\"http:\/\/www.bofh.org.uk\/articles\/2005\/12\/21\/fluent-interfaces\">described it best<\/a> when he described the style as &#8220;&#8230;essentially interfaces that do a good job of removing hoopage.&#8221; <strong>Update:<\/strong> <a href=\"http:\/\/rifers.org\/blogs\/gbevin\/2006\/1\/11\/fluent_interface\">Geert Bevin uses this style in the RIFE framework<\/a> and was calling the it &#8220;chainable builder methods&#8221; before Martin came along with the &#8216;fluent interface&#8217; term.<\/p>\n<p>Back to DWR.&nbsp;&nbsp;I spent the last couple days working on a &#8216;fluent&#8217; way of configuring DWR which obviously then wouldn&#8217;t require <a href=\"http:\/\/getahead.ltd.uk\/dwr\/server\/dwrxml\">dwr.xml<\/a>, the result of which is available <a href=\"http:\/\/cephas.net\/projects\/fluentdwr\/fluentdwr.zip\">here<\/a>. In short, given an XML configuration file that looks like this:<br \/>\n<code><br \/>\n&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;<br \/>\n&lt;!DOCTYPE dwr PUBLIC \"-\/\/GetAhead Limited\/\/DTD Direct Web Remoting<br \/>\n1.0\/\/EN\" \"http:\/\/www.getahead.ltd.uk\/dwr\/dwr10.dtd\"&gt;<br \/>\n&lt;dwr&gt;<br \/>\n&nbsp;&nbsp;&lt;init&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;converter id=\"testbean\" class=\"uk.ltd.getahead.testdwr.TestBean2Converter\"\/&gt;<br \/>\n&nbsp;&nbsp;&lt;\/init&gt;<br \/>\n&nbsp;&nbsp;&lt;allow&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;create creator=\"new\" javascript=\"Test\" scope=\"application\"&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param name=\"class\" value=\"uk.ltd.getahead.testdwr.Test\"\/&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;\/create&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;create creator=\"new\" javascript=\"JDate\"&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param name=\"class\" value=\"java.util.Date\"\/&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;exclude method=\"getHours\"\/&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;auth method=\"getMinutes\" role=\"admin\"\/&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;auth method=\"getMinutes\" role=\"devel\"\/&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;\/create&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;convert converter=\"bean\" match=\"$Proxy*\"\/&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;convert converter=\"testbean\" match=\"uk.ltd.getahead.testdwr.TestBean\"\/&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;convert converter=\"bean\" match=\"uk.ltd.getahead.testdwr.ObjB\"\/&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;convert converter=\"object\" match=\"uk.ltd.getahead.testdwr.ObjA\"&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param name=\"force\" value=\"true\"\/&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;\/convert&gt;<br \/>\n&nbsp;&nbsp;&lt;\/allow&gt;<br \/>\n&nbsp;&nbsp;&lt;signatures&gt;<br \/>\n&nbsp;&nbsp;&lt;![CDATA[<br \/>\n&nbsp;&nbsp;import java.util.*;<br \/>\n&nbsp;&nbsp;import uk.ltd.getahead.testdwr.*;<br \/>\n&nbsp;&nbsp;Test.testBeanSetParam(Set&lt;TestBean&gt;);<br \/>\n&nbsp;&nbsp;Test.testBeanListParam(List&lt;TestBean&gt;);<br \/>\n&nbsp;&nbsp;Test.charTestBeanMapParam(Map&lt;Character, TestBean&gt;);<br \/>\n&nbsp;&nbsp;Test.stringStringMapParam(Map&lt;String, String&gt;);<br \/>\n&nbsp;&nbsp;Test.stringStringHashMapParam(HashMap&lt;String, String&gt;);<br \/>\n&nbsp;&nbsp;Test.stringStringTreeMapParam(TreeMap&lt;String, String&gt;);<br \/>\n&nbsp;&nbsp;Test.stringCollectionParam(Collection&lt;String&gt;);<br \/>\n&nbsp;&nbsp;Test.stringListParam(List&lt;String&gt;);<br \/>\n&nbsp;&nbsp;Test.stringLinkedListParam(LinkedList&lt;String&gt;);<br \/>\n&nbsp;&nbsp;Test.stringArrayListParam(ArrayList&lt;String&gt;);<br \/>\n&nbsp;&nbsp;Test.stringSetParam(Set&lt;String&gt;);<br \/>\n&nbsp;&nbsp;Test.stringHashSetParam(HashSet&lt;String&gt;);<br \/>\n&nbsp;&nbsp;Test.stringTreeSetParam(TreeSet&lt;String&gt;);<br \/>\n&nbsp;&nbsp;]]&gt;<br \/>\n&nbsp;&nbsp;&lt;\/signatures&gt;<br \/>\n&lt;\/dwr&gt;<br \/>\n<\/code><br \/>\nyou can instead configure DWR using the FluentConfiguration class like this:<br \/>\n<code><br \/>\nFluentConfiguration fluentconfig = (FluentConfiguration)configuration;<br \/>\nfluentconfig<br \/>\n&nbsp;&nbsp;.withConverterType(\"testbean\", \"uk.ltd.getahead.testdwr.TestBean2Converter\")<br \/>\n&nbsp;&nbsp;.withCreator(\"new\", \"Test\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addParam(\"scope\", \"application\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addParam(\"class\", \"uk.ltd.getahead.testdwr.Test\")<br \/>\n&nbsp;&nbsp;.withCreator(\"new\", \"JDate\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addParam(\"class\", \"java.util.Date\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.exclude(\"getHours\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.withAuth(\"getMinutes\", \"admin\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.withAuth(\"getMinutes\", \"devel\")<br \/>\n&nbsp;&nbsp;.withConverter(\"bean\", \"$Proxy*\")<br \/>\n&nbsp;&nbsp;.withConverter(\"testbean\", \"uk.ltd.getahead.testdwr.TestBean\")<br \/>\n&nbsp;&nbsp;.withConverter(\"bean\", \"uk.ltd.getahead.testdwr.ObjB\")<br \/>\n&nbsp;&nbsp;.withConverter(\"object\", \"uk.ltd.getahead.testdwr.ObjA\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addParam(\"force\", \"true\")<br \/>\n&nbsp;&nbsp;.withSignature()<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"import java.util.*;\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"import uk.ltd.getahead.testdwr.*;\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.testBeanSetParam(Set);\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.testBeanListParam(List);\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.charTestBeanMapParam(Map);\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.stringStringMapParam(Map);\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.stringStringHashMapParam(HashMap);\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.stringStringTreeMapParam(TreeMap);\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.stringCollectionParam(Collection);\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.stringListParam(List);\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.stringLinkedListParam(LinkedList);\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.stringArrayListParam(ArrayList);\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.stringSetParam(Set);\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.stringHashSetParam(HashSet);\")<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;.addLine(\"Test.stringTreeSetParam(TreeSet);\")<br \/>\n&nbsp;&nbsp;.finished();<br \/>\n<\/code><br \/>\nIf you&#8217;re interested in using this in your DWR project, you need only to:<\/p>\n<li> create a class that extends DWRServlet (example: check out FluentDWRServlet.java in the zip file) and use that class as your DWR servlet\n<li> add a configuration param in web.xml called uk.ltd.getahead.dwr.Configuration and set the value to net.cephas.dwr.FluentConfiguration\n<li> add a configuration param in web.xml called skipDefaultConfig and set the value to true<br \/>\n<code><br \/>\n&lt;servlet&gt;<br \/>\n&nbsp;&nbsp;&lt;servlet-name&gt;dwr&lt;\/servlet-name&gt;<br \/>\n&nbsp;&nbsp;&lt;servlet-class&gt;net.cephas.dwr.FluentDWRServlet&lt;\/servlet-class&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;init-param&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-name&gt;uk.ltd.getahead.dwr.Configuration&lt;\/param-name&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-value&gt;net.cephas.dwr.FluentConfiguration&lt;\/param-value&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;\/init-param&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;init-param&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-name&gt;skipDefaultConfig&lt;\/param-name&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-value&gt;true&lt;\/param-value&gt;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;\/init-param&gt;<br \/>\n&lt;\/servlet&gt;<br \/>\n<\/code><\/p>\n<li> and then override the configure method in the servlet and use the fluent style of configuration I used above.\n<p>Send me an <a href=\"mailto:ajohnson@cephas.net\">email<\/a> if you have any questions!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A couple of weeks ago on the DWR users list, in the context of needing to wire up DWR without using an XML file, Joe Walker pointed to a blog posting by Martin Fowler. In it, Martin discusses an interface style called a &#8216;fluent interface&#8217;. It&#8217;s a little difficult to describe in words (so check &hellip; <a href=\"https:\/\/cephas.net\/blog\/2006\/07\/20\/fluentinterface\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">FluentInterface<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[3,29,2,10],"tags":[],"_links":{"self":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/posts\/822"}],"collection":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/comments?post=822"}],"version-history":[{"count":0,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/posts\/822\/revisions"}],"wp:attachment":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/media?parent=822"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/categories?post=822"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/tags?post=822"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}