markgoldin
It could have been explained before but I have to ask this again:
Is it possbile to send some data back to the server (data adapter) from the client page?
If yes, any samples available?
Thanks for help.
Alessandro Alinone
Hi Mark,
Currently you cannot talk directly to the Data Adapter from the client, but you can talk to the Metadata Adapter, through the
sendMessagemethod. The Metadata Adapter will receive a call to
notifyUserMessage . Then, the Metadata Adapter could talk to the Data Adapter.
Consider that for enterprise applications, you will probably have a cluster of Lightstreamer Servers and you may want to leverage a server-side middleware (e.g. JMS) to dispatch messages to all your Data Adapters. In this case, you will probably deliver messages from the client to a typical web server component (e.g. a servlet), which will publish the data to the messaging bus. And the Data Adapters will listen to this bus.
markgoldin
Does that require Java backend?
I am running .Net data Adapter though. Will it work then? If yes, could you please show some sample code?
Thanks
Dario Crivelli
The simple technique (i.e. sendMessage + notifyUserMessage + Metadata/Data Adapter communication) is also available with Remote .NET Data Adapters.
You should code your Metadata Adapter as a Remote .NET Adapter too ("NotifyUserMessage" is still provided by the .NET library interface).
Then you can have your Remote Metadata and Data Adapter talk to each other quite easily by loading them in the same Remote Server instance. This is shown in
DOCS-SDKs\sdk_adapter_dotnet; see chapter 1.6 in
doc\DotNet Adapters.pdf. The sample code shows loading both adapters, though communication between them is not covered.
The full technique (i.e. an intermediate servlet and a message bus) is entirely played outside Lightstreamer. We use it in the PortfolioDemo; see
http://www.lightstreamer.com/portfolioDemo.htm, where some raw code is available for the java case.
markgoldin
But isn't sendMessage a server side method?
How am I triggering it from the client (Browser)?
Thanks
Dario Crivelli
No, sorry for the confusion; I have now fixed my previous post.
sendMessage is provided by the Web Client Library as a method of the LightstreamerEngine object
http://www.lightstreamer.com/docs/client_web_jsdoc/LightstreamerEngine.html#sendMessage
A call to sendMessage by your client triggers, on the server side, the invocation of the notifyUserMessage method on your Metadata Adapter; this is supported both for java adapters and (as NotifyUserMessage) for remote .NET adapters.
markgoldin
How do I override notifyUserMessage to have my code there?
Also here is a fragment of my push page:
ls = "";
page.onEngineCreation = function(lsEngine) {
lsEngine.connection.setLSHost("UFD-SQL2008TEST.ufandd.local");
lsEngine.connection.setLSPort(8080);
lsEngine.context.setDebugAlertsOnClientError(debugAlerts);
lsEngine.context.setRemoteAlertsOnClientError(remoteAlerts);
lsEngine.connection.setAdapterName("PROXY_HELLOWORLD");
lsEngine.changeStatus("STREAMING");
ls = lsEngine;
}
page.bind();
page.createEngine("HelloWorldApp", "LS", "SHARE_SESSION");
var pushtable = new NonVisualTable(["floorupdate"], ["scan"], "MERGE");
page.addTable(pushtable, "hellotable");
pushtable.onItemUpdate =
function(itemPos, updateInfo, itemName)
{
// send completed scan to the front-end
if (updateInfo.getNewValue(itemPos) != "")
{
serverData(updateInfo.getNewValue(itemPos));
}
};
function sendMessage(message)
{
ls.sendMessage(message);
}
After fireing ls.sendMessage(message) LS console shows an error "unknown function" or something.
Am I too far from what I am looking for (sending message back to server)?
Thanks for your patience.
Mone
hi,
After fireing ls.sendMessage(message) LS console shows an error "unknown function" or something.
Am I too far from what I am looking for (sending message back to server)?
are you sure that you call the sendMessage method only once the ls object is initiated?
The error you're receiving tells you that the object does not have such method and this make sense because before being a LightstreamerEngine instance your ls variable contains a string
[syntax="JS"]ls = "";[/syntax]
for a quick check try to start with a null ls variable. The error message should change.
let me know if I'm wrong.
markgoldin
Ok, the exact message is:
<INFO> Refused Request: Session error: Unsupported function from ipxxxx : xxxxport
This is my function from the push page:
function sendMessage(message)
{
debugger;
ls.sendMessage(message);
}
and I am calling that function from Flex.
When it goes into debug the ls is the LS Engine object. So, that''s not a problem.
I think I need to do something on the server to make it work. Looks like it is the last piece of the puzzle to have my solution working.
Here is my .net code:
DataProviderServer server = new DataProviderServer();
server.Adapter = new SocketToLightStreamer();
MetadataProviderServer serverMeta = new MetadataProviderServer();
serverMeta.Adapter = new Lightstreamer.Adapters.Metadata.LiteralBasedProvider();
TcpClient reqrepSocket = new TcpClient(host, reqrepPort);
server.RequestStream = reqrepSocket.GetStream();
server.ReplyStream = reqrepSocket.GetStream();
TcpClient notifSocket = new TcpClient(host, notifPort);
server.NotifyStream = notifSocket.GetStream();
server.Start();
I am trying to understand what you are suggesting about both data adapter and meta data adapter working together but still not sure how to do that.
Thanks for your help.
Dario Crivelli
Ok, sorry, the error was server side, on the LS console.
The reported message is issued by the default Remote Metadata Adapter (i.e. the LiteralBasedProvider) upon a client message.
In fact, there is no default implementation for NotifyUserMessage.
You have to code a custom Remote Metadata Adapter and use it in place of the LiteralBasedProvider (you can, however, inherit from LiteralBasedProvider).
There, you can put your own implementation for NotifyUserMessage.
(I had to correct again some previous posts; in the .NET interface, the method name starts with a capital letter).
As said in a previous post, your Remote Metadata Adapter should then communicate with your Remote Data Adapter. The best way to achieve this is to run both adapters in the same process. There is no direct support for this, but the provided "StandaloneLauncher.cs" shows an example of a program doing this by leveraging the Lightstreamer.DotNet.Server interface.
Dario Crivelli
About Metadata Adapter and Data Adapter communication, this is no longer a problem,
as I see that you have already set up a Remote Server based on on the "StandaloneLauncher.cs" example.
This means that your code already creates an object of the custom class "SocketToLightStreamer" as the Data Adapter and,
as said in the previous post, it should create an object of some custom class (let's call it "MessageAwareLiteralBasedProvider") as the Metadata Adapter.
Then you just need to make the MessageAwareLiteralBasedProvider object, upon a NotifyUserMessage call, invoke some method on the SocketToLightStreamer object, so as to instruct the latter to send some update.
markgoldin
<it should create an object of some custom class (let's call <it "MessageAwareLiteralBasedProvider") as the Metadata Adapter.
You mean like this:
MetadataProviderServer MessageAwareLiteralBasedProvider = new MetadataProviderServer();
MessageAwareLiteralBasedProvider.Adapter = new Lightstreamer.Adapters.Metadata.LiteralBasedProvider();
If yes, then how do I override its NotifyUserMessage?
Dario Crivelli
No, in
let's call it "MessageAwareLiteralBasedProvider"
"it" referred to the class (by the way, is it bad english?);
I meant that you should create a class named MessageAwareLiteralBasedProvider and load it as:
MetadataProviderServer serverMeta = new MetadataProviderServer();
serverMeta.Adapter = new MessageAwareLiteralBasedProvider();
That class inherits from Lightstreamer.Adapters.Metadata.LiteralBasedProvider and, in addition, implements the NotifyUserMessage method.
markgoldin
Ok, while I was creating MessageAwareLiteralBasedProvider class:
using System;
using System.Collections;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Lightstreamer.Interfaces.Metadata;
public class MessageAwareLiteralBasedProvider : IMetadataProvider
{
public void NotifyUserMessage(string user, string session, string message)
{
}
}
I was forced to specify many more functions. Is that right?
Mone
hi,
yes it's correct because you are implementing the IMetadataProvider interface and so you have to implement all the methods declared in the interface
[syntax="CSHARP"]public class MessageAwareLiteralBasedProvider : IMetadataProvider
[/syntax]
maybe you want to write your class extending the LiteralBasedProvider so that you can re-implement just the NotifyUserMessage method
[syntax="CSHARP"]public class MessageAwareLiteralBasedProvider : LiteralBasedProvider
[/syntax]
HTH
markgoldin
Yes, I did that, compiler did not ask for other functions. But I haven't tested sending message yet.
This is the code from HelloWorld .Net adapter sample:
public void Run()
{
go = true;
int c = 0;
Random rand = new Random();
while (go)
{
IDictionary eventData = new Hashtable();
eventData["message"] = c % 2 == 0 ? "Hello" : "World";
eventData["timestamp"] = DateTime.Now.ToString("s");
_listener.Update("greetings", eventData, false);
c++;
Thread.Sleep(1000 + rand.Next(2000));
}
}
This while loop. Does LS need it or it just mimics a constant data feed?
Thanks
Mone
hi,
that code just publishes an update each 1000 + rand.Next(2000) milliseconds.
Lightstreamer doesn't need such loop, you should implement your own logic to send updates related to your feed
HTH