lbpeppers lbpeppers - 1 month ago 12
Java Question

How to properly use class methods in a thread? [Solved]

I'm working on this:

//
// Application: Golf App Server
// Author: Andres Martinez
// Year: 2016
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package com.andress.golfappserver.listener;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import com.andress.golfappserver.beans.Client;
import com.andress.golfappserver.client.ClientHandler;
import com.andress.golfappserver.client.ClientStatus;

/**
* This class has two main goals. First, start to listening the server in a certain port and
* second, accepting incoming connections from clients. It runs as a Thread. The server
* Administrator should provide the number of the port. When the Listener object is initialized
* the ServerSocket will be listening to the port provided. To start to accept new connections
* the Thread should be started. The Listener will create a new Client object every time when accepts
* a new connection. The new Client will have the Socket accepted and a ClientStatus by default of
* Connected. Then, a ClientHandler will be created with the Client as an argument.
* The ClientController will be notified every time a new ClientHandler Thread is created.
*/
public class Listener implements Runnable {
private final int port;
private final ServerSocket serverSocket;

/**
* The Listener is instantiated and initialized with a port number
* supplied by the Server Administrator. Then, the constructor
* creates a new SeverSocket with this port ready to start to listen
* for new connections.
* @param port Integer to identify port.
*/
public Listener(final int port) {
this.port = port;
this.serverSocket = listen();
}

public int getPort() {
return port;
}

public ServerSocket getServerSocket() {
return serverSocket;
}

/**
* Creates Client objects for accepted connections and spawns
* a new ClientHandler for each of the new Client connections.
*/
@Override
public void run() {
Client client = createClient(accept(this.serverSocket));
ClientHandler clientHandler = new ClientHandler(client);
//clientHandler.start();
}

/**
* Binds the port provided by the Server Administrator to a new
* ServerSocket.
* @return ServerSocket listening to the port provided.
*/
private final ServerSocket listen() {
try (ServerSocket serverSocket = new ServerSocket(port)) {
return serverSocket;
} catch (IOException e) {
throw new RuntimeException(e);
}
}

/**
* Starts to listen for connections to the port specified.
* @param serverSocket ServerSocket to listen for.
* @return Socket of the accepted connection.
*/
private final Socket accept(final ServerSocket serverSocket) {
try (Socket clientSocket = serverSocket.accept()) {
return clientSocket;
} catch (IOException e) {
throw new RuntimeException(e);
}
}

/**
* Creates a new Client Bean with ClientStatus by default
* of Connected and the Socket of the new connection.
* @param clientSocket Socket for the new connection.
* @return Client object with ClientStatus of Connected by default.
*/
private final Client createClient(final Socket clientSocket) {
Client client = new Client();
client.setSocket(clientSocket);
client.setStatus(ClientStatus.CONNECTED);
return client;
}
}


I'm having an error with the socket but, I'm not interested in this particular error. What I would like to know if a thread always need the code to be executed inside the run() method or is there a way to do it like I'm attempting to do it?

Error:

Exception in thread "Thread-0" java.lang.RuntimeException: java.net.SocketException: Socket is closed
at com.andress.golfappserver.listener.Listener.accept(Listener.java:85)
at com.andress.golfappserver.listener.Listener.run(Listener.java:58)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.SocketException: Socket is closed
at java.net.ServerSocket.accept(ServerSocket.java:509)
at com.andress.golfappserver.listener.Listener.accept(Listener.java:82)
... 2 more

Process finished with exit code 0

Answer

a thread always need the code to be executed inside the run() method

Yes. That's what a Java Thread does.

or is there a way to do it like I'm attempting to do it?

You're actually calling some methods inside run(), so it should work altogether.

UPDATE

In accept() method:

private final Socket accept(final ServerSocket serverSocket) {
    try (Socket clientSocket = serverSocket.accept()) {
        return clientSocket;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

You are accepting the socket in a try-with-resources construction. It means that as soon as this method ends, the socket closes. I bet that's not what you want to be done. Try this instead:

private final Socket accept(final ServerSocket serverSocket) {
    try {
        return serverSocket.accept();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}