Hello im doing a tcp server in java, and i got my listener class working but i want to declare an event to the listener class when it is intialized so in the listener class i can call the event newConnection(socket sck) and then it will go over to the main class again and run the method that is binded to that event like you are able to do in C# with the myclass.myevent +=
Can it be done in java or are there other ways arround, i have looked at eventlisteners or what its called but im really confused about how to handle this.
Regards Martin.
You can do something like this:
public interface ConnectionCallback {
void onConnected(Socket socket);
}
In your listener class:
public class Listener {
public void connect(ConnectionCallback callback){
//connect to your server here
Socket socket ....
callback.onConnected(socket);
}
}
In your main form, or wherever you're creating this listener:
public class MainForm{
public void createListener(){
Listener listener = new Listener();
listener.connect(new ConnectionCallback() {
public void onConnected(Socket socket) {
//perform custom logic here on the callback socket
}
});
}
}
Edit: if you were thinking of using Java 8, this might make it slightly easier for you to understand if you're coming from a C# perspective by using lambdas:
public class Listener {
public void connect(Consumer<Socket> socketConsumer){
Socket socket ....
socketConsumer.accept(socket);
}
}
Then, your MainForm is simplified:
public class MainForm {
public void createListener(){
Listener listener = new Listener();
listener.connect(socket -> onConnected(socket));
}
private void onConnected(Socket socket) {
//perform custom logic here...
}
}
Maybe something like this would help:
Declare an interface for your event listener:
public interface InitializationListener {
public void onInitialize();
}
Then, in the class which should trigger events:
//Using a List allows more than one listener to be registered
private List<InitializationListener> listeners = new ArrayList<InitializationListener>();
public void addInitializationListener(InitializationListener listener) {
this.listeners.add(listener);
}
When you want to trigger the listeners, maybe in newConnection():
public void newConnection(Socket sock) {
//do stuff..
//trigger listeners:
for (InitializationListener listener : listeners) {
listener.onInitialize();
}
}
Finally, in your client code:
server.addInitializationListener(new InitializationListener() {
public void onInitialize() {
//do stuff
}
});
Related
I'm trying to integrate twitter4j with vertx event loop and I don't know if I'm doing it the right way.
I'm new to vertx, although I'm a Node.js developer, so I'm familiar with the event loop/single thread concept.
In my test, I want to subscribe to a twitter stream and publish the stream on the vertx event bus.
I've created an agnostic TwitterAPI class which will transform the twitter stream into an Observable (this will be hooked to vertx later):
public class TwitterAPI {
public Observable<Status> getTwitterObservable() {
return Observable.create(emitter -> {
final TwitterStream twitterStream = new TwitterStreamFactory().getInstance();
twitterStream.addListener(new StatusListener(){
public void onStatus(Status status) {
emitter.onNext(status);
}
public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {}
public void onTrackLimitationNotice(int numberOfLimitedStatuses) {}
public void onException(Exception ex) {
emitter.onError(ex);
}
#Override
public void onScrubGeo(long userId, long upToStatusId) {}
#Override
public void onStallWarning(StallWarning warning) {}
});
//twitterStream.filter("some keyword");
twitterStream.sample();
});
}
}
Then I created a TwitterVerticle, which will listen to the above Observable and publish the stream on the event bus, so some other verticles can subscribe to it and process it:
public class TwitterVerticle extends AbstractVerticle {
public void start() {
EventBus eb = this.vertx.eventBus();
TwitterAPI twitterAPI = new TwitterAPI();
twitterAPI.getTwitterObservable()
.map(Status::getText)
.filter(text -> text.startsWith("my keyword"))
.subscribe(text -> {
eb.publish("tweet-feed", text);
});
}
}
For example, I created another verticle which will listen to "twitter-feed" on event bus and publish it on WebSocket, so you can see the feed in the browser.
Everything is working well at the first look...but...my main question is: I'm not sure twitter4j will play well with the event loop, maybe my integration technique is wrong. Maybe I should make TwitterVerticle a Worker Verticle?
Could somebody take a look and let me know if this is the best way to accomplish such task?
Thanks a lot!
EDIT
Publishing on event bus directly is a better pattern in this case?
Here is the modified code:
public class TwitterAPI {
public void publishStreamOnEventBus(Vertx vertx) {
EventBus eb = vertx.eventBus();
TwitterStream twitterStream = new TwitterStreamFactory().getInstance();
twitterStream.addListener(new StatusListener(){
public void onStatus(Status status) {
eb.publish("tweet-feed", status.getText());
}
public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {}
public void onTrackLimitationNotice(int numberOfLimitedStatuses) {}
public void onException(Exception ex) {
//emitter.onError(ex);
}
#Override
public void onScrubGeo(long userId, long upToStatusId) {}
#Override
public void onStallWarning(StallWarning warning) {}
});
twitterStream.sample();
}
}
public class Main {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
new TwitterAPI().publishStreamOnEventBus(vertx);
//vertx.deployVerticle(new TwitterVerticle()/*, new DeploymentOptions().setWorker(true)*/);
vertx.deployVerticle(new WebServerVerticle());
}
}
First a couple of general recommendations.
1/ If subscribing to an Observable involves invoking blocking APIs, use a blockingScheduler:
Scheduler blockingScheduler = io.vertx.rx.java.RxHelper.blockingScheduler(vertx);
Observable<String> obs = twitterObservable.subscribeOn(blockingScheduler);
2/ Then I assume twitter4j uses its own threads to invoke the StatusListener, so the EventBus#publish call will be made on one of those. To come back to the verticle context use the #observeOn operator:
Scheduler contextScheduler = io.vertx.rx.java.RxHelper.scheduler(context);
Observable<String> obs = twitterObservable.observeOn(contextScheduler);
Combining the two changes:
public class TwitterVerticle extends AbstractVerticle {
public void start() {
EventBus eb = this.vertx.eventBus();
Scheduler contextScheduler = io.vertx.rx.java.RxHelper.scheduler(context);
Scheduler blockingScheduler = io.vertx.rx.java.RxHelper.blockingScheduler(vertx);
TwitterAPI twitterAPI = new TwitterAPI();
twitterAPI.getTwitterObservable()
.map(Status::getText)
.filter(text -> text.startsWith("my keyword"))
.observeOn(contextScheduler)
.subscribeOn(blockingScheduler)
.subscribe(text -> {
eb.publish("tweet-feed", text);
});
}
}
All that said, if this the only job of the verticle, I would recommend to get rid of it and simply publish to the event bus. The event bus instance is thread safe and it's perfectly fine to invoke publish from the outside (non Vert.x) world. Actually, this is a good pattern to combine Vert.x code with legacy code.
Say, I have a SystemQueue class that wraps a Queue object. I add to this queue using systemQueue.add(whatever), and I have a different object thats a Runnable that checks the queue, and if its not empty, takes from the queue and uses "whatever" in its code. Is there any way to do this besides having an infinite loop in the run like
run(){
while(true){
if(!systemQueue.isEmpty()){
todo
}
}
}
and have that run forever?
What I'm asking is, how can I code using event-based-coding in java?
Is there any way I can add an eventListener to the queue inside SystemQueue, and if the queue changes, call out to SystemExecutor and have it run?
Queue itself doesn't provide that option. You can implement your own listener/event pair though.
Event:
public class SystemEvent extends java.util.EventObject{
public SystemEvent(SystemQueue src){
super(src);
}
public SystemQueue getSource(){
return (SystemQueue) super.getSource();
}
}
Listener:
public interface SystemListener extends java.util.EventListener{
public void eventQueued(SystemEvent e);
}
in SystemQueue:
ArrayList<SystemListener> listeners = new ArrayList<>();
protected void fireEventQueued(){
SystemEvent e = new SystemEvent(this);
listeners.forEach(l -> l.eventQueued(e));
}
public void addSystemListener(SystemListener l){
listeners.add(l);
}
public void add(something){
//add something
fireEventQueued();
}
Now all you need to do is make SystemExecutor implement SystemListener and add the instance as listener.
I have a view that I want to react to what happens in the editor. Right now I have a button that I want it so that when clicked it updates the data in the view to some new set of information. Where do I start, I have my selection event but no idea on how to communicate between the two. I'm looking for a loose coupling solution.
I'm sure there are many ways of doing this, but I've used the JFace IPropertyChangeListener interface in the past for simple event propagation.
Make your view implement IPropertyChangeListener. Create a Singleton class that you can register your IPropertyChangeListener with, and send a PropertyChangeEvent to. Then in the constructor of your view, register it with your Singleton.
Now you can get hold of your Singleton in your editor and fire off an event that will get picked up in your view.
Example code for the Singleton:
public class PropertyChangeEventBus {
private static PropertyChangeEventBus s_instance = new PropertyChangeEventBus();
public static PropertyChangeEventBus instance()
{
return s_instance;
}
private Set<IPropertyChangeListener> m_listeners;
private PropertyChangeEventBus()
{
// use CopyOnWriteArraySet to prevent ConcurrentModificationExceptions
m_listeners = new CopyOnWriteArraySet<IPropertyChangeListener>();
}
public void addListener(IPropertyChangeListener listener)
{
m_listeners.add(listener);
}
public void removeListener(IPropertyChangeListener listener)
{
m_listeners.remove(listener);
}
public void fire(final PropertyChangeEvent event)
{
// run property change events in UI thread to prevent having to have lots of syncExecs in the listener methods
ViewUtils.syncExec(new Runnable()
{
#Override
public void run()
{
for (IPropertyChangeListener listener : m_listeners)
{
try
{
listener.propertyChange(event);
}
catch(Exception e)
{
//log it, present error message
}
}
}
});
}
}
Example Code for the View:
//The constructor
public MyView()
{
PropertyChangeEventBus.instance().addListener(this);
}
#Override
public void propertyChange(PropertyChangeEvent event)
{
if(event.getProperty().equals(SOME_CONSTANT))
{
// Refresh View
}
}
I am trying to understand mechanism of callback handler. How is the handle() method invoked? Can anybody give an example of usage of custom callback handler (other than those used in Login Modules of JASS or so) in non Swing application?
Define an interface to handle the callback.
public interface ServiceListener<T> {
void callback(T result);
}
Define a method that takes ServiceListener as parameter and returns void.
Public void runInBackground(ServiceListener listener) {
...code that runs in the background...
listener.callback(...data to return to caller...);
}
And you can now do this from your main code:
runInBackground(new ServiceListener() {
#Override
public void callback(..returned data...) {
...Do stuff with returned data...
}
});
This is a basic example for requesting data from a webserver using the AsyncTask from an Android application.
First define the async class. Note that the constructor takes a listener which we use to publish the result once ready.
public class Webservice extends AsyncTask<String, Void, String> {
private DialogListener dialogListener;
public Webservice(final DialogListener dialogListener) {
this.dialogListener = dialogListener;
}
#Override
protected String doInBackground(final String... strings) {
// We cant trigger onComplete here as we are not on the GUI thread!
return "";
}
protected void onPostExecute(final String result) {
dialogListener.onComplete(result);
}
}
Basic server class for handling various network communications:
public class Server {
public void queryServer(final String url, final DialogListener service) {
// Simulate slow network...
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Webservice(service).execute(url);
}
}
We can now use this code inside our activity without having to worry how long the call takes as it is not going to halt the GUI as it is executed async.
Server s = new Server();
// Async server call.
s.queryServer("http://onto.dk/actions/searchEvents.jsp?minLatE6=55640596&minLngE6=12078516&maxLatE6=55642654&maxLngE6=12081948", new DialogListener() {
#Override
public void onComplete(final String result) {
toast("complete");
}
#Override
public void onError() {
toast("error");
}
});
I'm in the midst of porting a C# program over to Java that makes heavy use of delegates and the delegate's BeginInvoke method to notify of an event asynchronously. Take a data communication thread for example. It might have to notify another worker thread of its state as well as the GUI.
It seems to me that the best way to notify of the various events for different classes is to have an IClassNameHereWatcher interface that defines all of the types of events that the class "publishing" the event would need to notify about and then each class that needs to listen would implement this interface and register itself as a listener. The thing I'm not quite sure about is how to make this asynchronous. Here's approximately what I'm referring to:
public interface IFrobWatcher {
void frobDidSomething();
void frobReceivedData(object data);
}
public class Frob implements Runnable {
List<IFrobWatcher> watchers = new ArrayList<IFrobWatcher>();
private void run() {
while (true) {
// Long running task
if (blah) notifyWeDidSomething();
notifyOfData(someDataObject);
}
}
public void addWatcher(IFrobWatcher watcher) {
watchers.Add(watcher);
}
private void notifyWeDidSomething() {
for (IFrobWatcher watcher : watchers) {
watcher.frobDidSomething(); // How do I make this asynchronous?
}
}
private void notifyOfData(object someDataObject) {
for (IFrobWatcher watcher : watchers) {
watcher.frobReceivedData(someDataObject); // How do I make this asynchronous?
}
}
}
public class FrobWatcher implements IFrobWatcher {
private Frob frobToWatch;
public FrobWatcher(Frob frob) {
frobToWatch = frob;
frobToWatch.addListener(this);
}
public void FrobDidSomething() {
System.out.println("Frob did something!");
}
public void FrobReceivedData(object received) {
System.out.println("Frob received: " + received.ToString());
}
public static void main(string[] args) {
Frob f = new Frob();
FrobWatcher fw = new FrobWatcher(f);
(new Thread(f)).start();
}
}
And this is a fairly simplified example, but hopefully it conveys what I'm looking for. If something isn't clear or doesn't make sense, please comment and I'll try to clarify or fix the example.
I would recommend an Executor from the java.util.concurrent package.
This is how asynchronous callbacks are handled in the Raptor framework:
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(
filesPoller, 0 /*initial delay*/,
checkInterval,
TimeUnit.MILLISECONDS
);
NB. this scheduling is recurring.