Hi Mives29,

Jason's solution is correct. If you have TreeX implement his Callback
interface, then XmlParserUtil  will call TreeX.callback() when it has
retrieved and parsed the XML document, so you move the tree building
code (getTreeitem()) to start from TreeX.callback(String XML). This
will solve you immediate problem, but the design cost is that
XmlParserUtil can _only_  pass XML back to client widgets via that
route. That is not necessarily a good design decision in the GWT
asynchronous world.

Because remote calls have so much effect on the user experience
(network latency, deserialization etc) it is a good idea to keep as
much flexibility as possible in how you sequence remote calls and
widget construction. If you abandoned your idea of a reusable all in
one XML fetcher/parser utility, you would have other ways to build
this tree, e.g.

1) Make the XML fetch call and parse the XML in onModuleLoad() up
front before you build the Tree and supply the imgUri's to the Tree's
constructor
2) Make the fetch call from the Tree's constructor, and in
onResponseReceived(..) parse the returned XML then build the
Treeitems.

Since you would normally want to make the user experience as smooth
and uninterrupted as possible, it is good to maximize flexibility as
to where and when you make remote calls. That means you can move them
around to make improvements - it all depends on your particular
application and your users. For example, many people pre-fetch all
necessary data to build their top most layer of widgets and display an
"Application Loading..." type message whilst this is going on. This
might be good for a complex business application where users will
typically start it up in the morning and read their mail whilst its
loading. But in GMail Google don't do that: they pre-fetch the inbox
list, but they build the little contacts widget on the left separately
as you watch.

The point is it's not always immediately obvious what the "best" way
to sequence remote calls and widget construction is at first - I think
being able to try out different approaches is an important design goal
in GWT apps, maybe more so than making something like XmlParserUtil
reusable. The user's convenience is more important than yours.

regards
gregor



On Nov 11, 6:56 am, mives29 <[EMAIL PROTECTED]> wrote:
> Hi! I've just re-read your reply, but I cant understand how the
> interface would affect the program, and how would I use that new
> getDocument() method of the XmlUtilParser class. Could you provide
> another example (a working one, if possible)?
>
> This whole AsyncCallback/asynchronous stuff of GWT is driving me nuts.
> I've created the same parser using a service, and Java's own DOM
> parser, and it works already, however I really want to develop this
> app of mine full GWT-style. Hope you could help me again, thanks.
>
> On Nov 10, 5:58 pm, Jason Morris <[EMAIL PROTECTED]> wrote:
>
> > Heya,
>
> > Your basic problem here is that you can't have your XmlParserUtil return a
> > Document object. The doc field will only be filled in when the async
> > RequestBuilder request returns and the parser is finished with the XML 
> > string.
> > By that time, your method has already returned.
>
> > The only way to solve this is to create something like a:
>
> > public interface Callback<V> {
> >         void callback(V value);
>
> > }
>
> > and have the XmlParserUtil look something more like this:
>
> > public class XmlParserUtil {
> >         String url;
> >         Document doc;
> >         public RequestBuilder requestBuilder;
> >         String xmlStr;
>
> >         public XmlParserUtil(String xmlFileName) {
> >                 this.url = xmlFileName;
> >         }
>
> >         public void getDocument(Callback<Document> callback) {
> >                 if(doc != null) {
> >                         callback.callback(doc);
> >                         return;
> >                 }
>
> >                 try {
> >                         requestBuilder = new 
> > RequestBuilder(RequestBuilder.GET,url);
> >                         requestBuilder.sendRequest(null,new 
> > RequestCallback()
> >                         {public void onResponseReceived(Request arg0, 
> > Response arg1) {
> >                                 xmlStr = arg1.getText();
> >                                 callback.callback(doc = 
> > XMLParser.parse(xmlStr));
> >                         }
> >                         public void onError(Request request, Throwable 
> > exception) {
>
> >                         }});
> >                 }
> >                 catch (RequestException ex) {
> >                         GWT.log(ex.getMessage(), ex);
> >             }
> >         }
>
> > }
>
> > For more information about async problems, it's related to RPC, but 
> > applicable
> > to the RequestBuilder as well:
>
> >http://lemnik.wordpress.com/2008/07/04/gwt-rpc-is-called-aynchronous-...
>
> > mives29 wrote:
> > > okay, let me be clear on this, again, my code. (now posting full
> > > reworked source code)
>
> > > // A composite w/c contains a tree.
> > > public class TreeX extends Composite {
> > >    Document doc;
> > >    Tree t = new Tree();
> > >    int imgUris;
> > >    XmlParserUtil xmlParser;
> > >    public TreePol() {
> > >            TreeItem tItem = getTreeItem();
> > >            t.addItem(tItem);
> > >            initWidget(t);
> > >    }
> > >    private TreeItem getTreeItem() {
> > >            doc = getDoc();
> > >            imgUris = doc.getElementsByTagName("Image").getLength();
> > >            TreeItem root = null;
> > >            root = new TreeItem("Image Names");
> > >            for (int i=0;i<imgUris;i++) {
> > >                    String tmpImgUri =
> > > doc.getElementsByTagName("Image").item(i).getChildNodes().item(1).toString();
> > >                    root.addItem(tmpImgUri);
> > >            }
> > >            return root;
> > >    }
> > >    public Document getDoc() {
> > >            xmlParser = new XmlParserUtil("image_uris.xml");
> > >              while (doc==null) {
> > >                      doc = xmlParser.getDocument();
> > >              }
> > >            return doc;
> > >    }
> > > }
>
> > > //A class that i want to use as a utility class for parsing xml
> > > documents. intended to be reusable
> > > public class XmlParserUtil {
> > >    String url;
> > >    Document doc;
> > >    public RequestBuilder requestBuilder;
> > >    String xmlStr;
>
> > >    public XmlParserUtil(String xmlFileName) {
> > >            this.url = xmlFileName;
> > >    }
>
> > >    public Document getDocument() {
> > >            try {
> > >                    requestBuilder = new 
> > > RequestBuilder(RequestBuilder.GET,url);
> > >                    requestBuilder.sendRequest(null,new RequestCallback()
> > >                    {public void onResponseReceived(Request arg0, Response 
> > > arg1) {
> > >                            xmlStr = arg1.getText();
> > >                            doc = XMLParser.parse(xmlStr);
> > >                    }
> > >                    public void onError(Request request, Throwable 
> > > exception) {
>
> > >                    }});
> > >            }
> > >            catch (RequestException ex) {
> > >                    GWT.log(ex.getMessage(), ex);
> > >        }
> > >            return doc;
> > >    }
> > > }
>
> > > //my entrypoint's onModuleLoad(), which adds the various custom
> > > widgets i made to a tab panel
>
> > > public void onModuleLoad() {
> > >      RichTextAreaX1 rtaPol = new RichTextAreaX1();
> > >      PictureViewer imgBrowser = new PictureViewer();
> > >      TreeX tree = new TreeX();
>
> > >      TabPanel tp = new TabPanel();
> > >      tp.add(tree, "1");
> > >      tp.add(rtaPol, "2");
> > >      tp.add(imgBrowser, "3");
>
> > >      tp.selectTab(0);
> > >      tp.setWidth("100%");
>
> > >      RootPanel.get("leftpanel").add(tp);
> > >   }
>
> > > as you can see, I intend the XmlParserUtil class to be reusable. If I
> > > place there various logic, then it would be out of scope for that
> > > classs, because I intend to use XmlParserUtil just to parse an XML
> > > file, and bring me back a parsed Document object. now how would I do
> > > that if XmlParserUtil, which contains the requestbuilder and callback,
> > > would be used by another class (which is a composite).
>
> > > im new to this async thing, more so the  requestbuilder stuff. thank
> > > you for replying, i hope you could answer my question.
>
> > > On Nov 10, 3:44 pm, "alex.d" <[EMAIL PROTECTED]> wrote:
> > >> You have to accept the asynchronous nature of RPC-Requests in GWT and
> > >> stop trying to build smth. synchronous around them. This code:
> > >> -----------------------------------
> > >> doc = getDoc(); //(where doc is a Document object)
> > >> String subject =
> > >> doc.getElementsByTagName("Image").item(0).getChildNodes().item(1).toString();
> > >> String subject2 =
> > >> doc.getElementsByTagName("Image").item(1).getFirstChild().getNodeValue();
> > >> -----------------------------------
> > >> should not be executed in the onload-routine but in the
> > >> onResponseReceived()-method (or in any other procedure that you call
> > >> out of it).
>
> > >> On 10 Nov., 07:12, mives29 <[EMAIL PROTECTED]> wrote:
>
> > >>> hi all. ive re-done my code just a while ago(been a busy week) and my
> > >>> code kinda bothers me.  here's the code re-done:
> > >>> Entrypoint onModuleLoad() method:
> > >>> doc = getDoc(); //(where doc is a Document object)
> > >>> String subject =
> > >>> doc.getElementsByTagName("Image").item(0).getChildNodes().item(1).toString();
> > >>> String subject2 =
> > >>> doc.getElementsByTagName("Image").item(1).getFirstChild().getNodeValue();
> > >>> Entrypoiny getDoc() method:
> > >>> public Document getDoc() {
> > >>>           XmlParserUtil xmlParser = new XmlParserUtil("image_uris.xml");
> > >>>           int i = 0;
> > >>>           while (doc==null) {
> > >>>                   doc = xmlParser.getDocument();
> > >>>           }
> > >>>         return doc;
> > >>>   }
> > >>> here's the service implementation:
> > >>> public class XmlParserUtil {
> > >>>         String url;
> > >>>         Document doc;
> > >>>         RequestBuilder requestBuilder;
> > >>>         public String xmlStr;
> > >>>         public XmlParserUtil(String xmlFileName) {
> > >>>                 this.url = xmlFileName;
> > >>>         }
> > >>>         public Document getDocument() {
> > >>>                 RequestCallback xmlRcb = new RequestCallback()
> > >>>                 {public void onResponseReceived(Request arg0, Response 
> > >>> arg1) {
> > >>>                         xmlStr = arg1.getText();
> > >>>                         doc = XMLParser.parse(xmlStr);
> > >>>                 }
> > >>>                 public void onError(Request request, Throwable 
> > >>> exception) {
> > >>>                         // TODO Auto-generated method stub
> > >>>                 }};
> > >>>                 try {
> > >>>                         requestBuilder = new 
> > >>> RequestBuilder(RequestBuilder.GET,url);
> > >>>                         requestBuilder.sendRequest(null,xmlRcb);
> > >>>                 }
> > >>>                 catch (RequestException ex) {
> > >>>                         GWT.log(ex.getMessage(), ex);
> > >>>             }
> > >>>                 return doc;
> > >>>         }
> > >>> }
> > >>> my problem is on the Entrypoint logic. you see the getDoc() method
> > >>> there?
> > >>> it has this:
> > >>>           while (doc==null) {
> > >>>                   doc = xmlParser.getDocument();
> > >>>           }
> > >>> which just loops around until the service implementation has already
> > >>> populated the parsed document.
> > >>> what bothers me with this code is that it
>
> ...
>
> read more »
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To post to this group, send email to Google-Web-Toolkit@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/Google-Web-Toolkit?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to