Наложи ми се да работя със услуга, която на определен TCP порт "хвърля" събития от друга услуга. Тези събития трбва да се следят от AJAX уеб интерфейс.
Избрах си streaming от всичките предложения в
http://en.wikipedia.org/wiki/Comet_(programming)Пробвал съм другите, JS/HTTP базирани решения, но не ми харесват.
Та ... на първа стъпка, това сътворих:
EventListener.java
GeSHi (Java):
import java.applet.Applet;
import java.net.Socket;
import java.net.URL;
import java.io.*;
import java.awt.*;
import java.net.MalformedURLException;
{
protected int port = 0;
protected String eventHandlerObject
= null;
protected boolean debugMode = false;
protected boolean autoConnect = false;
@Override
public void init()
{
this.debugMode = (this.getParameter("debugMode") != null);
this.autoConnect = (this.getParameter("autoConnect") != null);
if (this.debugMode)
{
this.setLayout(null);
this.
textArea.
setBounds(new Rectangle(0, 0,
800,
450));
this.add(this.textArea);
}
if (Integer.
parseInt(this.
getParameter("port")) != 0
) {
this.
port = Integer.
parseInt(this.
getParameter("port"));
}
else
{
this.log("Port is undefined or not integer");
return;
}
if (this.getParameter("handler") == null)
{
this.log("Handler is undefined");
return;
}
this.eventHandlerObject = this.getParameter("handler");
if (this.autoConnect)
{
this.connect();
}
}
public void setHandler
(String handler
) {
if (handler != null && handler.length() != 0)
this.eventHandlerObject = handler;
}
public boolean disconnect()
{
if (this.sock.isClosed())
return true;
try
{
this.sock.close();
}
{
this.log(e);
this.handle("onDisconnectFailure", e.toString());
return false;
}
this.handle("onDisconnectSuccess");
return true;
}
public boolean connect()
{
if (this.sock != null && this.sock.isConnected())
{
try
{
this.sock.close();
}
{
this.log(e);
return false;
}
}
try
{
sock
= new Socket(this.
getCodeBase().
getHost(),
this.
port);
}
{
this.log(this.getCodeBase().getHost() + ":" + this.port);
this.log(e);
this.handle("onConnectFailure", e.toString());
return false;
}
try
{
}
{
this.log(e);
this.handle("onConnectFailure", e.toString());
return false;
}
this.handle("onConnectSuccess");
sockerReaderThread.start();
return true;
}
public boolean write
(String message
) {
if (this.sock == null || !this.sock.isConnected())
{
this.handle("onConnectionFailure");
return false;
}
try
{
socketWriter.write(message);
socketWriter.flush();
}
{
this.log(e);
this.handle("onWriteFailure", e.toString());
return false;
}
this.handle("onWriteSuccess");
return true;
}
@Override
public void run()
{
try
{
while (true)
{
if (this.sock == null || !this.sock.isConnected())
{
this.handle("onConnectionFailure");
return;
}
if ( (line = this.socketReader.readLine()) != null)
{
this.log(line);
this.handle("onReadSuccess", line);
}
}
}
{
this.log(e);
this.handle("onReadFailure", e.toString());
}
}
@Override
public void stop()
{
if (this.sock.isClosed())
return;
try
{
this.sock.close();
}
{
this.log(e);
}
}
{
if (handler == null)
return;
try
{
this.
getAppletContext().
showDocument(new URL("javascript:"+ this.
eventHandlerObject + "['" + handler
+ "']" + "(\"" + data
+"\")"));
}
{
this.log(e);
}
}
public void handle
(String handler
) {
if (handler == null)
return;
try
{
this.
getAppletContext().
showDocument(new URL("javascript:" + this.
eventHandlerObject + "['" + handler
+ "']()"));
}
{
this.log(e);
}
}
public void log
(String message
) {
if (this.debugMode && this.textArea != null)
{
textArea.append(message + "\n");
}
}
{
this.log(ex.toString());
}
}
baseHandler.js
GeSHi (Javascript):
Ext.namespace("Ext.EventListener");
Ext.EventListener.BaseHandler = function(config)
{
Ext.apply(this, config);
Ext.EventListener.BaseHandler.superclass.constructor.call(this);
this.addEvents(
'connectSuccess',
'readSuccess',
'writeSuccess',
'disconnectSuccess',
'connectFailure',
'readFailure',
'writeFailure',
'disconnectFailure',
'readResponse',
'receivedResponse',
'receivedEvent'
);
this.eventListener = window.document[config['listenerName']];
}
Ext.extend(Ext.EventListener.BaseHandler, Ext.util.Observable,
{
eventListener : null,
request : function (msg)
{
this.eventListener.write(msg);
},
connect : function ()
{
this.eventListener.connect();
},
onConnectSuccess : function ()
{
this.fireEvent("connectSuccess", this);
},
onReadSuccess : function (data)
{
this.fireEvent("readSuccess", data, this);
},
onWriteSuccess : function ()
{
this.fireEvent("writeSuccess", this);
},
onDisconnectSuccess : function ()
{
this.fireEvent("disconnectSuccess", this);
},
onConnectFailure : function (msg)
{
this.fireEvent("connectFailure", msg, this);
},
onReadFailure : function (msg)
{
this.fireEvent("readFailure", msg, this);
},
onWriteFailure : function (msg)
{
this.fireEvent("writeFailure", msg, this);
},
onDisconnectFailure : function (msg)
{
this.fireEvent("disconnectFailure", msg, this);
}
});
index.php
GeSHi (HTML):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="/scripts/ext/ext-base.js"></script> <script type="text/javascript" src="/scripts/ext/ext-debug.js"></script> <script type="text/javascript" src="/scripts/baseHandler.js"></script> var handler = null;
Ext.onReady(function ()
{
handler = new Ext.EventListener.BaseHandler(
{
listenerName : 'asterisk',
});
handler.connect();
handler.on(
{
connectSuccess :
{
scope : handler,
fn : function ()
{
alert("Connected");
}
},
readSuccess :
{
scope : handler,
fn : function (text)
{
alert(text);
}
}
})
});
<applet code="EventListener.class" archive="EventListener.jar" width="0" height="0" name="asterisk"> <param name="port" value="5038"> <param name="handler" value="handler">
Използвам self-signed applet (мисля, че трябва да е така за да може да отваря сокети изън localhost, но не съм сигурен). Java-та не ми е силната страна, а съм сигурен, че тук има хора, които биха ме подпомогнали с градивна критика.
Благодаря предварително!
ПП: Прикачам, jar файла, но с добавено разширение .zip (файлът не е ZIP-нат наистина), защото такива са разрешенията за форума.