UCMA Generic QuestionAnswer activity - lync-2010

I am working on a UCMA 3.0 workflow application and am attempting to generate queries into our client management system allowing end users to obtain data about specific clients via voice or instant message. I was wondering anyone knows how to create a generic questionanswer activity using UCMA that allows generic input. I know that I can set up expected inputs and grammars, but with the bi-capitalization options, and the likelihood that an end user would know the exact client name (or client number for that matter), I would prefer to allow the user to enter part of the name and then search the database for a list of names that might meet the criteria. Does anyone know of a way, and have sample code that might allow me to do this if it is possible?

I had the same problem and had to write a custom activity to capture generic input from a user. This needs some work to make it production ready. Note the classy catching of system.exception in multiple places, as well as throwing an exception if input isn't received within the timeout period instead of reprompting the user. Also no regex on the user input...
The InstanceDependencyProperty is something else that was frustrating about Workflow. Without using InstanceDependencyProperties you won't be able to retrieve any results after the activity is completed.
Hope this helps!
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.Runtime;
using Microsoft.Rtc.Collaboration;
using Microsoft.Rtc.Workflow.Activities;
using Microsoft.Rtc.Workflow.Common;
namespace ActivityLibrary
{
public partial class CaptureIMInput : Activity, IInstanceDependencyContainer
{
#region Private member variables
private CallProvider _callProvider;
private Timer _maximumTimer;
private string _imText;
private bool messageReceived = false;
private bool _maximumTimerElapsed = false;
#endregion
public CaptureIMInput()
{
InitializeComponent();
_instanceDependencyProperties = new Dictionary<string, object>();
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
try
{
this._callProvider = Utilities.GetCallProviderFromParent<InstantMessagingCall>(this);
InstantMessagingCall call = (InstantMessagingCall)this._callProvider.Call;
try
{
if (call.State == CallState.Established)
{
call.Flow.EndSendInstantMessage(call.Flow.BeginSendInstantMessage(MainPrompt, null, null));
_maximumTimer = new Timer(new TimerCallback(OnMaximumTimerFired), null, MaximumPrompt, new TimeSpan(0, 0, 0, 0, -1));
call.Flow.MessageReceived += this.InstantMessagingFlow_MessageReceived;
while (!messageReceived)
{
if (_maximumTimerElapsed)
throw new TimeoutException("User input was not detected within alloted time");
}
if (!string.IsNullOrEmpty(_imText))
{
IMText = _imText;
{
this.Stop();
return ActivityExecutionStatus.Closed;
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
catch (Exception ex)
{
throw ex;
}
return ActivityExecutionStatus.Closed;
}
protected override ActivityExecutionStatus Cancel(ActivityExecutionContext executionContext)
{
this.Stop(); //Clean up timer
return ActivityExecutionStatus.Canceling;
}
private void Stop()
{
if (_maximumTimer != null)
{
_maximumTimer.Dispose();
_maximumTimer = null;
}
}
private void InstantMessagingFlow_MessageReceived(object sender, InstantMessageReceivedEventArgs e)
{
//Can't set dependencyproperties directly from sub-thread
_imText = e.TextBody;
//Mark bool so main while loop exits
messageReceived = true;
}
//Callback to
private void OnMaximumTimerFired(object state)
{
_maximumTimerElapsed = true;
}
#region InstanceDependency dictionary
private Dictionary<string, object> _instanceDependencyProperties;
[Browsable(false)]
public Dictionary<string, object> InstanceDependencyProperties
{
get { return _instanceDependencyProperties; }
}
#endregion
#region Maximum Prompt Timeout
[NonSerialized]
private static readonly InstanceDependencyProperty MaximumPromptProperty = InstanceDependencyProperty.Register("MaximumPrompt", typeof(TimeSpan), typeof(CaptureIMInput), new TimeSpan(0, 0, 30));
[TypeConverter(typeof(TimeSpanConverter))]
public TimeSpan MaximumPrompt
{
get
{
if (base.DesignMode)
return (TimeSpan)InstanceDependencyHelper.GetValue<CaptureIMInput>(this, MaximumPromptProperty);
else
return (TimeSpan)InstanceDependencyHelper.GetValue<CaptureIMInput>(this, this.WorkflowInstanceId, MaximumPromptProperty);
}
set
{
if (base.DesignMode)
InstanceDependencyHelper.SetValue<CaptureIMInput>(this, MaximumPromptProperty, value);
else
InstanceDependencyHelper.SetValue<CaptureIMInput>(this, this.WorkflowInstanceId, MaximumPromptProperty, value);
}
}
#endregion
#region MainPrompt
public static DependencyProperty MainPromptProperty =
DependencyProperty.Register("MainPrompt", typeof(string), typeof(CaptureIMInput));
[ValidationOption(ValidationOption.Required)]
public string MainPrompt
{
get
{
return (string)base.GetValue(MainPromptProperty);
}
set
{
base.SetValue(MainPromptProperty, value);
}
}
#endregion
#region Instant Message Text
public static InstanceDependencyProperty IMTextProperty =
InstanceDependencyProperty.Register("IMText",
typeof(string),
typeof(CaptureIMInput));
[Description("InstantMessaging Text from user")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string IMText
{
get
{
if (base.DesignMode) return ((string)InstanceDependencyHelper.GetValue<CaptureIMInput>(this, CaptureIMInput.IMTextProperty));
else return ((string)(InstanceDependencyHelper.GetValue<CaptureIMInput>(this, this.WorkflowInstanceId, CaptureIMInput.IMTextProperty)));
}
set
{
if (base.DesignMode) InstanceDependencyHelper.SetValue<CaptureIMInput>(this, CaptureIMInput.IMTextProperty, value);
else InstanceDependencyHelper.SetValue<CaptureIMInput>(this, this.WorkflowInstanceId, CaptureIMInput.IMTextProperty, value);
}
}
#endregion
}
}

Related

Read Events from EventHub in Unity3D and HoloLens

We are trying to show events from an Azure EventHub in our HoloLens application. When we run our project in Unity 3D, it works and paint the data from the events.
But when we deploy the same solution on the HoloLens, we don't receive events and also we don't receive any error.
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.UI;
using TMPro;
using System;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using Azure.Messaging.EventHubs;
using Azure.Messaging.EventHubs.Processor;
using Azure.Storage.Blobs;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.MixedReality.Toolkit.Examples.Demos
{
[AddComponentMenu("Scripts/MRTK/Examples/SliderLunarLander")]
public class Manager : MonoBehaviour
{
[SerializeField]
public Animator helice2;
public TextMeshPro textovelocidad;
public EventProcessorClient processor;
public BlobContainerClient storageClient;
private const string storageConnectionString = "XXXX";
private const string blobContainerName = "XXXX";
private const string eventHubsConnectionString = "XXXX";
private const string consumerGroup = "hololens";
private const string EventHubName = "XXXX";
private float? speedValue;
private string errorText = string.Empty;
private CancellationToken cancellationToken;
async void Start()
{
errorText = "Init EventReader...";
storageClient = new BlobContainerClient(storageConnectionString, blobContainerName);
var clientOptions = new EventProcessorClientOptions()
{
ConnectionOptions = new EventHubConnectionOptions ()
{
TransportType = EventHubsTransportType.AmqpWebSockets
}
};
processor = new EventProcessorClient
(
storageClient,
consumerGroup,
eventHubsConnectionString,
clientOptions
);
processor.ProcessEventAsync += processEventHandler;
processor.ProcessErrorAsync += processErrorHandler;
errorText = "Start EventReader...";
await processor.StartProcessingAsync();
try
{
//The processor performs its work in the background; block until cancellation
//to allow processing to take place.
errorText = "Infinite Loop...";
await Task.Delay(Timeout.Infinite);
}
catch (TaskCanceledException tcex)
{
//This is expected when the delay is canceled.
textoError.text = tcex.Message;
}
//Debug.Log("Device client initialited...");
}
public void OnSliderUpdated(SliderEventData eventData)
{
helice2.speed = eventData.NewValue;
}
async void OnDestroy()
{
try
{
await processor.StopProcessingAsync();
}
finally
{
//To prevent leaks, the handlers should be removed when processing is complete.
processor.ProcessEventAsync -= processEventHandler;
processor.ProcessErrorAsync -= processErrorHandler;
}
}
private void Update()
{
if (speedValue != null)
{
helice2.speed = float.Parse(speedValue.ToString());
}
textovelocidad.text = (helice2.speed).ToString("F2") + " r.p.m.";
textovelocidad.text += " | " + infoText;
textoError.text = errorText;
}
async Task processEventHandler(ProcessEventArgs eventArgs)
{
try
{
// Write the body of the event to the console window
//Console.WriteLine("\tRecevied event: {0}", Encoding.UTF8.GetString(eventArgs.Data.Body.ToArray()));
infoText = " Event Received ";
string json = Encoding.UTF8.GetString(eventArgs.Data.Body.ToArray());
var deviceTurbine = JsonSerializer.Deserialize<DeviceTurbine>(json);
if (deviceTurbine != null)
{
speedValue = deviceTurbine.speed;
}
// Update checkpoint in the blob storage so that the app receives only new events the next time it's run
await eventArgs.UpdateCheckpointAsync(eventArgs.CancellationToken);
}
catch (Exception ex)
{
// Handle the exception from handler code
// Debug.LogError(ex.Message);
errorText = ex.Message;
}
}
Task processErrorHandler(ProcessErrorEventArgs eventArgs)
{
try
{
// Write details about the error to the console window
//Console.WriteLine($"\tPartition '{ eventArgs.PartitionId}': an unhandled exception was encountered. This was not expected to happen.");
//Console.WriteLine(eventArgs.Exception.Message);
errorText = eventArgs.Exception.Message;
}
catch
{
// Handle the exception from handler code
errorText = eventArgs.Exception.Message;
}
return Task.CompletedTask;
}
}
class DeviceTurbine
{
private float _speed;
private DateTime _timestamp;
private string _deviceId;
public float speed
{
get; set;
}
public DateTime timestamp
{
get;set;
}
public string deviceId
{
get; set;
}
}
}

Polly Retry with RX Observable.Interval

I'm new to Polly and I'm trying to apply the Retry policy, so that I can have it manually handling the retry connection in case of IBMMQ connection issue.
Please, consider the following code:
public class ReconnectException : Exception
{
}
public class QueueMonitor : IObservable<Message>, IDisposable
{
private readonly MQQueue mqQueue;
private readonly MQQueueManager queueManager;
private readonly string queueName;
private IDisposable timer;
private readonly object lockObj = new object();
private bool isChecking;
private readonly TimeSpan checkingFrequency;
private readonly List<IObserver<Message>> observers;
private TimeSpan reconnectInterval;
private readonly IScheduler scheduler;
private readonly int maxReconnectCount;
private static readonly ILog Logger = LogProvider.For<AonQueueManager>();
private readonly Policy pollyPolicy;
public QueueMonitor(IConfiguration configuration, string queueName, IScheduler scheduler = null)
{
this.queueManager = QueueFactory.GetIstance(configuration);
this.queueName = queueName;
this.scheduler = scheduler ?? Scheduler.Default;
checkingFrequency = configuration.GetValue("checkingFrequency", new TimeSpan(0, 0, 5));
reconnectInterval = configuration.GetValue("reconnectInterval", new TimeSpan(0, 0, 5));
maxReconnectCount = configuration.GetValue("maxReconnectCount", 3);
observers = new List<IObserver<Message>>();
pollyPolicy = Policy.Handle<ReconnectException>().WaitAndRetry(maxReconnectCount, _ => TimeSpan.FromSeconds(2));
mqQueue = queueManager.AccessQueue(queueName,
MQC.MQOO_INPUT_AS_Q_DEF // open queue for input
+ MQC.MQOO_FAIL_IF_QUIESCING); // but not if MQM stopping
}
public void Start()
{
var x = pollyPolicy.ExecuteAndCapture(CreateTimer);
}
private void CreateTimer()
{
Logger.DebugFormat("Repeating timer started, checking frequency: {checkingFrequency}", checkingFrequency);
timer = Observable.Interval(checkingFrequency, scheduler).Subscribe(_ =>
{
lock (lockObj)
{
if (isChecking) return;
Logger.Log(LogLevel.Debug, () => "Listening on queues for new messages");
isChecking = true;
var mqMsg = new MQMessage();
var mqGetMsgOpts = new MQGetMessageOptions { WaitInterval = checkingFrequency.Milliseconds };
// 15 second limit for waiting
mqGetMsgOpts.Options |= MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING |
MQC.MQCNO_RECONNECT_Q_MGR | MQC.MQOO_INPUT_AS_Q_DEF;
try
{
mqQueue.Get(mqMsg, mqGetMsgOpts);
if (mqMsg.Format.CompareTo(MQC.MQFMT_STRING) == 0)
{
var text = mqMsg.ReadString(mqMsg.MessageLength);
Logger.Debug($"Message received : [{text}]");
Message message = new Message { Content = text };
foreach (var observer in observers)
observer.OnNext(message);
}
else
{
Logger.Warn("Non-text message");
}
}
catch (MQException ex)
{
if (ex.Message == MQC.MQRC_NO_MSG_AVAILABLE.ToString())
{
Logger.Trace("No messages available");
//nothing to do, emtpy queue
}
else if (ex.Message == MQC.MQRC_CONNECTION_BROKEN.ToString())
{
Logger.ErrorException("MQ Exception, trying to recconect", ex);
throw new ReconnectException();
}
}
finally
{
isChecking = false;
}
}
});
}
public IDisposable Subscribe(IObserver<Message> observer)
{
if (!observers.Contains(observer))
observers.Add(observer);
return new Unsubscriber(observers, observer);
}
public void Dispose()
{
((IDisposable)mqQueue)?.Dispose();
((IDisposable)queueManager)?.Dispose();
timer?.Dispose();
}
}
public class Unsubscriber : IDisposable
{
private readonly List<IObserver<Message>> observers;
private readonly IObserver<Message> observer;
public Unsubscriber(List<IObserver<Message>> observers, IObserver<Message> observer)
{
this.observers = observers;
this.observer = observer;
}
public void Dispose()
{
if (observer != null) observers.Remove(observer);
}
}
The problem I've is that when an exception is thrown inside the lamda ( throw new ReconnectException();), Polly doesn't catch it (and I understand why, since it's on another thread) and the application quits since it's on a different thread.
This code is a part of a library,so I don't know that if in every project the Global exceptions are correctly handed.
How do I get it "catched" by the Polly's code?
Thanks in advance
The code posted in the question applies the policy only to the act of creating the timer (the execution of CreateTimer()), not to the code executed by the timer (the lambda inside the .(Subscribe(_ => { }) call).
This is the same as the behaviour if the call to CreateTimer() was surrounded by a try { } catch { }. The catch would only cover the act of executing the CreateTimer() method, the creation of the timer.
For the Polly policy to govern exceptions thrown within the lambda, it needs to be applied within the lambda, to the relevant block/group of statements which are expected to throw the exception.
For example, you might code:
pollyPolicy.ExecuteAndCapture(() => mqQueue.Get(mqMsg, mqGetMsgOpts));
(with a policy configured to govern the particular MQException/s you want to handle).
Or you can apply the policy to a wider group of statements - just as with a try { } clause.
pollyPolicy.ExecuteAndCapture(() =>
{
// ...
mqQueue.Get(mqMsg, mqGetMsgOpts));
// ...
}

Migrating EJB 2.0 to EJB 3.x Web app forgets lower tier value

I'm currently trying to migrate an EAR Project
-The old Project-
EJB 2.0
Jboss 5.0.1
-New Project-
EJB 3.0
Wildfly 13.0.0Final
Its session beans which I have managed to create and I can call upon it. the logic in it self seems to work. The issues I'm having is one of the follow ups seems to forget what it was doing.
the current issue I'm seeing is the following:
In the Web application in an class we are creating an object of Another class which we then trigger its parent method. this parent method then calls upon a class with it self as an argument which then checks which type it is and then stars a session bean depending on what type. which then calls on the arguments function performExecute() in this function we call upon a Query and actually get the correct results, we then add the resultsets values to a private dto member. and then performExecute is done. and we are back at the web applications class and we then try to access the same dto member with a get function. this returns a nullpointer. I'm wondering if I've forgotten something in my session beans?
Old sessionbean:
public class TxNotSupportedCommandServerBean implements SessionBean {
SessionContext sessionContext;
public void ejbCreate() throws CreateException {}
public void ejbRemove() {
sessionContext = null;
}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(SessionContext sessionContext) {
this.sessionContext = sessionContext;
}
public void executeCommand(TargetableCommand cmd) throws CommandException {
try {
cmd.performExecute();
}
catch (CommandException ex) {
throw ex;
}
}
}
The new one:
#Stateless
#Remote
#TransactionManagement(value=TransactionManagementType.CONTAINER)
#TransactionAttribute(value=REQUIRED)
public class TxNotSupportedCmdServerBean implements TxNotSupportedCmdServerRemote{
/**
* Default constructor.
*/
public TxNotSupportedCmdServerBean() {
// TODO Auto-generated constructor stub
}
public void executeCommand(TargetableCommand cmd) throws CommandException {
try {
cmd.performExecute();
}
catch (CommandException ex) {
throw ex;
}
}
}
Both these are in the EJB.Jar
the interface is implemented in the EJBClient.jar
The old Interface:
public interface TxNotSupportedCommandServerLocal extends EJBLocalObject {
public void executeCommand(TargetableCommand cmd) throws CommandException;
}
The new Interface:
public interface TxNotSupportedCmdServerRemote {
public void executeCommand(TargetableCommand cmd) throws CommandException;
}
Now here come s the next set of files that is also in the EJBClient.jar
TargetableCommand:
public abstract class TargetableCommand implements Command {
private boolean constraintViolated;
protected RequestContext requestContext;
protected String dataSourceName;
public TargetableCommand(RequestContext requestContext, String dataSourceName) {
this.requestContext = requestContext;
this.dataSourceName = dataSourceName;
}
public TargetableCommand(RequestContext requestContext) {
this.requestContext = requestContext;
}
public TargetableCommand(String dataSourceName) {
this.dataSourceName = dataSourceName;
}
public TargetableCommand() {
}
public void setConstraintViolated(boolean constraintViolated) {
this.constraintViolated = constraintViolated;
}
public boolean isConstraintViolated() {
return constraintViolated;
}
public abstract void performExecute() throws CommandException;
public void execute() throws CommandException {
CommandTarget.executeCommand(this);
}
}
Command:
public interface Command extends Serializable {
public void execute() throws CommandException;
}
The commented code is the old session beans.
CommandTarget:
public class CommandTarget {
public CommandTarget() {
}
/**
* Exekverar ett kommando i rätt miljö, t.ex. med eller utan transaktionshantering
* #param cmd TargetableCommand Kommandot som ska utföras
* #throws CommandException
*/
public static void executeCommand(TargetableCommand cmd) throws CommandException {
Context context = null;
try {
ServiceLocator sl = ServiceLocator.getInstance();
// if (cmd instanceof TxRequired) {
// TxRequiredCommandServerLocalHome cmdSrvHome = (TxRequiredCommandServerLocalHome) sl.getEJBLocalHome("TxRequiredCommandServer");
// TxRequiredCommandServerLocal cmdSrv = cmdSrvHome.create();
// cmdSrv.executeCommand(cmd);
// }
// else if(cmd instanceof TxNotSupported) {
// TxNotSupportedCommandServerLocalHome cmdSrvHome = (TxNotSupportedCommandServerLocalHome) sl.getEJBLocalHome("TxNotSupportedCommandServer");
// TxNotSupportedCommandServerLocal cmdSrv = cmdSrvHome.create();
// cmdSrv.executeCommand(cmd);
// }
// else {
// throw new CommandException("Cannot instanciate command server");
// }
//
System.out.println("CT: Inside commandTarget. about to diffrientate what instance");
context = JNDILookupClass.getInitialContext();
if (cmd instanceof TxRequired) {
System.out.println("CT: TxRequired");
TxRequiredCmdServerRemote cmdSrv = (TxRequiredCmdServerRemote)context.lookup(JNDILookupClass.getLookupName("TxRequiredCmdServerRemoteBean", TxRequiredCmdServerRemote.class.getName()));
cmdSrv.executeCommand(cmd);
}
else if(cmd instanceof TxNotSupported) {
System.out.println("CT: TxNotSupported");
System.out.println("CT: cmd: " + cmd.getClass());
TxNotSupportedCmdServerRemote cmdSrv = (TxNotSupportedCmdServerRemote)context.lookup(JNDILookupClass.getLookupName("TxNotSupportedCmdServerBean", TxNotSupportedCmdServerRemote.class.getName()));
cmdSrv.executeCommand(cmd);
}
else {
throw new CommandException("Cannot instanciate command server");
}
}
catch (CommandException ex) {
throw ex;
}
// catch (CreateException ex) {
// throw new CommandException(ex);
// }
//new catch
catch(NamingException ex) {
throw new CommandException(ex);
}
catch (ServiceLocatorException ex) {
throw new CommandException(ex);
}
}
}
Phew ...
Ok now that's the important parts from EJBClient. now onwards to the Web.war
I'm only pasting the part that actually runs and were it returns a nullpoint
public class ActionIdentitetKonsultCommand implements Command {
private static Logger logger = Logger.getLogger(ActionIdentitetKonsultCommand.class);
public ActionIdentitetKonsultCommand() {
}
public String execute(RequestContext requestContext) throws CommandException {
GetPersonByPersnrEJBCommand personCmd;
logger.info("execute()");
try {
UserBean user = (UserBean) requestContext.getSession().getAttribute("user");
String kstnr = requestContext.getParameter("kstnr");
//Tilldela konsultuppgifter
personCmd = new GetPersonByPersnrEJBCommand();
personCmd.setPersnr(user.getPersnr());
System.out.println("AI: Before execute DTO " + personCmd.dto);
personCmd.execute();
System.out.println("AI: After execute DTO " + personCmd.dto);
logger.info("person hamtad med personnummer (EJB):");
logger.info(personCmd.getPerson().toString());
So the personCmd.getPerson().tostring() is what causes the nullpointer. GetPersonByPersnrEJBCommand():
public class GetPersonByPersnrEJBCommand extends TargetableCommand implements TxNotSupported {
public PersonDTO dto;
private long persnr;
public GetPersonByPersnrEJBCommand() {
}
public void setPersnr(long persnr) {
this.persnr = persnr;
}
public PersonDTO getPerson() {
return this.dto;
}
public void performExecute() throws CommandException {
try {
QueryPersonByPersnrCommand cmd = new QueryPersonByPersnrCommand();
cmd.setPersnr(persnr);
cmd.execute();
if(cmd.next()){
this.dto = new PersonDTO();
System.out.println("GP: inside PerformExecute DTO: " + dto);
dto.setPersnr(cmd.getPersnr());
dto.setEfternamn(cmd.getEfternamn());
dto.setFornamn(cmd.getFornamn());
dto.setEpostAdress(cmd.getEpostAdress());
dto.setKonsult((cmd.getKonsult() == 1));
dto.setAnsvarig((cmd.getAnsvarig() == 1));
System.out.println("GP: Inside Perform Execute DTO: " + dto);
}
}
catch (DataAccessCommandException ex) {
System.out.println("GetPersonByPersnrEJBCommand.performExecute misslyckades " + ex.getMessage());
throw new CommandException(ex);
}
}
}
So that's it; I don't understand why it forgets it. when we do sysouts inside the last class we see that both the dto and the cmd has data in them, but once the function ends and we are back in the class that called on this the data is empty.
I'm suspecting its something to do with my session beans, I'm missing an property or something. because this code works with the old beans in the old JBOSS server. Hopefully someone can help me and others can learn from this as well as me.
I managed to solve this issue. Since the scope of the project is to get this to work. Its not a beautiful solution and with more time rewriting this would have been better. so onwards to the solution:
We need to change in both the bean, targetableCommand, CommandTarget and in the GetPersonByPersnrEJBCommand
TargetableCommand - add method:
public TargetableCommand execute(TargetableCommand cmd) throws CommandException
{
return CommandTarget.executeCommand(cmd);
}
CommandTarget - We change the method executeCommand to return a TargetableCommand, and make sure that after the bean is done we return that cmd.
public static TargetableCommand executeCommand(TargetableCommand cmd) throws CommandException {
Context context = null;
try {
context = JNDILookupClass.getInitialContext();
if (cmd instanceof TxRequired) {
TxRequiredCmdServerRemote cmdSrv = (TxRequiredCmdServerRemote)context.lookup(JNDILookupClass.getLookupName("TxRequiredCmdServerRemoteBean", TxRequiredCmdServerRemote.class.getName()));
cmd = cmdSrv.executeCommand(cmd);
}
else if(cmd instanceof TxNotSupported) {
TxNotSupportedCmdServerRemote cmdSrv = (TxNotSupportedCmdServerRemote)context.lookup(JNDILookupClass.getLookupName("TxNotSupportedCmdServerBean", TxNotSupportedCmdServerRemote.class.getName()));
cmd = cmdSrv.executeCommand(cmd);
}
else {
throw new CommandException("Cannot instanciate command server");
}
}
catch (CommandException ex) {
throw ex;
}
catch(NamingException ex) {
throw new CommandException(ex);
}
}
return cmd;
}
The bean - cange the method Execute command to return Targetablecommand
public TargetableCommand executeCommand(TargetableCommand cmd) throws CommandException {
try {
cmd = cmd.performExecute();
}
catch (CommandException ex) {
throw ex;
}
return cmd;
}
Then lastly to get it all to work I had to create a new method in the classes that needed to do the perform execute so in the GetPersonByPersnrEJBCommand class i created the method wf13Layer(); wich is a just an extra step:
public void wf13Layer() throws CommandException
{
GetPersonByPersnrEJBCommand tmp;
try{
tmp = (GetPersonByPersnrEJBCommand) execute(this);
dto = tmp.getPerson();
} catch (Exception ex) {
throw new CommandException(ex);
}
}
This is what i did to make it work. as i said its not a beautiful solution but it works. IT seems to be a combination that once we cross between the projects the scope vanishes. and to obtain it futher we need to layer it like this. I really hope this helps someone at some point since theres till alot of old code running around out there.
Kind regards
VeryTired

Instance-Specific EventHandler to provide data visibility beyond the Class-Level

May I ask for help with the following?
I am attempting to connect and control three pieces of household electronic equipment by computer through a GlobalCache GC-100 and iTach. As you will see in the following code, I created a class ("GlobalCacheAdapter") that can communicate and control the equipment, and created an instance of the class for each piece of equipment. Although each instance seems to work well with communicating and in controlling each piece of equipment, the *feedback returned from the equipment* seems only to be visible at the defining class level's - "ReaderThreadProc" procedure. Further processing of the feedback is required for each piece of equipment and I am uncertain as to how to forward this feedback at the equipment specific instance-level. I suspect that an instance-specific EventHandler will need to be implemented; however I am not aware as to how to implement this type of instance-specific EventHandler in order to complete processing and update the appropriate controls.
Any help wold be greatly appreciated.
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
// Create three new instances of GlobalCacheAdaptor and connect.
// GC-100 (Elan) 192.168.1.70 4998
// GC-100 (TuneSuite) 192.168.1.70 5000
// GC iTach (Lighting) 192.168.1.71 4999
private GlobalCacheAdaptor elanGlobalCacheAdaptor;
private GlobalCacheAdaptor tuneSuiteGlobalCacheAdaptor;
private GlobalCacheAdaptor lutronGlobalCacheAdaptor;
public Form1()
{
InitializeComponent();
elanGlobalCacheAdaptor = new GlobalCacheAdaptor();
elanGlobalCacheAdaptor.ConnectToDevice(IPAddress.Parse("192.168.1.70"), 4998);
tuneSuiteGlobalCacheAdaptor = new GlobalCacheAdaptor();
tuneSuiteGlobalCacheAdaptor.ConnectToDevice(IPAddress.Parse("192.168.1.70"), 5000);
lutronGlobalCacheAdaptor = new GlobalCacheAdaptor();
lutronGlobalCacheAdaptor.ConnectToDevice(IPAddress.Parse("192.168.1.71"), 4999);
elanTextBox.Text = elanGlobalCacheAdaptor._line;
tuneSuiteTextBox.Text = tuneSuiteGlobalCacheAdaptor._line;
lutronTextBox.Text = lutronGlobalCacheAdaptor._line;
}
private void btnZoneOnOff_Click(object sender, EventArgs e) { elanGlobalCacheAdaptor.SendMessage("sendir,4:3,1,40000,4,1,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,181,21,800" + Environment.NewLine); }
private void btnSourceInput1_Click(object sender, EventArgs e) { elanGlobalCacheAdaptor.SendMessage("sendir,4:3,1,40000,1,1,20,179,20,179,20,179,20,179,20,179,20,179,20,179,20,278,20,179,20,179,20,179,20,780" + Environment.NewLine); }
private void btnSystemOff_Click(object sender, EventArgs e) { elanGlobalCacheAdaptor.SendMessage("sendir,4:3,1,40000,1,1,20,184,20,184,20,184,20,184,20,184,20,286,20,286,20,286,20,184,20,184,20,184,20,820" + Environment.NewLine); }
private void btnLightOff_Click(object sender, EventArgs e) { lutronGlobalCacheAdaptor.SendMessage("sdl,14,0,0,S2\x0d"); }
private void btnLightOn_Click(object sender, EventArgs e) { lutronGlobalCacheAdaptor.SendMessage("sdl,14,100,0,S2\x0d"); }
private void btnChannel31_Click(object sender, EventArgs e) { tuneSuiteGlobalCacheAdaptor.SendMessage("\xB8\x4D\xB5\x33\x31\x00\x30\x21\xB8\x0D"); }
private void btnChannel30_Click(object sender, EventArgs e) { tuneSuiteGlobalCacheAdaptor.SendMessage("\xB8\x4D\xB5\x33\x30\x00\x30\x21\xB8\x0D"); }
}
}
public class GlobalCacheAdaptor
{
public Socket _multicastListener;
public string _preferredDeviceID;
public IPAddress _deviceAddress;
public Socket _deviceSocket;
public StreamWriter _deviceWriter;
public bool _isConnected;
public int _port;
public IPAddress _address;
public string _line;
public GlobalCacheAdaptor() { }
public static readonly GlobalCacheAdaptor Instance = new GlobalCacheAdaptor();
public bool IsListening { get { return _multicastListener != null; } }
public GlobalCacheAdaptor ConnectToDevice(IPAddress address, int port)
{
if (_deviceSocket != null) _deviceSocket.Close();
try
{
_port = port;
_address = address;
_deviceSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_deviceSocket.Connect(new IPEndPoint(address, port)); ;
_deviceAddress = address;
var stream = new NetworkStream(_deviceSocket);
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream) { NewLine = "\r", AutoFlush = true };
_deviceWriter = writer;
writer.WriteLine("getdevices");
var readerThread = new Thread(ReaderThreadProc) { IsBackground = true };
readerThread.Start(reader);
_isConnected = true;
return Instance;
}
catch { DisconnectFromDevice(); MessageBox.Show("ConnectToDevice Error."); throw; }
}
public void SendMessage(string message)
{
try
{
var stream = new NetworkStream(_deviceSocket);
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream) { NewLine = "\r", AutoFlush = true };
_deviceWriter = writer;
writer.WriteLine(message);
var readerThread = new Thread(ReaderThreadProc) { IsBackground = true };
readerThread.Start(reader);
}
catch { MessageBox.Show("SendMessage() Error."); }
}
public void DisconnectFromDevice()
{
if (_deviceSocket != null)
{
try { _deviceSocket.Close(); _isConnected = false; }
catch { MessageBox.Show("DisconnectFromDevice Error."); }
_deviceSocket = null;
}
_deviceWriter = null;
_deviceAddress = null;
}
**private void ReaderThreadProc(object state)**
{
var reader = (StreamReader)state;
try
{
while (true)
{
var line = reader.ReadLine();
if (line == null) break;
_line = _line + line + Environment.NewLine;
}
**// Feedback from each piece of equipment is visible here.
// Need to create EventHandler to notify the TextBoxes to update with _line**
}
catch { MessageBox.Show("ReaderThreadProc Error."); }
}
}
From my understanding of the question, you want to do something like this?
You need to know when a GlobalCacheAdapter updates and which one updated in order to update textboxes on a form. My question to you is this - do you actually need to know which updated?
If you declare in your class an event handler like this:
public class GlobalCacheAdaptor
{
public event EventHandler<EventArgs> Updated;
protected virtual void OnUpdated()
{
var handler = Updated;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
private void Foo()
{
// When an update is received, raise Updated event
OnUpdated();
}
}
Then in your form subscribe to Updated for all three GlobalCacheHandler instances
public Form1()
{
elanGlobalCacheAdaptor.Updated += (s,e) =>
{
elanTextBox.Text = elanGlobalCacheAdaptor._line;
}
tuneSuiteGlobalCacheAdaptor.Updated += (s,e) =>
{
tuneSuiteTextBox.Text = tuneSuiteGlobalCacheAdaptor._line;
}
lutronGlobalCacheAdaptor.Updated += (s,e) =>
{
lutronTextBox.Text = lutronGlobalCacheAdaptor._line;
}
}
You should be able to update the correct text box when the appropriate cache handler raises the Updated event.
Finally you may need to handle cross-thread interactions. if so, see this article on MSDN, particularly the part "Thread-Safe Calls to a Windows Forms Control"

Implemention Class proposal mechanism in SWT field

i know how to implement it,using field assist and search pattern, but the mechanism each time triggers a new search. I am not sure, how the mechanism is implemented in Open Type for example ( i think with indexes). How to use this cache to make in time classpath search
This almost my entire solution. Each time a call createProposalData
private TreeSet<String> data;
private SearchParticipant[] participants = new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() };
private SearchPattern pattern;
private IJavaProject prj;
private JavaSearchScope scope;
private SearchEngine searchEngine = new SearchEngine();
private SearchRequestor requestor = new SearchRequestor() {
#Override
public void acceptSearchMatch(SearchMatch match) throws CoreException {
String text = getText(match.getElement());
if (text != null) {
data.add(text);
}
}
public String getText(Object element) {
...
}
};
public ProposalEngine(IJavaProject prj) {
super();
this.prj = prj;
scope = new JavaSearchScope();
try {
scope.add(prj);
} catch (JavaModelException e) {
//
}
}
public Collection<String> createProposalData(final String patternText) {
data = new TreeSet<String>();
try {
pattern = getPatternForSeach(patternText);
searchEngine.search(pattern, participants, scope, requestor, null);
} catch (Exception e) {
// skip
}
return data;
}
protected SearchPattern getPatternForSeach(String patternText) {
return SearchPattern.createPattern(patternText,
IJavaSearchConstants.CLASS_AND_INTERFACE,
IJavaSearchConstants.DECLARATIONS,
SearchPattern.R_CAMELCASE_MATCH);
}
I believe that you are doing exactly what the Open Type dialog is doing. Indexing to speed up search happens underneath JDT API.