Rob Cernich's Bloghttps://developer.jboss.org/people/rcernich/blogJive Engage2012-03-05T18:48:10Z2012-03-05T18:48:10ZCreating Extensible GWT-Platform ApplicationsRob Cernich/people/rcernichdo-not-reply@jboss.com2012-03-05T18:48:10Z2012-03-05T18:48:10Z<!-- [DocumentBodyStart:0002a612-d1a0-4644-a02f-445da63fb995] --><div class="jive-rendered-content"><p>Recently, I started looking at integrating the SwitchYard console into the core AS7 console.&#160; In generic terms, the goals of this effort were:</p><ol><li style="text-align: start;">The base/core should be able to be packaged as a standalone application, without modification.</li><li style="text-align: start;">An extension need only contain functionality specific to one or more extensions.</li><li style="text-align: start;">Creating an extended application should be as simple as packaging the base with a select set of extensions. </li></ol><p style="min-height: 8pt; padding: 0px;">&#160;</p><p>While new to GWT, this turned out to be more difficult than I had originally anticipated.&#160; The basic problem, creating an extension/plug-in mechanism, can be solved in many ways, most of which involve the use of a generator.&#160; Things get complicated when GWT-Platform is thrown into the mix.&#160; Specifically, it becomes difficult to meet the first goal.</p><p style="min-height: 8pt; padding: 0px;">&#160;</p><p>The complication arises out of the following GWT-P constraints:</p><ul><li style="text-align: start;">The Ginjector interface must provide a getter for all presenters.</li><li style="text-align: start;">The Ginjector interface must be known during code generation (GWT-P proxy generators)</li></ul><p style="min-height: 8pt; padding: 0px;">&#160;</p><p>Extending the Ginjector interface is pretty trivial (interface Foo extends ...).&#160; Specifying the new interface is also pretty trivial (override the gin.ginjector property).&#160; The problem then boils down to making sure the base application instantiates the extended Ginjector interface.</p><p style="min-height: 8pt; padding: 0px;">&#160;</p><p>Turns out, this is pretty easy to accomplish using deferred binding, double deferred binding to be exact.&#160; Instead instantiating the Ginjector using the traditional GWT.create(MyGinjector.class) (typically in the base application's EntryPoint), a factory class is instantiated, which then instantiates the appropriate Ginjector.</p><p style="min-height: 8pt; padding: 0px;">&#160;</p><p>Tying everything together, an extended application simply needs to:</p><ol><li style="text-align: start;">Define an extended Ginjector interface (e.g. ExtendedGinjector extends BaseGinjector, ExtensionGinjector...).</li><li style="text-align: start;">Override the gin.ginjector property (i.e. gin.ginjector=ExtendedGinjector).</li><li style="text-align: start;">Implement a GinjectorFactory that serves up an ExtendedGinjector.</li><li style="text-align: start;">Tell GWT to use its ExtendedGinjectorFactory (i.e. replace-with ...) </li></ol><p style="min-height: 8pt; padding: 0px;">&#160;</p><p>This concept can be taken a step further by changing the factory into a singleton.&#160; This allows any part of the application to access the Ginjector through the same method of indirection.&#160; For example,</p><!--[CodeBlockStart:5f8c2fc8-33ac-45c9-ae4f-53d24141b5a9][excluded]--><pre class="java" name="code">interface GinjectorSingleton {
&#160;&#160;&#160; BaseGinjector instance();
}
</pre><!--[CodeBlockEnd:5f8c2fc8-33ac-45c9-ae4f-53d24141b5a9]--><div style="display:none;"></div><p style="min-height: 8pt; padding: 0px;">&#160;</p><p>A specific implementation might look like:</p><!--[CodeBlockStart:7f1cae86-b67e-434a-92ee-fb439f99c2de][excluded]--><pre class="java" name="code">class ExtendedGinjectorSingleton implements GinjectorSingleton {
&#160;&#160;&#160; private static final BaseGinjector instance = GWT.create(ExtendedGinjector.class);
&#160;&#160;&#160; public BaseGinjector instance() { return instance; }
}
</pre><!--[CodeBlockEnd:7f1cae86-b67e-434a-92ee-fb439f99c2de]--><div style="display:none;"></div><p style="min-height: 8pt; padding: 0px;">&#160;</p><p>Any part of the application can then access the Ginjector using:</p><!--[CodeBlockStart:52100775-3ff9-4e09-b68a-da9d7d19b7f9][excluded]--><pre class="java" name="code">BaseGinjector ginjector = GWT.&lt;GinjectorSingleton&gt;(GinjectorSingleton.class).instance();
</pre><!--[CodeBlockEnd:52100775-3ff9-4e09-b68a-da9d7d19b7f9]--><div style="display:none;"></div><p style="min-height: 8pt; padding: 0px;">&#160;</p><p><span>I've put together a complete, simplified example here: </span><a class="jive-link-external-small" href="https://github.com/rcernich/fools-errands/tree/master/modular-mvp" target="_blank">https://github.com/rcernich/fools-errands/tree/master/modular-mvp</a></p><p><span>A more complex example, integrating the SwitchYard console with the core AS console can be found here:&#160; </span><a class="jive-link-external-small" href="https://github.com/jboss-switchyard/console" target="_blank">https://github.com/jboss-switchyard/console</a></p><p style="min-height: 8pt; padding: 0px;">&#160;</p><p>Happy coding!</p></div><!-- [DocumentBodyEnd:0002a612-d1a0-4644-a02f-445da63fb995] -->2012-03-05T18:48:10Z4 years 9 months ago0https://developer.jboss.org/people/rcernich/blog/comment/creating-extensible-gwt-platform-applicationshttps://developer.jboss.org/people/rcernich/blog/feeds/comments?blogPost=4749