Creating SockJS server with Java - java

I'm very new with Vert.x so excuse my newbness.
I was able to create a very simply SockJS server with Vert.x however I can't figure out how to register events/callbacks/handlers when connections are open or closed.
With JSR-356, it's drop dead simple to handle open/close connection events:
#OnOpen
public void onOpen(Session userSession) {
// Do whatever you need
}
#OnClose
public void onClose(Session userSession) {
// Do whatever you need
}
Using the SockJS support in Spring Framework 4.0 M1+, it's almost the same as JSR-356:
public class MySockJsServer extends TextWebSocketHandlerAdapter {
#Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// Do whatever you need
}
#Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
// Do whatever you need
}
}
For some reason I couldn't figure out how to do something so conceptually simple in Vert.x. I though Vert.x was simple ?!!
If anyone can point me in the right direction, please help.
I played around with EventBus and EventBus hooks but it didn't work. Perhaps that's the wrong approach anyhow.
I'm using Vert.x version 2.0.1
TIA

This is the answer:
HttpServer httpServer = vertx.createHttpServer();
// Create HTTP server
httpServer = httpServer.requestHandler(new Handler<HttpServerRequest>() {
#Override
public void handle(HttpServerRequest req) {
req.response().sendFile("web/" + req.path());
}
});
// Create SockJS Server
SockJSServer sockJSServer = vertx.createSockJSServer(httpServer);
sockJSServer = sockJSServer.installApp(new JsonObject().putString("prefix", "/test"), new Handler<SockJSSocket>() {
public void handle(final SockJSSocket sock) {
System.out.println("New session detected!");
// Message handler
sock.dataHandler(new Handler<Buffer>() {
public void handle(Buffer buffer) {
System.out.println("In dataHandler");
}
});
// Session end handler
sock.endHandler(new Handler<Void>() {
#Override
public void handle(Void arg) {
System.out.println("In endHandler");
}
});
}
});
httpServer.listen(8080);

Related

How to know: How many requests is HttpServer-in-Vertx serving

I write a server with Vertx.
I have about 40k users. I can print every request but I don't know how to know how many current requests my server is serving
I used this class: http://vertx.io/docs/apidocs/io/vertx/core/http/HttpServer.html but this is no method to do it
Vertx is great toolkit but it can not show server status, really????
My server code:
public class MyFirstVerticle extends AbstractVerticle {
private HttpServer httpServer = null;
#Override
public void start() throws Exception {
httpServer = vertx.createHttpServer();
httpServer.requestHandler(new Handler<HttpServerRequest>() {
#Override
public void handle(HttpServerRequest request) {
String path = request.path();
System.out.println("incoming request: [" + request.remoteAddress() + "] at " + path);
}
});
httpServer.listen(9999);
}
}
Since vert.x 3.x.x http://vertx.io/docs/vertx-dropwizard-metrics is an official component of vert.x
I think what you search is this:
http://vertx.io/docs/vertx-dropwizard-metrics/java/#http-server-metrics
There are several possibilities to view the metrics
jmx http://vertx.io/docs/vertx-dropwizard-metrics/java/#jmx
http bridge for jmx http://vertx.io/docs/vertx-dropwizard-metrics/java/#_using_jolokia_and_hawtio
In our project we write periodically to a log file and send it in parallel to a graphite / grafana instance over udp
Vert.x requests are very short lived, so basing calculations solely on number of requests per second is not optimal. But, for the sake of discussion, you can achieve what you want in the following way:
public class MyFirstVerticle extends AbstractVerticle {
private HttpServer httpServer = null;
// Bad, done for the sake of simplicity
public final static AtomicInteger counter = new AtomicInteger(0);
#Override
public void start() throws Exception {
httpServer = vertx.createHttpServer();
httpServer.requestHandler(new Handler<HttpServerRequest>() {
public void handle(HttpServerRequest request) {
counter.incrementAndGet();
String path = request.path();
System.out.println("incoming request: [" + request.remoteAddress() + "] at " + path);
request.response().end();
request.endHandler(new Handler<Void>() {
#Override
public void handle(Void aVoid) {
counter.decrementAndGet();
}
});
}
});
httpServer.listen(9999);
}
}
Then to test yourself you can try something like that:
public class Main {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
MyFirstVerticle verticle = new MyFirstVerticle();
vertx.deployVerticle(verticle);
// Very bad, but our request are very short
vertx.setPeriodic(1, new Handler<Long>() {
#Override
public void handle(Long aLong) {
// Otherwise will overflow our console
if (MyFirstVerticle.counter.intValue() > 0) {
System.out.println(MyFirstVerticle.counter.intValue());
}
}
});
}
}

Adding new resources dynamically - CoAP

Once CoAP server is started I need to add new resources dynamically. But I have to stop and start the server again in order to access new resources. I suppose adding new resources same as adding a new HTTP servlet into already started HTTP server.
Here I added source code which is used for adding dynamic resources. If I am missing anything here let me know.
private static CoapServer server;
public CoAPEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
this.eventAdapterConfiguration = eventAdapterConfiguration;
this.globalProperties = globalProperties;
if(server == null){
server = new CoapServer();
server.start();
}
}
#Override
public void connect() {
registerDynamicEndpoint(eventAdapterConfiguration.getName());
isConnected = true;
}
private void registerDynamicEndpoint(String adapterName) {
server.stop();
server.add(new HelloWorldResource(adapterName));
server.start();
}
class HelloWorldResource extends CoapResource {
public HelloWorldResource(String resourceName) {
// set resource identifier
super(resourceName);
// set display name
getAttributes().setTitle("Hello-World Resource");
}
#Override
public void handleGET(CoapExchange exchange) {
// respond to the request
exchange.respond("Hello World!");
}
}
I've just tried to add a CoapResource dynamically:
#Override
public void handleGET(CoapExchange exchange) {
server.getRoot().add(new CoapResource("dynstatus") {
#Override
public void handleGET(CoapExchange exchange) {
System.err.println("dynstatus!!!");
}
});
And was able to call it.

Cling with tomcat

I am trying to create a service to autodiscover upnp devices in my local network, implementing it in a webapplication running on tomcat 7 and using 4thline Cling library.
I got this error
org.fourthline.cling.transport.RouterImpl handleStartFailure
SEVERE: Unable to initialize network router: org.fourthline.cling.transport.spi.InitializationException: Failed to set modified URLStreamHandlerFactory in this environment. Can't use bundled default client based on HTTPURLConnection, see manual.
In the cling's manual they say that Cling couldn't use the Java JDK's HTTPURLConnection for HTTP client operations. They suggest to configure network transport.
I didn't understand well how to do. Anyone had a similar problem?
Can you suggest me an example?
Thanks.
The code I am using is:
public class Example {
public static void startDiscovery() {
RegistryListener listener = new RegistryListener() {
public void remoteDeviceDiscoveryStarted(Registry registry,RemoteDevice device) {
String name = device.getDisplayString();
String url = device.getDetails().getBaseURL().toString();
String friendlyName = device.getDetails().getFriendlyName();
}
public void remoteDeviceDiscoveryFailed(Registry registry,RemoteDevice device, Exception ex) {
}
public void remoteDeviceAdded(Registry registry, RemoteDevice device) {
}
public void remoteDeviceUpdated(Registry registry,RemoteDevice device) {
}
public void remoteDeviceRemoved(Registry registry,RemoteDevice device) {
}
public void localDeviceAdded(Registry registry, LocalDevice device) {
}
public void localDeviceRemoved(Registry registry, LocalDevice device) {
}
public void beforeShutdown(Registry registry) {
}
public void afterShutdown() {
}
};
try{
UpnpService upnpService = new UpnpServiceImpl(listener);
upnpService.getControlPoint().search(new STAllHeader());
// wait 5 seconds for them to respond
Thread.sleep(5000);
upnpService.shutdown();
}catch(Exception e){
e.printStackTrace();
}
}
}

Play Framework 2: Handle client disconnection in chunked response

I'm forwarding some real-time data to web clients using chunked encoding.
In the following way, I could make HTTP streaming responses,
public Result action() {
return ok(new StringChunks() {
public void onReady(final Out<String> out) {
openStream().onData(new Consumer<String>() {
public void accept(String string) {
out.write(string);
}
}
}
}
}
But I need to clean up some resources after the client has disconnected. (by e.g. closing the browser window or when the stream reaches EOF)
When using WebSocket I could detect client disconnection using Iteratee.mapDone.
Is there an equivalent method to detect it when using Chunks?
Thanks
Well, just figured it out.
Results.Chunked.Out<A> object has onDisconnected(Callback0) method that I can register a disconnection callback. so
public Result action() {
return ok(new StringChunks() {
public void onReady(final Out<String> out) {
out.onDisconnected(new F.Callback0() {
public void invoke() throws Throwable {
// clean up things ...
}
}
openStream().onData(new Consumer<String>() {
public void accept(String string) {
out.write(string);
}
}
}
}
}

tomcat websocket servlet listening port

I'm trying to write a servlet that uses org.apache.catalina.websocket.WebSocketServlet. I've found an example of websocket chat, but I can't figure out how can I specify the listening port for a websocket server (which is implemented in this servlet)? For example I need to listen for clients connection on port 11337. But how I can express this?
OK, here is the (simplified) code:
public class TestServlet extends WebSocketServlet {
private static final Logger logger = LoggerFactory.getLogger(TestServlet.class);
public TestServlet() {
logger.error("Initializing TestServlet");
}
#Override
protected StreamInbound createWebSocketInbound(String subProtocol, HttpServletRequest request) {
logger.error("New WS connection, subProtocol=" + subProtocol + ", request=" + request.getRequestURL());
return new TestConnection();
}
private class TestConnection extends MessageInbound {
#Override
protected void onBinaryMessage(ByteBuffer byteBuffer) throws IOException {
logger.error("onBinaryMessage");
}
#Override
protected void onTextMessage(CharBuffer charBuffer) throws IOException {
logger.error("onBinaryMessage: " + charBuffer);
sendMessage("Test message");
}
public void sendMessage(String message) {
WsOutbound outbound = this.getWsOutbound();
CharBuffer cb = CharBuffer.wrap(message);
try {
outbound.writeTextMessage(cb);
} catch (IOException e) {
logger.error("failed to write outbound");
}
}
}
}
I can't find where and how I can set listening port. Official websocket documentation also doesn't help much.
So I guess it can be set somewhere in servlet settings, but can't find where.
Does anyone have any ideas?
WebSocket is designed to work over HTTP protocol and so it won't have different listening port like normal TCP Socket but it use the same server port that it deployed on.
so here in your case, if you are using tomcat server than websocket may use port 8080 (if you haven't modified explicitly) for communication. You may need to override onOpen and onClose methods of MessageInbound class to get notified on Connection established and connection close. Refer below sample code for more details.
public class IncomingMessageHandler extends MessageInbound {
private WsOutbound myoutbound;
public IncomingMessageHandler() {
}
#Override
public void onOpen(WsOutbound outbound) {
logger.info("Open Client.");
this.myoutbound = outbound;
}
#Override
public void onClose(int status) {
logger.info("Close Client.");
}
/**
* Called when received plain Text Message
*/
#Override
public void onTextMessage(CharBuffer cb) throws IOException {
}
/**
* We can use this method to pass image binary data, eventually !
*/
#Override
public void onBinaryMessage(ByteBuffer bb) throws IOException {
}
public synchronized void sendTextMessage(String message) {
try {
CharBuffer buffer = CharBuffer.wrap(message);
this.getMyoutbound().writeTextMessage(buffer);
this.getMyoutbound().flush();
} catch (IOException e) {
}
}
/**
* Set timeout in milliseconds, -1 means never
*/
#Override
public int getReadTimeout() {
return -1;
}
public WsOutbound getMyoutbound() {
return myoutbound;
}
public void setMyoutbound(WsOutbound myoutbound) {
this.myoutbound = myoutbound;
}
}

Categories

Resources