I need to close connection but I get this
2016-10-28 10:46:07.624:WARN:oeji.nio:handle failed
java.lang.NullPointerException: ssl == null
at com.android.org.conscrypt.NativeCrypto.SSL_read_BIO(Native Method)
at com.android.org.conscrypt.OpenSSLEngineImpl.unwrap(OpenSSLEngineImpl.java:477)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:1014)
at org.eclipse.jetty.io.nio.SslConnection.unwrap(SslConnection.java:536)
at org.eclipse.jetty.io.nio.SslConnection.process(SslConnection.java:359)
at org.eclipse.jetty.io.nio.SslConnection.access$900(SslConnection.java:48)
at org.eclipse.jetty.io.nio.SslConnection$SslEndPoint.fill(SslConnection.java:678)
at org.eclipse.jetty.websocket.WebSocketParserRFC6455.parseNext(WebSocketParserRFC6455.java:181)
at org.eclipse.jetty.websocket.WebSocketConnectionRFC6455.handle(WebSocketConnectionRFC6455.java:225)
at org.eclipse.jetty.io.nio.SslConnection.handle(SslConnection.java:196)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:667)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:833)
This is my code for sockets:
private WebSocket webSocket = new WebSocket.OnTextMessage() {
#Override
public void onMessage(String data) {
//...
}
#Override
public void onOpen(Connection connection) {
//...
}
#Override
public void onClose(int closeCode, String message) {
//...
// this is called after connection.close()
}
};
WebSocketClientFactory webSocketClientFactory = new WebSocketClientFactory();
public void start(){
webSocketClientFactory.stop();
String urlConnect = "wss://test.test.com:111111/websocket";
webSocketClientFactory.setBufferSize(100000);
webSocketClientFactory.start();
WebSocketClient webSocketClient = webSocketClientFactory.newWebSocketClient();
webSocketClient.setMaxBinaryMessageSize(100000);
webSocketClient.setMaxTextMessageSize(100000);
Future<WebSocket.Connection> connectionFuture = webSocketClient.open(URI.create(urlConnect), webSocket);
}
// .......
// after some time call this
public void stop(){
try {
connection.close(); //this is going fine, error comes after
} catch (Throwable t) {
t.printStackTrace();//this not called
}
}
I can't understand what is the reason of that error and how I can fix it? I look through jetty docs and checked some thread here, but found nothing about that specific error
You have to stop the WebSocketClient.
Try this:
public void stop(){
try {
webSocketClient.stop();
} catch (Throwable t) {
t.printStackTrace();//this not called
}
}
or
public void stop(){
try {
webSocketClient.stop();
connection.close();
} catch (Throwable t) {
t.printStackTrace();//this not called
}
}
Link: where I have see it
Related
I am attempting to abruptly disconnect from an SFTP connection in Java without using the sftp.disconnect() method. Using this to build an integration test that checks that clean up happens everytime. See the test below:
public void checkDisruptedConnections() throws JSchException, InterruptedException {
ChannelSftp sftp = setupSftp(null);
sftp.connect();
try {
//disrupt connection OVER HERE
} catch (Exception e) {
assertEquals("1", jedis.get(SESSION_KEY));
}
waitForConnectionClose();
assertEquals("0", jedis.get(SESSION_KEY));
}
Ended up using a separate thread that connects and gets interupted.
#Test
public void testSftpInterupt() throws InterruptedException, JSchException, SftpException {
Connect thread = new Connect();
thread.start();
while (thread.isAlive()) {
waitForConnectionClose();
}
waitForConnectionClose();
assertEquals("0", jedis.get(SESSION_KEY));
}
Connect looks as follows:
private class Connect extends Thread {
#Override
public void run() {
ChannelSftp sftp = null;
Thread thread = this;
SftpProgressMonitor monitor = new SftpProgressMonitor() {
#Override
public void init(int op, String src, String dest, long max) {
}
#Override
public boolean count(long count) {
currentThread().interrupt();
return false;
}
#Override
public void end() {
}
};
try {
sftp.connect();
sftp.put(LOCAL_FILE_LARGE, remoteFile, monitor);
} catch (JSchException | SftpException e) {
assertEquals("java.io.InterruptedIOException", e.getMessage());
}
}
}
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);
I need help with connect on android to my WebSocket server based on Spring boot. Source code of this server I have taken https://spring.io/guides/gs/messaging-stomp-websocket/
Everything works fine on server and browser client on this sample,
but if I use StompClient (https://github.com/NaikSoftware/StompProtocolAndroid) to connect on my socket I am getting mStompClient.isConnected() == false and conand mStompClient.send(...) doesn't send anything (?).
After few minutes socketweb server closes the connection and I get in my log: '~~ Stomp connection closed'.
Web server locates on Heroku cloud system.
There is my connecting code from android activity:
private StompClient mStompClient;
private void connectStomp(){
mStompClient = Stomp.over(WebSocket.class, "wss://myserver/gs-guide-websocket");
mStompClient.topic("/topic/greetings").subscribe(new Action1<StompMessage>() {
#Override
public void call(StompMessage stompMessage) {
Log.w(TAG, "== "+stompMessage.getPayload());
}
});
mStompClient.connect();
mStompClient.lifecycle().subscribe(new Action1<LifecycleEvent>() {
#Override
public void call(LifecycleEvent lifecycleEvent) {
switch (lifecycleEvent.getType()) {
case OPENED:
Log.w(TAG, "~~ Stomp connection opened");
break;
case ERROR:
Log.e(TAG, "~~ Error", lifecycleEvent.getException());
break;
case CLOSED:
Log.w(TAG, "~~ Stomp connection closed "+lifecycleEvent.getMessage());
break;
}
}
});
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
connectStomp();
}
// Send test request to server
public void onSend(View view){
Log.w(TAG,"onSend: click");
mStompClient.send("/app/hello","Test").subscribe(new Observer<Void>() {
#Override
public void onCompleted() {
Log.w(TAG, "~~~~ onCompleted");
}
#Override
public void onError(Throwable e) {
Log.w(TAG, "~~~~ onCompleted "+e.getMessage());
}
#Override
public void onNext(Void aVoid) {
Log.w(TAG, "~~~~ onNext ");
}
});
if (mStompClient.isConnected()){
mStompClient.send("/app/hello","test msg").subscribe();
Log.w("aaaa : ","onCreate: connected");
}
}
It would be my mistake but if I connect to my server socket with spring boot WebSocketStompClient everithing works fine:
private SockJsClient sockJsClient;
private WebSocketStompClient stompClient;
private final WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
#Before
public void setup() {
List<Transport> transports = new ArrayList<>();
transports.add(new WebSocketTransport(new StandardWebSocketClient()));
this.sockJsClient = new SockJsClient(transports);
this.stompClient = new WebSocketStompClient(sockJsClient);
this.stompClient.setMessageConverter(new MappingJackson2MessageConverter());
}
#Test
public void getGreeting() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<Throwable> failure = new AtomicReference<>();
StompSessionHandler handler = new TestSessionHandler(failure) {
#Override
public void afterConnected(final StompSession session, StompHeaders connectedHeaders) {
session.subscribe("/topic/greetings", new StompFrameHandler() {
#Override
public Type getPayloadType(StompHeaders headers) {
return Greeting.class;
}
#Override
public void handleFrame(StompHeaders headers, Object payload) {
Greeting greeting = (Greeting) payload;
try {
System.out.println(greeting.getContent());
assertEquals("Hello, Spring!", greeting.getContent());
} catch (Throwable t) {
System.out.println(t.getMessage());
failure.set(t);
} finally {
session.disconnect();
latch.countDown();
}
}
});
try {
session.send("/app/hello", "Test");
} catch (Throwable t) {
failure.set(t);
latch.countDown();
}
}
};
this.stompClient.connect("wss://myserver/gs-guide-websocket", this.headers, handler, 443);
if (latch.await(10, TimeUnit.SECONDS)) {
if (failure.get() != null) {
throw new AssertionError("", failure.get());
}
}
else {
fail("Greeting not received");
}
}
private class TestSessionHandler extends StompSessionHandlerAdapter {
private final AtomicReference<Throwable> failure;
public TestSessionHandler(AtomicReference<Throwable> failure) {
this.failure = failure;
}
#Override
public void handleFrame(StompHeaders headers, Object payload) {
this.failure.set(new Exception(headers.toString()));
}
#Override
public void handleException(StompSession s, StompCommand c, StompHeaders h, byte[] p, Throwable ex) {
this.failure.set(ex);
}
Any ideas? Thanks a lot!
I used the same Library in order to connect with Stomp based web socket. There were some configurations on the server side. On the android side, I was using URL as starting with "ws://" and ending with "websocket" like "ws://" + SERVER_URL + "/websocket".
See this answer for server side https://stackoverflow.com/a/41751897/5392825
I used jmDNS to find some services on wifi network.
The problem is that sometimes after service is resolved, and I remove this listener, it triggers again with serviceResolved() method. jmDNS 3.4.1
private static JmDNS jmDNS;
private static ServiceType currentType;
private static ServiceListener currentListener;
public static Observable<String> getXXXIp(final ServiceType type,
final WifiManager wifiManager) {
return Observable.create(new Observable.OnSubscribe<String>() {
#Override public void call(final Subscriber<? super String> subscriber) {
InetAddress inetAddress = WifiUtils.getDeviceIpAddress(wifiManager.getConnectionInfo());
try {
jmDNS = JmDNS.create(inetAddress);
currentType = type;
currentListener = new ServiceListener() {
#Override public void serviceAdded(ServiceEvent event) { ... }
#Override public void serviceRemoved(ServiceEvent event) { }
#Override public void serviceResolved(ServiceEvent event) { ... }
};
jmDNS.addServiceListener(type.getCode(), currentListener);
} catch (IOException e) {
LOGGER.error("Exception occurred while searching " + type.getCode(), e);
subscriber.onError(e);
}
}
}).doOnNext(new Action1<String>() {
#Override public void call(String s) {
finish();
}
}).doOnError(new Action1<Throwable>() {
#Override public void call(Throwable throwable) {
finish();
}
});
}
private static void finish() {
if (jmDNS != null) {
LOGGER.info("jmDNS -> close");
try {
jmDNS.removeServiceListener(currentType.getCode(), currentListener);
jmDNS.close();
} catch (IOException e) {
LOGGER.error("Cannot close jmDNS ", e);
}
jmDNS = null;
currentListener = null;
}
}
It is a little complicated logic of service check, so I cut it off, but the main thing that's matter is in one moment onNext() is called once so method finish() is called. And I checked hashcode for listener which I've nullified in finish() and when after this listener onServiceResolved() is called I check it hashcode and it is the same. What is going on? Any ideas?
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 !!!