I have a very basic question. I have just started with vertx Framework. There is one thing I am not able to understand like
vertx.createNetServer().connectHandler(new Handler<NetSocket>() {
#Override
public void handle(final NetSocket socket) {
socket.dataHandler(new Handler<Buffer>() {
public void handle(Buffer buffer) {
/* I can access the socket object inside this handler */
socket.write("Hello");
}
});
}
}).listen(1234);
but if I write the handler function separately like this
Handler<Message> socketHandler = new Handler<Buffer>() {
public void handle(Buffer buffer) {
/* How can i access the socket object now */
socket.write("Hello"); //this will give error as it does not recognize the socket object
}
};
vertx.createNetServer().connectHandler(new Handler<NetSocket>() {
#Override
public void handle(final NetSocket socket) {
socket.dataHandler(socketHandler);//now I write handler separately
}
}).listen(1234);
Handler can be anywhere in the same java class or other java class. Please help me me how I can write handler separately and still access the socket object.
In your second example, you're not passing socket to socketHandler, so you cannot expect socketHandler to know about it.
You could solve this by creating a method like createSocketHandler(final Socket socket) that returns a Handler<Message> and that replaces your socketHandler variable.
To learn more, and to find out why you need socket to be final, look up "anonymous inner classes"
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have a problem when I want to run several methods not in the main thread. I created a class extends from Runnable and put all my tasks there. There are a lot of tasks actually. Then in the main thread I created a new instance of Thread and passed my runnable class as a parameter, but what I got is that the run method is the only code which executed in the thread, and if call any method inside the runnable class it will execute in the main thread instead of the new thread.
Example:
public class ConnectionManager implements Runnable {
#Override
public void run() {
login();
}
public void login() {
//Login Logic
}
public void sendMessage() {
//Send Message Via TCP Connection
}
public void updateInfo() {
//Update Information
}
public void logOut() {
//LogOut Logic
}
}
Now I wanted to call any of these methods in another thread, so I did this:
public class Login implements SomeInterface {
private Thread thread;
private ConnectionManager connection;
public void main(String[] args) {
connection = new ConnectionManager();
thread= new Thread(connection);
thread.start(); // This will execute the run method and the login process works fine.
}
#Override
public void someCallback() {
connection.sendMessage();//this call is not executed and block the main thread !!
}
}
What am I supposed to do to run all my methods in another thread without making a new thread for each method?
You should split your logic
public class Logger implements Runnable {
#Override
public void run() {
// login logic here;
}
}
public class MessegeSender implements Runnable {
#Override
public void run() {
//Send Message Via TCP Connection
}
}
public class MessegeSender implements Runnable {
#Override
public void run() {
//Update Information
}
}
public class MessegeSender implements Runnable {
#Override
public void run() {
//LogOut Logic
}
}
And then in some client:
Runnable logger = new Logger(credentials);
Executors.newSingleThreadExecutor().execute(logger);
Well this is how threads work in java. One possibility is to use Actors in java. You will have to download the Akka framework here:http://akka.io/downloads/.
Actors works by messages, they act in a separate process and are even driven messages. In other words depending on the message you send to the actor it will process a corresponding method.
Check in the following link for instances: http://doc.akka.io/docs/akka/snapshot/java/untyped-actors.html
The method run equivalent in java actors is onReceive().
And to send a message to the actor, myActor.tell(...)
Hope this helps you!!!!
Well, that is the way threads work in Java. When You call connection.sendMessage() Your method just treats ConnectionManager and runs it's code. You need to execute Your method in another threads run(), or it will not run. Perhaps You need a way to comunicate with Your thread to make it execute a method in run() or just explore the possibilities that Future objects give You?
That's how does Runnable or Multithread handling work.
You should never call the run() directly and only this function and other function calls inside this function are executed in the new thread.
Basically your Runnable class should only contains one public function: the run() and you should not call it directly...
I suggest you to put other functions in their own classes. As you can see the workflow is not continuous, sendMessage() is not called directly after login() (otherwise you can do it inside run() and don't need that someCallback()).
Otherwise what should that new thread supposed to do in the time between? block and wait for sendMessage()? That's not a good design. So you should start a new thread for sendMessage().
How can I add to the sending queue, for example I choose a file with JFileChooser and then send it in a new thread to the client, and I want to choose another and send it as well. What happens is that it sends the files simultaneously and the output on the client side is broken.
I'd like to be able to add to a "queue" of some sort, so that when the first file is sent, the server will start sending the next one.
A good aproach for socket communication between server->client, is to have 1 thread per client and have this thread reading from a java.util.concurrent.BlockingQueue. Such interface is ideal (just like all the java.util.concurrent objects) for managing multithreading concurrency.
The idea, is that the Server has a ClientThread like this:
class BroadCastThread extends Thread{
LinkedBlockingQueue<SendFileTask> bcQueue = new LinkedBlockingQueue<>();
#Override
public void run() {
while( true ){
try {
SendFileTask task = bcQueue.take();
task.sendFile();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
void addTask(SendFileTask rt) throws InterruptedException{
bcQueue.put(rt);
}
}
interface SendFileTask{
void sendFile() throws Exception;
}
And use this by adding tasks to you thread object:
BroadCastThread bct = new BroadCastThread();
bct.start();
//With lambda
bct.addTask(() -> {
//Send file code
});
//Without lambda
bct.addTask(new SendFileTask() {
#Override
void sendFile() throws Exception {
//Send file code
}
});
You can even store the Socket information with the thread, and pass it throw the task interface, if you want the sendFile method to receive it as parameter.
I want to send more than one response to client based on back end process. But in Netty examples I saw echo server is sending back the response at the same time.
My requirement is, I need to validate the client and send him OK response, then send him the DB updates when available.
How can I send more responses to client? Pls direct me to an example or any guide?
at every point in your pipeline you can get the pipeline Channel object from the MessageEvent object (or ChannelEvent) which is passed from handler to handler. you can use this information to send multiple responses at different points in the pipeline.
if we take the echo server example as a base, we can add a handler which send the echo again (that can be done also in the same handler, but the example is to show that multiple handlers can respond).
public class EchoServerHandler extends ChannelHandlerAdapter {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Channel ch = e.getChannel();
// first message
ch.write(e.getMessage());
}
// ...
}
public class EchoServerHandler2 extends ChannelHandlerAdapter {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Channel ch = e.getChannel();
// send second message
ch.write(e.getMessage());
}
// ...
}
You can do that as long as you have the reference to the relevant Channel (or ChannelHandlerContext). For example, you can do this:
public class MyHandler extends ChannelHandlerAdapter {
...
public void channelRead(ctx, msg) {
MyRequest req = (MyRequest) msg;
ctx.write(new MyFirstResponse(..));
executor.execute(new Runnable() {
public void run() {
// Perform database operation
..
ctx.write(new MySecondResponse(...));
}
}
}
...
}
You can do this as long as Netty doesn't close the Channel. Its better you call close() yourself when you're done.
Here's a sample: https://stackoverflow.com/a/48128514/2557517
I don't know how to solve this problem I hope that you can help me.
Behind Server side I have this:
class Baza0 implements Runnable{
anotherclass arraylist_handle = new anotherclass();
public method1(string s1){uses methods figured in arraylist_handle)
public run(){
while(true){
Socket s = s.accept();
if(s==NULL) continue;
//there I'm starting another thread that handles client connection
}
}
public static void main(){
Baza0 baza0 = new Baza0();
Thread t = new Thread(baza0);
}
}
Connected clients sends Strings by socketserver feature to client handler. How can I send this string from client handler to the method1 as parameter? It must use the only one Baza0 object, because of the ArrayList that must be common for all the clients.
EDIT
can someone tell me why something like Baza0.baza0.method1() won't work?
EDIT2
Look what I did!
I've made in Class Baza0 an static variable:
static Baza0 baza1;
and in main method I've started an Baza0 object:
Baza0 baza0 = new Baza0();
after this run the method that makes baza1 = baza0.
now from client handler I have access to method, by:
Baza0.baza1.method1(param);
It does work! :D ...don't know why.
If you are using the arraylist only for reading, then all the child threads are free to access it concurrently;
if the threads want to modify the list, then the list must be thread-safe;
if the modification involves many steps (reading and writing), then you must use synchronized blocks within which a "transaction" with the list happens.
Pass a Baza0 reference to Client Handler thread which can be used for calling method1.
public method1(string s1){
synchonized(arrayList){
//list operation
}
}
...
while(true){
Socket s = s.accept();
if(s==NULL) continue;
new Thread(
new WorkerRunnable(
clientSocket, this).start();
}
....
public class WorkerRunnable implements Runnable{
public WorkerRunnable(Socket socket,Baza0 ba){
this.socket = socket;
this.baza =ba;
}
public void run(){
...
this.ba.method1(...);
}
}
Your client thread must have a reference to that ArrayList - directly or (better) indirectly. Simplest way to do this is to pass Baza0 instance (this) to the client thread:
public class Client implements Runnable {
private final Baza0 baza;
public Client(Baza0 baza) {
this.baza = baza;
}
public void run() {
//...
baza.method1("Some string");
}
}
When you create your Client thread simply pass this:
new Thread(new Client(this)).start();
Important thread safety issue: method1() has to be synchronized or your ArrayList must be thread-safe.
I'd say what #Marko Topolnik said. Also I have a book Java Concurrency In Practice (that right now is not responding to me :-() or a link that led me to the book, in the blog The Java Specialists for handling thread issues. The book has examples of all queues, concurrent, synchronized lists, ways to implement code to do several things, etc, and all pretty straight forward, an example and a few paragraphs of every subject.
I'm mostly there with Netty but one concept is still alluding me, and I can't find anything in the tutorials and so on. Firstly I do understand that Netty is asynchronous, but there must be a way for a client to call the server and be able to get a response beyond the handler. Let me explain more.
I have a client as illustrated below. And please note that I understand it's bootstrapped and a new connection is established on each call, that's just there to make the example smaller and more succinct. Please ignore that fact.
Client.java
// ServerResponse is a result from the server, in this case
// a list of users of the system (ignore that each time it's all bootstrapped).
public User[] callServerForInformationFromGUIWidget()
{
ClientBootstrap bootstrap = new ClientBootstrap(...);
bootstrap.setPipelineFactory(...);
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
Channel channel = future.awaitUninterruptibly().getChannel();
// Where request is a POJO sent to the server,
// with a request such as get me a list of users
RequestPojo request = new RequestPojo(requestUserListCommand);
ChannelFuture lastWriteFuture = channel.write(request);
if(lastWriteFuture != null)
lastWriteFuture.awaitUninterruptibly();
}
Now I understand how to get the data on the server, and fire back the result. The only thing is how do I handle it on the client side? Yes the clientHandler class can do something like the following:
ClientHandler.java
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
{
User[] users = (User[])e.getMessage();
}
The problem is how does the client code actually get that result? All the examples are similar to a chat service, where the event fires off something else on the client that's not waiting on a response. Even the http client example I found lacking this. The documentation overall is really good, but it's lacking on how to do callbacks. Anyways, in this case I need the client to get the response from the server, and based on the results it will do what it needs.
In other words, how do I write the client to do something like this:
IdealClient.java
// ServerResponse is a result from the server, in this case
// a list of users of the system.
public User[] callServerForInformationFromGUIWidget()
{
...
RequestPojo request = new RequestPojo(requestUserListCommand);
ChannelFuture lastWriteFuture = channel.write(request);
if(lastWriteFuture != null)
lastWriteFuture.awaitUninterruptibly();
User[] users = resultFromCallToServer();
performSomeAction(users);
}
Because the handler doesn't know who is looking for the answer, or who asked the question. And if it's done in the handler, than how?
Back to my comments about the examples, the http client (and handler) examples just dump the result to System.out. If you had a GUI how would you pass the result from your request up to the GUI? I never saw any examples for this.
Jestan is correct. In my case I have a client that need to process price tick data. I use Antlr for the parsing. I fire my events in my parser, but in my case my protocol is String based. Below is an example without Antlr, I pass the String message in your case it could be the users.
//----------------- Event --------------
public class DataChangeEvent {
private String message;
public DataChangeEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
//----------------- Listener --------------
public interface DataChangeListenter {
public void dataChangeEvent(DataChangeEvent event);
}
//----------------- Event Handler that fires the dataChange events --------------
// This class needs to be static since you need to register all your classes that want to be notified of data change events
public class DataChangedHandler {
private static List<DataChangeListenter> listeners = new ArrayList<DataChangeListenter>();
public static void registerDataChangeListener(DataChangeListenter listener) {
listeners.add(listener);
}
public static void fireDataChange(DataChangeEvent dataChangeEvent) {
for(DataChangeListenter listenter : listeners) {
listenter.dataChangeEvent(dataChangeEvent);
}
}
}
//----------------- Example class that implements the listener and registers itself for events --------------
public class ProcessMessage implements DataChangeListenter {
public ProcessMessage() {
DataChangedHandler.registerDataChangeListener(this);
}
public void dataChangeEvent(DataChangeEvent event) {
//Depending on your protocal, I use Antlr to parse my message
System.out.println(event.getMessage());
}
}
//---------------- Netty Handler -----------
public class TelnetClientHandler extends SimpleChannelHandler {
private static final Logger logger = Logger.getLogger(TelnetClientHandler.class.getName());
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
String message = (String) e.getMessage();
DataChangedHandler.fireDataChange(message);
}
}
You have to handle it in the Handler with messageReceived(). I'm not sure what your issue is exactly. My guess is you have a response to a request that changes depending on what request was made? Maybe a concrete description of something you are doing of a response that has to know what request it came from. One thing you might be able to do is to pass a long living object the handler that knows the outstanding request, and it can match up the response when it receives it. The pipeline factory method can pass a reference to a manager type object to the Handler.
This was pretty much what I was trying to say. Your Handler is created in the PipelineFactory which is easy to pass parameters to the Handler from there:
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.nulDelimiter()));
pipeline.addLast("decoder", new XMLDecoder() );
pipeline.addLast("encoder", new XMLEncoder() );
// notice here I'm passing two objects to the Handler so it can
// call the UI.
pipeline.addLast("handler", new MyHandler(param1, param2));
return pipeline;
}
});
When you create your pipeline you'll add your Handler upon a new connection. Simply pass one or more objects that allows it to communicate back to the UI or a controller.