For my project I have to use pubsub and cometD subscriber.
I use Oracle Weblogic application server for two applciations.
One of them publish some messages to pubsubs channels and the other one subscribe to channels to display the messages.
My pubsub server is on the weblogic application server too and configured with some xml files (weblogic.xml and weblogic-pubsub.xml).
Here is how my pubsub server is configured (weblogic-pubsub.xml):
<wlps:channel>
<wlps:channel-pattern>/gip/**</wlps:channel-pattern>
</wlps:channel>
<wlps:channel-constraint>
<wlps:channel-resource-collection>
<wlps:channel-resource-name>all-permissions</wlps:channel-resource-name>
<wlps:description>Grant all permissions for everything by everyone</wlps:description>
<wlps:channel-pattern>/gip/*</wlps:channel-pattern>
</wlps:channel-resource-collection>
</wlps:channel-constraint>
And it works well because my second application can susbscribe to channel with the cometD subscirber javascript API and dojo toolkit.
So now the subscription is done client side of my web application thanks to this Javascript API.
Here is how the subscription is done client side (Javascript API) with the dojo toolkit:
//Initialize Dojo (CometD) for pubsub events
dojo.require("dojo.io.script");
dojo.require("dojox.cometd");
dojo.require("dojox.cometd.callbackPollTransport");
dojo.addOnLoad(function ()
{
console.log("on load dojo");
dojox.cometd.init("/WebInterface/cometd", {
});
dojox.cometd.subscribe("/gip/**", onEvent);
initMap();
});
This client side implementation works well, the onEvent() function is well fired when messages reach the pubsub channel.
Now, I would like the subscription and the message handling are done server side. For this, I understood that CometD has also a client Java API allowing to subscribe to pubsub channel and to handle the messages.
But I have not succeeded to do that.
Here is now what I tried to do for the server side following the CometD 3 documentation (https://docs.cometd.org/current/reference/#_java_client) :
import com.vaadin.ui.CustomComponent;
import java.util.HashMap;
import java.util.Map;
import org.cometd.bayeux.Channel;
import org.cometd.bayeux.Message;
import org.cometd.bayeux.client.ClientSession;
import org.cometd.bayeux.client.ClientSessionChannel;
import org.cometd.client.BayeuxClient;
import org.cometd.client.transport.ClientTransport;
import org.cometd.client.transport.LongPollingTransport;
import org.eclipse.jetty.client.HttpClient;
public class WireServerCometD extends CustomComponent {
private static final String CHANNEL = "/gip";
private final ClientSessionChannel.MessageListener gipListener = new GIPListener();
public WireServerCometD() {
System.out.println("Wire CometD constructor");
setSizeFull();
setWidth(50, Unit.PERCENTAGE);
setHeight(300, Unit.PIXELS);
addStyleName("customBackground");
try {
// Create (and eventually set up) Jetty's HttpClient:
HttpClient httpClient = new HttpClient();
// Here set up Jetty's HttpClient, for example:
// Prepare the transport
Map<String, Object> options = new HashMap<String, Object>();
ClientTransport transport = new LongPollingTransport(options, httpClient);
// Create the BayeuxClient
ClientSession client = new BayeuxClient("http://localhost:8080/WebInterface/cometd", transport);
client.getChannel(CHANNEL).addListener(new ClientSessionChannel.MessageListener() {
public void onMessage(ClientSessionChannel channel, Message message) {
if (message.isSuccessful()) {
// Here handshake is successful
System.out.println("Handshake is successfull");
}
}
});
client.handshake();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static class GIPListener implements ClientSessionChannel.MessageListener {
public void onMessage(ClientSessionChannel channel, Message message) {
System.out.println("message received");
}
}
}
This is a Vaadin framework component, the channel subscription and message listener are done in the try block.
I have the following error at the code line HttpClient httpClient = new HttpClient(); :
SEVERE:
java.lang.IncompatibleClassChangeError: org/eclipse/jetty/client/HttpClient
And the onMessage function is never fired ...
Can you bring me some help please ?
Thank you,
First of all, I think WebLogic may ship a very old version of CometD, or a very customized one that does not match the official one from the CometD project.
The dojox.cometd.callbackPollTransport was not something that ever existed in the CometD project, it was probably a draft attempt when CometD was 0.x, or something that was not officially released, or something created by WebLogic.
Your chances to have an official CometD 3.x client work with the "CometD" shipped by WebLogic are very slim. I doubt they are compatible.
Furthermore, I don't think Vaadin will be able to translate the component you wrote above in JavaScript.
A while back, people wrote bindings for CometD in JavaScript, but those never entered officially the CometD project (lack of traction, see https://github.com/cometd/cometd/issues/63), so I am not sure in what state they are now.
The IncompatibleClassChangeError is probably due to the fact that you are using a JDK older than JDK 7, and CometD 3.x only works with JDK 7+.
I'm afraid you will have to rethink the whole system.
I would suggest to stick with the official CometD on the server (not the one shipped by WebLogic), and if you really have to use Vaadin/GWT have a look at how people wrote those bindings in the past, and perhaps replicate them if you can't use those libraries.
Once you have the Vaadin/GWT bindings in place, and the official CometD in the server, and JDK 7+, you should be good.
Related
I am new to React-Naive and trying to build an app that sends message through app using react-native-get-sms-android.
I am able to send and read SMS from inbox but there is no Event in the package to know if a new sms has been received.
Is there any Event or API in react native for this?
I think I will have to use polling to check if a new sms has arrived.
You can either create your own native module or use react-native-android-sms-listener to listen for the new messages similar to Whatsapp.
Manual Installation is provided in the docs
Usage
import SmsListener from 'react-native-android-sms-listener'
componentDidMount() {
this.subscription = SmsListener.addListener(message => {
console.info(message)
})
}
componentWillUnmount() {
this.subscription.remove()
}
where the contents are in the format
{
originatingAddress: string,
body: string
}
Also make sure that you need specific permissions to read SMS for android, check the permissions docs here
I just start create a live chat app with Twilio.
I have downloaded the twilio-csharp library from twilio.com/docs/csharp/install and started with a sample console application.
code example from Twilio:
// Download the twilio-csharp library from twilio.com/docs/csharp/install
using System;
using Twilio.IpMessaging;
class Example {
static void Main (string[] args) {
// Find your Account Sid and Auth Token at twilio.com/user/account
const string accountSid = "accountSid";
const string authToken = "authToken";
const string serviceSid = "serviceSid";
const string channelSid = "channelSid";
// List all Messages
var client = new IpMessagingClient(accountSid, authToken);
MessageResult result = client.ListMessages(serviceSid, channelSid);
Console.WriteLine(result);
}
}
But this code doesn't work in my case, I got always an errors "type or namespace could not be found".
I have these like reference:
I tried tutorial of IP Messaging , it works. But in the tutorial, they used Javascript SDK to initialize the IP messaging client
tc.accessManager = new Twilio.AccessManager(tokenResponse.token);
tc.messagingClient = new Twilio.IPMessaging.Client(tc.accessManager);
So I just don't understand how can I use this C# library to send an IP Messaging, or maybe I can just control my IP Messaging applications from the client side?
I unstand why I got this error.
I just follow the steps of installation on twilio-csharp library gitHub. But this project's README is only for SMS project. If we want to use Library for IpMessaging, we must also import another Library, Twilio.IpMessaging.
So What I got know like reference and the project IP Messaging works.
Hope this will help the others.
I am new in the area of websocket.
I can connect to websocket server using JavaScript using this code:
var webSocket = new WebSocket(url);
But for my application, I need to connect to the same server using c#. The code I am using is:
ClientWebSocket webSocket = null;
webSocket = new ClientWebSocket();
await webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
3rd line of the code results following error:
"Server returned status code 200 when status code 101 was expected"
After little bit of survey, I realised that somehow server can't switch http protocol to websocket protocol during connection process.
Am I doing anything stupid in my C# code or there is something going wrong with the server. I don't have any access to the server, as the url I am using is a third party one .
Could you please give me any suggestion regarding the issue?
TL; DR:
Use ReceiveAsync() in loop until Close frame is received or CancellationToken is canceled. That's how you get your messages. Sending is straightworward, just SendAsync(). Do not use CloseAsync() before CloseOutputAsync() - because you want to stop your receiving loop first. Otherwise - either the CloseAsync() would hang, or if you use CancellationToken to quit ReceiveAsync() - the CloseAsync() would throw.
I learned a lot from https://mcguirev10.com/2019/08/17/how-to-close-websocket-correctly.html .
Full answer:
Use Dotnet client, here, have an example cut out from my real life code, that illustrate how the handshaking is made. The most important thing most people don't understand about how the thing operates is that there is no magic event when a message is received. You create it yourself. How?
You just perform ReceiveAsync() in a loop that ends, when a special Close frame is received. So when you want to disconnect you have to tell the server you close with CloseOutputAsync, so it would reply with a similar Close frame to your client, so it would be able to end receiving.
My code example illustrates only the most basic, outer transmission mechanism. So you send and receive raw binary messages. At this point you cannot tell the specific server response is related to the specific request you've sent. You have to match them yourself after coding / decoding messages. Use any serialization tool for that, but many crypto currency markets use Protocol Buffers from Google. The name says it all ;)
For matching any unique random data can be used. You need tokens, in C# I use Guid class for that.
Then I use request / response matching to make request work without dependency on events. The SendRequest() methods awaits until matching response arrives, or... the connection is closed. Very handy and allows to make way more readable code than in event-based approach. Of course you can still invoke events on messages received, just make sure they are not matched to any requests that require response.
Oh, and for waiting in my async method I use SemaphoreSlim. Each request puts its own semaphore in a special dictionary, when I get the response, I find the entry by the response token, release the semaphore, dispose it, remove from the dictionary. Seems complicated, but it's actually pretty simple.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
namespace Example {
public class WsClient : IDisposable {
public int ReceiveBufferSize { get; set; } = 8192;
public async Task ConnectAsync(string url) {
if (WS != null) {
if (WS.State == WebSocketState.Open) return;
else WS.Dispose();
}
WS = new ClientWebSocket();
if (CTS != null) CTS.Dispose();
CTS = new CancellationTokenSource();
await WS.ConnectAsync(new Uri(url), CTS.Token);
await Task.Factory.StartNew(ReceiveLoop, CTS.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
public async Task DisconnectAsync() {
if (WS is null) return;
// TODO: requests cleanup code, sub-protocol dependent.
if (WS.State == WebSocketState.Open) {
CTS.CancelAfter(TimeSpan.FromSeconds(2));
await WS.CloseOutputAsync(WebSocketCloseStatus.Empty, "", CancellationToken.None);
await WS.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
}
WS.Dispose();
WS = null;
CTS.Dispose();
CTS = null;
}
private async Task ReceiveLoop() {
var loopToken = CTS.Token;
MemoryStream outputStream = null;
WebSocketReceiveResult receiveResult = null;
var buffer = new byte[ReceiveBufferSize];
try {
while (!loopToken.IsCancellationRequested) {
outputStream = new MemoryStream(ReceiveBufferSize);
do {
receiveResult = await WS.ReceiveAsync(buffer, CTS.Token);
if (receiveResult.MessageType != WebSocketMessageType.Close)
outputStream.Write(buffer, 0, receiveResult.Count);
}
while (!receiveResult.EndOfMessage);
if (receiveResult.MessageType == WebSocketMessageType.Close) break;
outputStream.Position = 0;
ResponseReceived(outputStream);
}
}
catch (TaskCanceledException) { }
finally {
outputStream?.Dispose();
}
}
private async Task<ResponseType> SendMessageAsync<RequestType>(RequestType message) {
// TODO: handle serializing requests and deserializing responses, handle matching responses to the requests.
}
private void ResponseReceived(Stream inputStream) {
// TODO: handle deserializing responses and matching them to the requests.
// IMPORTANT: DON'T FORGET TO DISPOSE THE inputStream!
}
public void Dispose() => DisconnectAsync().Wait();
private ClientWebSocket WS;
private CancellationTokenSource CTS;
}
}
BTW, why use other libraries than the .NET built in? I can't find any reason other than maybe poor documentation of the Microsoft's classes. Maybe - if for some really weird reason you would want to use modern WebSocket transport with an ancient .NET Framework ;)
Oh, and I haven't tested the example. It's taken from the tested code, but all inner protocol parts were removed to leave only the transport part.
Since WebsocketSharp is not .NET Core compatible I suggest using websocket-client instead.
Here's some sample code
static async Task Main(string[] args)
{
var url = new Uri("wss://echo.websocket.org");
var exitEvent = new ManualResetEvent(false);
using (var client = new WebsocketClient(url))
{
client.MessageReceived.Subscribe(msg => Console.WriteLine($"Message: {msg}"));
await client.Start();
await client.Send("Echo");
exitEvent.WaitOne();
}
Console.ReadLine();
}
Be sure to use ManualResetEvent. Otherwise it doesn't work.
If you connect with a WebSocket client and you get an HTTP 200 as response, means that probably you are connecting to the wrong place (host, path and/or port).
Basically, you are connecting to a normal HTTP endpoint that is not understanding your WebSocket requirement, and it is just returning the "OK" response (HTTP 200). Probably the WebSocket server runs in another port or path in the same server.
Check your URL.
Not quite sure what happened to WebSocketSharp nuget package, however I noticed that now WebSocket# is showing up as most relevant result in nuget repo. It took me some time before I realized that Connect() is now returning Task, hopefully this example will be useful to someone:
using System;
using System.Threading.Tasks;
using WebSocketSharp;
namespace Example
{
class Program
{
private static void Main(string[] args)
{
using (var ws = new WebSocket(url: "ws://localhost:1337", onMessage: OnMessage, onError: OnError))
{
ws.Connect().Wait();
ws.Send("Hey, Server!").Wait();
Console.ReadKey(true);
}
}
private static Task OnError(ErrorEventArgs errorEventArgs)
{
Console.Write("Error: {0}, Exception: {1}", errorEventArgs.Message, errorEventArgs.Exception);
return Task.FromResult(0);
}
private static Task OnMessage(MessageEventArgs messageEventArgs)
{
Console.Write("Message received: {0}", messageEventArgs.Text.ReadToEnd());
return Task.FromResult(0);
}
}
}
All the libraries mentioned above are Wrappers. The .Net Frameworks class doing this is System.Net.WebSockets.ClientWebSocket
Websocket URLs should start with ws:// or wss:// where the latter is secure websocket.
I have generated a UDID string on the client side of Android. I need to send this to the javascript side so that it could communicate to the database server (via php) in order to store this UDID.
Is there a way to do it either directly (by avoiding php) or otherwise?
** My Android application has a WebView
Post to http with params:
public void postData() {
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.yoursite.com/yourexample.php");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("UDID", "12345"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
}
}
for your server side maybe it would be useful to learn somethings about web api's. take a look at this 2 links to start from some place:
Creating a RESTful API with PHP
[GUIDE] Android Client-Server Communication (PHP-MYSQL REST API)
You should show what you have already done, take a look at this to make better - to the point- questions
If you want to store data in a database from an Android app, without having to learn a server-side language, the simplest soulution is to use a MBaaS (Mobile Backend as a service) like :
Firebase
Appback
If you want to have lower fees you could also host your own solution but this could get more complicated:
http://hood.ie/
http://firehose.io/
http://remotestorage.io/
http://socky.org/
http://sockethub.org/
http://deployd.com/
My personal preference is Hoodie.
You could also generate your own RESTful API using Node.js + Express with MongoDB :
Yeoman generator for RESTful API
I am new to WebSockets.
I have already made a simple server-client chat in WebSockets.
And now I am trying to make client-server-client chat application.
I have a question that in java server how can we send a message to particular WebSocket connection.
If user-A want to send a message to User-B.
Then how can I manage that User-B is using this or that connection or send a message to that particular connection?
I am searching too much for this on google but could not find anything good.
You have to design an architecture for that.
When a client establishes a connection with the server (opens the WebSocket), the server has to keep the connection somewhere (howsoever you're identifying a specific connection with the Java backend you're using), in a data structure that will depend on what you're trying to do. A good identifier would be an ID the user provides (like a nickname that's not already picked by another peer connected to the same server). Otherwise, simply use the socket object as a unique identifier and, when listing other users on the frontend, associate them with their unique identifier so that a client can send a message to a specific peer.
A HashMap would be a good choice for a data structure if a client is going to chat with another specific client, as you can map the unique ID of a client to the socket and find an entry with in O(1) in a hash table.
If you want to broadcast a message from a client to all other clients, although a HashMap would also work pretty well (with something like HashMap.values()), you may use a simple List, sending the incoming message to all connected clients except the original sender.
Of course, you also want to remove a client from the data structure when you lose connection with it, which is easy using a WebSocket (the Java framework you are using should call you back when a socket closes).
Here's an (almost complete) example using a Jetty 9 WebSocket (and JDK 7):
package so.example;
import java.io.IOException;
import java.util.HashMap;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
#WebSocket
public class MyWebSocket {
private final static HashMap<String, MyWebSocket> sockets = new HashMap<>();
private Session session;
private String myUniqueId;
private String getMyUniqueId() {
// unique ID from this class' hash code
return Integer.toHexString(this.hashCode());
}
#OnWebSocketConnect
public void onConnect(Session session) {
// save session so we can send
this.session = session;
// this unique ID
this.myUniqueId = this.getMyUniqueId();
// map this unique ID to this connection
MyWebSocket.sockets.put(this.myUniqueId, this);
// send its unique ID to the client (JSON)
this.sendClient(String.format("{\"msg\": \"uniqueId\", \"uniqueId\": \"%s\"}",
this.myUniqueId));
// broadcast this new connection (with its unique ID) to all other connected clients
for (MyWebSocket dstSocket : MyWebSocket.sockets.values()) {
if (dstSocket == this) {
// skip me
continue;
}
dstSocket.sendClient(String.format("{\"msg\": \"newClient\", \"newClientId\": \"%s\"}",
this.myUniqueId));
}
}
#OnWebSocketMessage
public void onMsg(String msg) {
/*
* process message here with whatever JSON library or protocol you like
* to get the destination unique ID from the client and the actual message
* to be sent (not shown). also, make sure to escape the message string
* for further JSON inclusion.
*/
String destUniqueId = ...;
String escapedMessage = ...;
// is the destination client connected?
if (!MyWebSocket.sockets.containsKey(destUniqueId)) {
this.sendError(String.format("destination client %s does not exist", destUniqueId));
return;
}
// send message to destination client
this.sendClient(String.format("{\"msg\": \"message\", \"destId\": \"%s\", \"message\": \"%s\"}",
destUniqueId, escapedMessage));
}
#OnWebSocketClose
public void onClose(Session session, int statusCode, String reason) {
if (MyWebSocket.sockets.containsKey(this.myUniqueId)) {
// remove connection
MyWebSocket.sockets.remove(this.myUniqueId);
// broadcast this lost connection to all other connected clients
for (MyWebSocket dstSocket : MyWebSocket.sockets.values()) {
if (dstSocket == this) {
// skip me
continue;
}
dstSocket.sendClient(String.format("{\"msg\": \"lostClient\", \"lostClientId\": \"%s\"}",
this.myUniqueId));
}
}
}
private void sendClient(String str) {
try {
this.session.getRemote().sendString(str);
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendError(String err) {
this.sendClient(String.format("{\"msg\": \"error\", \"error\": \"%s\"}", err));
}
}
The code is self explanatory. About JSON formatting and parsing, Jetty has some interesting utilities within package org.eclipse.jetty.util.ajax.
Also note that if your WebSocket server framework is not thread-safe, you will need to synchronize the data structure to make sure there's no data corruption (here MyWebSocket.sockets).