Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Operation Timed Out message

    Hello,

    If our application server goes down and we try to execute a fetch through our application, then SmartClient will display a "Finding Records" dialog box for awhile and then eventually display "Operation Timed Out". Is there any way to better control this behavior? I'd like to either reduce the amount of time before this time-out message appears? Or, perhaps recognize that our server is down and display a more helpful message to the user that the server is temporarily down and will return soon. Finally, if we are able to route traffic to another temporary server that is able to return a custom "application not available" message to the client (ie. "We have gone down for temporary maintenance, will be back up in 30 minutes"), how can I format the response from this temporary server so that SmartClient will display it for the user?

    #2
    Hi senordhuff -

    Yes, you can control all aspects of this timeout and resulting behavior. The default timeout time is controlled by the RPCManager.defaultTimeout parameter. - see: http://www.smartclient.com/docs/5.5....defaultTimeout

    You can also set timeouts on a per-request basis via RPCRequest.timeout (note that this is one is not currently publicly documented, but will be starting with the 5.6 release - but the functionality is there and you can use this with 5.5.1).

    If you want to override the default text that is shown to the user in case of failure (or do something completely custom), you can do so by providing a custom implementation for RPCManager.handleError - docs here: http://www.smartclient.com/docs/5.5....er.handleError

    If you want, you could use that override point to send an RPC to a different server to obtain a custom error message, but keep in mind that if you do this, you'll need to set document.domain on the top-level page to a subdomain that's shared between the origin server (the server you loaded the top-level page from) and the server you'll be targeting with this special RPC. The SmartClient server-side RPCManager will auto-adapt to the document.domain of the top-level page, so you don't need to do anything special on that RPC response.

    Comment


      #3
      Hi,

      I'm not clear on how to implement an override of handleError based on the documentation. If my primary objective is to simply change "Operation Timed Out" to a custom message, what do I need to do in handleError in order to achieve that?

      Regarding your comment on document.domain, are you saying that the document.domain needs to be the same at the sub-domain level and not just the domain level so that putting simply document.domain="domain.com" is not enough and it needs to be document.domain="subdomain.domain.com" ?

      Finally, does this temporary server need to be able to respond specifically to SmartClient RPC requests or can it simply respond to any request with a basic "Application not available" text via html and SmartClient will then display that?

      Comment


        #4
        Sorry, one other thing. I noticed that your relogin process doesn't display the "Operation Timed Out" message if the server is no longer available. Is that accurate? If so, is there any way to inform the user on relogin that the server is no longer available?

        Comment


          #5
          Well, the handleError method is passed two parameteres, the RPC/DSResponse and the RPC/DSRequest (depending on the underlying type of operation). Both the RPCResponse and the DSResponse objects have a 'status' field which will have an integer value that maps to one of the static values defined on RPC/DSResponse. So you can do e.g:

          Code:
          isc.RPCManager.addClassProperties({
              handleError : function (response, request) {
                  if(response.status != isc.RPCResponse.STATUS_SUCCESS) {
                      isc.warn("Something bad happened");
                  } 
              }
          });
          Take a look at the 'Class APIs' tab of the RPCRequest documentation for a list of status codes.

          On the document.domain issue, the answer is no - I wasn't trying to imply that you need any particular number of subdomain levels, just that it needs to be some kind of subdomain based on the origin server name. So for example, if your host is foo.bar.zoo.company.com, then any of: bar.zoo.company.com, zoo.company.com, or company.com would do as a subdomain setting - but whatever subdomain you choose has to match the subdomain portion of the server that provides the error message. So if you choose e.g. company.com, then the error server can be anything that ends with company.com.

          There's no special built-in operation that fetches an error text to display to a user, so no, it's not currently possible just to send some html back in response to that error RPC and have SmartClient automatically display it. But it's pretty easy to build.

          This error-providing server does need to respond with a structured RPC and so does need to use the SmartClient server. Ordinarily, you can obtain the body of an HTTP response by setting transport: "xmlHttpRequest" and serverOutputAsString: true on your request and then the server response is available as the 'data' parameter in your callback. But you can't use that in this case, because you'd be targeting that xmlHttpRequest at a non-origin server and this isn't allowed by the browser security model. But you can target the "hiddenFrame" transport at a non-origin server, provided you use the document.domain approach and have the SmartClient server installed on that machine to respond to such a request.

          If you really can't live with a SmartClient server on that temporary server, you could potentially pursue some more exotic solutions, like e.g. targeting the origin server with the error-fetching RPC, but setting a special query parameter or cookie on the request that's read by a firewall, loadbalancer, or some other high-layer router that understands HTTP and can route requests to different servers based on specifics of the HTTP protocol (such as a cookie value or query parameter).

          Consider also that a fully redundant server-side setup can eliminate or at least significantly reduce the likelihood of a large number of these failure cases, although you can never eliminate them - and having this kind of client-side backstop is a great feature of the Ajax approach and SmartClient in particular.

          Lastly, regarding the relogin RPC not displaying the Operation Timeout Out - if that's the case, then I think that's a bug.
          Last edited by Isomorphic; 23 May 2008, 14:44.

          Comment


            #6
            Thanks for your very thorough response.

            -I went to look up the Class APIs on the RPCRequest and I think you meant to say the RPCResponse, right? I found the status code there.

            -Yes, we can live with Smartclient server on our temporary server. Just wanted to know if we could get away with no having it. We are going to be using a loadbalancer that can auto-direct to a different server. But, I think we'll still install SmartClient server to return this error message.


            -Yes, perhaps the relogin issue is a bug. I just recreated it. If the relogin form is displayed and I shut down my server and then try to login, I never receive an Operation Timed Out message.

            Comment


              #7
              Hi, I just saw in your docs that:

              http://www.smartclient.com/docs/5.5.1/a/b/c/go.html#class..RPCResponse
              (Class API, STATUS_SERVER_TIMEOUT)

              "NOTE that if using hiddenFrame as the transport (not the default), a malformed response such as a "500 Server Error" or 404 errors will be reported as a timeout."

              Since we are using hiddenFrame, I want to clarify this. Does this mean that any server error like 500 or 404 is going to return STATUS_SERVER_TIMEOUT? If so, I'll need to word my timeoutErrorMessage more generically:
              http://www.smartclient.com/docs/5.5.1/a/b/c/go.html#classAttr..RPCManager.timeoutErrorMessage

              Comment


                #8
                That's accurate, with the "hiddenFrame" transport, 404 or hard server errors are reported as timeouts

                Comment


                  #9
                  Hi, were you able to confirm if that is indeed a bug where the relogin form does not display a timeout message if the server is no longer responding? If so, when do you anticipate that it'll be fixed?

                  Comment


                    #10
                    We have not deeply investigated it, but it is highly likely that even if it is possible to discriminate some kinds of hard server errors from timeouts (by e.g. replacing the default error page a webserver returns with something that is SmartClient aware), it may not be possible to accurately discern all or even most such cases cross-browser, especially if document.domain is set.

                    Is this an important feature given your use cases? You could avoid the lengthy timeout period by simply specifying a custom timeout that is reasonable, but not as long as the default of 4 minutes. For example, a 10 second timeout is almost certainly longer than any reasonable response from the server - having hit that limit, you could deal with it as a server error condition. I would think that lengthy timeouts of this type are not really different from an end-user perspective than a hard server failure. Did you plan to handle such cases differently?

                    Comment


                      #11
                      Hi, I just saw the following in your 5.7 beta release notes:

                      Fixed: bug where relogin dialog could fail to be displayed after session timeout in Internet Explorer on HTTPS sites using document.domain


                      Was this bug possibly in response to the issues I posted in this thread? Just curious.

                      Comment


                        #12
                        Hi Senordhuff,
                        Actually this was unrelated - this was a fix for an issue encountered by another customer involving cross-domain redirects within their application.

                        Comment


                          #13
                          problem in capturing exceptions

                          Hi

                          I have followed the above explanation on how to capture exceptions. but it doesn't display my custom error message displayed in here ("Something bad happened") instead it displays default error message "Transport error http code 12029 for url"

                          please guide me on how to override the default error message . my code is displayed bellow

                          Thanks

                          Shivantha




                          Code:
                              DataSource.create({
                          
                                   ID:"Login",
                          
                                   transformRequest : function (dsRequest) {
                          
                                     var params =
                                      {
                                          railRoadId :document.getElementById('railRoad').value,
                                          deviceId : document.getElementById('device').value,
                          		    employerId :mainFrm.getValue('employerId')
                                      };
                                        return params;
                                  },
                          
                          
                          
                              fields:[
                                  {name:"loginId",  type:"sequence",  primaryKey:true,  hidden:true},
                                  {name:"employerId", title:"Employer Id", type:"text", length:500},
                                  {name:"railRoad", title:"Rail Road", type:"text", length:500},
                                  {name:"deviceId", title:"Device", type:"text", length:500}
                              ]
                          });
                                           var image = isc.Canvas.imgHTML("mobilecommand/MobileCommandLogo-trans.gif",400,80                  );
                          isc.Label.create({
                              title:"Label0",
                              autoDraw:false,
                              width:400,
                              contents:image,
                              styleName:"textItem",
                              ID:"titleLbl",
                              height:100
                          });
                              
                          
                          isc.RPCManager.addProperties({
                              handleError : function (response, request) {
                                  if(response.status != isc.RPCResponse.STATUS_SUCCESS) {
                                      isc.warn("Something bad happened");
                                  } 
                              }
                          });
                              isc.RPCManager.actionURL =  "http://localhost:8090/WRLSS_CMD_WEB/servlets/mcommand/login";
                          
                          
                          isc.DynamicForm.create({
                              colWidths:[
                                  200,
                                  100
                              ],
                              fields:[
                                  {name:"employerId", title:"Enter Employee ID", _constructor:"PasswordItem"},
                                  {
                                      name:"submitBtn",
                                      title:"Submit",
                                      contents:"",
                                      colSpan:2,
                                      click:"mainFrm.showWindow()",
                                      align:"center",
                                      _constructor:'ButtonItem'
                                  }
                              ],
                              top:350,
                              dataSource:"Login",
                              showEdges:false,
                              edgeShowCenter:false,
                              left:30,
                          
                          	passowrdText : function (data) {
                                   	if( mainFrm.getValue("employerId") == null ){
                                  		mainFrm.setValue( "employerId"   , data );
                                  	}
                                  	else if( mainFrm.getValue("employerId") != null ){
                                   			mainFrm.setValue( "employerId"   ,mainFrm.getValue("employerId")+ data );
                                           if(mainFrm.getValue("employerId").length == 7 )
                                                mainFrm.getField("employerId").setDisabled(true);
                                      }
                          	},
                          
                          
                          	reset : function () {
                          
                          		mainFrm.setValue( "employerId"   ,'' );
                          	},
                          
                          	deleteLast : function () {
                          	       var pstr=  mainFrm.getValue("employerId");
                          		mainFrm.setValue( "employerId", pstr.substr(0, pstr.length -1 ));
                                  if(mainFrm.getValue("employerId").length < 7 )
                                                mainFrm.getField("employerId").setDisabled(false);
                              },
                          
                          
                          
                          	showWindow :function(){
                                 getConfigurationSettings();
                                 Login.fetchData(null,"mainFrm.processResult(data)");
                              },
                          
                               processResult :function(data){
                          
                          		if(data != "Valid")
                          		{
                          		 	isc.warn("Invalid Emplyer ID");
                          
                          		}else
                          		{
                          			( window.open("../"+"views/switchList.jsp?railRoad="+
                                                                document.getElementById("railRoad").value +
                                                                "&deviceId="+document.getElementById('device').value)).focus();
                                  	//	new_win.focus();
                          		}
                          
                          
                          	},
                          
                          
                          
                              autoDraw:false,
                              width:300,
                              showHover:false,
                              ID:"mainFrm",
                              height:100
                          })

                          Comment


                            #14
                            Hello Shivantha,

                            Use addClassProperties() to add your handleError() handler. Correct in the docs, but a preceding forum post was incorrect.

                            Comment

                            Working...
                            X