I am trying to connect with secure websocket connection wss:// in android using org.java_websocket.client.WebSocketClient API, but unable to connect with https. However it is working fine with ws://.. Here is my code.
private void connect(String websocketEndPointUrl) throws Exception {
URI uri;
try {
websocketEndPointUrl="wss://echo.websocket.org:443";
Log.i(TAG, " WSURL: " + websocketEndPointUrl);
uri = new URI(websocketEndPointUrl);
} catch (URISyntaxException e) {
Log.e(TAG, e.getMessage());
return;
}
mWebSocketClient = new WebSocketClient(uri,new Draft_17()) {
#Override
public void onOpen(ServerHandshake serverHandshake) {
Log.i("Websocket", "Opened");
}
#Override
public void onMessage(String s) {
//final String message =s;
}
#Override
public void onClose(int i, String s, boolean b) {
Log.i("Websocket", "Closed " + s);
}
#Override
public void onError(Exception e) {
Log.i("Websocket", "Error " + e.getMessage());
}
};
mWebSocketClient.connect();
}
i am using online test websocket url:
ws://echo.websocket.org (port 80) // working with that
wss://echo.websocket.org (port 443)
As per my observation there is no need of certificate required in my code. Can anyone suggest me what is a reason and how i can fix this.
Find a solution. I don't know why this is not a part of the documentation. You just need to set setWebSocketFactory after WebSocketClient initialization and before the .connect() method
mWebSocketClient = new WebSocketClient(uri,new Draft_17())
{
#Override
public void onOpen(ServerHandshake serverHandshake) {
Log.i("Websocket", "Opened");
}
#Override
public void onMessage(String s) {
//final String message =s;
}
#Override
public void onClose(int i, String s, boolean b) {
Log.i("Websocket", "Closed " + s);
}
#Override
public void onError(Exception e) {
Log.i("Websocket", "Error " + e.getMessage());
}
};
if (websocketEndPointUrl.indexOf("wss") == 0)
{
try {
SSLContext sslContext = SSLContext.getDefault();
mWebSocketClient.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(sslContext));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
mWebSocketClient.connect();
In my case, I need two thing to fix "Trust anchor for certification path not found" error when websocket connect():
HttpsURLConnection requests that particular wss host (but in https:// form) successfully at least once.
Then dosetWebSocketFactory() as mentioned in accepted answer. Which this extra method (plus new Draft_17()) only appeared in library version org.java-websocket:Java-WebSocket:1.3.0, not 1.4.0.
Note that don't test with allowAllSSL() like this answer do, which affect the two thing above not working.
Related
I am migrating an enterprise-level application based on JBOSS EAP 7.3 using the WebSocket Servlets to IBM WebSphere Application Server 9.0.5.6 (WAS). The problem is that when I try to connecting to WebSocket endpoint it does nothing. In WebSphere, I have configured all virtual hosts and ports accordingly and my WebSocket endpoint class looks like below.
#ServerEndpoint("/WebSocketServices")
public class ClientConnectorWebSocketCore {
private static final OMSLogHandlerI logger = new Log4j2HndlAdaptor("ClientConnectorWebSocketCore");
private ClientConnectorFacadeWrapperRemote clientConnectorFacadeRemote;
private EJBServiceLocatorI ejbServiceLocatorI;
#OnOpen
public void onConnectionOpen(Session session) {
session.setMaxIdleTimeout(120000); //todo //milli seconds
getEjbServiceLocatorI();
logger.elkLog("29", LogEventsEnum.WSOCKET_SESSION_CONNECT, " Session Create:" + session.getId());
}
#OnMessage
public String onMessage(String message) {
return handleJSONRequest(message);
}
#OnClose
public void onConnectionClose(Session session) {
logger.elkLog("42", LogEventsEnum.WSOCKET_SESSION_CLOSE, " Session Close:" + session.getId());
}
#OnError
public void onConnectionError(Session session, Throwable t) {
// logger.info("LN:47", session.getId(), LogEventsEnum.WEB_SOCKET_ONERROR, "WebSocket OnException" + t.getMessage());
logger.elkLog("48", LogEventsEnum.WEB_SOCKET_ONERROR, " Session error:" + session.getId() + ", Msg:" + t.getMessage());
}
public void msgBroadCast(Session session, String msg) {
for (Session session1 : session.getOpenSessions()) {
if (session1.isOpen()) {
session1.getAsyncRemote().sendText(msg);
}
}
}
private EJBServiceLocatorI getEjbServiceLocatorI(){
if (ejbServiceLocatorI == null){
ejbServiceLocatorI =
(EJBServiceLocatorI) SpringBeanFactoryLoader.getInstance().getBeanLoader().getBean(EJBServiceLocatorI.class);
}
return ejbServiceLocatorI;
}
private ClientConnectorFacadeWrapperRemote getClientConnectFacade() {
if (clientConnectorFacadeRemote == null) {
try {
ejbServiceLocatorI = getEjbServiceLocatorI();
clientConnectorFacadeRemote =
(ClientConnectorFacadeWrapperRemote) ejbServiceLocatorI.contextLookupConnectorFacadeRemote(ClientConnectorFacadeWrapperRemote.class);
} catch (Exception e) {
logger.error("LN:66", "Error in Creating Client connector " + e.getMessage(), e);
}
}
return clientConnectorFacadeRemote;
}
private String handleJSONRequest(String jsonRequest) {
ClientConnectorFacadeWrapperRemote clientConnector = getClientConnectFacade();
String response = null;
if (clientConnector != null) {
response = clientConnector.processMessage(jsonRequest);
}
return response;
}
#OnMessage
public void pongMessage(Session session, PongMessage msg) {
msg.getApplicationData().toString();
}
public void setEjbServiceLocatorI(EJBServiceLocatorI ejbServiceLocatorI) {
this.ejbServiceLocatorI = ejbServiceLocatorI;
}
}
Any advice is highly appreciated.
If your requests flow through a web server with WebSphere plugin, you need to ensure plugin is at level 9.0.5.6 or higher due to bug (PH27966) which can block websocket traffic.
I am creating an Android App which I want to connect to my server running secure websockets (wss). My code to connect is as below:
private void createWebSocketClient() {
URI uri;
try {
// Connect to local host
uri = new URI("wss://mysocketsdomain:8080/ws");
}
catch (URISyntaxException e) {
Log.d("Connection", "I am not even connecting");
e.printStackTrace();
return;
}
webSocketClient = new WebSocketClient(uri) {
#Override
public void onOpen() {
Log.i("WebSocket", "Session is starting");
webSocketClient.send("Hello World!");
}
#Override
public void onTextReceived(String s) {
Log.i("WebSocket", "Message received");
final String message = s;
runOnUiThread(new Runnable() {
#Override
public void run() {
try{
//TextView textView = findViewById(R.id.mainText);
//textView.setText(message);
} catch (Exception e){
e.printStackTrace();
}
}
});
}
#Override
public void onBinaryReceived(byte[] data) {
}
#Override
public void onPingReceived(byte[] data) {
}
#Override
public void onPongReceived(byte[] data) {
}
#Override
public void onException(Exception e) {
System.out.println(e.getMessage());
}
#Override
public void onCloseReceived() {
Log.i("WebSocket", "Closed ");
System.out.println("onCloseReceived");
}
};
webSocketClient.setConnectTimeout(10000);
webSocketClient.setReadTimeout(60000);
webSocketClient.enableAutomaticReconnection(5000);
webSocketClient.connect();
}
I am getting the error below:
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
The connection works fine if I visit the web front end from a browser and I can see that the certificate is valid from the padlock symbol. Also, the frontend web app that I developed using Svelte in JavaScript works fine.
Can anyone advise what I need to do? I am reading a lot of confusing information online. Some things suggest that I need to create a trusted certificate store in the Android app. Another thing that I saw suggested it is a problem with the server certificate chain. I set the server to use the certificate file containing the chain, but the error still happens. I am not sure if it would be the server when it works for the JavaScript app and the web front end.
try upgrade WeSocketClient library:
implementation 'tech.gusavila92:java-android-websocket-client:1.2.0'
I have the following java code that I'd like to use in an android app to query an api for continuous lat/lng changes of a device that is running a client app, I want to track the device. I believe the WebSocketCall method I'm attempting to use is deprecated. From what I can tell, there's a problem with how I'm trying to use the webSocket call to create the retrofit client and enqueue the data from the WebSocketListner into retrofit. I've researched several WebSocketListener examples and being a total n00b, I haven't been able to figure out the code. My idea is to keep the connection open to the api via WebSocket and process the data response using retrofit. Any assistance would be greatly appreciated.
private WebSocketCall webSocket;
private void createWebSocket() {
final MainApplication application = (MainApplication) getActivity().getApplication();
application.getServiceAsync(new MainApplication.GetServiceCallback() {
#Override
public void onServiceReady(final OkHttpClient client, final Retrofit retrofit, WebService service) {
User user = application.getUser();
map.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(user.getLatitude(), user.getLongitude()), user.getZoom()));
service.getDevices().enqueue(new WebServiceCallback<List<Device>>(getContext()) {
#Override
public void onSuccess(retrofit2.Response<List<Device>> response) {
for (Device device : response.body()) {
if (device != null) {
devices.put(device.getId(), device);
}
}
Request request = new Request.Builder().url(retrofit.baseUrl().url().toString() + "api/socket").build();
webSocket = WebSocketCall.create(client, request);
webSocket.enqueue(new WebSocketListener() {
#Override
public void onOpen(WebSocket webSocket, Response response) {
}
#Override
public void onFailure(IOException e, Response response) {
reconnectWebSocket();
}
#Override
public void onMessage(ResponseBody message) throws IOException {
final String data = message.string();
handler.post(new Runnable() {
#Override
public void run() {
try {
handleMessage(data);
} catch (IOException e) {
Log.w(MainFragment.class.getSimpleName(), e);
}
}
});
}
#Override
public void onClose(int code, String reason) {
reconnectWebSocket();
}
});
}
});
}
#Override
public boolean onFailure() {
return false;
}
});
}
So because I'm a total n00b it took some time and a lot of questions to figure this out. Maybe it'll help someone else in the future.
private WebSocket webSocket;
private void createWebSocket() {
final MainApplication application = (MainApplication) getActivity().getApplication();
application.getServiceAsync(new MainApplication.GetServiceCallback() {
#Override
public void onServiceReady(final OkHttpClient client, final Retrofit retrofit, WebService service) {
User user = application.getUser();
map.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(user.getLatitude(), user.getLongitude()), user.getZoom()));
service.getDevices().enqueue(new WebServiceCallback<List<Device>>(getContext()) {
#Override
public void onSuccess(retrofit2.Response<List<Device>> response) {
for (Device device : response.body()) {
if (device != null) {
devices.put(device.getId(), device);
}
}
Request request = new Request.Builder().url(retrofit.baseUrl().url().toString() + "api/socket").build();
Log.e("WebSockets", "Headers: " + request.headers().toString());
WebSocketListener webSocketListener = new WebSocketListener() {
private static final int NORMAL_CLOSURE_STATUS = 1000;
#Override
public void onOpen(WebSocket webSocket, Response response) {
webSocket.send("{Auth-Token:secret-api-token-here}");
Log.e("WebSockets", "Connection accepted!");
}
#Override
public void onFailure(#NotNull WebSocket webSocket, #NotNull Throwable t, #Nullable Response response) {
reconnectWebSocket();
}
#Override
public void onMessage(#NotNull WebSocket webSocket, #NotNull String text) {
final String data = text;
Log.e("WebSockets", "Receiving : " + text);
handler.post(new Runnable() {
#Override
public void run() {
try {
handleMessage(data);
} catch (IOException e) {
Log.w(MainFragment.class.getSimpleName(), e);
}
}
});
}
#Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
Log.e("WebSockets", "Receiving bytes : " + bytes.hex());
}
#Override
public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(NORMAL_CLOSURE_STATUS, null);
Log.e("WebSockets", "Closing : " + code + " / " + reason);
}
#Override
public void onClosed(#NotNull WebSocket webSocket, int code, #NotNull String reason) {
reconnectWebSocket();
}
};
webSocket = client.newWebSocket(request, webSocketListener);
}
});
}
#Override
public boolean onFailure() {
return false;
}
});
}
I created a basic selfhosted SignalR server with the following code:
class Program
{
static void Main(string[] args)
{
// This will *ONLY* bind to localhost, if you want to bind to all addresses
// use http://*:8080 to bind to all addresses.
// See http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx
// for more information.
string url = "http://localhost:8080";
using (WebApp.Start(url))
{
Console.WriteLine("Server running on {0}", url);
Console.ReadLine();
}
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
public class MyHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addMessage(name, message);
}
}
Which is taken from: https://learn.microsoft.com/en-us/aspnet/signalr/overview/deployment/tutorial-signalr-self-host and works with the Javascript client.
I am now trying to create a Java client and got the following code that is simply supposed to send a message to the server:
String host = "http://localhost:8080";
HubConnection connection = new HubConnection(host);
HubProxy proxy = connection.createHubProxy("MyHub");
connection.start();
try {
System.out.println("Sendng message...");
proxy.invoke( "Send", "Client", "Hello world!" ).get();
System.out.println("Message sent!");
} catch (InterruptedException e) {
System.out.println("err1");
// Handle ...
} catch (ExecutionException e) {
System.out.println("err2");
// Handle ...
}
The problem that im having is that the message is not received by the server, it seems like the code is stuck at the invoke call and doesn't print the Hello world! message. Does someone know what im doing wrong?
hubProxy.invoke("sendMessageByUser", Message, WebApiToken).done(new Action<Void>() {
#Override
public void run(Void aVoid) {
if (aVoid != null)
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MyApplicationService.this, "Mesaj gönderildi", Toast.LENGTH_SHORT).show();
}
});
}
}).onError(new ErrorCallback() {
#Override
public void onError(final Throwable error) {
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MyApplicationService.this.getApplicationContext(), "Bir hata oluştu" + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
});
I have a client-side java code running in my Android Activity using the Gottox/socket.io.-java-client implementation on Github. This is the client code that needs to simple connect to a server and receive messages from it from time to time. Please bear with me as I'm very new to this domain and might be understanding this completely wrong!
This is what my client code looks like right now:
package com.example.culami;
import io.socket.IOAcknowledge;
import io.socket.IOCallback;
import io.socket.SocketIO;
import io.socket.SocketIOException;
import org.json.JSONException;
import org.json.JSONObject;
public class AcknowledgeExample implements IOCallback {
private SocketIO socket;
int connectionEstablished;
/**
* #param args
*/
/*public static void main(String[] args) {
try {
new AcknowledgeExample();
} catch (Exception e) {
e.printStackTrace();
}
}*/
public AcknowledgeExample() throws Exception
{
connectionEstablished = 0;
socket = new SocketIO();
socket.connect("http://192.168.0.108:3000/", this);
//socket.connect("http://localhost:3000/", this);
// Sends a string to the server.
//socket.send("Hello Server");
// Sends a JSON object to the server.
//socket.send(new JSONObject().put("key", "value").put("key2", "another value"));
//socket.send("server says hello!");
// Emits an event to the server.
//socket.emit("event", "argument1", "argument2", 13.37);
}
#Override
public void onMessage(JSONObject json, IOAcknowledge ack) {
try {
System.out.println("Server said:" + json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onMessage(String data, IOAcknowledge ack) {
System.out.println("Server said: " + data);
}
#Override
public void onError(SocketIOException socketIOException) {
System.out.println("an Error occured");
socketIOException.printStackTrace();
}
#Override
public void onDisconnect() {
System.out.println("Connection terminated.");
}
#Override
public void onConnect() {
System.out.println("Connection established");
connectionEstablished = 1;
}
#Override
public void on(String event, IOAcknowledge ack, Object... args) {
System.out.println("Server triggered event '" + event + "'");
}
}
The server side code I'm currently trying to work with is taken from Socket.io's getting started tutorial page and looks as under:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res)
{
//res.sendFile(__dirname + '/index.html');
res.send('<h1>Hello world</h1>');
});
io.on('connection', function(socket)
{
console.log('a user connected');
/*socket.on('chat message', function(msg)
{
io.emit('chat message', msg);
});*/
});
All I need is to figure out a way to make my client and server codes connect. The server side code needs to be java script as sends the client a string keyword/message from time to time. Any pointers/suggestions/fixes will be highly appreciated.