This is an interesting issue that you all are discussing here because it is
a problem that had to solve for my own api. Let me tell you what I did and
then you can apply it to your situation as appropriate. On the JavaScript
side I created Objects to represent PageContext, Request, Response,
Listener, and EventObject. All of my of my method calls back to the server
use the writer obtained from request to write xml to the post or get method
of my request object. If I choose not to wait on the return of the method
call then I just tell the request to execute asynchronously and the post
gets fired via a setTimeout so that control is returned to my js object. If
I chose to do this and I want a call back for the return object I call the
request object's addListener method and hand it a js class that implements
EventObject whereby the fireEvent method is called. Ok sorry for the long
explanation. In a nut shell you just want to use some sort of a callback
method and chain your method calls in a certain order. If you want the
JavaScript that I am talking about you can download it at
http://www.xoscript.org just follow the setup configuration and run the
application tag one time and you will see the objects I am talking about
along with the rest of java.util.* written in js.

Ok, back to the original conversation. I created the AJAXAction and I have
one concern. On the line below and just before this line of code.

ProxyObjectFactory.writeProxyObject(response.getWriter(), o);

I need to figure out how I can call an action class's execute method and
safely pass it the current mapping and request and response wrappers
allowing the user to call forward as many time as they like. Then I would
take the resulting data writen to the response and add it to the xml in a
way that the client can feel as though they have just called a method on the
server and assigned the returned string to their own veriable. Long story
short, can I do an include from an Action class?

Here is what the AJAXAction would look like.

package org.apache.struts.webapp.example.action;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.xoscript.server.HttpMetaData;
import org.xoscript.service.LogFactory;
import org.xoscript.service.LogProvider;
import org.xoscript.service.ProxyObject;
import org.xoscript.service.ProxyObjectFactory;
import org.xoscript.service.XOService;
import org.xoscript.service.XOServiceFactory;

public class AjaxAction extends Action {

 private static LogProvider log = LogFactory.getLogProvider();
 private static XOService xoService = null;

    public ActionForward execute(ActionMapping mapping,
     ActionForm form,
     HttpServletRequest request,
     HttpServletResponse response)
 throws Exception {

     ActionForward forward = null;

  if (log.isInfoEnabled()) {
   log.info("begin processRequest ------------------------------>: ");
  }

  try {
   /**
    * The (POJO)'s method call invoked by xoService below
    * can retrieve this meta data object from the
    * XOServiceFactory to get information about the
    * request and response objects
    */
   xoService = XOServiceFactory.getService();
   HttpMetaData metaData = new HttpMetaData();
   response.setContentType("text/xml; charset=ISO-8859-1");
   metaData.setRequest(request);
   metaData.setResponse(response);
   metaData.setContext(null);
   XOServiceFactory.setMetaData(metaData);

   /**
    * The xml is read in and a ProxoyObject is created.
    * The ProxyObject now contains the lookup information
    * for the POJO and what method and argument should be
    * invoked. The return value of the method is stored as
    * an Object.
    */
   Object o = xoService.invoke((ProxyObject)
    ProxyObjectFactory.readProxyObject(request.getReader()));

   /**
    * If the return value of the object is null. A Void class
    * is put in it's place.
    */
   if(o == null){
    o = Void.TYPE;
    if (log.isInfoEnabled()) {
     log.info("object was null returning void");
    }
   }

   /**
    * Here is the point at which I need to decide how to handle
    * forwards. The following Writer is prepaired with the xml
    * representing the returned object. If I return an ActionForward
    * from this method, then the ProxyObject xml will never
    * get created. Some how I need to cause an include to happen here
    * and give the user a way to pass back an ActionForward from
    * their method call if they want to send the result of a jsp page
    * back to the calling JavaScript as a string or optionaly return
    * an object of their choosing.
    */

   ProxyObjectFactory.writeProxyObject(response.getWriter(), o);

   metaData = null;
  } catch (Exception e) {
   try {
    /*
     * In the event that an exception is thrown, the Throwable
     * is wrapped in a ProxyObject and writen back to the
     * browser.
     */
    ProxyObjectFactory.writeProxyObject(response.getWriter(), e);
    if (log.isDebugEnabled()) {
     log.debug(e);
    }
   } catch (Exception e1) {
    if (log.isDebugEnabled()) {
     log.debug(e1);
    }
   }
  }finally{
   XOServiceFactory.destroy();
  }

  return forward;
    }

}

----- Original Message -----
From: "Frank W. Zammetti" <[EMAIL PROTECTED]>
To: "Struts Developers List" <dev@struts.apache.org>
Sent: Wednesday, February 01, 2006 11:59 PM
Subject: Re: Help adding Struts to AJAX impl


>
> Laurie Harper wrote:
> > Sounds like it'd be a lot easier to just fire the first request with a
> > handler function that fires the next request, and so on, using
> > onreadystatechange.
>
> I would agree with that, *IF* the requests being sent are always the
> same and *IF* they are always in the same order.  I suppose you could
> have branching logic in the handler if the variations aren't numerous,
> but a more general-purpose approach might be better, such as the
> suggestion I made about the queue and the timer firing calls off the
stack.
>
> Frank
>
> > L.
> >
> > Frank W. Zammetti wrote:
> >> No Wendy, you are correct in your explanation :)  I see Ajax in Action
> >> is serving you well :)
> >>
> >> I wouldn't expect it to be the best answer though because that
> >> parameter blocks *all* Javascript, not just further XMLHttpRequest's.
> >>
> >> What you will probably want to do Michael is build up a queue on the
> >> client and write some code to ensure the order the handlers fire.
> >> This could be pretty tricky to say the least.
> >>
> >> Take a look at the RequestSender tag in AjaxTags in Java Web Parts...
> >> AjaxTags builds up such a queue so that multiple requests can fire
> >> simultaneously without stepping on each other.  I suspect you would be
> >> able to extend this to ensure firing order.  Off the top of my head, I
> >> would think you would need to set up a timer, and when the responses
> >> come back, instead of processing them on the spot in the callback,
> >> instead set a flag in the call structure that says "yes, this request
> >> completed, but don't process it until the previous one completes"...
> >> fire the timer every half a second or something like that to examine
> >> all the call structures in the queue and fire them as appropriate.
> >>
> >> Probably not a trivial exercise, but should be doable.
> >>
> >> Frank
> >>
> >>
> >> Wendy Smoak wrote:
> >>> On 2/1/06, Michael Jouravlev <[EMAIL PROTECTED]> wrote:
> >>>
> >>>> Hi, Ajax gurus, I have an OT question: how to ensure the proper order
> >>>> of several XHRs? I found how to create several XHRs simultaneously,
> >>>> but I have a requirement: to wait for the first request to return
> >>>> before firing the second,
> >>>
> >>> (Hardly an expert but...) the third parameter of
> >>> XMLHttpRequest.open(...) is a flag that says whether the request
> >>> should be asynchronous.  It's usually true.  Set it to false and I
> >>> think it will block until the response is received.  Frank will now
> >>> correct me if I'm wrong. :)
> >>>
> >>> And lets move to the user list if this gets any further off topic,
> >>> shall we?
> >>>
> >>> --
> >>> Wendy
> >>>
> >>> ---------------------------------------------------------------------
> >>> To unsubscribe, e-mail: [EMAIL PROTECTED]
> >>> For additional commands, e-mail: [EMAIL PROTECTED]
> >>>
> >>>
> >>>
> >>>
> >>>
> >>
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> >
> >
> >
> >
> >
>
> --
> Frank W. Zammetti
> Founder and Chief Software Architect
> Omnytex Technologies
> http://www.omnytex.com
> AIM: fzammetti
> Yahoo: fzammetti
> MSN: [EMAIL PROTECTED]
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to