Vert.x SockJSHandler class - websocket

I'm trying to build a web socket application with Vert.x, and I have found plenty of examples using the SockJSHandler, to communicate with SockJS javascript library on the front end of the application.
The examples are using version 3.5.0 of Vert.x Core and Vert.x Web, and they create an instance of the class using the method SockJSHandler.create(vertx), bridging the SockJSHandler to the Vert.x event bus through the method SockJSHandler.bridge. This last method returns the type SockJSHandler, that gets routed with router.route("/eventbusroute/*").handler(sockJsHandler()).
I'm using the latest version of Vert.x Core and Vert.x Web, the 3.8.3, and in this release the method bridge returns an instance of type Router, as stated in the documentation.
My question is: what would be the best way to route the SockJSHandler Router instance to a particular route?

see e.g.
https://vertx.io/docs/vertx-web/java/
Router router = Router.router(vertx);
SockJSHandler sockJSHandler = SockJSHandler.create(vertx);
BridgeOptions options = new BridgeOptions();
// mount the bridge on the router
router.mountSubRouter("/eventbus", sockJSHandler.bridge(options));
vertx/examples/service/ProcessorServiceVerticle.java
Router router = Router.router(vertx);
// Allow events for the designated addresses in/out of the event bus bridge
BridgeOptions opts = new BridgeOptions()
.addInboundPermitted(new PermittedOptions().setAddress("vertx.processor"))
.addOutboundPermitted(new PermittedOptions().setAddress("vertx.processor"));
// Create the event bus bridge and add it to the router.
router.mountSubRouter("/eventbus", SockJSHandler.create(vertx).bridge(opts));
router.route().handler(StaticHandler.create());
Code which works for me:
Router router = Router.router(vertx);
BridgeOptions options = new BridgeOptions();
options.addOutboundPermitted(new PermittedOptions().setAddressRegex(".*"));
options.addInboundPermitted(new PermittedOptions().setAddressRegex(".*"));
SockJSHandler sockJSHandler = SockJSHandler.create(vertx);
router.mountSubRouter("/eventbus", sockJSHandler.bridge(options));

I've found the documentation I needed in version 3.8.2 deprecations documentation.
The correct way to handle the SockJSHandler.bridge return value is to include it as a subrouter.
So, instead of using the SockJSHandler implementation like the (pre Vert.x web 3.8.2 version):
EventBus eventBus = vertx.eventBus();
Handler<BridgeEvent> handler = ...;
SockJSHandler sockJSHandler = SockJSHandler.create(vertx).bridge(options, handler);
Router router = Router.router(vertx);
router.route("/eventbusroute/*").handler(sockJSHandler);
One must include the result of the bridge method call as a subRouter like this (Vert.x web version 3.8.2+):
EventBus eventBus = vertx.eventBus();
Handler<BridgeEvent> handler = ...;
Router sockJSSubRouter = SockJSHandler.create(vertx).bridge(options, handler);
Router router = Router.router(vertx);
router.mountSubRouter("/eventbusroute", sockJSSubRouter);

Related

Listener for NATS JetStream

Can some one help how to configure NATS jet stream subscription in spring boot asynchronously example: looking for an equivalent annotation like #kafkalistener for Nats jetstream
I am able to pull the messages using endpoint but however when tried to pull messages using pushSubscription dispatcherhandler is not invoked. Need to know how to make the listener to be active and consume messages immediately once the messages are published to the subject.
Any insights /examples regarding this will be helpful, thanks in advance.
I don't know what is your JetStream retention policy, neither the way you want to subscribe. But I have sample code for WorkQueuePolicy push subscription, wish this will help you.
public static void subscribe(String streamName, String subjectKey,
String queueName, IMessageHandler iMessageHandler) throws IOException,
InterruptedException, JetStreamApiException {
long s = System.currentTimeMillis();
Connection nc = Nats.connect(options);
long e = System.currentTimeMillis();
logger.info("Nats Connect in " + (e - s) + " ms");
JetStream js = nc.jetStream();
Dispatcher disp = nc.createDispatcher();
MessageHandler handler = (msg) -> {
try {
iMessageHandler.onMessageReceived(msg);
} catch (Exception exc) {
msg.nak();
}
};
ConsumerConfiguration cc = ConsumerConfiguration.builder()
.durable(queueName)
.deliverGroup(queueName)
.maxDeliver(3)
.ackWait(Duration.ofMinutes(2))
.build();
PushSubscribeOptions so = PushSubscribeOptions.builder()
.stream(streamName)
.configuration(cc)
.build();
js.subscribe(subjectKey, disp, handler, false, so);
System.out.println("NatsUtil: " + durableName + "subscribe");
}
IMessageHandler is my custom interface to handle nats.io received messages.
First, configure the NATS connection. Here you will specify all your connection details like server address(es), authentication options, connection-level callbacks etc.
Connection natsConnection = Nats.connect(
new Options.Builder()
.server("nats://localhost:4222")
.connectionListener((connection, eventType) -> {})
.errorListener(new ErrorListener(){})
.build());
Then construct a JetStream instance
JetStream jetStream = natsConnection.jetStream();
Now you can subscribe to subjects. Note that JetStream consumers can be durable or ephemeral, can work according to push or pull logic. Please refer to NATS documentation (https://docs.nats.io/nats-concepts/jetstream/consumers) to make the appropriate choice for your specific use case. The following example constructs a durable push consumer:
//Subscribe to a subject.
String subject = "my-subject";
//queues are analogous to Kafka consumer groups, i.e. consumers belonging
//to the same queue (or, better to say, reading the same queue) will get
//only one instance of each message from the corresponding subject
//and only one of those consumers will be chosen to process the message
String queueName = "my-queue";
//Choosing delivery policy is analogous to setting the current offset
//in a partition for a consumer or consumer group in Kafka.
DeliverPolicy deliverPolicy = DeliverPolicy.New;
PushSubscribeOptions subscribeOptions = ConsumerConfiguration.builder()
.durable(queueName)
.deliverGroup(queueName)
.deliverPolicy(deliverPolicy)
.buildPushSubscribeOptions();
Subscription subscription = jetStream.subscribe(
subject,
queueName,
natsConnection.createDispatcher(),
natsMessage -> {
//This callback will be called for incoming messages
//asynchronously. Every subscription configured this
//way will be backed by its own thread, that will be
//used to call this callback.
},
true, //true if you want received messages to be acknowledged
//automatically, otherwise you will have to call
//natsMessage.ack() manually in the above callback function
subscribeOptions);
As for the declarative API (i.e. some form of #NatsListener annotation analogous to #KafkaListener from Spring for Apache Kafka project), there is none available out of the box in Spring. If you feel like you absolutely need it, you can write one yourself, if you are familiar with Spring BeanPostProcessor-s or other extension mechanism that can help to do that. Alternatively you can refer to 3rd party libs, it looks like a bunch of people (including myself) felt a bit uncomfortable when switching from Kafka to NATS, so they tried to bring the usual way of doing things with them from the Kafka world. Some examples can be found on github:
https://github.com/linux-china/nats-spring-boot-starter,
https://github.com/dstrelec/nats
https://github.com/amalnev/declarative-nats-listeners
There may be others.

Embedded node-red in a feathersjs application get websocket error

I can embed node-red with a custom service with the following node-red.service.js :
// Initializes the `node-red` service on path `/red`
const { NodeRed } = require('./node-red.class');
const hooks = require('./node-red.hooks');
const RED = require("node-red");
module.exports = function (app) {
const paginate = app.get('paginate');
const options = {
paginate
};
// Create the node-red settings object
const settings = {
httpAdminRoot:"/red",
httpNodeRoot: "/red",
userDir: "./red",
functionGlobalContext: { } // enables global context
};
// Initialise the runtime with a server and settings
RED.init(app,settings);
// Serve the editor UI from /red
app.use('/red' , RED.httpAdmin );
RED.start()
};
If I go to localhost:3030/red I get the node-red page, but after few seconds it lost connection to server with the following error:
WebSocket connection to 'ws://localhost:3030/red/comms' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
I think there is a problem serving thru websocket or maybe since /red/comms is not defined in feathersjs it can't connect. Any idea?
Thank you
The issue comes with this line:
// Initialise the runtime with a server and settings
RED.init(app,settings);
As the comment says, you need to initialise the runtime with a server object. Here you are passing it an Express application, not a server.
It is not possible to mount websocket listeners on an express app - Node-RED needs access to the underlying HTTP Server object.
I am not familiar with what apis featherjs provides, but it does appear to allow you access to the http server object - for example by calling app.listen yourself - https://docs.feathersjs.com/api/express.html#app-listen-port

How to use socket.io in RestApplication of loopback 4?

I have created my rest application in Loopback 4 and now I want to implement socket in it. Is there any way to do so in RestApplication?
export class MyApplication extends BootMixin(
ServiceMixin(RepositoryMixin(RestApplication)),
) {
constructor(
options: ApplicationConfig = {}
) {
super(options);
}
....
async start() {
await super.start();
const io = socketio(this.restServer);
io.on('connection', (socket: any) => {
console.log('connected');
});
}
}
const io = socketio(this.restServer); isn't working for me
Here is a Official Loopback 4 example with socket.io integration. This example is created to explore how to expose Websocket (socket.io) endpoints in conjunction with LoopBack controllers.
https://github.com/raymondfeng/loopback4-example-websocket
I have created my rest application in Loopback 4 and now I want to implement socket in it.
What is your demand? After Customer A successfully calls a REST API, and the result of this call will be sent to the specified client via websocket?
You can created both rest server and websocket server at the same time in application.ts (how to creat websocket server). Then you can create Interceptor to send message via websocket after each controller method is called.

Red5 Websocket chat application support multiple chat rooms

Using Red5 and
https://github.com/Red5/red5-websocket-chat
I try to do a basic chat.
It works ok for a example channel
var socket = new WebSocket('ws://serverIP:80/chat', 'chat');
Is there any way to do something similar to chat rooms using Red5 Websocket chat?
An example I want to do from JavaScript is using URL:
var socketRoom1 = new WebSocket('ws://serverIP:80/chat/Room1', 'chat');
var socketRoom2 = new WebSocket('ws://serverIP:80/chat/Room2', 'chat');
...
var socketRoomN = new WebSocket('ws://serverIP:80/chat/RoomN', 'chat');
or using Protocol:
var socketRoom1 = new WebSocket('ws://serverIP:80/chat', 'Room1');
var socketRoom2 = new WebSocket('ws://serverIP:80/chat', 'Room2');
...
var socketRoomN = new WebSocket('ws://serverIP:80/chat', 'RoomN');
But I only can make it works in JavaScript with that:
var socket = new WebSocket('ws://serverIP:80/chat', 'chat');
Thanks for your time.
You are able to do this by integrating with the Red5 scopes and creating the new scopes as needed. Scopes are basically interchangeable with "rooms" or contexts. This endeavor will require that you learn at least at a basic level how the scopes work. You'll also need to modify / extend the listener to add/remove the scopes as needed and to route your messages.
https://github.com/Red5/red5-websocket-chat/blob/master/src/main/java/org/red5/demos/chat/WebSocketChatDataListener.java
Here's some additional reading regarding scopes / rooms:
http://ria101.wordpress.com/2010/03/09/red5-cabin-fever-advanced-scope-and-room-management/
http://gregoire.org/2009/04/07/on-demand-room-scope-creation/

Accessing particular service method from metro app?

i have a web services which i am accessing in my client application(metro app) , but i want to access a particular method inside those many methods i have how should i do it ,
as of now , i am doing it in this way to accessing the web services from my metro app:-
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
string responseBodyAsText;
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("http://182.134.34.99/OE/examplewebservices.svc");
response.EnsureSuccessStatusCode();
StatusText.Text = response.StatusCode.ToString();
responseBodyAsText = await response.Content.ReadAsStringAsync();
}
my requirement is :- there are many methods inside that examplewebservices , so i want to access one of the method inside that , pass input parameters to that method and get the result.
1)How to access one a particular method inside those many methods ( from metro app) ?
2)how to pass input to that service method (from metro app)?
Question might be very basic to you , pls help out. i am new to metro application development.
Thanks in advance.
The code you have does not call a service, it downloads service definition page. You will need to add a service reference to your project (right click on project node, choose Add Service Reference from context menu). Then you will be able to call methods of your service. In WinRT app, you will only be able to call web service asynchronously, so all methods will have 'Async' suffix and you will have to use async/await pattern when calling it.
To call an operation on the service you can use this pattern:
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("http://182.134.34.99/OE/examplewebservices.svc");
HttpResponseMessage response = await client.GetAsync("MyOperation");
...
}
To send values in this simplistic example you can send them as QueryStrings appended to the MyOperation string as follows: MyOperation?myvalue=1 etc.
Other than that #Seva Titov gave a good response to the dynamic aspect.

Resources