I try to write a client that receives events from several event sources. At programming time I do not know how many instances of the event source there will be. So I have to know for example the device endpoint reference to identify the event source. The way to distinguish between the sources like in the documentation example cannot be used I think. So I tried to use the following construct:
It works fine for a certain time (in the documentation example about 5 event receives or round about 10 seconds). But then I get the following null pointer exception (I'm using JMEDS beta 10.):
Notification event received from me (46)
[ERROR] null
java.lang.NullPointerException
at org.ws4d.java.DocuExampleEventClient.eventReceived(DocuExampleEventClient.java:248)
at org.ws4d.java.eventing.DefaultEventSink$EventSinkMessageListener.handle(Unknown Source)
at org.ws4d.java.communication.receiver.IncomingSOAPReceiver.receive(Unknown Source)
at org.ws4d.java.communication.protocol.soap.generator.DefaultSOAP2MessageGenerator.sendInvokeMessageToReceiver(Unknown Source)
at org.ws4d.java.communication.protocol.soap.generator.DefaultSOAP2MessageGenerator.deliverBody(Unknown Source)
at org.ws4d.java.communication.protocol.soap.generator.DefaultSOAP2MessageGenerator.deliverMessage(Unknown Source)
at org.ws4d.java.communication.protocol.soap.generator.DefaultSOAP2MessageGenerator.deliverMessage(Unknown Source)
at org.ws4d.java.communication.protocol.soap.server.SOAPServer$SOAPHandler.handle(Unknown Source)
at org.ws4d.java.communication.protocol.http.server.HTTPServer$HTTPConnectionHandler.handle(Unknown Source)
at org.ws4d.java.communication.connection.tcp.TCPListener$TCPConnectionThread.run(Unknown Source)
at org.ws4d.java.concurrency.ThreadPool$WorkerThread.run(Unknown Source)
As a minimum example the documentation example can be used with following lines inserted in the "eventReceived" method in the "if (subscription.equals(notificationSub))" block:
DeviceReferences that do not have at least one DeviceListener are automatically cleaned up by the framework after 20 seconds. If you want to keep the DeviceReferences which are created during service search you have to change the line “SearchManager.searchService(search, client, null);” to “SearchManager.searchService(search, client, client);”
Generally service searches generate much network traffic because the DPWS protocol does only support device searches. Thus the framework performs a service search as follows:
- searching for all available devices without any restriction
- get the metadata of all devices found
- check the metadata for the service types and propagate only the matching ones
From that point of view the example is not so good and we will change it with the next release in the following way:
publicclassDocuExampleEventServiceProvider{privatefinalstaticStringnamespace="http://www.mydemo.com/tutorial";finalstaticQNamedeviceQName=newQName("BasicDevice",namespace);/** * @param args */publicstaticvoidmain(String[]args){// mandatory: Starting the DPWS FrameworkJMEDSFramework.start(args);// first we need a deviceDefaultDevicedevice=newDefaultDevice(DPWSCommunicationManager.COMMUNICATION_MANAGER_ID);// and it needs a type to find it easilydevice.setPortTypes(newQNameSet(deviceQName));...
publicclassDocuExampleEventClientextendsDefaultClient{finalstaticStringnamespace="http://www.mydemo.com/tutorial";finalstaticQNameserviceQName=newQName("BasicServices",namespace);finalstaticQNamedeviceQName=newQName("BasicDevice",namespace);privateClientSubscriptionsolicitSub=null;privateClientSubscriptionnotificationSub=null;privateEventSourceeventSourceSolicitResponse=null;publicstaticvoidmain(String[]args){// mandatory starting of DPWS frameworkJMEDSFramework.start(args);DPWSProperties.getInstance().removeSupportedDPWSVersion(DPWSProtocolVersion.DPWS_VERSION_2006);// create clientDocuExampleEventClientclient=newDocuExampleEventClient();// search for event and subscribeSearchParametersearch=newSearchParameter();search.setDeviceTypes(newQNameSet(deviceQName),DPWSCommunicationManager.COMMUNICATION_MANAGER_ID);SearchManager.searchDevice(search,client,client);}publicvoiddeviceFound(DeviceReferencedevRef,SearchParametersearch,StringcomManId){Iteratoriter;try{iter=devRef.getDevice().getServiceReferences(newQNameSet(serviceQName),SecurityKey.EMPTY_KEY);}catch(CommunicationExceptione){e.printStackTrace();return;}while(iter.hasNext()){ServiceReferenceservRef=(ServiceReference)iter.next();try{// use this code to subscribe to the simple event{// get event sourceEventSourceeventSource=servRef.getService().getEventSource(serviceQName,"DocuExampleSimpleEvent",null,null);if(eventSource!=null){// add bindingDataStructurebindings=neworg.ws4d.java.structures.ArrayList();HTTPBindingbinding=newHTTPBinding(IPNetworkDetection.getInstance().getIPAddressOfAnyLocalInterface("127.0.0.1",false),10235,"/EventSink",DPWSCommunicationManager.COMMUNICATION_MANAGER_ID);bindings.add(binding);// subscribenotificationSub=eventSource.subscribe(this,0,bindings,CredentialInfo.EMPTY_CREDENTIAL_INFO);}}// use this code to subscribe to the solicit-response event{// get event sourceeventSourceSolicitResponse=servRef.getService().getEventSource(serviceQName,"DocuExampleComplexEvent",null,null);if(eventSourceSolicitResponse!=null){// add bindingDataStructurebindings=neworg.ws4d.java.structures.ArrayList();HTTPBindingbinding=newHTTPBinding(IPNetworkDetection.getInstance().getIPAddressOfAnyLocalInterface("127.0.0.1",false),7896,"/EventSink",DPWSCommunicationManager.COMMUNICATION_MANAGER_ID);bindings.add(binding);// subscribesolicitSub=eventSourceSolicitResponse.subscribe(this,0,bindings,CredentialInfo.EMPTY_CREDENTIAL_INFO);}}}catch(CommunicationExceptione){e.printStackTrace();}catch(InvocationExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}}}...
Best regards,
Ingo
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi everyone,
I try to write a client that receives events from several event sources. At programming time I do not know how many instances of the event source there will be. So I have to know for example the device endpoint reference to identify the event source. The way to distinguish between the sources like in the documentation example cannot be used I think. So I tried to use the following construct:
It works fine for a certain time (in the documentation example about 5 event receives or round about 10 seconds). But then I get the following null pointer exception (I'm using JMEDS beta 10.):
As a minimum example the documentation example can be used with following lines inserted in the "eventReceived" method in the "if (subscription.equals(notificationSub))" block:
Can anybody help me with this? Or / and is there a smarter way to get a reference to the device that fired the event in the eventReceived method?
Thanks and regards,
Martin
Hello Martin,
thank you for your bug report. We were able to reproduce the error and will look into it to fix it as soon as possible.
Best regards,
Chris
Hi Martin,
DeviceReferences that do not have at least one DeviceListener are automatically cleaned up by the framework after 20 seconds. If you want to keep the DeviceReferences which are created during service search you have to change the line “SearchManager.searchService(search, client, null);” to “SearchManager.searchService(search, client, client);”
Generally service searches generate much network traffic because the DPWS protocol does only support device searches. Thus the framework performs a service search as follows:
- searching for all available devices without any restriction
- get the metadata of all devices found
- check the metadata for the service types and propagate only the matching ones
From that point of view the example is not so good and we will change it with the next release in the following way:
Best regards,
Ingo