////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package mx.messaging
{
import flash.events.TimerEvent;
import flash.net.Responder;
import flash.utils.Timer;
import mx.messaging.messages.IMessage;
import mx.messaging.messages.ErrorMessage;
import mx.resources.IResourceManager;
import mx.resources.ResourceManager;
[ResourceBundle("messaging")]
/**
* The MessageResponder class handles a successful result or fault from a message
* destination. For each message that a Channel sends, the Channel creates a
* MessageResponder to handle the result. Upon a response, the Channel will
* invoke either the result()
or status()
callback
* on the MessageResponder. MessageResponder subclasses should override these
* methods to perform any necessary processing. For every response, whether a
* successful result or an error, the MessageResponder should invoke
* acknowledge()
on its agent. If the response was a fault, the
* MessageResponder should also invoke fault()
on its agent.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public class MessageResponder extends Responder
{
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructs a MessageResponder to handle the response for the specified
* Message for the specified MessageAgent.
*
* @param agent The MessageAgent sending the Message.
*
* @param message The Message being sent.
*
* @param channel The Channel used to send.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function MessageResponder(agent:MessageAgent, message:IMessage,
channel:Channel = null)
{
super(result, status);
_agent = agent;
_channel = channel;
_message = message;
_requestTimedOut = false;
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
/**
* @private
* Flag indicating whether the request corresponding to this responder
* has timed out. This is used by responders that cannot close
* their underlying connection (NetConnection for instance) so they must
* instead ignore any response that is returned after the request timeout
* is reached.
*/
private var _requestTimedOut:Boolean;
/**
* @private
* Timer used to trigger a request timeout.
*/
private var _requestTimer:Timer;
/**
* @private
*/
private var resourceManager:IResourceManager =
ResourceManager.getInstance();
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// agent
//----------------------------------
/**
* @private
*/
private var _agent:MessageAgent;
/**
* Provides access to the MessageAgent that sent the message.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get agent():MessageAgent
{
return _agent;
}
//----------------------------------
// channel
//----------------------------------
/**
* @private
*/
private var _channel:Channel;
/**
* Provides access to the Channel used to send the message.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get channel():Channel
{
return _channel;
}
//----------------------------------
// message
//----------------------------------
/**
* @private
*/
private var _message:IMessage;
/**
* Provides access to the sent Message.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get message():IMessage
{
return _message;
}
/**
* @private
*/
public function set message(value:IMessage):void
{
_message = value;
}
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
/**
* @private
* Starts a timer to monitor a request timeout. If the timer hits the
* specified requestTimeout before a response is returned,
* requestTimedOut()
is invoked and any subsequent
* response is ignored by this responder.
*
* @param requestTimeout The amount of time in seconds to allow a request
* to run before timing it out.
*/
final public function startRequestTimeout(requestTimeout:int):void
{
_requestTimer = new Timer(requestTimeout * 1000, 1);
_requestTimer.addEventListener(TimerEvent.TIMER, timeoutRequest);
_requestTimer.start();
}
/**
* Called by the channel that created this MessageResponder when a
* response returns from the destination.
* This method performs core result processing and then invokes the
* resultHandler()
method that subclasses may override to
* perform any necessary custom processing.
*
* @param message The result Message returned by the destination.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
final public function result(message:IMessage):void
{
// Ignore any response after the request has timed out.
if (!_requestTimedOut)
{
// Shut down the timeout timer if it's alive.
if (_requestTimer != null)
{
releaseTimer();
}
resultHandler(message);
}
}
/**
* Called by the channel that created this MessageResponder when a fault
* response returns from the destination.
* This method performs core result processing and then invokes the
* statusHandler()
method that subclasses may override to
* perform any necessary custom processing.
*
* @param message The fault Message returned by the destination.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
final public function status(message:IMessage):void
{
// Ignore any response after the request has timed out.
if (!_requestTimedOut)
{
// Shut down the timeout timer if it's alive.
if (_requestTimer != null)
{
releaseTimer();
}
statusHandler(message);
}
}
//--------------------------------------------------------------------------
//
// Protected Members
//
//--------------------------------------------------------------------------
/**
* Constructs an ErrorMessage that can be passed to the associated
* MessageAgent's callbacks upon a request timeout.
*
* @return Returns an ErrorMessage that can be passed to the associated
* MessageAgent's callbacks upon a request timeout.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
protected function createRequestTimeoutErrorMessage():ErrorMessage
{
var errorMsg:ErrorMessage = new ErrorMessage();
errorMsg.correlationId = message.messageId;
errorMsg.faultCode = "Client.Error.RequestTimeout";
errorMsg.faultString = resourceManager.getString(
"messaging", "requestTimedOut");
errorMsg.faultDetail = resourceManager.getString(
"messaging", "requestTimedOut.details");
return errorMsg;
}
/**
* Subclasses must override this method to perform custom processing of
* the result and invoke the proper callbacks on the associated
* MessageAgent.
*
* @param message The result Message returned by the destination.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
protected function resultHandler(message:IMessage):void {}
/**
* Subclasses must override this method to handle a request timeout and
* invoke the proper callbacks on the associated MessageAgent.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
protected function requestTimedOut():void {}
/**
* Subclasses must override this method to perform custom processing of
* the status and invoke the proper callbacks on the associated
* MessageAgent.
*
* @param message The fault Message returned by the destination.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
protected function statusHandler(message:IMessage):void {}
//--------------------------------------------------------------------------
//
// Private Members
//
//--------------------------------------------------------------------------
/**
* @private
* Helper callback that flags the request as timed out before delegating
* to custom timeout processing.
*/
private function timeoutRequest(event:TimerEvent):void
{
_requestTimedOut = true;
releaseTimer();
requestTimedOut();
}
/**
* @private
* Utility method to shutdown the request timeout Timer.
*/
private function releaseTimer():void
{
_requestTimer.stop();
_requestTimer.removeEventListener(TimerEvent.TIMER, timeoutRequest);
_requestTimer = null;
}
}
}