Author: Sameer Chunilall Date: 2010-01-24 Description: Responsible for the invocation of a Dynamic Service and/or bizrule The invocation of the service is not internal to any dynamic service object as the service is a singleton and we want every service request to be executed in insolation of other as we are working in a static and multi-threaded environment
Inheritance: IDynamicServicesInvoker, IDisposable
Ejemplo n.º 1
0
 /// <summary>
 /// Invoke a Dynamic Service
 /// </summary>
 /// <param name="sa">The action of type InvokeDynamicService</param>
 /// <param name="dataListID">The data list ID.</param>
 /// <returns>
 /// UnlimitedObject
 /// </returns>
 public Guid DynamicService(ServiceAction sa, Guid dataListID)
 {
     ErrorResultTO errors;
     IDynamicServicesInvoker invoker = new DynamicServicesInvoker();
     // Issue request with blank data payload
     return invoker.Invoke(sa.Service, (new UnlimitedObject()), dataListID, out errors);
 }
Ejemplo n.º 2
0
        /// <summary>
        ///     Responsible for the processing of all inbound requests
        ///     This method is reentrant and will call itself to
        ///     for every invocation required in every generation
        ///     of nesting. e.g services made up of services
        /// </summary>
        /// <param name="resourceDirectory">The singleton instance of the service library that contains all the logical services</param>
        /// <param name="xmlRequest">The actual client request message</param>
        /// <param name="dataListId">The id of the data list</param>
        /// <param name="errors">Errors resulting from this invoke</param>
        /// <returns></returns>
        public Guid Invoke(IDynamicServicesHost resourceDirectory, dynamic xmlRequest, Guid dataListId,
                           out ErrorResultTO errors)
        {
            // Host = resourceDirectory

            #region Async processing of client request - queue the work item asynchronously

            //Get an UnlimitedObject from the xml string provided by the caller
            //TraceWriter.WriteTraceIf(_managementChannel != null && _loggingEnabled, "Inspecting inbound data request", Resources.TraceMessageType_Message);
            Guid result = GlobalConstants.NullDataListID;

            var allErrors = new ErrorResultTO();
            errors = new ErrorResultTO();

            if(xmlRequest.Async is string)
            {
                //TraceWriter.WriteTrace(_managementChannel, "Caller requested async execution");
                bool isAsync;

                bool.TryParse(xmlRequest.Async, out isAsync);

                if(isAsync)
                {
                    ThreadPool.QueueUserWorkItem(delegate
                    {
                        ErrorResultTO tmpErrors;
                        //TraceWriter.WriteTrace(_managementChannel, "Queuing Asynchronous work", Resources.TraceMessageType_Message);
                        xmlRequest.RemoveElementByTagName("Async");
                        IDynamicServicesInvoker invoker = new DynamicServicesInvoker(_dsfChannel, _managementChannel);
                        result = invoker.Invoke(resourceDirectory, xmlRequest, dataListId, out tmpErrors);
                        if(tmpErrors.HasErrors())
                        {
                            allErrors.MergeErrors(tmpErrors);
                        }
                        //TraceWriter.WriteTrace(result.XmlString);
                        if(result != GlobalConstants.NullDataListID)
                        {
                            // PBI : 5376
                            SvrCompiler.DeleteDataListByID(result, true); //TODO: Clean it up ;)
                        }
                    });
                    dynamic returnData = new UnlimitedObject();
                    returnData.Load(string.Format("<ServiceResponse>{0} Work Item Queued..</ServiceResponse>",
                                                  DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff")));
                    return returnData;
                }
            }

            #endregion

            #region Get a handle on the service that is being requested from the service directory

            string serviceName = string.Empty;

            //Set the service name as this is a complex message
            //with multiple services requests embedded in the inbound data
            //This will allow us to 
            if(xmlRequest.Service is IEnumerable<UnlimitedObject>)
            {
                IEnumerable<UnlimitedObject> services = xmlRequest.Service;
                dynamic serviceData = services.First();
                if(serviceData.Service is string)
                {
                    serviceName = serviceData.Service;
                }
            }


            //If there is only a single service request then get the service name
            if(xmlRequest.Service is string)
            {
                serviceName = xmlRequest.Service;
            }

            //If the service name does not exist return an error to the caller
            if(string.IsNullOrEmpty(serviceName))
            {
                xmlRequest.Error = Resources.DynamicServiceError_ServiceNotSpecified;
            }

            //Try to retrieve the service from the service directory

            IEnumerable<DynamicService> service;
            Host.LockServices();

            try
            {
                service = from c in resourceDirectory.Services
                          where serviceName != null
                          && c.Name.Trim().Equals(serviceName.Trim(), StringComparison.CurrentCultureIgnoreCase)
                          select c;
            }
            finally
            {
                Host.UnlockServices();
            }

            service = service.ToList();

            if(!service.Any())
            {
                TraceWriter.WriteTrace(_managementChannel, string.Format("Service '{0}' Not Found", serviceName),
                                       Resources.TraceMessageType_Error);

                allErrors.AddError(string.Format("Service '{0}' Not Found", serviceName));

                throw new InvalidOperationException(string.Format("Service '{0}' Not Found", serviceName));

                //xmlRequest.Error = Resources.DynamicServiceError_ServiceNotFound;
            }

            #endregion

            //Instantiate a Dynamic Invocation type to invoke the service

            #region  Transactionalized Service Invocation with support for MS-DTC

            dynamic dseException = null;

            //The transactionScope is used to create an ambient transaction that every action will be subject to
            //This transaction 
            try
            {
                //TraceWriter.WriteTrace(_managementChannel, string.Format("Setting up transaction scope", serviceName), Resources.TraceMessageType_Message);
                using(var transactionScope = new TransactionScope())
                {
                    //TraceWriter.WriteTrace(_managementChannel, string.Format("Invoking Service '{0}'", serviceName), Resources.TraceMessageType_Message);

                    #region Process several requests to different services as a single unit of work

                    //Type 3 request (read above)
                    //This is handled differently to type 1 and 2 requests
                    //as it can execute in the context of either a single or 
                    //multiple services.
                    //if (xmlRequest.IsMultipleRequests) {
                    //    TraceWriter.WriteTrace(_managementChannel, "Caller requested multiple service execution in single request", Resources.TraceMessageType_Message);
                    //    dynamic results = new UnlimitedObject();

                    //    foreach (dynamic request in xmlRequest.Requests) {

                    //        dynamic result = new DynamicServicesInvoker(_dsfChannel, _managementChannel).Invoke(resourceDirectory, request);
                    //        if (result.HasError) {
                    //            return result;
                    //        }
                    //        results.AddResponse(result);
                    //    }
                    //    transactionScope.Complete();

                    //    return results;
                    //}

                    #endregion

                    DynamicService s = service.First();
                    result = Invoke(s, xmlRequest, dataListId, out errors);
                    if(result == GlobalConstants.NullDataListID)
                    {
                        allErrors.AddError("Failed to invoke service");
                 
                    }
                    
                    if(!ClientCompiler.HasErrors(result))
                    {
                        transactionScope.Complete();
                    }

                    //The service exists so invoke the service which runs all actions defined for the service
                    //Return the response
                    //return xmlResponses;
                }
            }
            //Occurs when an operation is attempted on a rolled back transaction
            catch(TransactionAbortedException abortEx)
            {
                dseException = abortEx;
            }
            //This exception is thrown when an action is attempted on a transaction that is in doubt. 
            //A transaction is in doubt when the state of the transaction cannot be determined. 
            //Specifically, the final outcome of the transaction, whether it commits or aborts, is never known for this transaction.
            catch(TransactionInDoubtException inDoubtEx)
            {
                dseException = inDoubtEx;
            }
            //Thrown when a resource manager cannot communicate with the transaction manager. 
            catch(TransactionManagerCommunicationException transactionManagerEx)
            {
                dseException = transactionManagerEx;
            }
            //Thrown when a promotion fails
            catch(TransactionPromotionException promotionException)
            {
                dseException = promotionException;
            }
            catch(TransactionException transactionEx)
            {
                dseException = transactionEx;
            }

            if(dseException != null)
            {
                TraceWriter.WriteTrace(_managementChannel,
                                       string.Format("Service Execution Failed With Error\r\n{0}",
                                                     new UnlimitedObject(dseException).XmlString),
                                       Resources.TraceMessageType_Error);
            }

            // set error variable
            errors = allErrors;
            if(errors.HasErrors())
            {
                DispatchDebugState(xmlRequest, dataListId, allErrors);
            }

            return result;

            #endregion
        }
Ejemplo n.º 3
0
        public dynamic BizRule(ServiceAction sa, dynamic xmlRequest, Guid dataListID)
        {
            dynamic bizRuleException = null;

            // ReSharper disable JoinDeclarationAndInitializer
            dynamic result;
            // ReSharper restore JoinDeclarationAndInitializer

            ErrorResultTO errors;
            IDynamicServicesInvoker invoker = new DynamicServicesInvoker();
            result = invoker.Invoke(sa.Service, xmlRequest, dataListID, out errors);

            // ReSharper disable InconsistentNaming
            string Expression = sa.BizRule.Expression;
            // ReSharper restore InconsistentNaming

            string[] expressionColumns = sa.BizRule.ExpressionColumns;

            for(int count = 0; count < expressionColumns.Length; count++)
            {
                //Retrieve the value from the response of service
                object inputValue = result.GetValue(expressionColumns[count]);
                //The value does not exist so we stop right here
                if(inputValue.GetType() != typeof(string))
                {
                    _returnVal.Error = string.Format("Unable to execute business rule '{0}'", sa.BizRule.Name);
                    _returnVal.ErrorDetail = string.Format(
                        "Value of '{0}' does not exist in response from action '{1}'", expressionColumns[count], sa.Name);
                    return _returnVal;
                }
                //Build an executable c# expression that we can evaluate this must always evaluate to a boolean value
                //true=input passed the business rule;  false=input failed the business rule.
                
                // ReSharper disable SpecifyACultureInStringConversionExplicitly
                Expression = Expression.Replace("{" + count.ToString() + "}", inputValue.ToString());
                // ReSharper restore SpecifyACultureInStringConversionExplicitly
            }

            #region Evaluate the c# expression dynamically

            try
            {
                object o = Eval(Expression);

                bool bizRuleSuccess;

                bool.TryParse(o.ToString(), out bizRuleSuccess);

                if(!bizRuleSuccess)
                {
                    _returnVal.Error = string.Format("Request Failed Business Rule '{0}'", sa.BizRule.Name);
                    return _returnVal;
                }
            }
            catch(InvalidExpressionException invalidExpressionEx)
            {
                bizRuleException = invalidExpressionEx;
            }
            catch(Exception ex)
            {
                bizRuleException = ex;
            }

            if(bizRuleException != null)
            {
                ExceptionHandling.WriteEventLogEntry(
                    Resources.DynamicService_EventLogTarget
                    , Resources.DynamicService_EventLogSource
                    // ReSharper disable PossibleNullReferenceException
                    , bizRuleException.ToString()
                    // ReSharper restore PossibleNullReferenceException
                    , EventLogEntryType.Error);

                _returnVal.Error = string.Format("Could not evaluate business rule expression {0}", Expression);
                _returnVal.ErrorDetail = bizRuleException.ToString();
                return _returnVal;
            }

            #endregion

            return result;
        }
Ejemplo n.º 4
0
        public dynamic Switch(ServiceAction serviceAction, dynamic xmlRequest, Guid dataListID)
        {
            dynamic result = new UnlimitedObject();

            DynamicService anonymousService = new DynamicService();
            if(!string.IsNullOrEmpty(serviceAction.Cases.DataElementValue))
            {
                List<ServiceAction> anonymousServiceActions;

                IEnumerable<ServiceActionCase> caseMatch =
                    serviceAction.Cases.Cases.Where(c => Regex.IsMatch(serviceAction.Cases.DataElementValue, c.Regex));
                // ReSharper disable ConvertIfStatementToConditionalTernaryExpression
                // ReSharper disable PossibleMultipleEnumeration
                if(caseMatch.Any())
                // ReSharper restore PossibleMultipleEnumeration
                // ReSharper restore ConvertIfStatementToConditionalTernaryExpression
                {
                // ReSharper disable PossibleMultipleEnumeration
                    anonymousServiceActions = caseMatch.First().Actions;
                // ReSharper restore PossibleMultipleEnumeration
                }
                else
                {
                    anonymousServiceActions = serviceAction.Cases.DefaultCase.Actions;
                }


                anonymousService.Name = string.Format("serviceOf{0}", serviceAction.Name);
                anonymousService.Actions = anonymousServiceActions;

                IDynamicServicesInvoker invoker = new DynamicServicesInvoker();
                ErrorResultTO errors;
                result = invoker.Invoke(anonymousService, xmlRequest, dataListID, out errors);
            }

            return result;
        }