I need to implement front-end for Server-Sent-Event. I use GWT, and i can not find any solution to create a listener for SSE. I need to push the data from server and to receive it on client every time hen data was changed. So for now i have a something like this:
private void method() {
final EventSource eventSource = EventSource.newEventSourceIfSupported();
if (null != eventSource) {
eventSource.setListener(this);
eventSource.open(GWT.getHostPageBaseURL() + "rest/myresource");
}
}
#Override
public void onOpen(EventSource eventSource) {
Window.alert("Open");
}
#Override
public void onClose(EventSource eventSource) {
Window.alert("onClose");
}
#Override
public void onMessage(EventSource eventSource, String lastEventId, String type, String data) {
Window.alert("lastEventId: " + lastEventId);
Window.alert("type: " + type);
Window.alert("data: " + data);
}
#Override
public void onError(EventSource eventSource) {
Window.alert("onError");
}
my class implements EventSourceListener
But it does not work. Actually this code reacting only when connection is opened, but it is impossible to receive any message from server. Do somebody know how to deal the issue with receiving data on client using GWT?
There are so many methods exist in GWT for push back services like a GWT Event Services enter link description here
In order for the server to initiate a request to the client, you will need to use WebSockets, and experimental HTML5 feature currently only supported by Chrome.
Or, to simulate this kind of interaction, you can use Comet (long-polling), made available in GWT by the rocket-gwt project.
Related
I'm in the middle of creating an application for Wear that has a phone companion app to do some of the heavier processes and make API calls.
So far in regards to communication between the two devices, I have been following this tutorial - http://android-wear-docs.readthedocs.io/en/latest/data.html
This has left me with the phone being able to communicate with the watch, but now I'm wondering how I replicate it working the other way.
The current code I have on the Wear app is like this (a seperate listener class is also present on the phone and watch):
public void sendTestMessage(View view)
{
String WEARABLE_DATA_PATH = "/wearable_data";
DataMap dataMap = new DataMap();
dataMap.putString("WATCH2PHONE TEST MESSAGE EVENT!", "1");
new SendToDataLayerThread(WEARABLE_DATA_PATH, dataMap).start();
}
class SendToDataLayerThread extends Thread
{
String path;
DataMap dataMap;
SendToDataLayerThread(String p, DataMap data)
{
path = p;
dataMap = data;
}
public void run()
{
PutDataMapRequest putDMR = PutDataMapRequest.create(path);
putDMR.getDataMap().putAll(dataMap);
PutDataRequest request = putDMR.asPutDataRequest();
DataApi.DataItemResult result = Wearable.DataApi.putDataItem(googleClient, request).await();
if (result.getStatus().isSuccess())
{
Log.v("myTag", "DataMap: " + dataMap + " sent successfully to data layer ");
}
else
{
Log.v("myTag", "ERROR: failed to send DataMap to data layer");
}
}
}
Listener Class (for watch, the phone version is identical):
public class ListenerService extends WearableListenerService
{
#Override
public void onDataChanged(DataEventBuffer dataEvents)
{
DataMap dataMap;
for (DataEvent event : dataEvents)
{
Log.v("myTag", "DataMap received on device: " + DataMapItem.fromDataItem(event.getDataItem()).getDataMap());
}
}
}
So sending the test message sends the messages to the layer and they send, but are received by the watch's listener service.
I'm assuming the "String WEARABLE_DATA_PATH = "/wearable_data";" is what's causing it to end up being received by the watch but I'm unsure what to change it to in order to get it to send properly.
The Data API works the same in both directions. The specific architecture to use on the handheld depends on your app's structure, but there is a good overview of the options in the documentation at https://developer.android.com/training/wearables/data-layer/events.html#Listen.
That page also discusses using a path to filter the data events received. Again, this depends on your architecture, but it might be reasonable to use paths like "/data_from_handheld" and "/data_from_wearable" to differentiate the DataItems going in the different directions. Or you can use the same path, and then the data events will appear on all connected devices - which may or may not be what you want.
One other common "gotcha": Data API events only fire when the data has actually changed. This is an efficient way for the API to handle real-world communications, but can make development difficult. To force it, simply include an item that is always different, such as:
dataMap.putLong("timestamp", System.nanoTime());
...but be sure to take that out before deploying the app!
My Jgroups config file contains the protocol/config
<FD timeout="3000" max_tries="3" />
But how do I use this in the Java code. For example, if there is a cluster and when I detect a failure I want to call an external notifier service via a REST call, like /nodeDown/nodeID
I'm not able to find any java code which does this, all I see is message receive and send, is there a way I can implement this?
Thanks
Adding some more info
I have done the step of writing a RecieverAdpater and override the start, stop, send, recieve method. Please find some code here,
public void receive(Message msg) {
JGroupsDataPacket pckt = (JGroupsDataPacket) msg.getObject();
if ( pckt.getCmd().equals("cacheUpdate") ){
int uid = pckt.getAffectedUid();
cacheUpdateRoutine(uid);
}
if ( pckt.getCmd().equals("ack") ){
System.out.println("got the mesaage!");
}
logger.log(LogLevel.ERROR, "received msg from " + msg.getSrc() + ": " + msg.getObject());
}
public void send(JGroupsDataPacket pckt){
Message msg = new Message(null, null, pckt);
msg.setFlag(Message.Flag.RSVP);
try {
channel.send(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
I want to know where should I add code for example to handle the TimeOutException when I'm sending a message with the RSVP flag enabled. Another requirement is to know, which is the Java callback method which is called when SUSPECT(P) is triggered. I want to catch and handle the machine's going down, timout etc.
Is the viewAccepted() the only place where I can handle this? Is there a sample code around this?
Also is http://www.jgroups.org/manual/html/user-channel.html
the section 3. APIs give all java/programmatic things we can do with JGroups.
Thanks again
I found some documentation here, I think this is the class which I'm supposed to override
public interface MembershipListener {
void viewAccepted(View new_view);
void suspect(Object suspected_mbr);
void block();
void unblock();
}
OK, first off, you have a JChannel. You need to use it to register for view callbacks, like this:
JChannel ch;
ch.setReceiver(this);
'this' extends ReceiverAdapter and overrides viewAccepted():
public void viewAccepted(View view) {
// handle new view
}
To determine the members which left between views v1 and v2:
List<Address> left_mbrs=View.leftMembers(v1,v2);
I am trying to set the state in a Vaadin custom widget from a click generated by the user. In the component connector after instantiating the server rpc I get the GWT button and add an onclick method. In the method I set the state (getState.text = "new text";) but when I try to get it from the server side I get the original state text. The onStateChange method is not triggered.
Code in the connector:
getWidget().getSaveButton().addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
alert("does it work without jquery?");
getState().text = "text changed from connector";
getWidget().getTextBox().setText(getState().text);
}
});
after clicking GWT button the textbox contains the text to "text changed from connector"
In the state:
public String text = "original state text";
The UI implementation to get the state:
vaadinButton.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
Notification.show(sig.getState().text);
}
});
When clicking the vaadin button after clicking the GWT button the notification still displays "original state text".
My question:
How do I change the state in the connector so it triggers the onStateChange method and I get the text changes server side?
It's not possible to update state from the client side. Only server can update state. You should do so that you sent a RPC request from client to server, and on the server you update the value to state.
Edit, here is an example on how to send a value from client to server using Vaadin's RPC mechanism:
Create an interface extending ServerRpc:
public interface MyServerRpc extends com.vaadin.shared.communication.ServerRpc {
void setValue(String value)
}
Use a proxy created from the above interface to send value to server. This call is done inside the connector.
getRpcProxy(MyServerRpc.class).setValue("New value to server");
Register an interface implementation to your server-side component to receive RPC calls:
registerRpc(new MyServerRpc() {
public void setValue(String value) {
// set the value to state here by saying getState().myValue = value;
// or do something else
}
});
I want to know that is it possible to send major Swing classes event/actionlisteners, Events, components via RMI.
Possible scenario: If one client press the button or move the slider every client's button or slider move etc same for other swing elements.
I am expecting the answer in the context of RMI and swing MVC architecture, i want to call the swing component's models e.g ButtonModel and want to send swing ActionEvent on wire and register PropertyChangeListener/PropertyChangeSupport as remote objects for getting updates at client site.
typical examples :
the server should call this method for each client, when ever some change occur in model
public void propertyChange(PropertyChangeEvent evt) {
for (AbstractViewPanel view: registeredViews) {
view.modelPropertyChange(evt);
}
}
in case of an event on one client, each client actionPerformed should be called from server:
#Override
public void actionPerformed(ActionEvent e) {
}
is it feasible? if not then why? where i could face the problems, i mean which classes are transferable (serialized) and which are not...
EDIT: here you see i m invoking Java Swing defaultbuttonmodel remotely, the only thing left when some of it's property or method change the other client's get updates, best would be following swing propertychangelistener if someone can just help me, realizing this, it would be great:
public class RemoteButtonModel extends UnicastRemoteObject implements Model {
private ButtonModel model = new DefaultButtonModel() ;
protected myModel() throws RemoteException {
super();
}
#Override
public void setEnabled(boolean b) throws RemoteException {
if (isEnabled())
model.setEnabled(false);
else{
model.setEnabled(true);
}
}
#Override
public boolean isEnabled() throws RemoteException {
return model.isEnabled();
}
}
I think it would be more efficient to send across something like a "scroll message" or "button pressed" message, utilizing the command pattern. This would allow different clients to act correctly with different implementations.
Edits:
the way I do it in my client/server applications (which is easily adapted to this peer-to-peer architecture you're doing) is with something like this (copy and pasted from my production code, mind you.)
abstract public class UserRequest implements Serializable {
public final String username;
private transient ServersideThread thread;
protected UserRequest(String username) {
this.username = username;
this.thread = null;
}
abstract public EngineMessage engineCallback(GenericEngine engine);
public void setThread(ServersideThread thread) {
if(this.thread == null) {
this.thread = thread;
return;
}
throw new IllegalStateException("Cannot set thread when already set:" + thread.getName());
}
public ServersideThread getThread() {
return this.thread;
}
}
So, with this approach, I would do something like...
public class SliderMoveNotification extends UserRequest {
// need some way to say what slider moved
public final int sliderId;
public final int slideDistance;
public SliderMoveNotification(String username) {
super(username);
sliderId = 0;
sliderDistance = 0;
throw new UnsupportedOperationException("Must supply a slider and a distance");
}
public SliderMoveNotification(String username, int sliderID, int slideDistance) {
super(username);
this.sliderId = sliderId;
this.slideDistance = slideDistance;
}
public EngineMessage engineCallback(GenericEngine engine) {
if(engine instanceof WindowEngine) {
WindowEngine manager = (WindowEngine)engine;
manager.slideWindow(sliderId,slideDistance);
// you wouldn't need engine messages like I do in my client/server
// relationship, but the idea stands.
}
}
}
The Javadoc for every Swing class says that it should not be serialized.
More probably you should be transmitting the associated Model classes.
And event listening via RMI is an anti-pattern. Too much traffic, too many points of failure.
EDIT: removed reference to C# as the only accepted answer is about Java. If someone needs information about websocket server implementation in C#, ask a new question.
Do you know "production ready" framework for creating WebSockets Server in Java? I found one library http://nugget.codeplex.com/ but i did not know how it is stable and fast.
The accepted answer is 3 years old, with the recent release of JEE7, now every Web Containers that implement servert 3.1 will support websocket via standard API (javax.websocket) package.
The following code show example how to implement websocket using JEE7:
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
#ServerEndpoint(value = "/chat")
public class ChatServer {
private static final Logger LOGGER =
Logger.getLogger(ChatServer.class.getName());
#OnOpen
public void onOpen(Session session) {
LOGGER.log(Level.INFO, "New connection with client: {0}",
session.getId());
}
#OnMessage
public String onMessage(String message, Session session) {
LOGGER.log(Level.INFO, "New message from Client [{0}]: {1}",
new Object[] {session.getId(), message});
return "Server received [" + message + "]";
}
#OnClose
public void onClose(Session session) {
LOGGER.log(Level.INFO, "Close connection for client: {0}",
session.getId());
}
#OnError
public void onError(Throwable exception, Session session) {
LOGGER.log(Level.INFO, "Error for client: {0}", session.getId());
}
}
Example in details here.
Web Container that support Websocket:
Tomcat 8
WildFly (Previously Jboss AS)
Glassfish 4.0
and much more
For Java, check out this informative post. Copy-paste from there:
Jetty WebSocket Server – Jetty has supported WebSockets since last September. This seems to be a good option.
Caucho Resin
jWebSocket
GlassFish/Grizzly (see a DZone posting on it here)
JBoss Netty (see patch here)
Webbit
Out of these options, I guess Jetty and Resin are the most mature and stable. However, always good to do your own testing.
The Vert.x option is also worth considering.
Creating a ws server can be as simple as
vertx.websocketHandler(new Handler<ServerWebSocket>() {
public void handle(ServerWebSocket ws) {
// A WebSocket has connected!
}
}).listen(8080);
or
vertx.createHttpServer().websocketHandler(new Handler<ServerWebSocket>() {
#Override
public void handle(final ServerWebSocket ws) {
logger.info("ws connection established with " + ws.remoteAddress());
ws.dataHandler(new Handler<Buffer>() {
#Override
public void handle(Buffer data) {
JsonObject item = new JsonObject(data.toString());
logger.info("data in -> " + item.encodePrettily());
// if you want to write something back in response to the client
//ws.writeTextFrame(...);
}
});
}
}).listen(port, new Handler<AsyncResult<HttpServer>>() {
#Override
public void handle(AsyncResult<HttpServer> event) {
logger.info("ws server is up and listening on port " + port);
}
});
For more details look here http://vertx.io/docs/vertx-core/java/#_websockets
So one can write his own WebSocket server with Vert.x, package it as FatJar, and run it on its own.
Or you can embed Vert.x env. in your app, and deploy your verticle (that implements the ws server) programmatically.
Another alternative is JBoss's web server Undertow. Which is easily embeddable in applications.
Add these dependencies:
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-servlet</artifactId>
<version>${version.io.undertow}</version>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-websockets-jsr</artifactId>
<version>${version.io.undertow}</version>
</dependency>
And here's a sample ws server:
Undertow server = Undertow.builder()
.addHttpListener(8080, "localhost")
.setHandler(path()
.addPrefixPath("/myapp", websocket(new WebSocketConnectionCallback() {
#Override
public void onConnect(WebSocketHttpExchange exchange, WebSocketChannel channel) {
channel.getReceiveSetter().set(new AbstractReceiveListener() {
#Override
protected void onFullTextMessage(WebSocketChannel channel, BufferedTextMessage message) {
final String messageData = message.getData();
for (WebSocketChannel session : channel.getPeerConnections()) {
WebSockets.sendText(messageData, session, null);
}
}
});
channel.resumeReceives();
}
}))
.build();
server.start();
Take a look at the Bristleback Framework. It is a high level overlay for commonly used Java Websocket Servers, like Jetty, Netty or Tomcat. If you like Spring Framework, you must definitely try Bristleback!
Disclaimer: I'm a contributor in Bristleback Framework project.
Apache Tomcat 8.0 implements WebSockets 1.1 API (JSR-356). You can even play with examples after installing by navigating to examples folder: there are echo chat and snake game.
JETTY
I've spent the past week mauling over how to make a WebSocket server. Finally got something to work hope this helps. It uses libraries from Jetty (jars).
File WebRTC_IceServer.java
package com.evanstools;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.websocket.server.*;
public class WebRTC_IceServer{
public static void main(String[] args){
try{
////////////////////////
if(args.length == 0){
System.out.printf("%s%n","WebRTC_IceServer [port]");
return;
}
Server server = new Server(Integer.parseInt(args[0]));
WebSocketHandler.Simple webSocketHandlerSimple = new WebSocketHandler.Simple(WebsocketPOJO.class);
server.setHandler(webSocketHandlerSimple);
server.start();
server.join();
////////////////////////
}catch(Exception w){w.printStackTrace();}
}
}
File WebsocketPOJO.java
package com.evanstools;
import org.eclipse.jetty.websocket.api.annotations.*;
import org.eclipse.jetty.websocket.api.Session;
//The class must be not abstract and public.
#WebSocket
public class WebsocketPOJO{
//Flags one method in the class as receiving the On Connect event.
//Method must be public, not abstract, return void, and have a single Session parameter.
#OnWebSocketConnect
public void onWebSocketConnect(Session session){
System.out.printf("%s%n","test client connected");
}
//Flags one method in the class as receiving the On Close event.
//Method signature must be public, not abstract, and return void.
//The method parameters:
////Session (optional)
////int closeCode (required)
////String closeReason (required)
#OnWebSocketClose
public void OnWebSocketClose(Session session,int closeCode,String closeReason){}
//Flags up to 2 methods in the class as receiving On Message events.
//You can have 1 method for TEXT messages, and 1 method for BINARY messages.
//Method signature must be public, not abstract, and return void.
//The method parameters for Text messages:
////Session (optional)
////String text (required)
//The method parameters for Binary messages:
////Session (optional)
////byte buf[] (required)
////int offset (required)
////int length (required)
#OnWebSocketMessage
public void onWebSocketMessageString(Session session, String text){}
//Flags one method in the class as receiving Error events from the WebSocket implementation.
//Method signatures must be public, not abstract, and return void.
//The method parameters:
////Session (optional)
////Throwable cause (required)
//#OnWebSocketError
//Flags one method in the class as receiving Frame events from the WebSocket implementation after they have been processed by any extensions declared during the Upgrade handshake.
//Method signatures must be public, not abstract, and return void.
//The method parameters:
////Session (optional)
///Frame (required)
//The Frame received will be notified on this method, then be processed by Jetty, possibly resulting in another event, such as On Close, or On Message. Changes to the Frame will not be seen by Jetty.
//#OnWebSocketFrame
}