Hyperlinklistener will not connect [duplicate] - java

I'm encountering a weird issue in Java at the moment that I've never seen before.
The error is "No enclosing instance of type Server is accessible. Must qualify the allocation with an enclosing instance of type Server (e.g. x.new A() where x is an instance of Server)."
The line I've commented on is where the error occurs.
package game;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
public class Server {
private static List<ThreadModtagClient> clients;
class ReceiveDataListener implements SocketListener {
#Override
public void dataReceived(ThreadModtagClient client, String data) {
}
}
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
clients = new ArrayList<ThreadModtagClient>();
ServerSocket welcomeSocket = new ServerSocket(16567);
while (true) {
Socket connectionSocket = welcomeSocket.accept();
ThreadModtagClient client = new ThreadModtagClient(connectionSocket);
ReceiveDataListener listener = new ReceiveDataListener(); // <--- this is where the error occurs
client.addSocketListener(listener);
clients.add(client);
}
}
}
class ThreadModtagClient extends Thread implements SocketThread {
private BufferedReader inFromClient;
private DataOutputStream outToClient;
private Player player;
private List<SocketListener> listeners;
public ThreadModtagClient(Socket connection) throws IOException {
inFromClient = new BufferedReader(new InputStreamReader(connection.getInputStream()));
outToClient = new DataOutputStream(connection.getOutputStream());
listeners = new ArrayList<SocketListener>();
}
public void addSocketListener(SocketListener listener) {
listeners.add(listener);
}
public void removeSocketListener(SocketListener listener) {
listeners.remove(listener);
}
public Player getPlayer() {
return player;
}
public void setPlayer(Player player) {
this.player = player;
}
public void sendData(String data) throws IOException {
outToClient.writeChars(data);
}
public void run() {
while (true) {
try {
String data = inFromClient.readLine();
for(SocketListener listener : listeners) {
listener.dataReceived(this, data);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch(NoSuchElementException e1) {
e1.printStackTrace();
}
}
}
}

Server.ReceiveDataListener is a (non-static) inner class. You are creating it from a static context. You need to supply an instance of Server to be the outer instance. However, almost certainly you want ReceiveDataListener to be a static nested class, or probably an outer class.

well the error tells you exactly what needs to be done. ReceiveDataListener is a non-static inner class and must be accessed via an object of the outer class (Server). You have three options:
1. take the compiler's advice (access via an object of Server)
2. make ReceiveDataListener static
3. pull ReceiveDataListener out to a separate .java and use it.
HTH

You cannot instantiate a non-static inner class from a static context like main.

This is because you're trying to create a ReceiveDataListener from a static method, and since ReceiveDataListener is not a static class, it needs to be attached to an instance of Server.

Related

RMI: Proper synchronization when Server is accessed by multiple clients

I started working with Java RMI a couple of days ago. I am wondering if the following example is properly synchronized.
Consider the following Server class which provides resource strings to clients. It shall never provide the same resource twice, therefor it stores the provided strings in a list. This is the ServerEngine class:
package dummy;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.LinkedList;
public class ServerEngine implements Server {
private final String s1 = "Resource Object 1";
private final String s2 = "Resource Object 2";
private final LinkedList<String> list = new LinkedList<>();
private final int timer = 5000;
public static void main(String[] args) {
try {
String name = "server";
ServerEngine engine = new ServerEngine();
Server stub = (Server) UnicastRemoteObject.exportObject(engine, 0);
Registry registry = LocateRegistry.getRegistry();
registry.rebind(name, stub);
System.out.println("ServerEngine bound");
} catch (Exception e) {
System.err.println("ServerEngine exception:");
}
}
#Override
public String getResource() throws RemoteException {
Object lock = new Object();
if ( ! list.contains(s1)) {
synchronized (lock) {
// wait to ensure concurrency
try {
lock.wait(timer);
} catch (InterruptedException ex) {}
}
list.add(s1);
return s1;
}
if ( ! list.contains(s2)) {
list.add(s2);
return s2;
}
return null;
}
}
The Server interface:
package dummy;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Server extends Remote {
public String getResource(boolean synced) throws RemoteException;
}
and the Client:
package dummy;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
public static void main(String[] args) {
try {
String name = "server";
Registry registry = LocateRegistry.getRegistry();
Server server = (Server) registry.lookup(name);
boolean sync = args.length > 0;
String s = server.getResource(sync);
System.out.println("Resource: " + s);
} catch (Exception e) {
System.err.println("Client exception:");
}
}
}
The ServerEngine is implemented in such a way that it will cause a concurrency issue. If two clients are started from two different VMs within five seconds then they both will get the same String returned.
From what I have researched so far, this is my approach to solve the issue:
package dummy;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.LinkedList;
public class ServerEngine implements Server {
private final String s1 = "Resource Object 1";
private final String s2 = "Resource Object 2";
private final LinkedList<String> list = new LinkedList<>();
private final int timer = 5000;
public static void main(String[] args) {
try {
String name = "server";
ServerEngine engine = new ServerEngine();
Server stub = (Server) UnicastRemoteObject.exportObject(engine, 0);
Registry registry = LocateRegistry.getRegistry();
registry.rebind(name, stub);
System.out.println("ServerEngine bound");
} catch (Exception e) {
System.err.println("ServerEngine exception:");
}
}
private synchronized String localGetResource() {
Object lock = new Object();
if ( ! list.contains(s1)) {
synchronized (lock) {
// wait to ensure concurrency
try {
lock.wait(timer);
} catch (InterruptedException ex) {}
}
list.add(s1);
return s1;
}
if ( ! list.contains(s2)) {
list.add(s2);
return s2;
}
return null;
}
#Override
public String getResource() throws RemoteException {
return localGetResource();
}
}
I would like to know if this is a feasible solution. Are there any caveats? Do I actually need a second function or could I synchronize getResource() directly?
Your synchronization is broken on several levels:
You're not supposed to wait() on something unless you expect some other thread to notify() you.
You're implementing only half of double-checked locking, which translates to "no locking", as the same value may end up in the list several times.
You should have a look at proper thread-safe collection implementations under java.util.concurrent, rather than doing this by hand.
Your locally create lock object is useless, as tsolakp noted, every method call creates its own instance.
Create the object as a field in order to use it's monitor for sychronization.
If you declare a method as synchronized you've use implicitly the monitor of the instance the method is invoked on. It makes no sense to mix these two approaches.
If you want to synchronize the access to your list use the according object's monitor for synchronization.
I am wondering if the following example is properly synchronized.
It isn't synchronized at all. It uses a lock, but not correctly, so it isn't sequentialized either.
public String getResource() throws RemoteException {
Object lock = new Object();
if ( ! list.contains(s1)) {
synchronized (lock) {
// wait to ensure concurrency
try {
lock.wait(timer);
} catch (InterruptedException ex) {}
}
list.add(s1);
return s1;
}
if ( ! list.contains(s2)) {
list.add(s2);
return s2;
}
return null;
}
You don't need all this, and you certainly don't need the wait(). This code will never actually lock the list effectively, because every invocation gets its own lock object.
Throw it all away and just synchronize the method:
public synchronized String getResource() throws RemoteException {
if ( ! list.contains(s1)) {
list.add(s1);
return s1;
}
if ( ! list.contains(s2)) {
list.add(s2);
return s2;
}
return null;
}

How to print lines from another class

UPDATE
I was wrong the whole time. I was blocking the output with a method I was using and didn't add here. Now it works well and I'm able to write from other process.
I would like to know if there is any way of printing a line to a console view from outside. I have a class (class1) that has an onMessage method.
public class Class1 implements MessageListener {
...
public void onMessage(Message msg) {
System.out.println(msg.getText());
}
...
}
And then I have a class with a main that creates an instance of this class and while doing things the onMessage of Class1 fires.
public class Class2{
public static void main(String args[]) {
Class1 obj = new Class1();
...
while(!":q".equals((action = scanner.next()))){
obj.anotherAction(action);
}
...
}
}
When I try that the object seems to be blocked. I think that I'm approaching wrong to the solution. Maybe calling println from outside blocks as it doesn't have anywhere to print to.
I would like to understand what's happening and how could I solve this. My problem is using the output that creates the Class2 main from Class1.
I hope I explained well, I'm not a native speaker.
EDIT
Now I added more coding. I'm now realizing that waiting for the standard input maybe is interfering with the Print of the other class. Should I run an external proccess for the output? How could I do it on the same console view?
try this
Class1.java
import java.util.Scanner;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;
public class Class1 {
public static void main(String args[]) throws JMSException {
Class2 obj = new Class2();
Scanner s=new Scanner(System.in);
Message m;
TextMessage textMessage = null;
System.out.println("Enter a message");
textMessage.setText(s.next());
m=(Message)textMessage;
obj.onMessage(m);
}
}
Class2.java
import javax.jms.*;
public class Class2 implements MessageListener{
public void onMessage(Message msg) {
System.out.println(msg.toString());
TextMessage textMessage = (TextMessage) msg;
try {
System.out.println(textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}

Why am I getting this error: "error: { expected" in JCreator?

I am in an introductory networking class this semester and we are working with Server/Client chat rooms. This is my Server program so far, and I can't figure out why I'm getting the error in the title. It show the error on lines 17, 33, and 53, which are all lines where I've named new classes.
Any help with me appreciated!
import java.io.*;
import java.net.*;
public class Server
{
public static void main(String[] args) throws Exception
{
new MyServer().start(); //Creates new Server for Clients to connect
}
}
public class MyServer() extends Thread
{
ServerSocket SS = new ServerSocket(11200);
Socket S;
ClientManager CM = new ClientManager();
public void run()
{
while(true)
{
S = SS.Accept; //Endless loop allowing clients to repeatedly connect
CM.Add(); //Calls the Add method in ClientManager, which adds the Client to the Array
}
}
}
public class MyClient() extends Thread
{
MyClient Client = new MyClient(Socket, CM);
Scanner S;
public void run()
{
while(true)
{
S = new Scanner(System.in);
CM.SendToAllClients(S); //Calls the method that will send each client the received message
}
}
public void Send(String S)
{
PrintWriter.println(S);
}
}
public class ClientManager()
{
MyClient[] X = new MyClient[15];
int num = 0;
public synchronized void Add(MyClient C)
{
X[num] = C;
num++;
C.start();
}
public synchronized void SendToAllClient(String S)
{
for(i = 0;i < num;i++);
{
X[i].Send(S);
}
}
}
Don't use () after your class names:
public class MyServer extends Thread {...}
public class MyClient extends Thread {...}
public class ClientManager {...}

How to call a string to appear in another class

I have this class called Main. java. In this the output is shown by inputLine which is a string taken serially from the com port. i want this string value to be used in some other class which is in the same default package. How do i call this string in other class. How do i create an instance of this class and call the string inputLine in any other xyz.java class. An example would be very helpful.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.util.Enumeration;
public class Main implements SerialPortEventListener
{
SerialPort serialPort;
/** The port we're normally going to use. */
private static final String PORT_NAMES[] = {
"COM30", // Windows
};
/**
* A BufferedReader which will be fed by a InputStreamReader
* converting the bytes into characters
* making the displayed results codepage independent
*/
private BufferedReader input;
/** The output stream to the port */
private OutputStream output;
/** Milliseconds to block while waiting for port open */
private static final int TIME_OUT = 2000;
/** Default bits per second for COM port. */
private static final int DATA_RATE = 9600;
public void initialize() {
CommPortIdentifier portId = null;
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
//First, Find an instance of serial port as set in PORT_NAMES.
while (portEnum.hasMoreElements()) {
CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
for (String portName : PORT_NAMES) {
if (currPortId.getName().equals(portName)) {
portId = currPortId;
break;
}
}
}
if (portId == null) {
System.out.println("Could not find COM port.");
return;
}
try {
// open serial port, and use class name for the appName.
serialPort = (SerialPort) portId.open(this.getClass().getName(),
TIME_OUT);
// set port parameters
serialPort.setSerialPortParams(DATA_RATE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// open the streams
input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
output = serialPort.getOutputStream();
// add event listeners
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
} catch (Exception e) {
System.err.println(e.toString());
}
}
/**
* This should be called when you stop using the port.
* This will prevent port locking on platforms like Linux.
*/
public synchronized void close() {
if (serialPort != null) {
serialPort.removeEventListener();
serialPort.close();
}
}
/**
* Handle an event on the serial port. Read the data and print it.
*/
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
String inputLine=input.readLine();
System.out.println(inputLine);
} catch (Exception e) {
System.err.println(e.toString());
}
}
// Ignore all the other eventTypes, but you should consider the other ones.
}
public static void main(String[] args) throws Exception {
Main main = new Main();
main.initialize();
Thread t=new Thread() {
public void run() {
//the following line will keep this app alive for 1000 seconds,
//waiting for events to occur and responding to them (printing incoming messages to console).
try {Thread.sleep(1000000);} catch (InterruptedException ie) {}
}
};
t.start();
System.out.println("Started");
}
}
In your case, you should just create a class variable.
Just declare inside the class, public static String inputLine;
Change String inputLine=input.readLine(); to inputLine=input.readLine(); and you can access it from other classes in the same package using Main.inputLine.
First of all the variable has to be either an instance variable or a class variable if you want to access it somewhere else, variables created within a method can only exist inside of that method and will die as soon as the method returns.
In order to access the variable from another class you have to make it available, there are no friends in Java as in C++. You have 3 options.
Create a public instance variable, then provide a reference to the instance to those that need to access the information.
Create a private instance variable and public setter/getter methods to access it from the outside, then provide a reference to the instance to those that need to access the information.
Create a public static (class) variable.
Sounds like the Observer Pattern for me...
Create an Interface eg. SerialListener that every class to be informed implements. The interface has one method with string parameter that is called by your Main Class every time new information arrives.
And of cause the main class has methods to register new listeners and stores them in a list
List toBeCalled = new ArrayList()
Just like other Listeners in Swing etc.

How to send an OBJECT over TCP in java?

I'm writing a program to send an object from one class to another class. Here is a short sample example of my program to represent the problem. As you can see the object to send from server to client is Student class which has been defined separately in each class(Server/Client). I have examined this code by sending an ArrayList which works fine but when it comes to a class type which defined by myself i'm receiving this error:
Exception in thread "main" java.lang.ClassCastException: ServerSide$1Student cannot be cast to ClientSide$1Student
at ClientSide.main(ClientSide.java:29)
Here is the code for Server side:
import java.io.*;
import java.net.*;
public class ServerSide {
public static void main(String[] args) {
class Student implements Serializable
{
int id;
public Student(int num){id=num;}
public void setID(int num){id=num;}
public void Print(){System.out.println("id = " + id);}
}
try
{
Student a = new Student(3);
ServerSocket myServerSocket = new ServerSocket(9999);
Socket skt = myServerSocket.accept();
try
{
ObjectOutputStream objectOutput = new ObjectOutputStream(skt.getOutputStream());
objectOutput.writeObject(a);
}
catch (IOException e)
{
e.printStackTrace();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
And for the client side is:
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientSide {
public static void main(String[] args)
{
class Student implements Serializable
{
int id;
public Student(int num){id=num;}
public void setID(int num){id=num;}
public void Print(){System.out.println("id = " + id);}
}
try {
Socket socket = new Socket("10.1.1.2",9999);
try {
ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream());
try {
Object object =(Student) objectInput.readObject();
Student tmp = (Student) object;
tmp.Print();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Edit:
I moved them to same file and added serialise ID. It works fine.
Having two classes with the same name is not enough. The two classes need to have
the same package
be in the same outer class if any
have the same serialVersionUID.
I suggest you have a single, stand alone class which is common for both the client and the server. In a more complex project you might consider building these common components in a module which both the client and server modules depend on.
You cannot ever deserialize a stream representing an instance of class X into an instance of class Y.
To solve your problem, you need to move the code for the Student class to another file, say Student.java, and use that single class on your client code and on your server code.
Note that if you modify your class, in most cases you will need to redeploy the server (otherwise the client would send the server an stream representing an instance of class that is known only to the client).
You are referencing two different classes. Student which is an inner of ClientSide and Student which is an inner class of ServerSide. You should move the Student class to a different file.

Categories