<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>OnRails.org: Dealing with HTTP errors in a Flex with Rails application.</title>
    <link>http://onrails.org/articles/2008/02/20/dealing-with-http-errors-in-a-flex-with-rails-application</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Ruby On Rails and related matters.</description>
    <item>
      <title>Dealing with HTTP errors in a Flex with Rails application.</title>
      <description>&lt;p&gt;The Flash Player is restricted in the way it deals with &lt;span class="caps"&gt;HTTP&lt;/span&gt; errors. This is mainly due to provide cross browser consistency and I believe is due to the restrictions the browser imposes on the Flash Player plugin. In fact when your Flex application performs &lt;span class="caps"&gt;HTTP&lt;/span&gt; requests using the HTTPService class, the request is passed by the Flash Player to the browser and in case of an Rails error (500, 404, ...) the response is somehow crippled on the way back.&lt;/p&gt;


&lt;h2&gt;Problem&lt;/h2&gt;
So let&amp;#8217;s consider that the Flex application requests to update a Person but the validation fails. In the update method of our Rails controller the &lt;span class="caps"&gt;HTTP&lt;/span&gt; Status is set to :unprocessable_entity. This corresponds the &lt;span class="caps"&gt;HTTP&lt;/span&gt; error code 422.

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;  # PUT /people/1
  # PUT /people/1.xml
  def update
    @person = Person.find(params[:id])

    respond_to do |format|
      if @person.update_attributes(params[:person])
        flash[:notice] = 'Person was successfully updated.'
        format.html { redirect_to(@person) }
        format.xml  { head :ok }
      else
        format.html { render :action =&amp;gt; &amp;quot;edit&amp;quot; }
        format.xml  { render :xml =&amp;gt; @person.errors, :status =&amp;gt; :unprocessable_entity }
      end
    end
  end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Now in our Flex application by default we cannot identify that the error 422 occured, more annoyingly we cannot retrieve the Rails error messages. All we get back is the following:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;[FaultEvent fault=[RPC Fault faultString=&amp;quot;HTTP request error&amp;quot; faultCode=&amp;quot;Server.Error.Request&amp;quot; faultDetail=&amp;quot;Error: [IOErrorEvent type=&amp;quot;ioError&amp;quot; bubbles=false cancelable=false eventPhase=2 text=&amp;quot;Error #2032: Stream Error. URL: http://localhost:3000/people/8.xml?_method=put&amp;quot;]. URL: http://localhost:3000/people/8.xml?_method=put&amp;quot;] messageId=&amp;quot;65EBBA92-5911-68D2-1710-18A687C28455&amp;quot; type=&amp;quot;fault&amp;quot; bubbles=false cancelable=true eventPhase=2]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Solution&lt;/h2&gt;

	&lt;p&gt;I haven&amp;#8217;t found a way to have the status code and error message appear in the Flex application without having to change the Rails application. But fortunately, I was able to deal with that by using an after_filter at the application controller level, hence having only one place in the application to take care of all controllers and requests. The trick is to &amp;#8220;hide&amp;#8221; the &lt;span class="caps"&gt;HTTP&lt;/span&gt; Status error code in Rails and as the Flex application deals with &lt;span class="caps"&gt;XML&lt;/span&gt; responses, simply check in Flex if the response starts with &amp;lt;errors&amp;gt;. This can then also be dealt with in the Flex application in one place of the application. In a Cairngorm application I had the Delegate transform these &amp;#8220;errors&amp;#8221; responses to Faults.&lt;/p&gt;


	&lt;p&gt;Here is an example of the change to the Rails ApplicationController.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;class ApplicationController &amp;lt; ActionController::Base

  after_filter :flex_error_handling

  def flex_error_handling
    response.headers['Status'] = interpret_status(200) if response.headers['Status'] == interpret_status(422)
  end

  def rescue_action_in_public(exception)
    render_exception(exception)
  end
  def rescue_action_locally(exception)
    render_exception(exception)
  end

  rescue_from ActiveRecord::RecordNotFound, :with =&amp;gt; :render_exception
  def render_exception(exception)
    render :text =&amp;gt; &amp;quot;&amp;lt;errors&amp;gt;&amp;lt;error&amp;gt;#{exception}&amp;lt;/error&amp;gt;&amp;lt;/errors&amp;gt;&amp;quot;, :status =&amp;gt; 200 
  end

end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Wed, 20 Feb 2008 15:56:23 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:ae18042c-a6a9-4061-a789-2384246ef0b6</guid>
      <author>Daniel Wanja</author>
      <link>http://onrails.org/articles/2008/02/20/dealing-with-http-errors-in-a-flex-with-rails-application</link>
    </item>
    <item>
      <title>"Dealing with HTTP errors in a Flex with Rails application." by John Burgoon</title>
      <description>&lt;p&gt;Thank you for this!  It doesn&amp;#8217;t prevent the error but at least it stops the cryptic &amp;#8220;Error #2032&amp;#8221; and allows me to confirm that this is the problem.&lt;/p&gt;</description>
      <pubDate>Sun, 23 Nov 2008 01:07:20 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:8be3bb86-a5d4-4022-913c-cc0489fb4bf5</guid>
      <link>http://onrails.org/articles/2008/02/20/dealing-with-http-errors-in-a-flex-with-rails-application#comment-4134</link>
    </item>
    <item>
      <title>"Dealing with HTTP errors in a Flex with Rails application." by tejaswini</title>
      <description>&amp;lt;?xml version=&amp;#8221;1.0&amp;#8221; encoding=&amp;#8221;utf-8&amp;#8221;?&amp;gt;


    
    
    
    
    
    
    
    

    &amp;lt;!&amp;#8212;
    &amp;#8212;&amp;gt;
    
        &amp;lt;![CDATA[
            import mx.validators.ValidationResult;
            import flash.net.sendToURL;
            import mx.controls.Alert;
            import mx.utils.ObjectUtil;
            import mx.controls.Text;
            import mx.collections.ArrayCollection;
            import mx.controls.ComboBox;
            import mx.rpc.xml.SimpleXMLEncoder;
            import mx.controls.DataGrid;
             var xml1:XML;
            //import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
        public   var arr_list1:Array=new Array();
           // var arr_list2:ArrayCollection=new ArrayCollection();
           public var arr_list2:ArrayCollection=new ArrayCollection();
                      //public    var arr_email:ArrayCollection= new ArrayCollection();
           // var arr_list3:Array=new Array();
          //var xml:XML = objectToXML(arr_list2.source);

         private function init():void{
             ws.ROLEMASTER.send();
         ws.email.send();
        // ws.addemail.send();
         }
         private function remove():void{
         arr_list2.removeItemAt(dg2.selectedIndex);

         }

                 private function dome():void    
                 {
                 arr_list2.addItem(txt.text);
                 dg2.dataProvider=arr_list2;
                 }    

                 private function handleResult():void
                 {
                Alert.show(ws.addemail.lastResult.toString());
                //Alert.show(ws.addemail.ResultEvent.toLocaleString());

                 }
             private function onResult(event:ResultEvent):void {

                    if (event.result.Tables != null)
                          {
                  // panel.removeAllChildren()    
                                for each (var table:Object in event.result.Tables)
                                    {
                                        displayROLEMASTERTable(table);
                                         //  displayemailTable(table);

                                    }

                            for each (var table1:Object in event.result.Tables)
                                   {
                                     displayemailTable(table1);

                                  }

                           }
       }

       private function displayROLEMASTERTable(tbl:Object):void {

                  for(var i:int=0;i&amp;lt;tbl.Rows.length;i++)
                          {
                             arr_list1.push(tbl.Rows[i].ROLENAME);        
                          }
                  comb.dataProvider=arr_list1;   

      }
/*/private function nextresult(event:ResultEvent):void{
    if (event.result.Tables!=null)
      for each (var table:Object in event.result.Tables)
                                    {
                                        displayemailTable(table);

                                    }
} */
private function displayemailTable(tbl1:Object):void{

    for(var j:int=0;j&amp;lt;tbl1.Rows.length;j++)
    {
    arr_list2.addItem({Email:tbl1.Rows[j].emailid});

    //arr_list3.push({Email:tbl1.Rows[j].a});
    }
    dg2.dataProvider=arr_list2;

	&lt;p&gt;}&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;public function objectToXML(obj:Object):XML {
              var qName:QName= new QName("root");
              var xmlDocument:XMLDocument= new XMLDocument();
              var simpleXMLEncoder:SimpleXMLEncoder= new SimpleXMLEncoder(xmlDocument); 
              var xmlNode:XMLNode= simpleXMLEncoder.encodeValue(obj,qName,xmlDocument);
               var xml:XML = new XML(xmlDocument.toString());&lt;/code&gt;&lt;/pre&gt;
	&lt;pre&gt;&lt;code&gt;return xml;
        }
                private function store():void{&lt;/code&gt;&lt;/pre&gt;
	&lt;pre&gt;&lt;code&gt;// var xml2:XML;
//  xml2=xml1.toXMLString();&lt;/code&gt;&lt;/pre&gt;
	&lt;pre&gt;&lt;code&gt;ws2.addemail.send(xml1.toXMLString(),'A');
 //myWS.Map.send(xml2,combo.selectedItem.RoleID);&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;// ws.addemail.send(xml1.dg2.selectedItem.emailid);&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;}&lt;/code&gt;&lt;/pre&gt;


]]&amp;gt;











    

&amp;lt;mx:operation name=&amp;#8221;addemail&amp;#8221;  resultFormat=&amp;#8221;object&amp;#8221; result=&amp;#8221;handleResult()&amp;#8221; 



    </description>
      <pubDate>Thu, 29 May 2008 13:17:50 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:687496ca-f1c7-4152-bb2b-55cfe51f4bc8</guid>
      <link>http://onrails.org/articles/2008/02/20/dealing-with-http-errors-in-a-flex-with-rails-application#comment-3636</link>
    </item>
    <item>
      <title>"Dealing with HTTP errors in a Flex with Rails application." by Walter</title>
      <description>&lt;p&gt;Very helpful.  Thanks for the post.&lt;/p&gt;


	&lt;p&gt;One tweak that I did&amp;#8230;  I wanted my application to give the normal responses if the client was something other than Flex.  So I modified to the following:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
  def flex_error_handling
    valid_status_codes = [201, 422].collect{|code| interpret_status(code)}
    if request.headers.has_key?('HTTP_X_FLASH_VERSION') &amp;#38;&amp;#38; valid_status_codes.include?(response.headers['Status'])
      response.headers['Status'] = interpret_status(200)
    end
  end
&lt;/code&gt;
&lt;/pre&gt;</description>
      <pubDate>Thu, 27 Mar 2008 22:34:39 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:0758d465-b53c-47f6-8074-2c185ffd8648</guid>
      <link>http://onrails.org/articles/2008/02/20/dealing-with-http-errors-in-a-flex-with-rails-application#comment-3416</link>
    </item>
    <item>
      <title>"Dealing with HTTP errors in a Flex with Rails application." by Chris</title>
      <description>&lt;p&gt;sorry, for my question. the reason was the application-server i used: lighttpd. with webrick (and i suppose the apache too) it works as expected.&lt;/p&gt;</description>
      <pubDate>Thu, 06 Mar 2008 12:00:54 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:3d560289-f85e-4e97-897b-077fb3eb6620</guid>
      <link>http://onrails.org/articles/2008/02/20/dealing-with-http-errors-in-a-flex-with-rails-application#comment-3361</link>
    </item>
    <item>
      <title>"Dealing with HTTP errors in a Flex with Rails application." by Chris</title>
      <description>&lt;p&gt;but what&amp;#8217;s make the responses of XMLHTTPRequest take such a long time (in most cases nearly 7 seconds), when the statuscode is set to less known status like 424, 415 or in your case 422? setting it to 400, 500 or other well known status-codes the response returns much faster. i checked it and found out that ther rendering itself doesn&amp;#8217;t cost that time. i really don&amp;#8217;t know. you can try and set your statuscode to 422. what is happening in the meantime? and how to prevent it? watching firebug: the reponse contains &amp;#8220;Loading&amp;#8230;&amp;#8221;. ???
i hope there is somebody out there who knows an answer.&lt;/p&gt;


	&lt;p&gt;best regards
chris&lt;/p&gt;</description>
      <pubDate>Wed, 05 Mar 2008 17:10:19 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:1058ba89-6d6a-42c8-916d-60734766a833</guid>
      <link>http://onrails.org/articles/2008/02/20/dealing-with-http-errors-in-a-flex-with-rails-application#comment-3358</link>
    </item>
    <item>
      <title>"Dealing with HTTP errors in a Flex with Rails application." by Matthijs Langenberg</title>
      <description>&lt;p&gt;It&amp;#8217;s good to know that the HTTP status and body are available when dealing with an Adobe AIR application.&lt;/p&gt;</description>
      <pubDate>Wed, 20 Feb 2008 20:05:54 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:334b4e95-4982-4151-9ad1-bf08a9aed106</guid>
      <link>http://onrails.org/articles/2008/02/20/dealing-with-http-errors-in-a-flex-with-rails-application#comment-3287</link>
    </item>
    <item>
      <title>"Dealing with HTTP errors in a Flex with Rails application." by Matthijs Langenberg</title>
      <description>&lt;p&gt;It&amp;#8217;s good to know that the HTTP status and body are available when dealing with an Adobe AIR application.&lt;/p&gt;</description>
      <pubDate>Wed, 20 Feb 2008 20:05:45 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:c46fd27f-a7ae-4d2a-ab60-0cb26ad593d0</guid>
      <link>http://onrails.org/articles/2008/02/20/dealing-with-http-errors-in-a-flex-with-rails-application#comment-3286</link>
    </item>
    <item>
      <title>"Dealing with HTTP errors in a Flex with Rails application." by Alex MacCaw</title>
      <description>&lt;p&gt;Yes, that&amp;#8217;s the way I&amp;#8217;ve done it. I have a parameter called &amp;#8216;always_return_200&amp;#8217; and check the response for errors. Or you could use a custom socket lib (like royston suggests). You could clean up the rails code though. There&amp;#8217;s a new method called rescue_from in edge. Also if the errors are on a model (which I presume they are) you can call model.errors.to_xml. e.g.&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;rescue_from ActiveRecord::RecordInvalid do |exception|
  respond_to do |wants|
   wants.xml { render :xml =&amp;gt; exception.record.errors }
  end
end&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Wed, 20 Feb 2008 16:59:05 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:84eb0908-1a19-4ba9-bb5d-a0365afecc86</guid>
      <link>http://onrails.org/articles/2008/02/20/dealing-with-http-errors-in-a-flex-with-rails-application#comment-3284</link>
    </item>
    <item>
      <title>"Dealing with HTTP errors in a Flex with Rails application." by royston</title>
      <description>&lt;p&gt;&lt;a href="http://code.google.com/p/as3httpclientlib/" rel="nofollow"&gt;http://code.google.com/p/as3httpclientlib/&lt;/a&gt;
You&amp;#8217;ll get back status codes just fine.&lt;/p&gt;</description>
      <pubDate>Wed, 20 Feb 2008 16:32:39 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:27883ff6-4099-4ef8-8e28-cc3a4b8e1483</guid>
      <link>http://onrails.org/articles/2008/02/20/dealing-with-http-errors-in-a-flex-with-rails-application#comment-3283</link>
    </item>
  </channel>
</rss>
