<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-804931010262428127</id><updated>2012-01-10T22:22:39.458+03:00</updated><category term='gwt'/><category term='oop'/><category term='development process'/><category term='python'/><title type='text'>Tim's Software Development Blog</title><subtitle type='html'>My personal software development experience and value judgement on various development technologies and approaches.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://timursdev.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://timursdev.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Tim</name><uri>http://www.blogger.com/profile/13946718929977648625</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_v6HvzVShiHU/TD9KIcEBu4I/AAAAAAAAABk/-XY8OUcH7mg/S220/The+Mars+ava.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-804931010262428127.post-7455971434295787960</id><published>2011-05-31T16:07:00.012+03:00</published><updated>2011-06-12T21:51:36.107+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='oop'/><title type='text'>Abstract methods in Python</title><content type='html'>&lt;div style="text-align: right;"&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://timursdev.blogspot.com/2011/05/abstract-methods-in-python.html';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'Abstract methods in Python';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;script src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;/div&gt;Python has no concept of an "abstract method" on a &lt;b&gt;language level&lt;/b&gt;.  This makes developers often implement abstract methods incorrectly.  Even though there is no language level construct for this - there is a  pretty strict and well known pattern for abstract methods, and there are according means for  that. Hereafter is a correct way to implement it (and most often - the  only correct way). I hope this post may be useful for new Python developers who are not familiar with the "abstract method" concept in Python yet.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;b&gt;Problem&lt;/b&gt;:&lt;br /&gt;Implement an abstract method. In most simple terms - abstract method is a method with a  defined signature, and with no implementation; if class A defines an  abstract method, it is supposed that classes inherited from A should  implement it (not necessarily direct subclasses, but some subclass should or otherwise what's the point of it?). Thus, abstract methods are used to define a behaviour this  or other classes use, while the implementation of this behaviour  is provided by subclasses. Most often this is used to define interfaces  or implement a "factory method" pattern.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Common error&lt;/b&gt;:&lt;br /&gt;Most common error is to merely omit an abstract method  declaration, use the not declared method whenever needed, and suppose subclasses  actually add it to the class. For example, the following class uses method &lt;b&gt;connect()&lt;/b&gt;, which is defined in a subclass only.&lt;br /&gt;&lt;pre&gt;&lt;b&gt;&lt;br /&gt;class &lt;/b&gt;ConnectionPool(&lt;b&gt;object&lt;/b&gt;):&lt;br /&gt;  &lt;b&gt;def &lt;/b&gt;__init__(&lt;b&gt;self&lt;/b&gt;):&lt;br /&gt;    self.pool = []&lt;br /&gt; &lt;br /&gt;  &lt;b&gt;def &lt;/b&gt;hasSpareConnection(&lt;b&gt;self&lt;/b&gt;):&lt;br /&gt;    # here goes the method implementation&lt;br /&gt;    # I don't put here for simplicity&lt;b&gt;&amp;nbsp; &lt;/b&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;  def &lt;/b&gt;acquire(&lt;b&gt;self&lt;/b&gt;):&lt;br /&gt;    &lt;b&gt;if not self&lt;/b&gt;.hasSpareConnection():&lt;br /&gt;      connection = &lt;b style="color: red;"&gt;self&lt;/b&gt;&lt;span style="color: red;"&gt;.connect()&lt;/span&gt;&lt;br /&gt;      &lt;b&gt;self&lt;/b&gt;.pool.append(connection)&lt;br /&gt;      &lt;b&gt;return &lt;/b&gt;connection&lt;br /&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;class &lt;/b&gt;MySqlConnectionPool(ConnectionPool):&lt;br /&gt;  &lt;b style="color: red;"&gt;def &lt;/b&gt;&lt;span style="color: red;"&gt;connect(&lt;/span&gt;&lt;b style="color: red;"&gt;self&lt;/b&gt;&lt;span style="color: red;"&gt;):&lt;/span&gt;&lt;br /&gt;    # connection = connect to MySQL somehow &lt;br /&gt;    &lt;b&gt;return &lt;/b&gt;connection&lt;/pre&gt;&lt;br /&gt;This is not correct for a number of  reasons. First of all - how would a subclass author (unless it is you for  the eternity and you have an ideal memory) know that he or she needs to implement it? It is not  defined and not documented anywhere. Secondly, classes using these "not  declared abstract methods" are not readable at all: when you read it not having a subclass -  you see a method being executed but can't&amp;nbsp; figure out where is it defined.  Finally, you get an &lt;b&gt;AttributeError &lt;/b&gt;with a weird message like "attribute  'bla' is not defined", which is true, but this message proposes &lt;b&gt;no  solution &lt;/b&gt;for a subclass author.&lt;br /&gt;&lt;br /&gt;All these issues are solved in a next section: the method is always defined there in a super class, its docstring describes what it  does, and the  error message says how a subclass should behave.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Solution 1:&lt;/b&gt;&lt;br /&gt;Python has no language level construct for abstract methods, but you  force class users to implement a method by throwing a &lt;b&gt; NotImplementedError &lt;/b&gt;from a method you define as an abstract. Ideally you  should as well put a docstring for the method and provide a detailed error  message. &lt;br /&gt;&lt;pre&gt;&lt;b&gt;&lt;br /&gt;class &lt;/b&gt;ConnectionPool(object):&lt;br /&gt;&amp;nbsp; # ...&lt;br /&gt;&amp;nbsp; &lt;b&gt;def &lt;/b&gt;acquire(&lt;b&gt;self&lt;/b&gt;):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;if not self&lt;/b&gt;.hasSpareConnection():&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; connection = &lt;span _mce_style="color: #ff0000;" style="color: red;"&gt;&lt;b&gt;self.&lt;/b&gt;connect()&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;self&lt;/b&gt;.pool.append(connection)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;return &lt;/b&gt;connection&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;  &lt;span style="color: red;"&gt;def &lt;/span&gt;&lt;/b&gt;&lt;span style="color: red;"&gt;connect(&lt;/span&gt;&lt;b style="color: red;"&gt;self&lt;/b&gt;&lt;span style="color: red;"&gt;):&lt;/span&gt;&lt;br /&gt;    '''Creates a new connection to the DB &lt;br /&gt;    and returns it. Should be implemented &lt;br /&gt;    in a subclass'''&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;   message = "Method connect() should be \&lt;br /&gt;    implemented and return a newly \&lt;br /&gt;    instantiated connection to the DB"&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;&amp;nbsp;   &lt;span style="color: red;"&gt;raise&lt;/span&gt; &lt;/b&gt;&lt;span style="color: red;"&gt;NotImplementedError(message)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;class &lt;/b&gt;MySqlConnectionPool(ConnectionPool):&lt;br /&gt;&amp;nbsp; &lt;b style="color: red;"&gt;def &lt;/b&gt;&lt;span _mce_style="color: #ff0000;" style="color: red;"&gt;connect&lt;/span&gt;&lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;b style="color: red;"&gt;self&lt;/b&gt;&lt;span style="color: red;"&gt;):&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # connection = connect to MySQL somehow &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;return &lt;/b&gt;connection&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now suppose you implement new &lt;b&gt;OracleConnectionPool&lt;/b&gt;. You create a subclass, don't implement a connect() method, and run a program. What you get is an error message: "Method connect() should be implemented and return a newly instantiated connection to the DB". Now you have plan! Go on, implement it and your job is done! This is much easier than digging into the AttributeError trace back and the base class implementation to find out what's happening there.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Solution 2:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;There is another (to my mind - better) solution ever since Python 2.6 - it's an abc modue. I don't think it is worth to describe it in all details here given that its documentation is pretty complete and easy to understand. I will only show an example of its usage in this concrete example, so that you can compare it with the previous one. Among its benefits I will mention the only one I personally consider the most important - users won't be able to instantiate an abstract class or instantiate its ancestor unless this ancestor implements all abstract methods. Yes, class users will see a &lt;b&gt;standard &lt;/b&gt;error message once they try to &lt;b&gt;instantiate &lt;/b&gt;a class, not only when an abstract method is executed.&lt;br /&gt;&lt;br /&gt;Changes are made to the ConnectionPool class only. We will do the two things: first, delcare it as an "&lt;i&gt;abstract base class&lt;/i&gt;", and define certain methods as abstract. Ancestror classes will look same way as with the previous solution - just implement abstract methods and you're good to go.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;b&gt;&lt;/b&gt;&lt;/pre&gt;&lt;pre style="color: red;"&gt;&lt;b&gt;from &lt;/b&gt;abc &lt;b&gt;import &lt;/b&gt;ABCMeta, abstractmethod&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;&lt;/b&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;class &lt;/b&gt;ConnectionPool(object):&lt;/pre&gt;&lt;pre&gt;&lt;span style="color: red;"&gt; &lt;/span&gt;&lt;b style="color: red;"&gt;__metaclass__&lt;/b&gt;&lt;span style="color: red;"&gt; = ABCMeta&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp; # ...&lt;br /&gt;&amp;nbsp; &lt;b&gt;def &lt;/b&gt;acquire(&lt;b&gt;self&lt;/b&gt;):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;if not self&lt;/b&gt;.hasSpareConnection():&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; connection = &lt;span _mce_style="color: #ff0000;" style="color: red;"&gt;&lt;b&gt;self.&lt;/b&gt;connect()&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;self&lt;/b&gt;.pool.append(connection)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;return &lt;/b&gt;connection&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;  &lt;span style="color: red;"&gt;@abstractmethod &lt;/span&gt;&lt;/b&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;  &lt;span style="color: red;"&gt;def &lt;/span&gt;&lt;/b&gt;&lt;span style="color: red;"&gt;connect(&lt;/span&gt;&lt;b style="color: black;"&gt;self&lt;/b&gt;&lt;span style="color: red;"&gt;):&lt;/span&gt;&lt;br /&gt;    '''Creates a new connection to the DB &lt;br /&gt;    and returns it. Should be implemented &lt;br /&gt;    in a subclass'''&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;&amp;nbsp;   &lt;span style="color: red;"&gt;return None&lt;/span&gt;&lt;/b&gt;&lt;span style="color: red;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;i&gt;Note: many thanks to user 'naglfar' for the hint about "abc" module. See comments below for details.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Resume&lt;/b&gt;:&lt;br /&gt;Well, I'm used to put a "resume" to all my posts, but this one is pretty self-descriptive - please, consider this pattern when implementing abstract factory methods or interfaces. It is a well known pattern and most Python developers actually expect your class to behave this way if you suppose subclasses should implement its abstract methods.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;Disclaimer&lt;/b&gt;: the example above is imaginary and is not likely how you implement a connection pool indeed.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;© Copyright 2011 Timur Rubeko&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://timursdev.blogspot.com/2011/05/abstract-methods-in-python.html';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'Abstract methods in Python';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;script src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/804931010262428127-7455971434295787960?l=timursdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timursdev.blogspot.com/feeds/7455971434295787960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://timursdev.blogspot.com/2011/05/abstract-methods-in-python.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/7455971434295787960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/7455971434295787960'/><link rel='alternate' type='text/html' href='http://timursdev.blogspot.com/2011/05/abstract-methods-in-python.html' title='Abstract methods in Python'/><author><name>Tim</name><uri>http://www.blogger.com/profile/13946718929977648625</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_v6HvzVShiHU/TD9KIcEBu4I/AAAAAAAAABk/-XY8OUcH7mg/S220/The+Mars+ava.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-804931010262428127.post-3194329442220530706</id><published>2010-06-29T22:47:00.021+03:00</published><updated>2010-08-18T10:21:46.932+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gwt'/><title type='text'>Add custom events to your GWT widget or, "Rich TextEditor, part 2"</title><content type='html'>&lt;p style="text-align: right;"&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://timursdev.blogspot.com/2010/06/add-custom-events-to-your-gwt-widget-or.html';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'Add custom events to your GWT widget or, "Rich TextEditor, part 2"';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;script src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This post is a "part 2" of the &lt;a href="http://timursdev.blogspot.com/2010/06/full-fledged-gwt-rich-text-editor.html" target="_blank"&gt;"Create a full-fledged GWT Rich Text Editor widget"&lt;/a&gt;. It is not necessary though that you read previous one, to dive into here. In previous post I described how to create your own TextEditor GWT widget by wrapping the TinyMCE Java Script library. In this article I will continue to enhance the widget and will add a support for a custom event - "save" event in particular.&lt;/p&gt;&lt;p&gt;You may &lt;a href="https://www.assembla.com/spaces/TextEditorGWT/documents/cvrKoQHfmr37ZBeJe5cbLA/download/TextEditor.jar" target="_self"&gt;download&lt;/a&gt;&amp;nbsp;the source code. This is also good news for those who read the previous post - I didn't attach the source code then, but was asked for later, so here it is. In fact, this download is a complete version of the widget and it also includes the changes described in this post.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Well, let's start...&lt;/p&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;h3&gt;Design the event handling from user standpoint&lt;/h3&gt;&lt;p&gt;What the widget lacks is an ability to save a document being edited. Without this ability its usage is limited to embedding it to certain form, having its own submit button. In fact, there is no even a "Save" button in a widget itself.&lt;/p&gt;&lt;p&gt;Hm..., there is one in the TinyMCE, however. Looks we are lucky - we might merely add one to the widget - it is a matter of one line of code, as the widget is flexible enough and configurable. But we still won't be able to hook the "save" event, unless we provide a callback Java Script function. But our idea with the widget was - none of the JSNI code for widget users. So, we will hide it all inside. Here comes its usage concept:&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;TextEditor editor = &lt;span style="color: #000080;"&gt;new &lt;/span&gt;TextEditor();&lt;br /&gt;// configure editor as needed (size, default content, etc.)&lt;br /&gt;editor.addSaveHandler(&lt;span style="color: #000080;"&gt;new &lt;/span&gt;SaveHandler() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;public void&lt;/span&gt; onSave(SaveEvent event) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;});&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;For me - looks nice :) So, let's sum up what we need to create and manage a new custom event:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Create an event class - it may store any information related to the event, its source, attributes, etc.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Create an event handler interface - it will be implemented by widget users and it will be registered within the widget itself&lt;/li&gt;&lt;li&gt;Suite the widget with a method to register an event handler&lt;/li&gt;&lt;li&gt;And, sure enough, implement an event management in the widget&lt;/li&gt;&lt;/ol&gt;&lt;h3&gt;Add support for GWT events&lt;/h3&gt;&lt;p&gt;Good news is that GWT already has almost everything what we need to manage events. GWT not only defines necessary interfaces and abstract classes, but even provides us with a HandlerManager - this "utility" will track all our event handlers and will fire events on them when we need it to. Thus, as we stick to GWT event model, we should implement our event and handler according to GWT standards.&lt;/p&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Event&lt;/span&gt;&lt;/p&gt;&lt;p&gt;SaveEvent is an event fired up when user clicks save button. In fact it won't hold much information within itself, and so its implementation is pretty straightforward. We only need to subclass a GwtEvent, as we want to use GWT's event management means.&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;span style="color: #000080;"&gt;public class&lt;/span&gt; SaveEvent &lt;span style="color: #000080;"&gt;extends &lt;/span&gt;GwtEvent&lt;span style="color: #808080;"&gt;&amp;lt;SaveEventHandler&amp;gt;&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;public static&lt;/span&gt; Type&lt;span style="color: #808080;"&gt;&amp;lt;SaveEventHandler&amp;gt;&lt;/span&gt; &lt;em&gt;TYPE &lt;/em&gt;= &lt;span style="color: #000080;"&gt;new &lt;/span&gt;Type&lt;span style="color: #808080;"&gt;&amp;lt;SaveEventHandler&amp;gt;&lt;/span&gt;(); &amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #808080;"&gt;@Override&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;public &lt;/span&gt;Type&amp;lt;SaveEventHandler&amp;gt; getAssociatedType()&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;return &lt;/span&gt;&lt;em&gt;TYPE&lt;/em&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #808080;"&gt;@Override&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;protected void&lt;/span&gt; dispatch(SaveEventHandler handler)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;handler.onSave(&lt;span style="color: #000080;"&gt;this&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;Note that we added a TYPE constant and implemented getAssociatedType() method - this is needed as we will use GWT's HandlerManager and it will "map" events and handlers by their event type. We will also need this constant to be public - we will get to it in a moment.&lt;/p&gt;&lt;p&gt;Another one point to note is that event also implements a dispacth() method - otherwise how would GWT know the event handler's method to execute? Instead of trying to guess it - it delegates the event&amp;nbsp;dispatching&amp;nbsp;to us :) It is pretty simple anyway.&lt;/p&gt;&lt;p&gt;We used an event handler already... Here it is:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;EventHandler&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Similarly, as we use GWT's event management means, our SaveEventHandler will extend an EventHandler interface. Our interface itself is even simpler than SaveEvent - obviously it should be that simple as we want our users to start using it with minimal efforts:&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;span style="color: #000080;"&gt;public interface&lt;/span&gt; SaveEventHandler &lt;span style="color: #000080;"&gt;extends &lt;/span&gt;EventHandler&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;void &lt;/span&gt;onSave(SaveEvent event);&lt;br /&gt;}&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;strong&gt;Register and track event handlers&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Finally, we want to suite our widget with a way to add SaveEventHandlers to it. We agreed already that we will use a GWT's HandlerManager to manage "save" event. But we don't want our users to access it directly, rather we want them to use a convenient method, like addSaveHandler(SaveEventHandler).&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;span style="color: #000080;"&gt;public class&lt;/span&gt; TextEditor &lt;span style="color: #000080;"&gt;extends &lt;/span&gt;TextArea &lt;span style="color: #000080;"&gt;implements &lt;/span&gt;EntryPoint&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private &lt;/span&gt;HandlerManager handlerManager = &lt;span style="color: #000080;"&gt;new &lt;/span&gt;HandlerManager(&lt;span style="color: #000080;"&gt;null&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;public void &lt;/span&gt;addSaveHandler(SaveEventHandler handler)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;handlerManager.addHandler(SaveEvent.&lt;em&gt;TYPE&lt;/em&gt;, handler);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;}&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;br /&gt;&lt;h3&gt;Fire an event&lt;/h3&gt;&lt;p&gt;Pretty cool, as you may notice we didn't much work to add an event. Well, it is not fired up anywhere yet, but not a huge work too. We'll see now.&lt;/p&gt;&lt;p&gt;In fact, TinyMCE already implements an ability to "catch" the user on clicking the "Save" button. So, this means we only need to add some JSNI code to do so, and link it together with our event model. To do so, we need to initialize the TinyMCE "save" plug-in, add a save button, and register so-called "save callback" function which is executed by TinyMCE. Hm, for me - I don't think it is a good idea to implement everything in the widget - in our implementation we will only ensure there is a "save" plug-in enabled, and add a callback function. We will let widget users to add a "save" button were they need it (and if they need it).&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;span style="color: #000080;"&gt;public class&lt;/span&gt; TextEditor &lt;span style="color: #000080;"&gt;extends &lt;/span&gt;TextArea &lt;span style="color: #000080;"&gt;implements &lt;/span&gt;EntryPoint&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private void&lt;/span&gt; initialize()&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #808080;"&gt;// initialize the stuff needed for "save" event&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;addPlugin(&lt;span style="color: #008000;"&gt;"save"&lt;/span&gt;); &lt;span style="color: #808080;"&gt;// ensure it is always there, even if widget user forgot to add it&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #808080;"&gt;// (we also assume here at least "save" button is added - otherwise how would end user click it?)&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;addOption(&lt;span style="color: #008000;"&gt;"save_onsavecallback"&lt;/span&gt;, &lt;span style="color: #008000;"&gt;"saveHandler"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;registerSaveHandler();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private native void&lt;/span&gt; registerSaveHandler()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;/*-{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;var &lt;/span&gt;thisTextEditor = &lt;span style="color: #000080;"&gt;this&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;$wnd&lt;/span&gt;.saveHandler = &lt;span style="color: #000080;"&gt;$entry&lt;/span&gt;(&lt;br /&gt;&lt;span style="color: #000080;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;function&lt;/span&gt;() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;thisTextEditor.@com.nimble.gwtaddons.texteditor.client.TextEditor::onSave()();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}-*/;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private void&lt;/span&gt; onSave()&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;handlerManager.fireEvent(&lt;span style="color: #000080;"&gt;new &lt;/span&gt;SaveEvent());&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;}&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;That's it. Few comments about the callback we added - it may look a bit tricky, but it is not that much really. $entry produces a JavaScript function you may reference, and it may be executed on the instance all right, but the trick is that we should use an instance variable other than "this". It is because at the time the function is executed, "this" - will be a current window, but not a TextEditor instance. And thus we store it first to another one variable in the JSNI code, which assumes "this" to be a widget instance.&lt;/p&gt;&lt;p&gt;All right! You now have a working Save event! You may add a "save" button to a widget now, and add your SaveEventHandler. Try it out!&lt;/p&gt;&lt;h3&gt;Resume&lt;/h3&gt;&lt;div&gt;To sum up, adding a custom event is a pretty easy 4-step process: you create an event class, an event handler interface, reuse the HandlerManager to manage the events and handlers, and the only thing left for you is to implement firing up the event on a HandlerManager instance, and it will do the rest for you.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;In particular, we added a SaveEvent to previously developed TextEditor GWT widget. You may&amp;nbsp;&lt;a href="https://www.assembla.com/spaces/TextEditorGWT/documents/cvrKoQHfmr37ZBeJe5cbLA/download/TextEditor.jar" target="_self"&gt;download&lt;/a&gt;&amp;nbsp;its source code and use it under the terms of LGPL 3.1 or higher.&lt;/div&gt;&lt;p/&gt;&lt;div&gt;© Copyright 2010 Timur Rubeko&lt;/div&gt;&lt;p style="text-align: left;"&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://timursdev.blogspot.com/2010/06/add-custom-events-to-your-gwt-widget-or.html';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'Add custom events to your GWT widget or, "Rich TextEditor, part 2"';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;br /&gt;Did you like the article?&lt;br /&gt;&lt;script src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/804931010262428127-3194329442220530706?l=timursdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timursdev.blogspot.com/feeds/3194329442220530706/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://timursdev.blogspot.com/2010/06/add-custom-events-to-your-gwt-widget-or.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/3194329442220530706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/3194329442220530706'/><link rel='alternate' type='text/html' href='http://timursdev.blogspot.com/2010/06/add-custom-events-to-your-gwt-widget-or.html' title='Add custom events to your GWT widget or, &quot;Rich TextEditor, part 2&quot;'/><author><name>Tim</name><uri>http://www.blogger.com/profile/13946718929977648625</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_v6HvzVShiHU/TD9KIcEBu4I/AAAAAAAAABk/-XY8OUcH7mg/S220/The+Mars+ava.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-804931010262428127.post-874003549403517295</id><published>2010-06-25T17:48:00.339+03:00</published><updated>2010-08-18T10:24:49.493+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gwt'/><title type='text'>Creating a full-fledged GWT Rich Text Editor widget</title><content type='html'>&lt;p style="text-align: right;"&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://timursdev.blogspot.com/2010/06/full-fledged-gwt-rich-text-editor.html';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'Creating a full-fledged GWT Rich Text Editor widget"';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;script src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Note: this post has a part 2 - &lt;a href="http://timursdev.blogspot.com/2010/06/add-custom-events-to-your-gwt-widget-or.html"&gt;Add custom events to your GWT widget or, "Rich TextEditor, part 2"&lt;/a&gt;&lt;/p&gt;&lt;p style="text-align: left;"&gt;There is a plenty of Java Script libraries doing many useful stuff for you. And it is pretty easy to integrate them into your GWT project, so you obviously want to do so rather than reimplementing the same functionality in Java. But you still want to use as less JSNI code as you can, right?&lt;/p&gt;&lt;p&gt;In this article I would like to show how to create new GWT widget by wrapping existing Java Script library.&lt;/p&gt;&lt;p&gt;It was a need in a nice text editor widget when I created my first one. GWT comes with RixhTextArea which is useful to display rich text, but not that useful to edit a text when you realize that it doesn't come with the full set of controls to trigger text formatting (like buttons to trigger bolder text, drop-downs with fonts, etc.). So, you will need to implement all these by your own, if you stick to this widget.&lt;/p&gt;&lt;p&gt;On the other hand, there is a well-known TinyMCE JavaScript library (&lt;a title="http://tinymce.moxiecode.com/" href="http://tinymce.moxiecode.com/" target="_blank"&gt;http://tinymce.moxiecode.com/&lt;/a&gt;) that does all the stuff for you. Well, in fact I think this is the reason why there is no pure GWT widgets with its functionality - why&amp;nbsp;create&amp;nbsp;one from scratch if we can reuse TinyMCE? So, that's what we will do here - we will create a TextEditor GWT widget reusing the functionality from TinyMCE. You can visit the page by link above and have a look on how it looks like, if you are not familiar with this library.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;Widget interface&lt;/h3&gt;&lt;p&gt;To get the idea on what it will be like, and what is a benefit of the separate widget, have a look at some sample code. The obvious benefit is no injection of any Java Script code to a host page. This is pure Java:&lt;span style="font-family: 'courier new', courier; font-size: x-small; color: #000080;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;span style="color: #000080;"&gt;final &lt;/span&gt;TextEditor editor = new TextEditor();&lt;br /&gt;editor.setWidth(&lt;span style="color: #008000;"&gt;"700px"&lt;/span&gt;);&lt;br /&gt;editor.setHeight(&lt;span style="color: #008000;"&gt;"400px"&lt;/span&gt;);&lt;br /&gt;editor.addOptions(TextEditorPreset.PRESET_ADVANCED);&lt;br /&gt;editor.addPlugin(&lt;span style="color: #008000;"&gt;"contextmenu"&lt;/span&gt;);&lt;br /&gt;editor.setText(&lt;span style="color: #008000;"&gt;"Hello, &amp;lt;b&amp;gt;World&amp;lt;/b&amp;gt;!"&lt;/span&gt;);&lt;br /&gt;editPanel.add(editor);&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;That's it! Nothing else. Once we have a widget implemented, we will be able to:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Add a text editor to a GWT application as a regular widget. No JSNI code at all, no changes to host HTML.&lt;/li&gt;&lt;li&gt;Use all the same functionality as for regular TextArea&lt;/li&gt;&lt;li&gt;Configure TextEditor with any options: select the controls to use, enable TinyMCE plugins (like spell checker, context menu, etc.).&lt;/li&gt;&lt;li&gt;Use "presets" to initialize the widget with a predefined set of options&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;And this is how the widget looks like:&lt;/p&gt;&lt;p&gt;&lt;img style="vertical-align: middle;" src="http://4.bp.blogspot.com/_v6HvzVShiHU/TCdo2bI9mqI/AAAAAAAAAAM/GZwxr7aXK9k/s1600/TextEditor.png" alt="" width="504" height="217" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;/ul&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;h3&gt;Create a Project&lt;/h3&gt;&lt;p&gt;Hereafter we will go through a widget implementation process, but I won't be much concentrating on the usual developments stuff, rather I will describe the general ideas behind the implementation. We also assume here that you have a GWT project for the widget. My project is named "TextEditor". To start with, our TextEditor.gwt.xml looks like:&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&amp;lt;module&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;inherits name=&lt;span style="color: #008000;"&gt;"com.google.gwt.user.User"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;entry-point class=&lt;span style="color: #008000;"&gt;"your.package.texteditor.client.TextEditor"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&amp;lt;/module&amp;gt;&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;I'd also recommend to create another one project where you will use the widget while implementing it. Create a panel with a widget, and launch this project in hosted mode from time to time to see what we have.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;TextEditor widget base&lt;/h3&gt;&lt;p&gt;Firstly, we need to identify the widget superclass. We have options to create a Composite, or a new widget from scratch, or extend an existing one. Obviously enough, we choose the latter: TinyMCE is a some kind of a "wrapper" over a &amp;lt;textarea&amp;gt; (well, not necesserily &amp;lt;textarea&amp;gt; only, though we will use it this way) - it needs to be initialized and linked to certain &amp;lt;textarea&amp;gt;s on a page. Well, it seems logical to implement our widget same way - it will be a TextArea subclass, and it will initialize TinyMCE over itself.&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;span style="color: #000080;"&gt;public class &lt;/span&gt;TextEditor &lt;span style="color: #000080;"&gt;extends &lt;/span&gt;TextArea &lt;span style="color: #000080;"&gt;implements &lt;/span&gt;EntryPoint&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #808080;"&gt;// ...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;public void &lt;/span&gt;onModuleLoad()&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;As you notice, we also implement EntryPoint. In fact we do nothing in the onModuleLoad() implementation, but it's still necessary if we want to compile the widget.&lt;/p&gt;&lt;p&gt;Well, pretty good to time - our widget already has the standard interface and an implementation for such methods as setHeight(), setText(), etc. Pretty cool, but... oh, our widget does nothing new yet... Well, here goes...&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;Wrap the JavaScript library&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Add the library to "public"&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Let's add the text editor functionality now. To do so, download a TinyMCE library, extract it and add it to a new "public" package. Yes, that's the point - any necessary JavaScript libraries will reside in the project's public directory, and thus will be available with the widget itself. This means that you will not need to add the library to the \web directory if you are willing to use the widget. Sure enough, you should also add the new public directory to TextEditor.gwt.xml:&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&amp;lt;module&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;inherits name=&lt;span style="color: #008000;"&gt;"com.google.gwt.user.User"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;entry-point class=&lt;span style="color: #008000;"&gt;"your.package.texteditor.client.TextEditor"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="background-color: #ffff00;"&gt;&amp;lt;public path=&lt;span style="color: #008000;"&gt;"public"&lt;/span&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;lt;/module&amp;gt;&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;While the directory structure may look like:&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;your\package\texteditor\TextEditor.gwt.xml&lt;br /&gt;&amp;nbsp;&amp;nbsp;your\package\texteditor\client&lt;br /&gt;&amp;nbsp;&amp;nbsp;your\package\texteditor\client\TextEditor.java&lt;br /&gt;&amp;nbsp;&amp;nbsp;your\package\texteditor\public&lt;br /&gt;&amp;nbsp;&amp;nbsp;your\package\texteditor\public\tiny_mce\&lt;br /&gt;&amp;nbsp;&amp;nbsp;your\package\texteditor\public\tiny_mce\tiny_mce.js&lt;br /&gt;&amp;nbsp;&amp;nbsp;etc. (the rest of the library)&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;strong&gt;Load the JavaScript to the host page&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Well, as we added the library to the public directory for our project, sure enough we won't be willing to modify the host page to load it. Remember? Our idea is - not any manipulation on a host page. So, thus we load the library in the TextEditor.gwt.xml as well&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&amp;lt;module&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;inherits name=&lt;span style="color: #008000;"&gt;"com.google.gwt.user.User"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;entry-point class=&lt;span style="color: #008000;"&gt;"your.package.texteditor.client.TextEditor"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;public path=&lt;span style="color: #008000;"&gt;"public"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="background-color: #ffff00;"&gt;&amp;lt;script src=&lt;span style="color: #008000;"&gt;"tiny_mce/tiny_mce.js"&lt;/span&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;lt;/module&amp;gt;&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Initialize the JavaScript library&lt;/span&gt;&lt;/p&gt;&lt;p&gt;O.K. Now we have a library included with the widget itself, it will be loaded to the host page, but it still has to be initialized. And so, we override the onLoad() method of the widget. It will launch a JSNI method in turn:&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;span style="color: #000080;"&gt;public class&lt;/span&gt; TextEditor extends TextArea implements EntryPoint&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private static final&lt;/span&gt; String &lt;em&gt;DEFAULT_ELEMENT_ID &lt;/em&gt;= &lt;span style="color: #008000;"&gt;"textEditor"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private boolean&lt;/span&gt; initialized = &lt;span style="color: #000080;"&gt;false&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private &lt;/span&gt;String elementId;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;public &lt;/span&gt;TextEditor()&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;this(&lt;em&gt;DEFAULT_ELEMENT_ID&lt;/em&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;public&lt;/span&gt; TextEditor(String elementId)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;this&lt;/span&gt;.elementId = elementId;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;getElement().setId(elementId);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;protected void &lt;/span&gt;onLoad()&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;super&lt;/span&gt;.onLoad();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;initialize();&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private void &lt;/span&gt;initialize()&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;initTinyMce();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;initialized = &lt;span style="color: #000080;"&gt;true&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private native void&lt;/span&gt; initTinyMce()&lt;br /&gt;&amp;nbsp;&amp;nbsp;/*-{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;var options = {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;mode: &lt;span style="color: #008000;"&gt;"exact"&lt;/span&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;elements: &lt;span style="color: #000080;"&gt;this&lt;/span&gt;.@your.package.texteditor.client.TextEditor::elementId,&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;theme: &lt;span style="color: #008000;"&gt;"simple"&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;$wnd&lt;/span&gt;.tinyMCE.init(options);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}-*/;&lt;br /&gt;}&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;As you can see, we tell TinyMCE to work with &lt;span style="color: #008000;"&gt;"exact"&lt;/span&gt; textarea we specify, which is the one created by the widget itself. To be able to tell which one it is, we set the id to the textarea element in the constructor, and specify it to TinyMCE in the initTinyMce method.&lt;/p&gt;&lt;p&gt;You maybe noticed the initialized &lt;span style="color: #000080;"&gt;boolean &lt;/span&gt;variable - don't bother much now, we will see what it is for in a moment.&lt;/p&gt;&lt;p&gt;If you have a project to test the widget - try launching it now - do you like the idea so far? :)&lt;/p&gt;&lt;p&gt;But, oops... If you try using getText() or setText() now - you will realize it is not working. This is because of some TinyMCE specifics I won't concentrate on here. Let's add this:&lt;span style="color: #000080;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;span style="color: #000080;"&gt;&amp;nbsp;&amp;nbsp;public &lt;/span&gt;String getText()&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;String result;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;if &lt;/span&gt;(initialized) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;result = getContent(elementId);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;} &lt;span style="color: #000080;"&gt;else &lt;/span&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;result = &lt;span style="color: #000080;"&gt;super&lt;/span&gt;.getText();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;return &lt;/span&gt;result;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private native&lt;/span&gt; String getContent(String elementId)&lt;br /&gt;&amp;nbsp;&amp;nbsp;/*-{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; return &lt;span style="color: #000080;"&gt;$wnd&lt;/span&gt;.tinyMCE.get(elementId).getContent();&lt;br /&gt;&amp;nbsp;&amp;nbsp;}-*/;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;public void&lt;/span&gt; setText(String text)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;if &lt;/span&gt;(initialized) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;setContent(elementId, text);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;} &lt;span style="color: #000080;"&gt;else &lt;/span&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;super&lt;/span&gt;.setText(text);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private native&lt;/span&gt; String setContent(String elementId, String text)&lt;br /&gt;&amp;nbsp;&amp;nbsp;/*-{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;$wnd&lt;/span&gt;.tinyMCE.get(elementId).setContent(text);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}-*/;&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;Now you see why we added an "initialized"&amp;nbsp;&lt;span style="color: #000080;"&gt;boolean &lt;/span&gt;variable also. This is just to prevent us from trying to get content via tinyMCE API while the tinyMCE is not yet initialized. For example, it will be omitted when you invoke the setText(String) method before the widget is loaded onto a page.&lt;/p&gt;&lt;p&gt;Congratulations! You now have a working widget! If you try to launch sample application using this widget, you will be able to edit text and get the text in you sample application. Cool!&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;span style="font-size: 12px; font-weight: bold;"&gt;Polishing up - configure initialization options&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;Well, so far looks good, but still, our widget lacks any ability to configure it. You can not add controls, TinyMCE plugins, etc. So, lets add this ability. Again, let's see how TinyMCE works - we define the set of initialization options, invoke tinyMCE.init() passing it in, and so it initializes as specified.OK, so this means we need a way to manage these options. Previously they were hard-coded in the initTinyMce method, now they'll be configurable and will be built at the tine the initialization is invoked. Let's add the following:&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private &lt;/span&gt;Set fixedOptions = new HashSet(2); &lt;span style="color: #808080;"&gt;// options that can not be overwritten&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private &lt;/span&gt;JSONObject options = &lt;span style="color: #000080;"&gt;new &lt;/span&gt;JSONObject(); &lt;span style="color: #808080;"&gt;// all other TinyMCE options&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;public &lt;/span&gt;TextEditor(String elementId)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;this&lt;/span&gt;.elementId = elementId;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;getElement().setId(elementId);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #808080;"&gt;// fixed attributes&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;addOption("mode", "exact");&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;addOption("elements", elementId);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;fixedOptions.addAll(options.keySet());&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #808080;"&gt;// load preset&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;addOptions(TextEditorPreset.&lt;em&gt;PRESET_BASIC&lt;/em&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;public void &lt;/span&gt;addOption(String key, String value)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// do not allow overriding fixed options&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;if &lt;/span&gt;(fixedOptions.contains(key)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;return&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;options.put(key, &lt;span style="color: #000080;"&gt;new &lt;/span&gt;JSONString(value));&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private void &lt;/span&gt;initialize()&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;initTinyMce(options.getJavaScriptObject());&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;initialized = &lt;span style="color: #000080;"&gt;true&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #000080;"&gt;&amp;nbsp;&amp;nbsp;private native void&lt;/span&gt; initTinyMce(JavaScriptObject options)&lt;br /&gt;&amp;nbsp;&amp;nbsp;/*-{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #000080;"&gt;$wnd&lt;/span&gt;.tinyMCE.init(options);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}-*/;&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;Even though may look logical, we don't store options in a Map. The better for us is to store options in a JSONObject because later it will much easier to convert them to a options array accepted by tinyMCE.init() method. We also add several convenient methods to add new options. But we still don't want widget users overriding some of them - in particular these are the options related to how the TinyMCE finds the textares to link to. For this purpose we add a so-called fixedOptions set and check that users don't override them.&lt;/p&gt;&lt;p&gt;Pretty cool, yeah? Notice that we added pretty rich functionality with minimal JSNI tricks now.&lt;/p&gt;&lt;p&gt;That's it. Oh, almost forgot - do inherit from the com.google.gwt.json.JSON in your TextEditor.gwt.xml, as we use the JSONObject.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;Polishing up - add configuration presets&lt;/h3&gt;&lt;p&gt;Great, we may configure our widget. But, the configuration process may be pretty tricky if you need to add about a dozen of options. Well, you noticed we have a convenient method to add a bunch of options from a Map - addOptions(). So, you may easily store your favorite presets in a static Map and reuse it whenever needed. Hmm.. Why not adding some of the preset to the widget itself? Let's do - we create a new class:&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;span style="color: #000080;"&gt;public class &lt;/span&gt;TextEditorPreset&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;public static&lt;/span&gt; Map &lt;em&gt;PRESET_ADVANCED &lt;/em&gt;= &lt;span style="color: #000080;"&gt;new &lt;/span&gt;HashMap();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;public static&lt;/span&gt; Map &lt;em&gt;PRESET_BASIC&lt;/em&gt; = &lt;span style="color: #000080;"&gt;new &lt;/span&gt;HashMap();&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;static &lt;/span&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;em&gt;PRESET_BASIC&lt;/em&gt;.put(&lt;span style="color: #008000;"&gt;"theme"&lt;/span&gt;, &lt;span style="color: #008000;"&gt;"simple"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;em&gt;PRESET_ADVANCED&lt;/em&gt;.put(&lt;span style="color: #008000;"&gt;"theme"&lt;/span&gt;, &lt;span style="color: #008000;"&gt;"advanced"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;em&gt;PRESET_ADVANCED&lt;/em&gt;.put(&lt;span style="color: #008000;"&gt;"plugins"&lt;/span&gt;, &lt;span style="color: #008000;"&gt;"emotions,spellchecker,advhr,insertdatetime,preview"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;em&gt;PRESET_ADVANCED&lt;/em&gt;.put(&lt;span style="color: #008000;"&gt;"theme_advanced_buttons1"&lt;/span&gt;,&amp;nbsp;&lt;span style="color: #008000;"&gt;"newdocument, |,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;bold, italic, underline, |, justifyleft, justifycenter,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;justifyright, fontselect, fontsizeselect, formatselect"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;em&gt;PRESET_ADVANCED&lt;/em&gt;.put(&lt;span style="color: #008000;"&gt;"theme_advanced_buttons2"&lt;/span&gt;, &lt;span style="color: #008000;"&gt;"cut, copy, paste, |,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;bullist, numlist, |, outdent, indent, |, undo, redo, |,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;link, unlink, anchor, image, |, code, preview, |, forecolor, backcolor"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;em&gt;PRESET_ADVANCED&lt;/em&gt;.put(&lt;span style="color: #008000;"&gt;"theme_advanced_buttons3", "insertdate, inserttime,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;|, spellchecker, advhr, ,removeformat, |,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;sub, sup, |, charmap, emotions"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;em&gt;PRESET_ADVANCED&lt;/em&gt;.put(&lt;span style="color: #008000;"&gt;"theme_advanced_toolbar_location", "top"&lt;/span&gt;);&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;em&gt;PRESET_ADVANCED&lt;/em&gt;.put(&lt;span style="color: #008000;"&gt;"theme_advanced_toolbar_align", "left"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;em&gt;PRESET_ADVANCED&lt;/em&gt;.put(&lt;span style="color: #008000;"&gt;"theme_advanced_statusbar_location", "bottom"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000080;"&gt;private &lt;/span&gt;TextEditorPreset() {}&lt;br /&gt;}&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;This is just an example. You may add any other options you like. You can find a detailed description of all supported options on the TinyMCE web site.&lt;/p&gt;&lt;p&gt;Finally, let's suite our widget with &amp;nbsp;another one method to load a perset in. In fact, it is the same as addOptions(), but just looks more natural: &amp;nbsp;&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&lt;span style="color: #000080;"&gt;public void &lt;/span&gt;applyPreset(Map preset)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;addOptions(preset);&lt;br /&gt;}&lt;/p&gt;&lt;hr style="width: 100%;" /&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;Resume&lt;/h3&gt;&lt;p&gt;That's it for this article. There is still lot to do with the widget, however. There are many ways to enhance it. Each next little step makes your widget even more flexible.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Well, to inspire you on this - I'll tell you a secret - as a proof of concept, this article was entirely written in the primitive WYSIWYG HTML editor created with the very same widget described here ;) True. Well, with some enhancements actually.&amp;nbsp;&lt;strong&gt;If you are interested - in next articles I'll show the complete widget source code, how to manage custom plugins, how to manage save events, and many more. Just let me know &lt;/strong&gt;;)&lt;/p&gt;&lt;p/&gt;&lt;div&gt;© Copyright 2010 Timur Rubeko&lt;/div&gt;&lt;p style="text-align: left;"&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://timursdev.blogspot.com/2010/06/full-fledged-gwt-rich-text-editor.html';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'Creating a full-fledged GWT Rich Text Editor widget"';&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;br /&gt;Did you like the article?&lt;br /&gt;&lt;script src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/804931010262428127-874003549403517295?l=timursdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timursdev.blogspot.com/feeds/874003549403517295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://timursdev.blogspot.com/2010/06/full-fledged-gwt-rich-text-editor.html#comment-form' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/874003549403517295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/874003549403517295'/><link rel='alternate' type='text/html' href='http://timursdev.blogspot.com/2010/06/full-fledged-gwt-rich-text-editor.html' title='Creating a full-fledged GWT Rich Text Editor widget'/><author><name>Tim</name><uri>http://www.blogger.com/profile/13946718929977648625</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_v6HvzVShiHU/TD9KIcEBu4I/AAAAAAAAABk/-XY8OUcH7mg/S220/The+Mars+ava.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_v6HvzVShiHU/TCdo2bI9mqI/AAAAAAAAAAM/GZwxr7aXK9k/s72-c/TextEditor.png' height='72' width='72'/><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-804931010262428127.post-1071715168180657232</id><published>2010-03-19T19:28:00.013+02:00</published><updated>2010-08-18T10:26:13.473+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development process'/><title type='text'>Development Tests or "Don't wait for Test Team!"</title><content type='html'>The issue I faced recently is that sometimes developers way too much rely on Test Team. I was there as well and I know how it works: you do very zen tests, commit your code, Test Team does necessary tests and... well, rejects it. I know that there are some developers who think this is a regular development process. Here I will describe what is wrong with this approach and why I think development tests are that important. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;When you don't test your code...&lt;/span&gt;&lt;br /&gt;Let's assume you implement a small feature. Once developed you run it one or two times to see if it works. Then you commit you changes.&lt;br /&gt;Here is what happens next:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Test Team receives a notification and spends an hour or two to test the feature, find bugs, check the logs, etc. and finally submit defects to bug tracker.&lt;/li&gt;&lt;li&gt;You then receive a bug and spend some time to analyze it, recall how it works, etc. and spend an hour&amp;nbsp; or two in total on a fix and commit changes again.&amp;nbsp;&lt;/li&gt;&lt;/ol&gt;What happens next is that Test Team should do the same test again, so they spend 2 hours on that... And what if there are bugs again?&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;The point is that sometimes Test Team could find bugs only one by one. Let's assume you did 5 fixes. Each "iteration" took about 3 or 4 hours, then it will be 15 or 20 hours in total. But this process could spread on several days... To sum up, it seems that fixes are small, not more than hour or two, but as a result it takes several days to debug and finalize the feature! Wow!&lt;br /&gt;&lt;br /&gt;What if you don't have Test Team? Then it means that your customers are your testers. Well, their time may cost even more. Not to say that some time your customer won't have a business with you if you deliver functionality that way.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;To test or not to test? &lt;/span&gt;&lt;br /&gt;At contrary, you could spend more time on tests. You won't be blocked by any defect because you could fix it at once.Yes, additional tests will take some time, but not more then bug fixing when bugs are raised by Test Team - because you then need to switch between your tasks.&lt;br /&gt;Also this way you exclude the ping-pong in bug tracker and e-mail and free up &lt;b&gt;much&lt;/b&gt; of Test Team time. Not to say that you improve your status with colleagues and your customer. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;So, if you want to implement high-quality and reliable application - just bear in mind that Test Team is not to test your job, but to &lt;b&gt;validate&lt;/b&gt; it. In ideal world, they should only approve that everything is all right and just close that ticket ;) Thinking that way helps me, hope it might be useful for you too&lt;br /&gt;&lt;p/&gt;&lt;div&gt;© Copyright 2010 Timur Rubeko&lt;/div&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://timursdev.blogspot.com/2010/03/development-tests-or-dont-wait-for-test.html';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'Development Tests or "Don't wait for Test Team!"';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;br /&gt;Did you like the article?&lt;br /&gt;&amp;nbsp;&lt;script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/804931010262428127-1071715168180657232?l=timursdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timursdev.blogspot.com/feeds/1071715168180657232/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://timursdev.blogspot.com/2010/03/development-tests-or-dont-wait-for-test.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/1071715168180657232'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/1071715168180657232'/><link rel='alternate' type='text/html' href='http://timursdev.blogspot.com/2010/03/development-tests-or-dont-wait-for-test.html' title='Development Tests or &quot;Don&apos;t wait for Test Team!&quot;'/><author><name>Tim</name><uri>http://www.blogger.com/profile/13946718929977648625</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_v6HvzVShiHU/TD9KIcEBu4I/AAAAAAAAABk/-XY8OUcH7mg/S220/The+Mars+ava.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-804931010262428127.post-8555053775778584019</id><published>2010-01-28T21:52:00.007+02:00</published><updated>2010-08-18T10:26:37.196+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development process'/><title type='text'>Fix bugs effectively in collaboration with the Test Team</title><content type='html'>In this article I would like to share some of my personal hints concerning the case when customer reports a bug and this bug is not that obvious like when you have an error log. There are plenty of customer cases when there is only a functional issue, when something merely "goes wrong".&lt;br /&gt;&lt;br /&gt;Let's suppose you are a developer who is assigned to fix this issue ASAP (well, you know, it is raised by customer - it is critical in most cases).&amp;nbsp; What I want to tell is not "how to fix bugs", but how to collaborate with Test Team so as to do it effectively. In some projects it is mandatory to collaborate with Test Team in this kind of situations, but still some developers don't do that - maybe because they think the issue is not that complex, or by some other reason - it doesn't matter. I would like to point out why is it that important.&lt;br /&gt;&lt;br /&gt;So, here goes... The very first thing you should do is&lt;b&gt; &lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;b&gt;Notify Test Team about the issue&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This &lt;i&gt;step is really easy&lt;/i&gt;. You don't even need to do any analysis before notifying Test Team. But&lt;i&gt; the benefit of that is really huge&lt;/i&gt;. In some cases your colleagues from Test Team will solve the entire problem for you.&lt;br /&gt;&lt;br /&gt;When you notify test team you gain at least one more person who is doing &lt;i&gt;a half of your job&lt;/i&gt; - he or she is trying to reproduce the error. Once the error is reproduced - you have a "full house" - it is only a matter of doing the same in your local development environment, then debugging and making a fix itself. In any case, you will try to reproduce the error on your side, won't you? So, while you do some preliminary analysis, there is at least one more person who already attempts to reproduce it.&lt;br /&gt;&lt;br /&gt;Moreover, I had many cases when test team merely told me what the problem is, because they faced it before but didn't consider it as a defect. Hey, they indeed use the system more often rather than you do.&lt;br /&gt;&lt;br /&gt;One more hint here is: let the person who is helping you with tests know your preliminary analysis results. Don't leave him or her alone - if you have more info about the issue - share it. It won't take much time, but will probably help your colleague.&lt;br /&gt;&lt;br /&gt;Finally, even if they won't reproduce the bug, at least they will be prepared to validate your fix. I mean, you won't send a fix to a customer without having at least one more person who could tell that it works, will you? This leads us to next hint:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Let Test Team validate your fix&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Well, this is a mandatory step. Once you succeed in analysis, debug and fix - you should validate it before claiming that it works. Never send a fix unless at least one more person reproduces the error without the fix, and then validates the fix by doing the same with the fix applied.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Ha, you can do that by yourself you say? Yes, indeed you can. In fact, you should - you should test your fix. But you should not be the one who does the &lt;i&gt;final&lt;/i&gt; test - there is always a chance that your first fix won't work well. Let others validate it. Do you remember we've notified Test Team about the issue? Yes, even if they didn't reproduce the error for you, they already have most of the information they need to validate your fix (hm, or reject it :) ) &lt;br /&gt;&lt;br /&gt;&lt;b&gt;We don't have Test Team - won't this work for us?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Indeed it is not that rare. In this situation - ask a colleague to play this role &lt;i&gt;for a while&lt;/i&gt;. Note, that I don't mean asking a colleague to help you with the fix. It's not the same. Your colleague should work for a while as a Test Team member. &lt;i&gt;It's not Pair Programming&lt;/i&gt;. The idea is that one person is dedicated to tests only. Well, if you usually work in pairs - all right, you can do that, but still ask &lt;i&gt;one more&lt;/i&gt; person to help you with tests. After all, you want to have a &lt;b&gt;quick and stable fix&lt;/b&gt;, don't you? &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;/ol&gt;As I already mentioned, these steps are mandatory in some teams. But even then some developers don't do that. Sometimes they don't ask Test Team at all, sometimes developers only ask them to validate the fix, i.e. on last stage. It should not be so. These steps are fairly simple and won't take much of your time. If you spend about several hours on a fix, it is not a big deal to spend several minutes to share the information with Test Team or a colleague. But this raises your chances in finding a bug quickly and always increases the fix stability. If you do that already - you know that for sure. If you do not - give it a try - you will see the benefits yourself.&lt;br /&gt;&lt;p/&gt;&lt;div&gt;© Copyright 2010 Timur Rubeko&lt;/div&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://timursdev.blogspot.com/2010/01/fix-bugs-effectively-in-collaboration.html';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'Fix bugs effectively in collaboration with the Test Team';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;br /&gt;Did you like the article?&lt;br /&gt;&amp;nbsp;&lt;script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/804931010262428127-8555053775778584019?l=timursdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timursdev.blogspot.com/feeds/8555053775778584019/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://timursdev.blogspot.com/2010/01/fix-bugs-effectively-in-collaboration.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/8555053775778584019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/8555053775778584019'/><link rel='alternate' type='text/html' href='http://timursdev.blogspot.com/2010/01/fix-bugs-effectively-in-collaboration.html' title='Fix bugs effectively in collaboration with the Test Team'/><author><name>Tim</name><uri>http://www.blogger.com/profile/13946718929977648625</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_v6HvzVShiHU/TD9KIcEBu4I/AAAAAAAAABk/-XY8OUcH7mg/S220/The+Mars+ava.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-804931010262428127.post-5057646145429348772</id><published>2010-01-26T13:53:00.012+02:00</published><updated>2010-08-18T10:27:03.634+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development process'/><title type='text'>What can I do about incorrect specifications?</title><content type='html'>If you work in the project where you receive requirements as formal documents like specifications, and the project is young enough – most likely that this is an article for you. It was a case in the project I work in, that sometimes specifications contain errors or the requirements are not detailed enough. This article would not discuss analysts and their job (which is really hard indeed) – let’s suppose that you already have received a document from them, and now have to implement something according to it. This article is the answer for question “what can I do about incorrect specifications &lt;b&gt;as a developer&lt;/b&gt;?” There will be no any brand new exciting techniques in this article, but just a little of my experience, which helps me much in these situations.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Possible problems with specifications&lt;/span&gt;&lt;br /&gt;I faced following problems with specifications&lt;br /&gt;•&amp;nbsp;&amp;nbsp;&amp;nbsp; the specification is not detailed enough, and thus it is not clear what exactly is supposed to be implemented&lt;br /&gt;•&amp;nbsp;&amp;nbsp;&amp;nbsp; there is a logic error in the requirements – customer requests something what is not logical at all and probably not the thing they need. Well, according to you :)&lt;br /&gt;&lt;br /&gt;These issues could have many reasons. It is often the case when customer has a general vision, but analysts merely missed some details. In fact, it could be anything: it could be that customer’s demands depend on other parties, and the requirements are not clear on that “third” side; it could be a problem of reverse engineering; etc.; finally, it could be merely an error in the document.&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;“What can I do about it?”&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Face it&lt;/b&gt;&lt;br /&gt;Firstly, you should understand that this is absolutely all right that documents may contain some issues. Yes, it’s not good. But you should understand that analysts’ job is not that easy, and it is possible that they also can miss something. In fact, you do miss bugs in your application, aren’t you? So, give a chance for others to do that too :)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Ask&lt;/b&gt;&lt;br /&gt;Next – just &lt;b&gt;ask&lt;/b&gt;. &lt;b&gt;Never leave it as is&lt;/b&gt;. You can use e-mail or chat or phone or whatever – but always contact the analyst and discuss the issue. And…&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Don’t miss even “tiny” issues. &lt;/b&gt;&lt;br /&gt;Yes, even if this issue is not that critical, or even if you think that you know what was supposed to be written there – still &lt;b&gt;ask&lt;/b&gt;. Because you could be wrong too. It is only the customer who can make a decision about certain requirement. &lt;br /&gt;Also, if you suppose something, it is possible that your colleague does not, though he needs to support you code with time. It is even possible that with time you can forget why did you decide to do the thing this way but not as described in the document. This is the case where you should be pedantic.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Propose solutions&lt;/b&gt;&lt;br /&gt;Don’t just ask, instead - &lt;b&gt;propose solutions&lt;/b&gt;. It is often the case when specification author doesn’t know possible standard solutions you used before even in the very same project. Or author doesn’t know about some standard details you usually need during development. In this case – share you knowledge with customer. Help analyst to create a correct document. Well, imaging for a moment you are an analyst. It’s really interesting!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;E-mail conclusions&lt;/b&gt;&lt;br /&gt;If you discussed in chat or by phone something that has an impact on project documentation – e-mail the conclusions to all discussion participants. I’m not sure if this is a case for you – but I never delete old messages in my inbox. This helps me much. Your mailbox becomes a second source of documentation.&lt;br /&gt;Plus, all discussion participants will also have a chance to review conclusions and see if everyone was understood correctly.&lt;br /&gt;&lt;b&gt;&lt;br /&gt;Force specification author to update the document&lt;/b&gt;&lt;br /&gt;&lt;b&gt;This is mandatory. I mean it.&lt;/b&gt; Having documentation that is out of sync with your implementation is worse than no documentation at all. Other developers working on the same project might know nothing about your discussions and decisions you made with customer or analyst. They might even rollback your changes so as to align them to specification :) It is not acceptable. Finally, you yourself can forget about decisions you made. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;In general, you should understand that analysts’ job is not that easy. Or, if you project has no analyst and customers provide documentation themselves – it is even harder for them. Help your colleagues in this hard work.&lt;br /&gt;&lt;p/&gt;&lt;div&gt;© Copyright 2010 Timur Rubeko&lt;/div&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://timursdev.blogspot.com/2010/01/what-can-i-do-with-incorrect.html';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'What can I do about incorrect specifications?';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;br /&gt;Did you like the article?&lt;br /&gt;&amp;nbsp;&lt;script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/804931010262428127-5057646145429348772?l=timursdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timursdev.blogspot.com/feeds/5057646145429348772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://timursdev.blogspot.com/2010/01/what-can-i-do-with-incorrect.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/5057646145429348772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/5057646145429348772'/><link rel='alternate' type='text/html' href='http://timursdev.blogspot.com/2010/01/what-can-i-do-with-incorrect.html' title='What can I do about incorrect specifications?'/><author><name>Tim</name><uri>http://www.blogger.com/profile/13946718929977648625</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_v6HvzVShiHU/TD9KIcEBu4I/AAAAAAAAABk/-XY8OUcH7mg/S220/The+Mars+ava.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-804931010262428127.post-299669171868027293</id><published>2009-12-19T13:40:00.002+02:00</published><updated>2010-08-18T10:25:39.218+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Imports in Python - possible pitfalls and how to avoid them</title><content type='html'>Nonetheless Python is a very powerful language and supports all the stuff an enterprise-level language should support, to my mind it has some drawbacks coming from its nature - Python is an interpreted language. In this article I would like to highlight several pitfalls of python "import" statement and some hints and good practices helping to avoid them.&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;h2&gt;Recursive imports&lt;/h2&gt;&lt;br /&gt;Not a big secret how "import" works in Python (&lt;a href="http://docs.python.org/reference/simple_stmts.html#the-import-statement"&gt;http://docs.python.org/reference/simple_stmts.html#the-import-statement&lt;/a&gt;). In general, when Python interpreter founds an "import" statement it loads and initializes the referenced module immediately (if not yet initialized). So, here is the consequence of that:&lt;br /&gt;&lt;br /&gt;If a module is being initialized and interpreter finds another "import" statement in it, interpreter leaves this module partially initialized for a moment. Python starts to initialize another module (referenced by import) and as a result the module being initialized before is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;already marked as loaded (which means you can reference it and Python won't attempt to load it again)&lt;/li&gt;&lt;li&gt;but lacks the staff declared in it after other import statements&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Well, this is what is going on "inside" the interpreter. But here is the consequence of that for our code:&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;Recursive imports (when A imports B and B imports A) do not work unless you let your module fully initialize before you import other dependent modules. That is a tricky description - better have a look on the example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# file: commands.py&lt;br /&gt;import helpcommand&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;class Command(object):&lt;br /&gt;  def __init__(self, name):&lt;br /&gt;    self.name = name&lt;br /&gt;&lt;br /&gt;  def run(self, *args, **kwargs):&lt;br /&gt;    raise NotImplementedError()&lt;br /&gt;&lt;br /&gt;registry = (&lt;br /&gt;  helpcommand.HelpCommand,&lt;br /&gt;  ...&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;# file: helpcommand.py&lt;br /&gt;import commands&lt;br /&gt;&lt;br /&gt;class HelpCommand(commands.Command):&lt;br /&gt;  ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As a matter of fact the code looks natural, but obviously it is not working (well, it depends on it's usages - later about that). If you attempt to load commands module first, then Python will import &lt;span class="misspell" suggestions="help command,help-command"&gt;helpcommand&lt;/span&gt; for you and will fail to define class &lt;span class="misspell" suggestions="Help Command,Help-Command"&gt;HelpCommand&lt;/span&gt; because (ha!) there is no class commands.Command - its definition was not yet processed and interpreter knows nothing about it. As a result you get a message stating that module commands doesn't have a class Command. That's true, but not that obvious indeed.&lt;br /&gt;&lt;br /&gt;There is a plenty of solutions for this case:&lt;br /&gt;&lt;br /&gt;1. You can import dependent module first (&lt;span class="misspell" suggestions="help command,help-command"&gt;helpcommand&lt;/span&gt;) - yes, in this case it works fine. But, whoa! - imports depend on the order they are being executed. I don't appreciate this solution because it is easy to brake it again - once you have to add "import commands" somewhere you first need to check if there was an import of dependent modules already. In fact, this means that you need to keep in mind the sequence in which your application modules are being initialized.&lt;br /&gt;&lt;br /&gt;2. Another solution is to merely import all dependent modules only after their "root" module is initialized completely. For example, see the code below.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# file: commands.py&lt;br /&gt;class Command(object):&lt;br /&gt;  def __init__(self, name):&lt;br /&gt;    self.name = name&lt;br /&gt;&lt;br /&gt;  def run(self, *args, **kwargs):&lt;br /&gt;    raise NotImplementedError()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;import helpcommand&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;registry = (&lt;br /&gt;  helpcommand.HelpCommand,&lt;br /&gt;  ...&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;However, some dislike this solution because you put import statements somewhere in the middle of your source file. As for me - I'm OK with that, but anyway there is even better solution:&lt;br /&gt;&lt;br /&gt;3. The best way to not fall into recursive dependencies with imports &lt;b&gt;is to not use them&lt;/b&gt;. Indeed - in most cases you don't really need to do that, so in fact this "import" behavior is not a problem at all if you use it correctly. For example, in our particular case, let's split the logic in commands module to 2 separate modules, and see what happens:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# file: commandsregistry.py&lt;br /&gt;import helpcommand&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;registry = [&lt;br /&gt;  helpcommand.HelpCommand,&lt;br /&gt;  ...&lt;br /&gt;]&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# file: commands.py&lt;br /&gt;class Command(object):&lt;br /&gt;  ...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# file: helpcommand.py&lt;br /&gt;import commands&lt;br /&gt;&lt;br /&gt;class HelpCommand(commands.Command):&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, whenever you import any module, it works fine, because you don't have any recursive dependencies between the modules in you application. The solution is - &lt;b&gt;do not mess up the stuff&lt;/b&gt;.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;h2&gt;Shared &lt;span class="misspell" suggestions="recourse's,resources,recourse,recces,rejoices"&gt;recources&lt;/span&gt; initialization&lt;/h2&gt;&lt;br /&gt;Another one potential problem with imports in Python is that some resource could be initialized incorrectly before you want it to. For example, consider this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# file: launcher.py&lt;br /&gt;import logging&lt;br /&gt;import logging.config&lt;br /&gt;&lt;br /&gt;import mymodule&lt;br /&gt;&lt;br /&gt;if __name__ == "__main__":&lt;br /&gt;  logging.config.fromFile("logging.ini")&lt;br /&gt;  mymodule.doStuff()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# file: mymodule.py&lt;br /&gt;import logging&lt;br /&gt;&lt;br /&gt;logger = logging.getLogger("mymodule")&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once you launch your application with launcher.&lt;span class="misspell" suggestions="Pu,pay,P,p,PT"&gt;py&lt;/span&gt;, it is first loading all modules it depends on (in the case above) - thus loads &lt;span class="misspell" suggestions="my module,my-module,module,moduli,modulo"&gt;mymodule&lt;/span&gt; before the logging was initialized correctly. Thus, logger initialized in &lt;span class="misspell" suggestions="my module,my-module,module,moduli,modulo"&gt;mymodule&lt;/span&gt; is initialized with default logging configuration, and will not be able to log anything even after the launcher had initialize the logging system. Again, this means that you need to keep an eye on the process of the system initialization - the sequence of imports and shared resources initialization. Eh, but we don't want to do that, so you can solve this in several ways:&lt;br /&gt;&lt;br /&gt;1. Lazy loading. For example, instead of initializing the logger in &lt;span class="misspell" suggestions="my module,my-module,module,moduli,modulo"&gt;mymodule&lt;/span&gt; once it is loaded, do a lazy loading:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;_logger = None&lt;br /&gt;def logger():&lt;br /&gt;  if not _logger: _logger = logging.getLogger("mymodule")&lt;br /&gt;  return _logger&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;2. Again, you can import dependent modules only at a time you really need them. Just put "import &lt;span class="misspell" suggestions="my module,my-module,module,moduli,modulo"&gt;mymodule&lt;/span&gt;" after your base  system initialization. But, again, we can go further. In general we could&lt;b&gt; clearly split the initialization logic and your system logic&lt;/b&gt;. For example, in this case that would be:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# file: main.py&lt;br /&gt;if __name__ == "__main__":&lt;br /&gt;  try:&lt;br /&gt;    import initialization&lt;br /&gt;    initialzation.init()&lt;br /&gt;  except Exception, ex:&lt;br /&gt;    ...&lt;br /&gt;  else:&lt;br /&gt;    import launcher&lt;br /&gt;    launcher.main()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# file: launcher.py&lt;br /&gt;import mymodule&lt;br /&gt;import ...&lt;br /&gt;&lt;br /&gt;def main():&lt;br /&gt;  mymodule.doStuff()&lt;br /&gt;  ...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# file: initialization.py&lt;br /&gt;import logging&lt;br /&gt;import logging.config&lt;br /&gt;&lt;br /&gt;def init():&lt;br /&gt;  logging.config.fromFile("logging.ini")&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# file: mymodule.py&lt;br /&gt;import logging&lt;br /&gt;&lt;br /&gt;logger = logging.getLogger("mymodule")&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h2&gt;Resume&lt;/h2&gt;&lt;br /&gt;Python's import is not that simple. Yes, it merely loads the module you ask him to. But, it is easy to find yourself solving bugs caused by its incorrect usage and you will need to constantly keep an eye on the sequence in which you import modules in your system... That is not what you are supposed to spend your time for. From the very beginning write your code without messy and cumbersome dependencies between parts of your system, follow few good practices and you will most likely avoid many potential problems described in this article.&lt;br /&gt;&lt;p/&gt;&lt;div&gt;© Copyright 2010 Timur Rubeko&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/804931010262428127-299669171868027293?l=timursdev.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timursdev.blogspot.com/feeds/299669171868027293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://timursdev.blogspot.com/2009/12/imports-in-python-possible-pitfalls-and.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/299669171868027293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/804931010262428127/posts/default/299669171868027293'/><link rel='alternate' type='text/html' href='http://timursdev.blogspot.com/2009/12/imports-in-python-possible-pitfalls-and.html' title='Imports in Python - possible pitfalls and how to avoid them'/><author><name>Tim</name><uri>http://www.blogger.com/profile/13946718929977648625</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_v6HvzVShiHU/TD9KIcEBu4I/AAAAAAAAABk/-XY8OUcH7mg/S220/The+Mars+ava.jpg'/></author><thr:total>2</thr:total></entry></feed>
