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.
Related
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;
}
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.
Its really hard for me to find on google what i am specially looking for or even explaining it correctly without knowing any special words, sry. I am working on my first SocketServer and want to expand it with a GUI. the first step i want to try is to create a simple logwindow for the server activity. i have a JFrame and can pass text to it.
public class Logger {
private JFrame frame;
private JTextArea tArea;
private JScrollPane jsp;
private StringBuilder sb = new StringBuilder();
File file = new File("C://");
public static void main(String[] args) {
String logTitle = new String(args[0]);
new Logger(logTitle);
}
public Logger(String logTitle) {
init(logTitle);
frame.setVisible(true);
//logToLogger(); // function to append logdata to textarea
}
public void logToLogger(String logText) {
tArea.append(logText.toString());
tArea.setCaretPosition(tArea.getDocument().getLength());
}
private void init(String logTitle) {
frame = new JFrame();
frame.setSize(400, 400);
frame.setTitle(logTitle);
frame.setLocationRelativeTo(null);
tArea = new JTextArea();
jsp = new JScrollPane(tArea);
frame.add(jsp, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
i also have a main class for starting my server. when starting the mainclass, a logger should be initiated and then i will pass it to a new started Thread.
my mainclass
I WANT TO PASS THE LOGGER TO THE MYTHREAD CLASS ON THE LINE WHERE I WROTE THE INLINE COMMENT
import java.net.*;
import java.io.*;
import java.util.*;
public class Server {
public static void main(String[] args) {
Integer port = new Integer(args[0]);
String logTitle = new String(args[1]);
Logger log = new Logger(logTitle);
MyThread t = new MyThread(port, log); // thats the part i cant handle
log.logToLogger("Started on port " + port);
}
}
and here is how i would start a thread
public class MyThread {
public static void main(int port, Logger log) {
log.logToLogger(port + "logged from MyThread");
}
}
It looks like you haven't written anything that takes data in from a socket. You just need to pass the Logger object to the MyThread constructor, and call log.logToLogger(receivedText); from MyThread.
Your code should look like:
public class MyThread implements Runnable {
private Logger log;
private ServerSocket socket;
public MyThread(int port, Logger log) {
this.log = log;
log.logToLogger("SocketServer opened on port "+port);
try {
socket = new ServerSocket(port);
} catch (IOException e) {
log.logToLogger(e.getMessage());
}
}
#Override
public void run() {
while(true) {
Socket server;
try {
server = socket.accept();
log.logToLogger("Connection from"+server.getRemoteSocketAddress());
BufferedReader reader = new BufferedReader(new InputStreamReader(server.getInputStream()));
log.logToLogger("Received:"+reader.readLine());
server.close();
} catch (IOException e) {
log.logToLogger(e.getMessage());
}
}
}
}
public static void main(String[] args) {
Integer port = new Integer(args[0]);
String logTitle = new String(args[1]);
Logger log = new Logger(logTitle);
MyThread t = new MyThread(port, log);
(new Thread(t)).start();
}
Socket code is adapted from here: http://www.bogotobogo.com/Java/tutorial/tcp_socket_server_client.php
From cmd prompt on windows, run telnet 127.0.0.1 1234 and type your message, it should come up in the JFrame assuming you run the app on port 1234.
You should probably extend the run() method to be more robust than just closing on line being received.
Hm, it seems to me that your entry point is ambiguous among the several classes... You may wanna start by renaming/modifying the 'main' methods in everything except your actual main class where you want it to enter. As it stands you currently have several acceptable entry points to your program from the looks of things. In particular, the 'main' method in your Logger class will never get called if your code executes the way you want it to, so you're gonna have to move that code elsewhere, perhaps to the constructor or something.
Also, init is called when running your java program as an applet, whereas public static void main(String[] args) is called when running as a standalone java application. However, both methods will not run at the beginning of the same program. In your Logger class you should move the code in init to an appropriate place in your constructor.
Jonno_FTW also has a good point about passing Logger as a parameter to constructor as well. You will also need to extend the Thread class or implement Runnable if you want to use MyThread as a thread (see http://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html). After that you will be able to actually start the thread using MyThread.start().
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.
I'm working on my chat project. I've programmed server and client sides that works without GUI, just console UI. Now, while working on clients GUI (with Netbeans provided tools, not as I am used to code by myself), I've stuck on binding problem.
Inside of ClientGui class I have Client object. In my GUI I want to disable input textfield until client isn't connected to a chat server. I've tried to bind (via Netbeans GUI) my input textfield's property enabled to that client object's method isConnected() (that returns boolean). isConnected isn't just returning some variable's value, it's combined boolean expression. So when user clicks to connect, it succeeds, but input textfield doesn't change it's state to enabled.
So as I get it, I have to work with event and listeners and notify in my Client class? But what is point of binding then, as I could just have event fired on my Client and my input field listen to clients connected event?
So I provide chunks of my code.
The Client class: (You may see some lines with action listeners and event, I didn't remove them, just experimented)
public class Client {
private ClientListener listener;
private ClientSender sender;
private Socket connection;
private boolean finnish = false;
private PropertyChangeEvent connected;
public Client(String hostname, int port) throws UnknownHostException, IOException {
connection = new Socket(hostname, port);
}
public void start() {
try {
connected = new PropertyChangeEvent(this, "connected", null, connection);
sender = new ClientSender(new ObjectOutputStream(connection.getOutputStream()));
Thread senderThread = new Thread(sender);
senderThread.start();
Logger.getLogger(Client.class.getName()).log(Level.INFO, "Sender thread has started");
listener = new ClientListener(new ObjectInputStream(connection.getInputStream()));
Thread listenerThread = new Thread(listener);
listenerThread.start();
Logger.getLogger(Client.class.getName()).log(Level.INFO, "Listener thread has started");
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, "IO problems", ex);
}
}
public ClientSender getSender() {
return sender;
}
public void stop() {
sender.stop();
listener.stop();
}
public boolean isConnected() {
return connection != null && !connection.isClosed();
}
}
The Client GUI class:
public class ClientGui extends javax.swing.JFrame {
private Client client;
public boolean getConnected() {
System.out.println( client != null && client.isConnected());
return client != null && client.isConnected();
}
/**
* Creates new form ClientGui
*/
public ClientGui() {
initComponents();
}
// GENERATED CODE
private void tfUserInputKeyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
Message message = new Message("user", tfUserInput.getText());
client.getSender().add(message);
tfUserInput.setText("");
}
}
private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {
try {
client = new Client(tfHostname.getText(), Integer.parseInt(tfPort.getText()));
client.start();
} catch (UnknownHostException ex) {
Logger.getLogger(ClientGui.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ClientGui.class.getName()).log(Level.SEVERE, null, ex);
}
}
// and somewhere GUI generated code of my binding (also tried with custom code, but no success)
org.jdesktop.beansbinding.Binding binding =
org.jdesktop.beansbinding.Bindings.createAutoBinding
(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ, this,
org.jdesktop.beansbinding.ELProperty.create("${connected}"), listConversation,
org.jdesktop.beansbinding.BeanProperty.create("enabled"), "listConversationBinding");
bindingGroup.addBinding(binding);
In fact it's a JList, but doesn't matter, because I want such binding for few components.
Here I try to use fake method in GUI Form, which calls clients connected (did it because don't how to add Client as a component).
I've read on forums, everywhere saying about beans and so on. I want my Client class to have least as possible code needed for GUI, interface implementations and calls for firing event and so on.
UPDATE
Very good! Thank you. Why can't I bind so I don't have to use setEnabled(value) method (make that enabled property keeps track of boolean expression "property" (connection != null && !connection.isClosed()). Also, because of this trick I have to do setConnected(value), even if this is resolved in runtime depending on a connection, and I even can't know old value (of course I can do private void setConnected(booleanvalue) and put calls to this with true or false depending on what happens in those places. Seems like my idea of using property is wrong, better do with actions or events.
You should add PropertyChangeSupport to the Client.
final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener listener) {
this.pcs.addPropertyChangeListener(listener);
}
boolean connected;
public boolean isConnected() {
return connected;
}
public void setConnected(boolean connected) {
boolean oldValue = this.connected;
this.value = connected;
this.pcs.firePropertyChange("connected", oldValue, newValue);
}
.....
public Client(String hostname, int port) throws UnknownHostException, IOException {
connection = new Socket(hostname, port);
setConnected(connection != null && !connection.isClosed());
}
in the GUI
public class ClientGui extends javax.swing.JFrame implements PropertyChangeListener
.....
propertyChanged(..){
tfUserInput.setEnabled(true);
}
private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {
try {
client = new Client(tfHostname.getText(), Integer.parseInt(tfPort.getText()));
client.addPropertyChangeListener(this);
client.start();
.....
Melasse framework ease the pain make such binding between model/view(ui component), in most case without even having to code extra anonymous classes: https://github.com/cchantep/melasse