protected virtual void SubscribeToTopic(ISession session, string topicName, string clientName, string subscriptionQueueName = null, SubscriptionOptions options = null) { if (string.IsNullOrEmpty(subscriptionQueueName)) { subscriptionQueueName = $"{clientName}_{typeof(TContent)}"; } this.subscriptionQueueName = subscriptionQueueName; log.Debug("Subscribing to topic {0} on {1} endpoint named {2}", topicName, options.Durable ? "durable" : "non-durable", subscriptionQueueName); ITopicEndpoint endpoint = null; if (options.Durable) { endpoint = ContextFactory.Instance.CreateDurableTopicEndpointEx(subscriptionQueueName); session.Provision(endpoint, new EndpointProperties { DiscardBehavior = EndpointProperties.EndpointDiscardBehavior.NotifySenderOn, AccessType = options.Exclusive ? EndpointProperties.EndpointAccessType.Exclusive : EndpointProperties.EndpointAccessType.NonExclusive }, ProvisionFlag.WaitForConfirm | ProvisionFlag.IgnoreErrorIfEndpointAlreadyExists, null); } else { endpoint = session.CreateNonDurableTopicEndpoint(subscriptionQueueName); } try { this.flow = session.CreateFlow( new FlowProperties { AckMode = (options?.SubscriptionType ?? SubscriptionType.PeekAndLock) == SubscriptionType.PeekAndLock ? MessageAckMode.ClientAck : MessageAckMode.AutoAck }, endpoint, ContextFactory.Instance.CreateTopic(topicName), HandleMessage, FlowEventHandler); flow.Start(); this.workerThread = new Thread(new ThreadStart(RunMessageLoop)); workerThread.Start(); } catch (global::SolaceSystems.Solclient.Messaging.OperationErrorException ex) { log.Error($"Failed to subscribe to topic. ErrorInfo: {ex.ErrorInfo}"); throw; } }
/// <summary> /// @see IState#Handle . /// </summary> /// <param name="executor"></param> /// <returns></returns> public override FlowExecutionStatus Handle(IFlowExecutor executor) { ICollection <Task <FlowExecution> > tasks = new List <Task <FlowExecution> >(); foreach (IFlow flow in _flows) { IFlow aFlow = flow; Task <FlowExecution> task = new Task <FlowExecution>(() => aFlow.Start(executor)); tasks.Add(task); try { _taskExecutor.Execute(task); } catch (TaskRejectedException) { throw new FlowExecutionException("TaskExecutor rejected task for flow=" + flow.GetName()); } } ICollection <FlowExecution> results = tasks.Select(task => task.Result).ToList(); return(DoAggregation(results, executor)); }
/// <summary> /// @see IState#Handle . /// </summary> /// <param name="executor"></param> /// <returns></returns> public override FlowExecutionStatus Handle(IFlowExecutor executor) { return(_flow.Start(executor).Status); }
void Run(IContext context, string host) { // Validate parameters if (context == null) { throw new ArgumentException("Solace Systems API context Router must be not null.", "context"); } if (string.IsNullOrWhiteSpace(host)) { throw new ArgumentException("Solace Messaging Router host name must be non-empty.", "host"); } if (string.IsNullOrWhiteSpace(VPNName)) { throw new InvalidOperationException("VPN name must be non-empty."); } if (string.IsNullOrWhiteSpace(UserName)) { throw new InvalidOperationException("Client username must be non-empty."); } // Create session properties SessionProperties sessionProps = new SessionProperties() { Host = host, VPNName = VPNName, UserName = UserName, ReconnectRetries = DefaultReconnectRetries }; // Connect to the Solace messaging router Console.WriteLine("Connecting as {0}@{1} on {2}...", UserName, VPNName, host); Session = context.CreateSession(sessionProps, null, null); ReturnCode returnCode = Session.Connect(); if (returnCode == ReturnCode.SOLCLIENT_OK) { Console.WriteLine("Session successfully connected."); // Provision the queue string queueName = "Q/tutorial"; Console.WriteLine("Attempting to provision the queue '{0}'...", queueName); // Set queue permissions to "consume" and access-type to "exclusive" EndpointProperties endpointProps = new EndpointProperties() { Permission = EndpointProperties.EndpointPermission.Consume, AccessType = EndpointProperties.EndpointAccessType.Exclusive }; // Create the queue Queue = ContextFactory.Instance.CreateQueue(queueName); // Provision it, and do not fail if it already exists Session.Provision(Queue, endpointProps, ProvisionFlag.IgnoreErrorIfEndpointAlreadyExists & ProvisionFlag.WaitForConfirm, null); Console.WriteLine("Queue '{0}' has been created and provisioned.", queueName); // Create and start flow to the newly provisioned queue // NOTICE HandleMessageEvent as the message event handler // and HandleFlowEvent as the flow event handler Flow = Session.CreateFlow(new FlowProperties() { AckMode = MessageAckMode.ClientAck }, Queue, null, HandleMessageEvent, HandleFlowEvent); Flow.Start(); Console.WriteLine("Waiting for a message in the queue '{0}'...", queueName); WaitEventWaitHandle.WaitOne(); } else { Console.WriteLine("Error connecting, return code: {0}", returnCode); } }
private void SubscribeAndSendMessage(ISession session) { // Provision the queue string queueName = "Q/tutorial/topicToQueueMapping"; Console.WriteLine("Attempting to provision the queue '{0}'...", queueName); // Create the queue using (IQueue queue = ContextFactory.Instance.CreateQueue(queueName)) { // Set queue permissions to "consume" and access-type to "exclusive" EndpointProperties endpointProps = new EndpointProperties() { Permission = EndpointProperties.EndpointPermission.Consume, AccessType = EndpointProperties.EndpointAccessType.Exclusive, }; // Provision it, and do not fail if it already exists session.Provision(queue, endpointProps, ProvisionFlag.IgnoreErrorIfEndpointAlreadyExists | ProvisionFlag.WaitForConfirm, null); Console.WriteLine("Queue '{0}' has been created and provisioned.", queueName); // Add subscription to the topic mapped to the queue ITopic tutorialTopic = ContextFactory.Instance.CreateTopic("T/mapped/topic/sample"); session.Subscribe(queue, tutorialTopic, SubscribeFlag.WaitForConfirm, null); // Create the message using (IMessage message = ContextFactory.Instance.CreateMessage()) { // Message's destination is the queue topic and the message is persistent message.Destination = tutorialTopic; message.DeliveryMode = MessageDeliveryMode.Persistent; // Send it to the mapped topic a few times with different content for (int i = 0; i < TotalMessages; i++) { // Create the message content as a binary attachment message.BinaryAttachment = Encoding.ASCII.GetBytes( string.Format("Topic to Queue Mapping Tutorial! Message ID: {0}", i)); // Send the message to the queue on the Solace messaging router Console.WriteLine("Sending message ID {0} to topic '{1}' mapped to queue '{2}'...", i, tutorialTopic.Name, queueName); ReturnCode returnCode = session.Send(message); if (returnCode == ReturnCode.SOLCLIENT_OK) { Console.WriteLine("Done."); } else { Console.WriteLine("Sending failed, return code: {0}", returnCode); } } } Console.WriteLine("{0} messages sent. Processing replies.", TotalMessages); // Create and start flow to the newly provisioned queue // NOTICE HandleMessageEvent as the message event handler // and HandleFlowEvent as the flow event handler Flow = session.CreateFlow(new FlowProperties() { AckMode = MessageAckMode.ClientAck }, queue, null, HandleMessageEvent, HandleFlowEvent); Flow.Start(); // block the current thread until a confirmation received CountdownEvent.Wait(); } }
/// <summary> /// Main entry point to the sample /// </summary> /// <param name="args"></param> public override void SampleCall(string[] args) { // Parse command line arguments ArgParser cmdLineParser = new ArgParser(); if (!cmdLineParser.Parse(args) || !SampleParseArgs(cmdLineParser)) { // Parse failed. PrintUsage(INVALID_ARGUMENTS_ERROR); return; } // Create the API components: starting with the properties ContextProperties contextProps = new ContextProperties(); SessionProperties sessionProps = new SessionProperties(); sessionProps.Host = cmdLineParser.Config.IpPort.ip; sessionProps.UserName = cmdLineParser.Config.RouterUserVpn.user; sessionProps.Password = cmdLineParser.Config.UserPassword; sessionProps.SSLValidateCertificate = false; sessionProps.ReconnectRetries = 3; if (cmdLineParser.Config.RouterUserVpn.vpn != null) { sessionProps.VPNName = cmdLineParser.Config.RouterUserVpn.vpn; } if (cmdLineParser.Config.Compression) { /* Compression is set as a number from 0-9, where 0 means "disable * compression", and 9 means max compression. The default is no * compression. * Selecting a non-zero compression level auto-selects the * compressed SMF port on the appliance, as long as no SMF port is * explicitly specified. */ sessionProps.CompressionLevel = 9; } // Create and connect the API components: create the context and session objects IContext context = null; session = null; IFlow flow = null; IEndpoint provisionedEndpoint = null; try { // Creating the context InitContext(cmdLineParser.LogLevel); Console.WriteLine("Creating the context ..."); context = ContextFactory.Instance.CreateContext(contextProps, null); // Creating the session Console.WriteLine("Creating the session ..."); session = context.CreateSession(sessionProps, HandleRequestMessage, SampleUtils.HandleSessionEvent); // Connecting the session Console.WriteLine("Connecting the session ..."); if (session.Connect() == ReturnCode.SOLCLIENT_OK) { Console.WriteLine("Session successfully connected"); } // Provisioning the endpoint if (serviceTopic != null) { // Provision a Durable Topic Endpoint provisionedEndpoint = ContextFactory.Instance.CreateDurableTopicEndpointEx("cscsmp_sample_" + DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond); } else { provisionedEndpoint = serviceQueue; } session.Provision(provisionedEndpoint, new EndpointProperties(), ProvisionFlag.WaitForConfirm, null); Console.WriteLine(string.Format("Provisioned new endpoint '{0}'", provisionedEndpoint)); // Create and start flow to to the newly provisioned endpoint FlowProperties flowProperties = new FlowProperties(); flowProperties.AckMode = MessageAckMode.AutoAck; flow = session.CreateFlow(flowProperties, provisionedEndpoint, /* the newly created endpoint*/ serviceTopic, /* null if we're listening on a queue*/ HandleRequestMessage, /* local delegate to process request messages and send corresponding reply messages */ SampleUtils.HandleFlowEvent); flow.Start(); Console.WriteLine("Listening for request messages ... Press any key(except for Ctrl+C) to exit"); Console.In.Read(); } catch (Exception ex) { PrintException(ex); } finally { Cleanup(flow, provisionedEndpoint, session, context); } }
/// <summary> /// Main entry point to the sample /// </summary> /// <param name="args"></param> public override void SampleCall(string[] args) { // Parse command line arguments ArgParser cmdLineParser = new ArgParser(); if (!cmdLineParser.Parse(args) || !SampleParseArgs(cmdLineParser)) { // Parse failed. PrintUsage(INVALID_ARGUMENTS_ERROR); return; } // Create the API components: starting with the properties ContextProperties contextProps = new ContextProperties(); SessionProperties sessionProps = new SessionProperties(); sessionProps.Host = cmdLineParser.Config.IpPort.ip; sessionProps.UserName = cmdLineParser.Config.RouterUserVpn.user; sessionProps.Password = cmdLineParser.Config.UserPassword; sessionProps.SSLValidateCertificate = false; sessionProps.ReconnectRetries = 3; if (cmdLineParser.Config.RouterUserVpn.vpn != null) { sessionProps.VPNName = cmdLineParser.Config.RouterUserVpn.vpn; } if (cmdLineParser.Config.Compression) { /* Compression is set as a number from 0-9, where 0 means "disable * compression", and 9 means max compression. The default is no * compression. * Selecting a non-zero compression level auto-selects the * compressed SMF port on the appliance, as long as no SMF port is * explicitly specified. */ sessionProps.CompressionLevel = 9; } // Create and connect the API components: create the context, session and flow objects IContext context = null; try { // Creating the context InitContext(cmdLineParser.LogLevel); Console.WriteLine("Creating the context ..."); context = ContextFactory.Instance.CreateContext(contextProps, null); // Creating the session Console.WriteLine("Creating the session ..."); session = context.CreateSession(sessionProps, SampleUtils.HandleMessageEvent, SampleUtils.HandleSessionEvent); // Connecting the session Console.WriteLine("Connecting the session ..."); if (session.Connect() == ReturnCode.SOLCLIENT_OK) { Console.WriteLine("Session successfully connected"); } // Creating the temporary queue and corresponding flow IQueue replyToQueue = session.CreateTemporaryQueue(); FlowProperties flowProperties = new FlowProperties(); flow = session.CreateFlow(flowProperties, replyToQueue, null, /* null when binding to a queue*/ HandleReplyMessage, /* defined in this sample to handle receipt of reply message*/ SampleUtils.HandleFlowEvent); flow.Start(); doRequest(requestDestination, replyToQueue, Operation.PLUS, 5, 4); Thread.Sleep(1000); doRequest(requestDestination, replyToQueue, Operation.MINUS, 5, 4); Thread.Sleep(1000); doRequest(requestDestination, replyToQueue, Operation.TIMES, 5, 4); Thread.Sleep(1000); doRequest(requestDestination, replyToQueue, Operation.DIVIDE, 5, 4); } catch (Exception ex) { PrintException(ex); } finally { if (flow != null) { flow.Dispose(); } if (session != null) { session.Dispose(); } if (context != null) { context.Dispose(); } // Must cleanup after. CleanupContext(); } }
public override void SampleCall(string[] args) { // Parse arguments and initialize Session properties. ArgParser cmdLineParser = new ArgParser(); if (!cmdLineParser.Parse(args)) { // Parse failed. PrintUsage(INVALID_ARGUMENTS_ERROR); return; } // Create Session properties from the command line options. SessionProperties sessionProps = SampleUtils.NewSessionPropertiesFromConfig(cmdLineParser.Config); try { InitContext(cmdLineParser.LogLevel); // Create and connect 'sessionA' with No Local delivery set to false. sessionProps.NoLocal = false; // No Local is set to 'false' by default. InitializeAndAssertCapabilities(ref context, ref sessionA, "sessionA", sessionProps); // Create and connect 'sessionB' with No Local delivery set to true. sessionProps.NoLocal = true; // <-- this is how we set NoLocal at the session level InitializeAndAssertCapabilities(ref context, ref sessionB, "sessionB", sessionProps); // Create a Flow to a temporary Queue within sessionA. IQueue queue = sessionB.CreateTemporaryQueue(); FlowProperties flowProps = new FlowProperties(); flowProps.NoLocal = true; // <-- this is how we set NoLocal at the flow level flowProps.BindBlocking = true; flowA = sessionA.CreateFlow(flowProps, queue, null, HandleMessageEvent, SampleUtils.HandleFlowEvent); flowA.Start(); // Add a Topic subscription to sessionB. ITopic topic = ContextFactory.Instance.CreateTopic(SampleUtils.SAMPLE_TOPIC); sessionB.Subscribe(topic, true /*wait for confirm*/); // Publish a Direct message to Topic T from each Session; verify it is not delivered locally. IMessage msg = ContextFactory.Instance.CreateMessage(); msg.BinaryAttachment = Encoding.ASCII.GetBytes(SampleUtils.MSG_ATTACHMENTTEXT); msg.Destination = topic; msg.DeliveryMode = MessageDeliveryMode.Direct; // Send from 'sessionA'. Console.WriteLine(string.Format("\nSending a direct message to topic '{0}' from sessionA", topic.ToString())); sessionA.Send(msg); Thread.Sleep(500); PrintCounters(); Console.WriteLine(string.Format("Expecting msgCounterForSessionB to be 1, it's '{0}'", msgCounterForSessionB)); Console.WriteLine(string.Format("Expecting msgCounterForSessionA to be 0, it's '{0}'", msgCounterForSessionA)); ResetCounters(); // Send from 'sessionB'. Console.WriteLine(string.Format("\nSending a direct message to topic '{0}' from sessionB", topic.ToString())); sessionB.Send(msg); Thread.Sleep(500); PrintCounters(); Console.WriteLine(string.Format("Expecting msgCounterForSessionA to be 0, it's '{0}'", msgCounterForSessionA)); Console.WriteLine(string.Format("Expecting msgCounterForSessionB to be 0, it's '{0}'", msgCounterForSessionB)); ResetCounters(); // Publish a message to the Queue on each Session; verify it is not delivered locally. msg.Destination = queue; msg.DeliveryMode = MessageDeliveryMode.Persistent; // Send from 'sessionA'. Console.WriteLine(string.Format("\nSending a persistent message to queue '{0}' from sessionA", queue.ToString())); sessionA.Send(msg); Thread.Sleep(500); PrintCounters(); Console.WriteLine(string.Format("Expecting msgCounterForFlowA to be 0, it's '{0}'", msgCounterForFlowA)); ResetCounters(); // Send from 'sessionB'. Console.WriteLine(string.Format("\nSending a persistent message to queue '{0}' from sessionB", queue.ToString())); sessionB.Send(msg); Thread.Sleep(500); PrintCounters(); Console.WriteLine(string.Format("Expecting msgCounterForFlowA to be 1, it's '{0}'", msgCounterForFlowA)); ResetCounters(); Console.WriteLine("\nDone"); } catch (Exception ex) { PrintException(ex); } finally { if (flowA != null) { flowA.Dispose(); } if (sessionA != null) { sessionA.Dispose(); } if (context != null) { context.Dispose(); } // Must cleanup after. CleanupContext(); } }