I have developed a plain native websocket + tomcat 8 websocket sample appliation works fine.
But when I use the sockjs.js , instead of native websocket , I genting 404 error .
I am getting error in my browser console as
GET http://localhost:8082/WebsocketsWithFallback/websocket/DataPublisher/info 404 (Not Found)
Here is my javascript code,
var ws = null;
var sessionId = null;
var target = "/WebsocketsWithFallback/websocket/DataPublisher";
var connectionLive = false;
var init = false;
var pageCount = 0;
var delay = 0;
$(document).ready(function(){
if(sessionId == null && init == false){
sendSessionId( $.trim($('#init').val()) );
}
});
function sendSessionId(session){
init = true;
sessionId = session;
// console.log("sessionId :"+sessionId);
if(sessionId != null ){
connect();
}
}
function connect() {
try{
if(connectionLive == false){
updateTarget(target);
}
if(ws == null){
try{
ws = new SockJS(target);
}
catch(e){
alert("WebSocket connection error :"+e.description);
setTimeout(function(){ connect(); }, 5000);
return;
}
}
try{
ws.onopen = function () {
console.log('Info: WebSocket connection was opened.');
initMessage();
connectionLive = true;
};
}
catch(e){
alert("WebSocket connection open error :"+e.description);
}
try{
ws.onmessage = function (event) {
// console.log('Received: ' + event.data);
//Process the data to UI
};
}
catch(e){
alert("WebSocket message send error :"+e.description);
}
try{
ws.onclose = function (event) {
console.log('Info: WebSocket connection closed, Code: ' + event.code + (event.reason == "" ? "" : ", Reason: " + event.reason));
ws = null;
setTimeout(function(){ connect(); }, 5000);
};
}
catch(e){
alert("webSocket connection closed Error :"+e.description);
}
}catch(e){
alert(e.description);
}
}
function disconnect() {
if (ws != null) {
ws.close();
ws = null;
}
}
function sendData(message) {
if (ws != null) {
// console.log('Sent: ' + message);
ws.send(message);
}
}
function updateTarget(val) {
var target = window.location.host + val;
}
//Send initial message to pass parameters
function initMessage(){
if(ws != null){
ws.send(sessionId);
}
}
My server side will be,
#ServerEndpoint("/websocket/DataPublisher/")
public class Test {
#OnMessage
public void pushData(Session session, String msg, boolean last) {
session.getBasicRemote().sendText(msg, last);
}
#OnOpen
public void openWebSocket(Session session) {
// My stuff
}
#OnClose
public void closeWebSocket(Session session) {
// My stuff
}
#OnError
public void errorWebSocket(Throwable exception,Session session) {
}
}
Please give any ideas or suggesstions.Thank you.
Related
I'm using generic-pool to send data from a NodeJS TCP client to a Java TCP server.
This is the relevant code in my NodeJS client entry point blockEventListener.js - full code here:
function createPool() {
const factory = {
create: function() {
return new Promise((resolve, reject) => {
const socket = new net.Socket();
socket.connect({
host: sdkAddress,
port: sdkPort,
});
socket.setKeepAlive(true);
socket.on('connect', () => {
resolve(socket);
});
socket.on('error', error => {
if (error.code === "ECONNREFUSED") {
//console.log(`Retry after ${poolRetry}ms`);
setTimeout(() => {
socket.connect({
host: sdkAddress,
port: sdkPort,
});
}, poolRetry);
} else {
reject(error);
}
});
socket.on('close', hadError => {
console.log(`socket closed: ${hadError}`);
});
});
},
destroy: function(socket) {
return new Promise((resolve) => {
socket.destroy();
resolve();
});
},
validate: function (socket) {
return new Promise((resolve) => {
if (socket.destroyed || !socket.readable || !socket.writable) {
return resolve(false);
} else {
return resolve(true);
}
});
}
};
return genericPool.createPool(factory, {
max: poolMax,
min: poolMin,
maxWaitingClients: poolQueue,
testOnBorrow: true,
acquireTimeoutMillis: queueWait
});
}
const pool = createPool();
const poolStatusReport = `pool.spareResourceCapacity = ${pool.spareResourceCapacity}, pool.available = ${pool.available}, pool.borrowed = ${pool.borrowed}, pool.pending = ${pool.pending}`;
async function processPendingBlocks(ProcessingMap, channelid, configPath) {
setTimeout(async () => {
let nextBlockNumber = fs.readFileSync(configPath, "utf8");
let processBlock;
do {
processBlock = ProcessingMap.get(channelid, nextBlockNumber);
if (processBlock == undefined) {
break;
}
if (pool.spareResourceCapacity == 0 && pool.available == 0) {
break;
}
try {
const sock = await pool.acquire();
await blockProcessing.processBlockEvent(channelid, processBlock, sock, configPath);
await pool.release(sock);
} catch (error) {
console.error(`Failed to process block: ${error}`);
}
ProcessingMap.remove(channelid, nextBlockNumber);
fs.writeFileSync(configPath, parseInt(nextBlockNumber, 10) + 1);
nextBlockNumber = fs.readFileSync(configPath, "utf8");
} while (true);
processPendingBlocks(ProcessingMap, channelid, configPath);
}, blockProcessInterval);
}
This is the relevant code in blockProcessing.js - full code here:
exports.processBlockEvent = async function (channelname, block, socket, configPath) {
return new Promise(async (resolve, reject) => {
// some code
for (var dataItem in dataArray) {
// more code
for (var actionItem in actions) {
// yet more code
for (var record in rwSet) {
// ignore lscc events
if (rwSet[record].namespace != "lscc") {
// create object to store properties
const writeObject = new Object();
writeObject.blocknumber = blockNumber;
writeObject.chaincodeid = chaincodeID;
writeObject.channelid = channelid;
writeObject.timestamp = timestamp;
writeObject.txnid = txnid;
writeObject.values = rwSet[record].rwset.writes;
writeToSocket(socket, writeObject, channelname, chaincodeID);
}
}
}
console.log("---------");
}
// update the nextblock.nextBlock file to retrieve the next block
fs.writeFileSync(configPath, parseInt(blockNumber, 10) + 1);
socket.write('<END>\n');
resolve(true);
})
}
function writeToSocket(socket, writeObject, channelname, chaincodeID) {
return new Promise(async (resolve, reject) => {
console.log(`ChannelID: ${writeObject.channelid}`);
console.log(`Transaction Timestamp: ${writeObject.timestamp}`);
console.log(`ChaincodeID: ${writeObject.chaincodeid}`);
console.log(`TxnID: ${writeObject.txnid}`);
console.log(writeObject.values);
let objstr = JSON.stringify(writeObject);
socket.on('error', function(ex) {
console.log('!!!!!!!!!!!!! ERROR !!!!!!!!!!!!!');
console.log(ex);
console.log(writeObject);
console.log('=================================');
});
socket.write(objstr);
socket.write('\n');
var outputLog = path.resolve(__dirname, folderLog, `${channelname}_${chaincodeID}.log`);
fs.appendFileSync(outputLog, objstr + "\n");
});
}
And this is the code in my simple Java TCP server:
package demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleListener {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(Integer.parseInt(args[0]));
int n = 0;
while (n < Integer.parseInt(args[1])) {
new ThreadSocket(server.accept());
n++;
}
server.close();
}
}
class ThreadSocket extends Thread{
private Socket insocket;
ThreadSocket(Socket insocket){
this.insocket = insocket;
this.start();
}
#Override
public void run() {
try {
InputStream is = insocket.getInputStream();
InputStreamReader reader = new InputStreamReader(is);
BufferedReader in = new BufferedReader(reader);
PrintWriter out = new PrintWriter(insocket.getOutputStream(), true);
StringBuilder sb = new StringBuilder();
String line = in.readLine();
while (line != null && !"<END>".equalsIgnoreCase(line)) {
sb.append(line + "\n");
line = in.readLine();
}
String output = sb.toString();
System.out.println("INCOMING: " + output);
out.println(200);
out.close();
in.close();
reader.close();
is.close();
insocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
When I run the programs, I expect to see all the data read by the client being sent to the server in full. Instead what I observe is similar to this sample output. Initially, the information is intact. However, after the first five lines (I believe this is because I set my pool minimum size to 5), I start seeing gaps in my information. Crucially, I see EPIPE and ERR_STREAM_DESTROYED in my client output:
!!!!!!!!!!!!! ERROR !!!!!!!!!!!!!
Error [ERR_STREAM_DESTROYED]: Cannot call write after a stream was destroyed
at doWrite (_stream_writable.js:399:19)
at writeOrBuffer (_stream_writable.js:387:5)
at Socket.Writable.write (_stream_writable.js:318:11)
at /root/nodejslistener/accessreal/product/sdk/nodejs/blockProcessing.js:103:16
at new Promise (<anonymous>)
at Object.exports.processBlockEvent (/root/nodejslistener/accessreal/product/sdk/nodejs/blockProcessing.js:16:12)
at Timeout._onTimeout (/root/nodejslistener/accessreal/product/sdk/nodejs/blockEventListener.js:185:39) {
code: 'ERR_STREAM_DESTROYED'
}
{
blocknumber: '427',
...more details...
}
Sample EPIPE error output:
!!!!!!!!!!!!! ERROR !!!!!!!!!!!!!
Error: write EPIPE
at afterWriteDispatched (internal/stream_base_commons.js:156:25)
at writeGeneric (internal/stream_base_commons.js:147:3)
at Socket._writeGeneric (net.js:788:11)
at Socket._write (net.js:800:8)
at doWrite (_stream_writable.js:403:12)
at writeOrBuffer (_stream_writable.js:387:5)
at Socket.Writable.write (_stream_writable.js:318:11)
at /root/nodejslistener/accessreal/product/sdk/nodejs/blockProcessing.js:124:16
at new Promise (<anonymous>)
at writeToSocket (/root/nodejslistener/accessreal/product/sdk/nodejs/blockProcessing.js:109:12) {
errno: 'EPIPE',
code: 'EPIPE',
syscall: 'write'
}
{
blocknumber: '426',
...more details...
}
I have a few questions regarding my current situation:
When I leave out the .close() statements in my Java server, I don't get any errors, but I only see the first five chunks of data. Subsequent data seems to be missing, but I don't see any errors in my client. Why?
What should I change in my NodeJS client and/or Java server so that I can successfully send all my data?
In my application I used Socket.io and I want when receive listener from socket I should update UI.
I write below codes, but not update my UI!
For test this i write Log.e when receive socket listener, show this Log, but not update UI!
My Codes:
#Override
public void onSocketUpdateBid(final JSONObject ob) {
Log.e("updateBidCount", "Receive");
super.onSocketUpdateBid(ob);
final int auction_id;
final String remainClick;
final JSONObject data = ob;
try {
UpdateBidResponse updateBidResponse = new Gson().fromJson(data.toString(), UpdateBidResponse.class);
auction_id = updateBidResponse.getAuction_id();
remainClick = updateBidResponse.getRemain_click();
Constants.currentActivity.runOnUiThread(() -> {
if (detail.getId() != null) {
Log.e("RemainClickLog", "" + remainClick);
if (detail.getId().equals(auction_id)) {
if (Integer.parseInt(remainClick) > 0) {
Log.e("updateBidLog", "RemainClick : " + remainClick);
auctionDetail_miniBottomBidTxt.setText(remainClick);
auctionDetail_footerPlusBidBtn.setAlpha(1.0f);
auctionDetail_footerPlusBidBtn.setEnabled(true);
auctionDetail_footerPlusBidBtn.setClickable(true);
Log.e("updateBidLog", "Enable");
auctionDetail_footerBottom.setEnabled(true);
auctionDetail_footerBottom.setClickable(true);
auctionDetail_footerBottom.setAlpha(1.0f);
isShowSendBid = true;
} else if (Integer.parseInt(remainClick) == 0) {
Log.e("updateBidLog", "Disable");
auctionDetail_footerBottom.setEnabled(false);
auctionDetail_footerBottom.setClickable(false);
auctionDetail_footerBottom.setAlpha(0.4f);
auctionDetail_miniBottomBidTxt.setText("0");
isNotEndBids = true;
isShowSendBid = false;
} else {
Log.e("updateBidLog", "Disable");
auctionDetail_footerBottom.setEnabled(false);
auctionDetail_footerBottom.setClickable(false);
auctionDetail_footerBottom.setAlpha(0.4f);
auctionDetail_miniBottomBidTxt.setText("0");
isNotEndBids = true;
isShowSendBid = false;
}
}
}
});
} catch (Exception e) {
Log.e("updateBidCount", "Err : " + e.getMessage());
}
}
When run application and receive socket listener i show Log.e("updateBidLog", "Disable"); into logcat tab.
But not run this code :
auctionDetail_footerBottom.setEnabled(false);
auctionDetail_footerBottom.setClickable(false);
auctionDetail_footerBottom.setAlpha(0.4f);
auctionDetail_miniBottomBidTxt.setText("0");
isNotEndBids = true;
isShowSendBid = false;
and not update UI !
Update : I used this Constants.currentActivity.runOnUiThread for update UI. but not update UI!
How can i fix it?
Currently using open source project (https://github.com/mcollinge/07kit/tree/master/src/main)
And when i build the application, it looks like this: http://prntscr.com/f2zh5a
The thing is, the API is on their side (public static final String API_URL = "https://api.somesite.com/user";)
Their API is down. Therefore i cannot register on their site, to go through the logging in process.
Would there be any way to bypass login?
Providing LoginController class code below.
public class LoginController extends Controller<LoginView> {
public static final String API_URL = "";
private final Logger logger = Logger.getLogger(LoginController.class);
private LoginView view;
public LoginController() {
ControllerManager.add(LoginController.class, this);
}
public void show() {
try {
if (Session.get().getApiToken() != null) {
logger.info("Existing API token found - trying to retrieve account info...");
if (loadAccount(Session.get().getApiToken(), true, Session.get().getEmail().getValue())) {
logger.info("Logged in with pre-existing key.");
return;
}
}
} catch (Exception e) {
logger.error("Failed to authenticate.", e);
}
Toolkit toolkit = Toolkit.getDefaultToolkit();
int centerX = (toolkit.getScreenSize().width / 2) - (getComponent().getWidth() / 2);
int centerY = (toolkit.getScreenSize().height / 2) - (getComponent().getHeight() / 2);
getComponent().setLocation(centerX, centerY);
getComponent().setIconImage(Application.ICON_IMAGE);
getComponent().setVisible(true);
}
public void login(String email, String password, boolean rememberMe) {
try {
SwingWorker worker = new SwingWorker() {
#Override
protected Object doInBackground() throws Exception {
HttpResponse response = Executor.newInstance(HttpUtil.getClient()).execute(Request.Post(API_URL + "/token")
.bodyString(JacksonUtil.serialize(new CreateTokenRequest(email, password)), ContentType.APPLICATION_JSON)).returnResponse();
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
UserToken tokenResponse = JacksonUtil.deserialize(
EntityUtils.toString(response.getEntity()),
UserToken.class);
if (loadAccount(tokenResponse.getUuid(), rememberMe, email)) {
logger.info("Logged in.");
return null;
}
}
logger.error("Invalid login, response: [" + response.toString() + "]");
getComponent().getStatusLbl().setText("Status: Invalid login");
return null;
}
};
worker.execute();
} catch (Exception e) {
logger.error("Oops.", e);
getComponent().getStatusLbl().setText("Status: Error logging in");
}
}
private boolean loadAccount(String uuid, boolean rememberMe, String email) throws IOException {
HttpResponse getAccountResponse = Executor.newInstance(HttpUtil.getClient()).execute(Request.Get(API_URL)
.addHeader("Authorization", "Bearer " + uuid)).returnResponse();
if (getAccountResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
logger.info("Processed login [" + getAccountResponse.toString() + "]");
UserAccount account = JacksonUtil.deserialize(
EntityUtils.toString(getAccountResponse.getEntity()),
UserAccount.class);
if (account != null && account.getStatus() == UserAccount.Status.ACTIVE &&
account.getType() != null) {
getComponent().getStatusLbl().setText("Status: Logged in");
getComponent().dispose();
Session.get().setUserAccount(account);
Session.get().setApiToken(uuid);
Property emailProperty = Session.get().getEmail();
Property apiKeyProperty = Session.get().getApiKey();
if (rememberMe) {
if (emailProperty == null) {
emailProperty = new Property(Session.EMAIL_PROPERTY_KEY, email);
emailProperty.save();
} else {
emailProperty.setValue(email);
emailProperty.save();
}
if (apiKeyProperty == null) {
apiKeyProperty = new Property(Session.API_KEY_PROPERTY_KEY, uuid);
apiKeyProperty.save();
} else {
apiKeyProperty.setValue(uuid);
apiKeyProperty.save();
}
} else {
if (emailProperty != null) {
emailProperty.remove();
}
if (apiKeyProperty != null) {
apiKeyProperty.remove();
}
}
Session.get().onAuthenticated();
ControllerManager.get(MainController.class).show();
return true;
} else {
getComponent().getStatusLbl().setText("Status: Only BETA users can login");
return false;
}
}
return false;
}
#Override
public LoginView getComponent() {
if (view == null) {
view = new LoginView(this);
}
return view;
}
I'm building a system which has push notification feature and use Jersey to create API.
I read an article about comet approach and end up with the following code:
Index.js
function checkExamNotification() {
$.ajax({
url: contextPath + '/api/notification/checkExamNotification',
type: 'get',
data: {
accountId: accountId,
sessionId: sessionId
},
success: function (res) {
console.log("success");
displayNumberOfNotification();
checkExamNotification();
},
error: function (jqXHR, textStatus, errorThrown) {
if (textStatus === "timeout") {
checkExamNotification();
}
}
});
}
$(document).ready(function () {
$.ajaxSetup({
timeout: 1000*60*3
});
checkExamNotification();
});
Check exam notification API
#GET
#Path("/checkExamNotification")
public Response checkExamNotification(#QueryParam("accountId") int accountId, #QueryParam("sessionId") String sessionId) throws InterruptedException {
if (memCachedClient.checkSession(sessionId, accountId)) {
while (!examNotificationQueue.hasItems()) {
Thread.sleep(5000);
}
ExamNotificationQueueItemModel examNotificationQueueItemModel = examNotificationQueue.dequeue();
if (examNotificationQueueItemModel.getAccountId() == accountId) {
LOGGER.info("[START] Check exam notification API");
LOGGER.info("Account ID: " + accountId);
LOGGER.info("Get notification with exam ID: " + examNotificationQueueItemModel.getExamId());
ExamEntity exam = examDAO.findById(examNotificationQueueItemModel.getExamId());
NotificationEntity notification = notificationDAO.findByExamId(exam.getExamid());
notification.setSend(1);
notificationDAO.getEntityManager().getTransaction().begin();
notificationDAO.update(notification);
notificationDAO.getEntityManager().getTransaction().commit();
LOGGER.info("[END]");
String result = gson.toJson(examNotificationQueueItemModel);
return Response.status(200).entity(result).build();
} else {
examNotificationQueue.enqueue(examNotificationQueueItemModel);
Thread.sleep(5000);
checkExamNotification(accountId, sessionId);
}
}
return Response.status(200).entity(gson.toJson("timeout")).build();
}
From my debug, the API did finish return but the success event SOMETIMES didn't fire.
Yes, sometimes console log success but sometimes it doesn't.
Can anybody explain to me this case?
Thanks in advance. Any help would be appreciated.
Ok after following #peeskillet comment. Here is my finally code.
Check exam notification API
#GET
#Produces(SseFeature.SERVER_SENT_EVENTS)
#Path("/checkExamNotification")
public EventOutput checkExamNotification(#QueryParam("accountId") final int accountId, #QueryParam("sessionId") final String sessionId) {
final EventOutput eventOutput = new EventOutput();
if (memCachedClient.checkSession(sessionId, accountId)) {
new Thread(new Runnable() {
public void run() {
try {
if (examNotificationQueue.hasItems()) {
ExamNotificationQueueItemModel examNotificationQueueItemModel = examNotificationQueue.dequeue();
if (examNotificationQueueItemModel.getAccountId() == accountId) {
LOGGER.info("[START] Check exam notification API");
LOGGER.info("Account ID: " + accountId);
LOGGER.info("Get notification with exam ID: " + examNotificationQueueItemModel.getExamName());
String result = gson.toJson(examNotificationQueueItemModel);
final OutboundEvent.Builder eventBuilder
= new OutboundEvent.Builder();
eventBuilder.data(result);
final OutboundEvent event = eventBuilder.build();
eventOutput.write(event);
LOGGER.info("[END]");
} else {
examNotificationQueue.enqueue(examNotificationQueueItemModel);
}
}
} catch (IOException e) {
throw new RuntimeException(
"Error when writing the event.", e);
} finally {
try {
eventOutput.close();
} catch (IOException ioClose) {
throw new RuntimeException(
"Error when closing the event output.", ioClose);
}
}
}
}).start();
}
return eventOutput;
}
Index.js
function checkExamNotification() {
var url = contextPath + '/api/notification/checkExamNotification?accountId=' + accountId + '&sessionId=' + sessionId;
var source = new EventSource(url);
source.onmessage = function (event) {
displayNumberOfNotification();
};
}
First of all Sorry for duplicate question but i didn't get the answer I was looking for.I am getting the above error on console
Firefox can't establish a connection to the server at ws://localhost:8080/websocket.
here is my jsp page
var username;
var wsUri = "ws://localhost:8080/chat/websocket";
var websocket = new WebSocket(wsUri);
websocket.onopen = function (evt) {
onOpen(evt);
};
websocket.onmessage = function (evt) {
onMessage(evt);
};
websocket.onerror = function (evt) {
onError(evt);
};
var output = document.getElementById("output");
function join() {
alert('join start');
username = textField.value;
websocket.send(username + " joined");
alert('join end');
}
function send_message() {
alert('sendmessage start');
websocket.send(username + ": " + textField.value);
alert('sendmessage end');
}
function onOpen() {
alert('onopen start');
writeToScreen("Connected to " + wsUri);
alert('onopen end');
}
function onMessage(evt) {
console.log("onMessage");
writeToScreen("RECEIVED: " + evt.data);
if (evt.data.indexOf("joined") !== -1) {
userField.innerHTML += evt.data.substring(0, evt.data.indexOf(" joined")) + "\n";
} else {
chatlogField.innerHTML += evt.data + "\n";
}
}
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function writeToScreen(message) {
output.innerHTML += message + "<br>";
}
Here is my java class
#ServerEndpoint(value = "/websocket")
public class ChatEndpoint {
private static final Set < Session > peers = Collections.synchronizedSet(new HashSet < Session > ());
#OnOpen
public void onOpen(Session peer) {
System.out.println("I am onOpen");
peers.add(peer);
}
#OnClose
public void onClose(Session peer) {
System.out.println("I am onClose");
peers.remove(peer);
}
#OnMessage
public void message(String message, Session client) throws IOException, EncodeException {
System.out.println("I am message");
for (Session peer: peers) {
peer.getBasicRemote().sendObject(message);
}
}
}
I am using Maven repository and trying to run this project for client to client interaction in java.