I'm trying to create a module for a flex application, and I want to send notifications to clients. I've been looking at the BlazeDS messaging service to push out the notifications to clients, but I want to be able to send certain updates to certain clients. The Flex notification framework doesn't seem to allow this - if we have a field in the message with a value of the user's user id for example, any client could theoretically subscribe to all messages for any given user id, and there's no verification on the server side to make sure that the client that has subscribed is logged in as that user id.
Is there something I've missed here, or is the best way to handle this writing my own polling mechanism on the client side?
There is indeed a solution for this in the APIs. The first step is to write a class which extends the FlexClientOutboundQueueProcessor class. You need to override one method:
public void add(List outboundQueue, Message message);
Basically all you need to do is write some logic to determine whether you should make the following call:
outboundQueue.add(message)
Simply put, if you don't add the message to the queue, then the message won't be pushed to the client. The other important method in this class is:
FlexClient getFlexClient()
Which you can use to get the associated FlexSession and ultimately the authentication information that presumably exists in your app.
Once this is done, you just need to register the processor with the appropriate channels. Simply add this element within the "properties" element of the "channel-definition" element:
<flex-client-outbound-queue-processor class="com.foo.YourProcessor"/>
I believe you can also specify a nested "properties" element for the queue processor but I don't believe it's required.
You can use subtopics for this as long as you disable wildcard subscriptions.
Related
I know this question was already asked in a lot of ways and flavors, I wanted to add another way and a concrete example.
Basically I know the we should avoid synchronous communication, I was just wondering if there are some patterns to really avoid all of it. Let me give you a short example for a situation in which I wouldn't know how to make it asynchronous:
I have a service that is managing e.g. users, basically a DB that hast users saved and their configuration etc.
Now another service that is the API Gates provides the Endpoint to register the user. And this is the point where the communication becomes a problem: if the register endpoint is called we somehow have to call synchronously the user service because we e.g. need the userId of the newly create user. So this is a very abstract example and needing the userId might not be needed in a lot of cases, but in generell I am curious about this patter:
A services needs to call another service in order to create a new resource but needs some kind of data of the newly created resource either to return it to it's caller or create locally some kind of connection between it's entities and the other services entities.
Is there some pattern for this or is this just a place where synchronous communication needs to happen?
What you are describing is the Orchestration vs Choreography patterns:
In the Orchestration pattern a microservice invokes its dependencies directly, just like in your example, a microservice invokes another to register the user and then uses the userId from the response.
On the other hand, we can have the Choreography pattern where we use need a message queue system, e.g., Kafka, RabbitMq, to decouple the microservices. The same example would work as following:
Your User-Manager microservice will publish an event (command) of type RegisterUser to the message queue, containing the user information.
The API Gates subscribes to the events of type RegisterUser and whenever it gets an event of that type it will create the user normally.
Now, the API Gates must let everyone know that the user was created, so it will publish another event of type UserCreated containing the user information, e.g., the userId.
Finally, the User Manager must also subscribe the UserCreated events, so it can proceed with the flow.
With this approach the two microservices do not know each other, they are decoupled, and you can have any number of dependencies subscribing the events, i.e., you can add new dependencies without needing to change the code.
I am using SignalR for displaying onscreen notifications in my web application(built using Asp.net MVC).
My question is How to show notifications to specific set of users eg. Display onscreen notifications to all the users with reader role?. The roles and user associated with roles are defined the database.
I have read it in the documentation where it is mentioned about groups. But i am not sure how to use it.
As you said, one of the ways to go is by using SignalR Groups.
Basically, when you start the connection to the SignalR hub, you can also include that user in a group, based on the type of account (try not to include the user in a group based on a client function call, do it on the server).
So each time the user connects, you can override the OnConnected method and add a user on the appropriate group (in the Groups object are stored ConnectionId strings.
Note - if you are going to scale the application, you will also need to add a backplane for the following reason: the groups and the connection ids are store in the memory of the server. If your application is load balanced, then you have multiple independent instances of the same application, each one with different connections.
The way to go here is to use a SignalR Backplane.
Hope this helps!
Best of luck!
The SignalR server hub does not retain a list of groups so I assume that when I send out a broadcast message to a group it is sent to everyone connected to the hub and the clients filter out the message based on their participating groups. If I send a message to a specific group it seems that it is sent down the wire to everyone and can be intercepted by someone not in the specified group who knows how to use a browser debugger. If I want to have a secure broadcast (not even sent over the wire to some clients) I assume I need separate hubs or do I need separate sub domains?
Separate hubs do not sound like a good idea. While you probably can validate users on connect and refuse connections for non-authorized users what if you need a way to create isolated hubs dynamically. If however this functionality is enough for you you can use the Authorize attribute to secure either hubs or hub methods.
For cases where you do need to replicate the same functionality for different groups of users you can use SignalR groups but you need to verify that the user belongs to the group each time he connects. The SignalR documentation contains an example on how to do that verification. Note that everyone can try to connect to your groups and you should validate upon connection and not depend on the fact that you do not call the add method for a certain client.
SignalR only sends to the clients in the group. It's just a design issue that you can't retrieve a list of connections in a group. Groups, as pretty much everything else in SignalR, are subscription based, so the server knows which connections need to receive a message, but it's buried deep in the internals.
I would point you to the relevant server-side code, but don't have time to look it up right now.
It's easy to see in the client-side code though since it's not a lot of code - so you can verify there is no filtering going on there.
Groups also aren't separated per hub.
I just finished one SignalR sample, the well-known Chat sample.
This sample just broadcast a chat message from one client to all the clients. What if we want to send message to only a specific client?
(I guess there should be some ID to identify each client. These IDs should be stored on server when clients subscribe to the server. And server can choose which ID to push message to. )
You have different way to map your user with a connection. You can compare the different ways in this tutorial depending on your requirements.
Another solution is to define 1 group per userId and notify the group when you want to notify a user (link). Be careful, groups are not secured.
Like Daniel describes you can use a group or use the hubcontext to get the context for a specific connection using the connection Id.
var client = context.Clients.Client(connectionId);
There are also several libraries that abstract SignalR, some of these comes with their own way of calling specific users.
I have made a library like this which is based on the Event aggregation pattern. It comes with a API to let you create code that determines which clients should receive a specific event
https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/wiki/Implement-constraint-handlers
Here is also a blog post I made showing how you can achieve declarative role authorization with my library, maybe it can give you some ideas.
http://andersmalmgren.com/2014/06/12/client-server-event-aggregation-with-role-authorization/
I have a web application, where users will see notifications for their new messages, I want to push the notifications to the users who are already logged in.
I have seen that I can do it using Server Push of PokeIn, I have tried and understood the simple application using it, but I am not getting the ClientID thing.
The ClientId it saves in "OnClientConnected" is a simple integer, so how does it recognizes clients and calls functions on them ?
Also, it is written that it uses a hybrid long polling approach, can somebody please explain me what is this?
I will not be able to implement without having sufficient knowledge of it.
Does saving the ClientID in the database for logged in user and then pushing data using this will do ?
UPDATE:
Even from requests within the same
browser window or tab, the ClientId
received every time on every request
is different, so I had to include the
Handler in my master page and on every
request, I had to map the ClientId
received to the Logged In user, so
that I can send messages to him.
Can't I just map the (ClientId to
LoggedIn UserId) only once on LogIn
and then use that same ClientId to
send him messages ?
ClientID represents the identification key of the specific client view of your application and subject to change on each time.
It helps you to manage and target specific views by keys. On the other hand, you can still use ASP.NET session ids with PokeIn client ids.
The only difference is, if any user opens your application on the different tabs of same browser, each tab will have a unique client id. Actually, this is a great
functionality you may need. On the other hand, PokeIn also notifies you when a client is disconnected (almost instantly)..
You may reach session id by the client id;
CometWorker.GetSessionId(string ClientId)
or client ids for a session id by;
CometWorker.GetClientIdsBySessionId(string sessionId)
Additionally, if you don't want to use client id system (which is very useful), you may choose the "Joint" option. It helps you the send and receive messages from
the client with the name you have defined. (There is a sample for the "Joint" feature in here)
Because PokeIn provides various connection options, you don't have to think about the approach behind it when you work with PokeIn. It simply provides benefits
from the various solutions. More information can be accessible from : "FAQ" and "Advanced Tutorial" (http://www.pokein.com/Help/AdvancedTutorial.aspx)
At last, you don't have to save PokeIn client id to the database. PokeIn manages your server side objects per each client efficiently.
I suggest you to check the samples and tutorials.
As an answer for your update, you are free to use Joint feature of PokeIn when you need shared server side instances for the clients or consistent naming for the clients.