Tyrus client websocket Message handler - java

I am experiencing a problem where client does not start in non-debug mode in eclipse. Message do appear in debug mode.
Please let me know if any one else also facing same issue.
Calling method:
client = ClientManager.createClient();
ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();
client.getProperties().put(ClientProperties.PROXY_URI, "http://192.168.1.1:80");
session = client.connectToServer(new ClientEndpoint(), cec, URI.create(url));
Below is the code of ClientEndpoint class:
private static class ClientEndpoint extends Endpoint {
#Override
public void onOpen(final Session session, EndpointConfig config) {
System.out.println("ClientEndpoint: server session opened: "+session);
session.addMessageHandler(new MessageHandler.Whole<String>() {
#Override
public void onMessage(String message) {
System.out.println("ClientEndpoint: received message: "+message);
if(lastmessage != message)
{
lastmessage = message;
session.getUserProperties().put("Message", lastmessage);
}
else
{
enter code here
session.getUserProperties().put("Message", lastmessage);
}
}
});
}
#Override
public void onClose(Session session, CloseReason closeReason) {
try {
latch.countDown();
session.close();
safeDisconnect(session);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onError(Session session, Throwable th)
{
try {
session.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
th.printStackTrace();
}
}
Any thoughts? Please do let me know the configuration.

Related

Java Websocket Server-Client decoder not working

I am creating a group chat functionality on my app and I am having some issues. Requirements are Java and Websockets in Java(both server and the client part). I have created both server and client WebSockets and communication by itself works(sending text from client to server and visa versa), but what I want to do is send Objects through the socket and serialize it into XML. I have created the serialization and it work perfectly without the socket. The problem appears when I want to combine the two.
For now I tried embedding the encoder and decoder to socket implementation and sending Player object through the socket and got this error(whatever I tried later the error stayed the same):
java.lang.ClassNotFoundException: model/Player
Continuing ...
java.lang.NoSuchMethodException: <unbound>=XMLDecoder.new();
Continuing ...
java.lang.IllegalStateException: The outer element does not return value
Continuing ...
java.lang.IllegalStateException: The outer element does not return value
Continuing ...
java.lang.ArrayIndexOutOfBoundsException: 0
at java.beans.XMLDecoder.readObject(Unknown Source)
at Util.Util.getObjectFromXml(Util.java:43)
at Util.WebDecoder.decode(WebDecoder.java:28)
at org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeText.decode(PojoMessageHandlerWholeText.java:108)
at org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeText.decode(PojoMessageHandlerWholeText.java:39)
at org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeBase.onMessage(PojoMessageHandlerWholeBase.java:57)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395)
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133)
at org.apache.tomcat.websocket.WsFrameClient.processSocketRead(WsFrameClient.java:95)
at org.apache.tomcat.websocket.WsFrameClient.resumeProcessing(WsFrameClient.java:209)
at org.apache.tomcat.websocket.WsFrameClient.access$300(WsFrameClient.java:31)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.doResumeProcessing(WsFrameClient.java:186)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:163)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:148)
at sun.nio.ch.Invoker.invokeUnchecked(Unknown Source)
at sun.nio.ch.Invoker$2.run(Unknown Source)
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
I tried serializing the data into String sending it through the socket like text, receiving String and deserializing it on the client side of the app. The Exception persisted.
Xml decoder and encoder, they both work properly, but just in case I am wrong I'll put it here.
public class Util
{
public static String getXmlFromObject(Object o)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLEncoder xmlEncoder = new XMLEncoder(baos);
xmlEncoder.writeObject(o);
xmlEncoder.close();
return new String(baos.toByteArray()).replace("\n", "")+"\n";
}
public static Object getObjectFromXml(String xml)
{
ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
XMLDecoder xmlDecoder = new XMLDecoder(bais);
Object o = xmlDecoder.readObject();
xmlDecoder.close();
return o;
}
}
WebSocket on the server side:
#ServerEndpoint(value="/chat", encoders= {WebEncoder.class}, decoders= {WebDecoder.class})
public class ChatWebSocket
{
List<Session> sessions = new ArrayList<Session>();
#OnOpen
public void open(Session session)
{
sessions.add(session);
}
#OnClose
public void close(Session session)
{
sessions.remove(session);
}
#OnError
public void OnError(Session session, Throwable t)
{
System.out.println(session);
sessions.remove(session);
t.printStackTrace();
}
#OnMessage
public void handleMessage(Object message, Session session)
{
for (Session s : sessions)
{
System.out.println(s);
try
{
s.getBasicRemote().sendObject(message);
} catch (IOException | EncodeException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
WebSocket for the client side and a code snippet sending the message and for receiving it on the client side:
#ClientEndpoint(encoders= {WebEncoder.class}, decoders= {WebDecoder.class})
public class ChatWebSocketClient
{
Session session = null;
private MessageHandler messageHandler;
public ChatWebSocketClient(URI endpointURI)
{
try
{
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, endpointURI);
} catch (Exception e)
{
e.printStackTrace();
}
}
#OnOpen
public void open(Session session)
{
this.session = session;
}
#OnClose
public void close(Session sesion, CloseReason reason)
{
this.session = null;
}
#OnError
public void onError(Session session, Throwable t)
{
t.printStackTrace();
}
#OnMessage
public void OnMessage(Object message)
{
if (this.messageHandler != null)
{
this.messageHandler.handleMessage(message);
}
}
public void addMessageHandler(MessageHandler msgHandler)
{
messageHandler = msgHandler;
}
public void sendMessage(Object message)
{
try
{
session.getBasicRemote().sendObject(message);
} catch (IOException | EncodeException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
final ChatWebSocketClient webSocket = new ChatWebSocketClient(new URI("ws://localhost:8080/XOX/chat"));
webSocket.addMessageHandler(new MessageHandler(){
#Override
public void handleMessage(Object message)
{
System.out.println("jsp "+message.getClass().getName());
System.out.println("jsp "+Util.getXmlFromObject(message));
}
});
webSocket.sendMessage(player);

Dependency Injection Not working for #ClientEndpoint java

Is there any way to enable cdi within this #ClientEndpoint class (still using annotations as opposed to programmatic endpoint classes)? I am using wildfly 14 and java 8.
Here is the code that creates the session, passing the classname to the "createConnection" method:
#ApplicationScoped //TODO move this to be request scoped
public class SessionProducer {
#Produces
public Session getSession(InjectionPoint ip) {
SessionAnnotation annotation = ip.getAnnotated().getAnnotation(SessionAnnotation.class);
if(annotation != null) {
Class clazz = annotation.clazz();
String url = annotation.serverURL();
WebSocketContainer webSocketContainer = ContainerProvider.getWebSocketContainer();
try {
return webSocketContainer.connectToServer(clazz, new URI(url)); //<----------this is the line that uses the annotated class (clazz is a reference to the class)
} catch (DeploymentException | IOException | URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
/**
* The destroy/disposer metho for the session
* #param session
*/
public void close(#Disposes Session session) {
try {
session.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here is the annotated endpoint class:
#ClientEndpoint
public class CryptoCompareWSClient {
#Inject
#CryptoCompare
private Event<String> cryptoCompareEvent; //<--------this is always null, no cdi happens
public CryptoCompareWSClient() {
System.out.println("constructor");
//cryptoCompareEvent = new Event();
}
#PostConstruct
public void init() {
System.out.println("post construct"); //<---------this never gets called
}
#OnOpen
public void open(Session session) {
//session.getAsyncRemote().sendText("SubAdd: { subs: ['0~Poloniex~BTC~USD'] }" /*"test"*/);
System.out.println("opened");
}
#OnClose
public void close(Session session) {
System.out.println("Session " + session + " closed");
}
#OnError
public void error(Throwable error) {
System.out.println("Error: " + error.getMessage());
}
#OnMessage
public void message(String message, Session session) {
System.out.println("Message");
//cryptoCompareEvent.fireAsync(message);
}
}
Is there any way to enable cdi in the enabled class?
Thanks.

How to disable Caching at runtime if Couchbase connection failed?

I have a similar problem as asked here - How to disable Redis Caching at run time if redis connection failed. My application is using #Cacheable at the service layer for most of the database/static resources call.
Cache is backed by Couchbase and whenever application fails to connect Couchbase node application goes down. Which is what we are not expecting, we expect data should be served from the source system whenever connection failed.
We tried implementing CacheErrorHandler but it does not work as expected because we want to execute the actual method which is making a service call and return the response rather than logging the Cache fail, basically bypassing the cache and as soon as the Couchbase node is up or connection established get the data from cache.
Any idea how we can achieve it?
Thanks #Daniel Bickler for the suggestion, below is the implementation I written referring #John Blum answer.
CouchbaseCustomCacheManager:
import java.util.Map;
import org.springframework.cache.Cache;
import com.couchbase.client.spring.cache.CacheBuilder;
import com.couchbase.client.spring.cache.CouchbaseCacheManager;
public class CouchbaseCustomCacheManager extends CouchbaseCacheManager {
public CouchbaseCustomCacheManager(
final Map<String, CacheBuilder> initialCaches) {
super(initialCaches);
}
#Override
public Cache getCache(String name) {
return new CouchbaseCacheWrapper(super.getCache(name));
}
protected static class CouchbaseCacheWrapper implements Cache {
private final Cache delegate;
public CouchbaseCacheWrapper(Cache couchbaseCache) {
this.delegate = couchbaseCache;
}
#Override
public String getName() {
try {
return delegate.getName();
} catch (Exception e) {
return null;
}
}
#Override
public Object getNativeCache() {
try {
return delegate.getNativeCache();
} catch (Exception e) {
return null;
}
}
#Override
public ValueWrapper get(Object key) {
try {
return delegate.get(key);
} catch (Exception e) {
return null;
}
}
#Override
public <T> T get(Object key, Class<T> type) {
try {
return delegate.get(key, type);
} catch (Exception e) {
return null;
}
}
#Override
public void put(Object key, Object value) {
try {
delegate.put(key, value);
} catch (Exception e) {
try {
handleErrors(e);
} catch (Exception e1) {
}
}
}
#Override
public ValueWrapper putIfAbsent(Object key, Object value) {
try {
return delegate.putIfAbsent(key, value);
} catch (Exception e) {
return null;
}
}
#Override
public void evict(Object key) {
try {
delegate.evict(key);
} catch (Exception e) {
try {
handleErrors(e);
} catch (Exception e1) {
}
}
}
#Override
public void clear() {
try {
delegate.clear();
} catch (Exception e) {
try {
handleErrors(e);
} catch (Exception e1) {
}
}
}
protected <T> T handleErrors(Exception e) throws Exception {
if (e instanceof Exception) {
return null;
} else {
throw e;
}
}
}
}
And used it as:
#Bean
public CacheManager cacheManager() {
final Map<String, CacheBuilder> cache = new HashMap<>();
for (final String appCache : "127.0.0.1,127.0.0.2,127.0.0.3".split(",")) {
cache.put(appCache, CacheBuilder.newInstance(CouchbaseCluster.create().openBucket(
"default", "")));
}
return new CouchbaseCustomCacheManager(cache);
}

How restart bluetooth service in bluecove?

I have desktop and android applications, which connected by bluetooth(in desktop side I use Bluecove 2.1.1 library). Desktop application create bluetooth service then android application connects to it. I want to add logout functionality from both desktop and android sides. For example in desktop app user click disconnect, both desktop and android apps reset their connections and should be able to connect again. Here is bluetoothService code for desktop side:
public class BluetoothService
{
private static final String serviceName = "btspp://localhost:"
// + new UUID("0000110100001000800000805F9B34F7", false).toString()
// + new UUID("0000110100001000800000805F9B34F8", false).toString()
+ new UUID("0000110100001000800000805F9B34F9", false).toString()
+ ";name=serviceName";
private StreamConnectionNotifier m_service = null;
private ListenerThread m_listenerThread;
private DataOutputStream m_outStream;
public BluetoothService()
{
Open();
}
public void Open()
{
try
{
assert (m_service == null);
m_service = (StreamConnectionNotifier) Connector.open(serviceName);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void Start()
{
try
{
StreamConnection connection = (StreamConnection) m_service
.acceptAndOpen();
System.out.println("Connected");
m_listenerThread = new ListenerThread(connection);
Thread listener = new Thread(m_listenerThread);
listener.start();
m_outStream = new DataOutputStream(connection.openOutputStream());
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void Send(String message)
{
assert (m_listenerThread != null);
try
{
m_outStream.writeUTF(message);
m_outStream.flush();
System.out.println("Sent: " + message);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void Close()
{
try
{
m_service.close();
m_listenerThread.Stop();
m_listenerThread = null;
m_outStream.close();
m_outStream = null;
m_service = null;
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
class ListenerThread implements Runnable
{
private DataInputStream m_inStream;
private boolean m_isRunning;
public ListenerThread(StreamConnection connection)
{
try
{
this.m_inStream = new DataInputStream(connection.openInputStream());
m_isRunning = true;
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
;
}
public void run()
{
while (m_isRunning)
{
try
{
assert (m_inStream != null);
if (m_inStream.available() > 0)
{
String message = m_inStream.readUTF();
System.out.println("Received command: " + message);
CommandManager.getInstance().Parse(message);
}
}
catch (IOException e)
{
System.err.println(e.toString());
}
}
}
public void Stop()
{
m_isRunning = false;
try
{
m_inStream.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
for restarting service I do:
BluetoothService::Close();
BluetoothService::Open();
BluetoothService::Start();
but seems I cannot reconnect. Maybe I should create service with different name?

try-catch arround callback

public class Test {
public static void main(String[] args) {
try {
doSomething(new TestCallback() {
#Override
public void doCallback() {
throw new NullPointerException();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public static void doSomething(TestCallback callback){
callback.doCallback();
}
interface TestCallback {
public void doCallback();
}
}
RESULT:
java.lang.NullPointerException
at managers.concurrency.Test$1.doCallback(Test.java:11)
at managers.concurrency.Test.doSomething(Test.java:20)
at managers.concurrency.Test.main(Test.java:8)
In the above code we will get NullPointerException because the callback code is executed in the different part of stack. Is there a way to catch the such exceptions locally?
You are already catching the exception. Try something as follows -
try {
doSomething(new TestCallback() {
#Override
public void doCallback() {
throw new NullPointerException();
}
});
} catch (Exception e) {
System.out.println("Exception caught !!!");
}
Output:
Exception caught !!!

Categories

Resources