Now I am following this example to achieve the exact thing described.
What I want
Receive an event from a resource
Use timerFacility.setTimer method to sleep for a fixed 5 secs
After 5 secs pass, the service needs to send a message back to the resource (in on onTimerEvent)
Where the problem is
The above is achieved perfectly for event being fired one at a time, but when event is fired multiple times with interval less than 5, then onTimerEvent is invoked with the latest activity context for both the requests, the newer context somehow seems to overwrite the previous one)
SBB class
Declaration:
// //////////////////////////////////////////////////////////
// Null Activities declaration for the timer event
// ////////////////////////////////////////////////////////
private NullActivityContextInterfaceFactory nullACIFactory;
private NullActivityFactory nullActivityFactory;
setSbbContext method:
public void setSbbContext(SbbContext context) {
this.sbbContext = (SbbContextExt) context;
logger = this.sbbContext.getTracer(getClass().getName());
logger.info("TimerSbb context set");
// this.timerFacility = this.sbbContext.getTimerFacility();
try {
final Context myEnv = (Context) new InitialContext();
// slee facilities
this.timerFacility = (TimerFacility) myEnv.lookup(TimerFacility.JNDI_NAME);
this.nullACIFactory = (NullActivityContextInterfaceFactory) myEnv.lookup(NullActivityContextInterfaceFactory.JNDI_NAME);
this.nullActivityFactory = (NullActivityFactory) myEnv.lookup(NullActivityFactory.JNDI_NAME);
// // the sbb interface to interact with SIP resource adaptor
// this.sipProvider = (SleeSipProvider) myEnv.lookup("java:comp/env/slee/resources/jainsip/1.2/provider");
} catch (Exception e) {
logger.severe("Failed to set sbb context", e);
}
}
onTimerEvent:
public void onTimerEvent(javax.slee.facilities.TimerEvent event, ActivityContextInterface aci) {
this.logger.info("[" + this.getRefId() + "] new TimerEvent Fired");
// detaching so the null AC is claimed after the event handling
aci.detach(sbbContext.getSbbLocalObject());
this.logger.info("[" + this.getRefId() + "] context detatched");
try {
// // create child
//
// DataSourceChildSbbLocalInterface child = (DataSourceChildSbbLocalInterface) getLocationChildRelation().create();
//
// // request bindings of the message target
//
// child.getBindings(getSender().getURI().toString());
} catch (Exception e) {
logger.severe("failed to create sip registrar child sbb, to lookup the sender's contacts", e);
return;
}
}
on Message Event:
public void onTelnetMessageEvent(com.kalsym.event.MessageEvent event, ActivityContextInterface aci/* , EventContext eventContext */) {
try {
// ////////////////////////////////////////////////////////////////
this.logger.info("onTelnetMessageEvent");
String message = event.getMessage();
String refId = event.getRefId();
this.setRefId(message);
this.logger.info("[" + this.getRefId() + "] Received onTelnetMessageEvent with message: " + message);
int timerDurationInSecs = 5;
ActivityContextInterface timerACI = this.nullACIFactory.getActivityContextInterface(this.nullActivityFactory.createNullActivity());
timerACI.attach(this.sbbContext.getSbbLocalObject());
// Have tried all TimerPreserveMised options here
TimerPreserveMissed tpm = TimerPreserveMissed.LAST;
// Have tried new TimerOptions() as well
TimerOptions options = new TimerOptions(5000, tpm);
this.timerFacility.setTimer(timerACI, null, System.currentTimeMillis() + timerDurationInSecs * 1000, options);
// ////////////////////////////////////////////////////////////////
} catch (Exception exp) {
this.logger.severe("Error in recieving Telent Event", exp);
}
}
This is my sbb-jar:
<event event-direction="Receive" initial-event="False">
<event-name>TimerEvent</event-name>
<event-type-ref>
<event-type-name>javax.slee.facilities.TimerEvent</event-type-name>
<event-type-vendor>javax.slee</event-type-vendor>
<event-type-version>1.0</event-type-version>
</event-type-ref>
</event>
<event event-direction="Receive" initial-event="True">
<event-name>TelnetMessageEvent</event-name>
<event-type-ref>
<event-type-name>TelnetMessageEvent</event-type-name>
<event-type-vendor>kalsym</event-type-vendor>
<event-type-version>1.0</event-type-version>
</event-type-ref>
</event>
This is the output I am getting:
2017-09-06 16:14:17,734 INFO [javax.slee.SbbNotification[service=ServiceID[name=timer,vendor=trangec,version=1.0],sbb=SbbID[name=TimerSbb,vendor=trangec,version=1.0]].trangec.timer.TimerSbbImpl] (SLEE-EventRouterExecutor-0-thread-1) TimerSbb context set
2017-09-06 16:14:17,743 INFO [javax.slee.SbbNotification[service=ServiceID[name=timer,vendor=trangec,version=1.0],sbb=SbbID[name=TimerSbb,vendor=trangec,version=1.0]].trangec.timer.TimerSbbImpl] (SLEE-EventRouterExecutor-0-thread-1) onTelnetMessageEvent
2017-09-06 16:14:17,745 INFO [javax.slee.SbbNotification[service=ServiceID[name=timer,vendor=trangec,version=1.0],sbb=SbbID[name=TimerSbb,vendor=trangec,version=1.0]].trangec.timer.TimerSbbImpl] (SLEE-EventRouterExecutor-0-thread-1) [d] Received onTelnetMessageEvent with message: d
2017-09-06 16:14:19,396 INFO [javax.slee.SbbNotification[service=ServiceID[name=timer,vendor=trangec,version=1.0],sbb=SbbID[name=TimerSbb,vendor=trangec,version=1.0]].trangec.timer.TimerSbbImpl] (SLEE-EventRouterExecutor-2-thread-1) onTelnetMessageEvent
2017-09-06 16:14:19,396 INFO [javax.slee.SbbNotification[service=ServiceID[name=timer,vendor=trangec,version=1.0],sbb=SbbID[name=TimerSbb,vendor=trangec,version=1.0]].trangec.timer.TimerSbbImpl] (SLEE-EventRouterExecutor-2-thread-1) [f] Received onTelnetMessageEvent with message: f
2017-09-06 16:14:22,750 INFO [javax.slee.SbbNotification[service=ServiceID[name=timer,vendor=trangec,version=1.0],sbb=SbbID[name=TimerSbb,vendor=trangec,version=1.0]].trangec.timer.TimerSbbImpl] (SLEE-EventRouterExecutor-7-thread-1) [f] new TimerEvent Fired
2017-09-06 16:14:24,398 INFO [javax.slee.SbbNotification[service=ServiceID[name=timer,vendor=trangec,version=1.0],sbb=SbbID[name=TimerSbb,vendor=trangec,version=1.0]].trangec.timer.TimerSbbImpl] (SLEE-EventRouterExecutor-0-thread-1) [f] new TimerEvent Fired
The last two log lines should print respectively d and f instead of f and f, please suggest what am I doing wrong?
The log in onTimerEvent shows the message [f] both times because that's the last one you saved in the Ref id attribute:
this.setRefId(message);
You could use a map to associate the timer ID to the message received, and then retrieve it when processing the onTimerEvent.
Related
I'm trying to implement smpp solution using opensmpp. Messages are sent succefully but for delivery receipts, I get only for some submited message and the same delivery receipts came several times. Can someone help me please.
private void receiveSms() {
try {
if (session != null && session.isBound()) {
PDU pdu = session.receive(1500);
if (pdu instanceof DeliverSM) {
DeliverSM received = (DeliverSM) pdu;
if (received.getEsmClass() == 0) {
// new message
System.out.println("RECEIVE NEW MESSAGE " + received.debugString());
} else {
//delivry Repport
System.out.println("RECEIVE NEW DELIVERED REPORT: " + received.debugString());
}
}
}
...
I am not familliar with opensmpp, but note that the messageId in norm smpp34 is still NULL,
The messageId associated to SUBMIT_SM is in DELIVER_SM "receipted_message_id" field,
or in the short_message if the appendixB is used,
If the "receipted_message_id" field has always the same value, you should check about the SMSC configuration/code, the DELIVER_SM is generated there
Why is the concurrent dictionary not behaving like a concurrent dictionary?
[Route("aaa")]
[HttpPost]
public Outbound Post(Inbound inbound)
{
Outbound outbound = new Outbound();
TaskState taskState = new TaskState();
taskState.state = 0;
TaskState s;
bool rc = taskDictionary.TryGetValue(inbound.taskId, out s);
if (rc == false)
taskDictionary.GetOrAdd(inbound.taskId, taskState);
else
return null;
if (s != null)
return null;
rc = taskDictionary.TryGetValue(inbound.taskId, out s);
if (rc)
{
string m0 = String.Format("POST dictionary count is " + taskDictionary.Count);
_logger.Log(LogLevel.Error, m0);
}
else
return null;
_logger.Log(LogLevel.Error, "POST method is doing long running work.");
long Billion = 1000000000;
// work quantity 5 means about 26 seconds // 30 billion is 215 seconds
for (long i = 0; i < inbound.WorkQuantity * Billion; i++)
;
outbound.Message = "The server did some work.";
outbound.BigObject = Modify(inbound.BigObject);
_logger.Log(LogLevel.Error, "POST finished long running work and will soon remove from the dictionary.");
rc = taskDictionary.Remove(inbound.taskId, out s);
if (rc == false)
return null;
if (s == null)
return null;
_logger.Log(LogLevel.Error, "POST is returning the object.");
return outbound;
}
[Route("bbb")]
[HttpPost]
public TaskState PostState(TaskId taskId)
{
TaskState s;
if (taskDictionary.TryGetValue(taskId, out s))
{
_logger.Log(LogLevel.Error, "POSTSTATE, state is " + s.AsString());
return s;
}
else
{
_logger.Log(LogLevel.Error, "POSTSTATE, state not found, dictionary count is " + taskDictionary.Count);
return null;
}
}
TaskDictionary taskDictionary = new TaskDictionary();
class TaskDictionary : ConcurrentDictionary<TaskId, TaskState>
{
internal bool IncrementState(TaskId taskId)
{
TaskState s;
if (TryGetValue(taskId, out s))
{
s.Increment();
return true;
}
else
return false;
}
}
The logging output is...
12.207 +00:00 [Error] MyController: POST dictionary count is 1
12.322 +00:00 [Error] MyController: POST method is doing long running work.
14.361 +00:00 [Error] MyController: POSTSTATE, state not found, dictionary count is 0
40.452 +00:00 [Error] MyController: POST finished long running work and will soon remove from the dictionary.
40.569 +00:00 [Error] MyController: POST is returning the object.
Specifically the problem is that request for the state information does not work because the dictionary appears empty.
So, based on the logging output you are doing two post requests to generate the output that you show us.
The way you initialize the Concurrent Dictionary, is the reason why it returns null on the second request. And that has to do with how the app receives those requests. Each request to your app is independent of another request.
Simply put;
A user POST's to you app.
The requests goes through the middleware pipeline, and eventually it will end up at your controller. Now, here's the important part, the controller will be 'constructed' for this particular request. And it will live for the duration of the request. That's because the lifetime of a controller is scoped by default. So the next request, will construct a new controller and that means that the Dictionary is different from the first one.
So to overcome this scoped request problem, you create a service that contains the dictionary, register this as a singleton (meaning it will only be constructed once and then it's shared), and use dependency injection to use it in the controller.
I would like to set a breakpoint in an application before it starts to run, so that I can make sure the application does not pass the breakpoint on startup.
In order to set a breakpoint you need to do something like:
EventRequestManager reqMan = vm.eventRequestManager();
BreakpointRequest bpReq = reqMan.createBreakpointRequest(locationForBreakpoint);
bpReq.enable();
In order to get the Location for the breakpoint, you can do something like:
Method method = location.method();
List<Location> locations = method.locationsOfLine(55);
Location locationForBreakpoint = locations.get(0);
In order to get a Method you can do something like:
classType.concreteMethodByName(methodNname, String signature)
However in order to get that classType you seem to require an ObjectReference which seems to require a running JVM.
Is there any way to set the breakpoint before the application JVM runs, to be sure the breakpoint is not passed during application startup?
First of all start you target program using a LaunchingConnector to get back the target virtual machine.
VirtualMachineManager vmm = Bootstrap.virtualMachineManager();
LaunchingConnector lc = vmm.launchingConnectors().get(0);
// Equivalently, can call:
// LaunchingConnector lc = vmm.defaultConnector();
Map<String, Connector.Argument> env = lc.defaultArguments();
env.get("main").setValue("p.DebugDummy");
env.get("suspend").setValue("true");
env.get("home").setValue("C:/Program Files/Java/jdk1.7.0_51");
VirtualMachine vm = lc.launch(env);
(change environment values according to your needs,but remember to start target VM with suspended=true).
With this VM in you hand intercept a ClassPrepareEvent using a ClassPrepareRequest.
ClassPrepareRequest r = reqMan.createClassPrepareRequest();
r.addClassFilter("myclasses.SampleClass");
r.enable();
Create a ClassPrepareEvent handler
executor.execute(()-> {
try {
while(true)
{
EventQueue eventQueue = vm.eventQueue();
EventSet eventSet = eventQueue.remove();
EventIterator eventIterator = eventSet.eventIterator();
if (eventIterator.hasNext()) {
Event event = eventIterator.next();
if(event instanceof ClassPrepareEvent) {
ClassPrepareEvent evt = (ClassPrepareEvent) event;
ClassType classType = (ClassType) evt.referenceType();
List<Location> locations = referenceType.locationsOfLine(55);
Location locationForBreakpoint = locations.get(0);
vm.resume();
}
}
}
} catch (InterruptedException | AbsentInformationException | IncompatibleThreadStateException e) {
e.printStackTrace();
}
}
then resume target VM with a call to vm.resume() to run program.
I hope this solve your problem.
We have tried the approach suggested at:
https://msdn.microsoft.com/en-us/library/windows/hardware/dn312121(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/hardware/dn303343(v=vs.85).aspx
We are able to find out list of all the magneticDevices using below code snippet
var magneticDevices = await DeviceInformation.FindAllAsync(aqsFilter);
but we are not able to get HidDevice object from the below code. It is giving null.
HidDevice device = await HidDevice.FromIdAsync(magneticDevices[0].Id
We have also set device capabilities in the app manifest file like below.
<DeviceCapability Name="humaninterfacedevice">
<Device Id="vidpid:0ACD 0520">
<Function Type="usage:0001 0006"/>
</Device>
</DeviceCapability>
<DeviceCapability Name="usb">
<Device Id="vidpid:0ACD 0520">
<Function Type="winUsbId:4d1e55b2-f16f-11cf-88cb-001111000030"/>
</Device>
</DeviceCapability>
Code for the complete Function
private async Task<bool> HasCardReader()
{
bool hasCardReader = false;
ushort usagePage = 0x0001;
ushort usageId = 0x0006;
ushort vendorId = 0x0ACD;
ushort productId = 0x0520;
var aqsFilter = HidDevice.GetDeviceSelector(usagePage, usageId, vendorId, productId);
var magneticDevices = await DeviceInformation.FindAllAsync(aqsFilter);
try
{
if (magneticDevices != null && magneticDevices.Count > 0)
{
HidDevice device = await HidDevice.FromIdAsync(magneticDevices[0].Id, Windows.Storage.FileAccessMode.Read);
inputReportEventHandler = new TypedEventHandler<HidDevice, HidInputReportReceivedEventArgs>(this.OnInputReportEvent);
device.InputReportReceived += inputReportEventHandler;
var watcher = DeviceInformation.CreateWatcher(aqsFilter);
watcher.Added += WatcherAdded;
watcher.Removed += WatcherRemoved;
watcher.Start();
hasCardReader = true;
}
else
{
}
}
catch (Exception ex)
{
Logging.LoggingSessionScenario.LogMessageAsync(ex.Message, LoggingLevel.Error);
}
return hasCardReader;
}
There are several reasons for the null return value, but I don't think there is something wrong with your code, since you can find the device by calling FindAllAsync. I will suggest you to troubleshoot this issue using this official HIDDevice sample on GitHub.
I successfully connected to my external hid device with that sample by changing the vid & pid & usagepage & usageid to my device.
In EventHandlerForDevice.cs, find the function OpenDeviceAsync, and you will notice the following possible reasons when null is returned by FromIdAsync.
else
{
successfullyOpenedDevice = false;
notificationStatus = NotifyType.ErrorMessage;
var deviceAccessStatus = DeviceAccessInformation.CreateFromId(deviceInfo.Id).CurrentStatus;
if (deviceAccessStatus == DeviceAccessStatus.DeniedByUser)
{
notificationMessage = "Access to the device was blocked by the user : " + deviceInfo.Id;
}
else if (deviceAccessStatus == DeviceAccessStatus.DeniedBySystem)
{
// This status is most likely caused by app permissions (did not declare the device in the app's package.appxmanifest)
// This status does not cover the case where the device is already opened by another app.
notificationMessage = "Access to the device was blocked by the system : " + deviceInfo.Id;
}
else
{
// Most likely the device is opened by another app, but cannot be sure
notificationMessage = "Unknown error, possibly opened by another app : " + deviceInfo.Id;
}
}
Have a try with that sample(Scenario1) and change the ids in both appxmanifest and SampleConfiguration.cs(class Device). If you cannot see your device in the device list, that means the configuration is incorrect for your device.
I am trying to delete a certain handler from my handler pipeline, but I am having trouble doing it. When I list the handlers in the pipeline before and after, the handler that I tried to remove is still there. So what am I doing wrong here? Here is a code snippet. All of this is in the startup phase. You can see that last thing that I do is configure the pipeline factory. I am using Netty 3.6.1.final.
List<String> handlers = new ArrayList<String>();
// list handlers in the pipeline
try {
handlers = this.pipelineFactory.getPipeline().getNames();
for (int len = handlers.size(), i = 0; i < len; i++) {
String s = handlers.get(i);
System.out.println("Item " + i + " is " + s);
}
} catch( Exception e ) {}
try {
System.out.println("Remove hexdump");
this.pipelineFactory.getPipeline().remove("hexdump");
} catch( Exception e ) {
System.out.println("error = " + e.getMessage());
}
try {
handlers = this.pipelineFactory.getPipeline().getNames();
for (int len = handlers.size(), i = 0; i < len; i++) {
String s = handlers.get(i);
System.out.println("Item " + i + " is " + s);
}
} catch( Exception e ) {}
// Configure the pipeline factory.
this.bootstrap.setPipelineFactory(this.pipelineFactory);
Here is the output:
Item 0 is framer
Item 1 is hexdump
Item 2 is handler
Remove hexdump
Item 0 is framer
Item 1 is hexdump
Item 2 is handler
Not sure without checking out full code, but looks like pipelineFactor.getPipeline() will always create a new pipeline in your case. Since its a factory, it will be creating the handlers each time. Put in one more sysout for this.pipelineFactory.getPipeline() and if you are seeing 3 different object hashcodes then this is the root cause.
Solution could be pipeline = this.pipelineFactory.getPipeline(), and then using the pipeline for adding removing etc.
Also for the record, it seems wrong usage anyway, you should be getting the pipeline from the ChannelHandlerContext object either in a decode method or a messageReceived method of a handler.