Is there a way to get around during the serialization of the object full match / repetition of the way? For example:
on the client -
com.example.myProjectOne.model.MyClass
on the server side -
com.example.notMyProject.entity.MyClass
I get -
java.lang.ClassNotFoundException:
com.example.myProjectOne.model.MyClass
with the full coincidence of the names of all work packages
public class Server implements Runnable {
private SettingsConnection settingsConnection;
private OnReceiveObject onReceiveObject;
private Serializer serializer;
/**
* #param remoteServerAddress - address remote server
* #param inputPort - the port on which the is server
* #param outputPort - the port which used for send
* #param password - the password which should to be same on the client side and the server side
* #param handler - defines the name of the method, which should to be called, after received the data on server side
*/
public Server(String remoteServerAddress, int inputPort, int outputPort, String password, OnReceiveObject handler) {
settingsConnection = new SettingsConnection();
settingsConnection.setAddressRemoteServer(remoteServerAddress);
settingsConnection.setInputPort(inputPort);
settingsConnection.setOutputPort(outputPort);
this.onReceiveObject = handler;
serializer = new Serializer();
new Thread(this).start();
}
public void sendData(Serializable object, String callBackFunction) {
Container container = new Container();
try {
container.setData(serializer.serialize(object), container.getInitVector()));
container.setHandler(callBackFunction);
InetAddress ipAddress = InetAddress.getByName(settingsConnection.getAddressRemoteServer());
try (Socket socketConnectionToSever = new Socket(ipAddress, settingsConnection.getOutputPort())) {
OutputStream outputStream = socketConnectionToSever.getOutputStream();
if (outputStream != null) {
outputStream.write(serializer.serialize(container));
outputStream.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
final ExecutorService asyncTakesCode = Executors.newCachedThreadPool();
Runnable threadTaskServer = new Runnable() {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(settingsConnection.getInputPort());
while (true) {
Socket connectionSocketClient = serverSocket.accept();
asyncTakesCode.submit(new ThreadTaskClient(connectionSocketClient));
}
} catch (IOException e) {
System.err.println("Unable to process client request");
e.printStackTrace();
}
}
};
Thread threadServer = new Thread(threadTaskServer);
threadServer.start();
}
private class ThreadTaskClient implements Runnable {
private final Socket connectionSocketClient;
private ThreadTaskClient(Socket connectionSocketClient) {
this.connectionSocketClient = connectionSocketClient;
}
#Override
public void run() {
InputStream inputStream = null;
try {
inputStream = connectionSocketClient.getInputStream();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
Object o = serializer.deserialize(IOUtils.readFully(inputStream, -1, false));
if (o instanceof Container) {
Container container = (Container) o;
Serializable remoteObject = (Serializable) serializer.deserialize(container.getData()));
String callBackFunction = container.getHandler();
onReceiveObject.processRemoteObject(remoteObject, callBackFunction);
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
connectionSocketClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
If you're using java's serialization, the classes must match both ends.
Include your class in the server side's classpath.
If you can't do that, you could make it work by effectively creating an alias of your class name for the other class:
package com.example.myProjectOne.model;
public class MyClass extends com.example.notMyProject.entity.MyClass {
}
There are a few caveats of course, for example the would only work if the two classes share the same non-transient instance field names and types.
Yes, you can. You have to extend the default ObjectInputStream and override the resolveClass method (maybe others, not sure).
So, for example:
ObjectInputStream ois = new ObjectInputStream( lis ) {
protected Class<?> resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException {
if (osc.getName().contains("some.package.element")) {
try {
Field nameField = osc.getClass().getField("name");
nameField.setAccessible(true);
nameField.set(osc, osc.getName().replace("some.package.element", "another.package.element"));
nameField.setAccessible(false); // hack because "name" is private
} catch (NoSuchFieldException | IllegalAccessException e) {
// ...
}
}
return super.resolveClass(osc);
}
}
Related
So my problem is I have a client with a Runnable that readobjects in background from the socket. In the server i send multiple times objects like notifications updates etc by writeUnshared, but the client is only receiving them when I send a request back to server by writeUnshared.
\ClientThread.java\
public class ThreadClientInFromServer implements Runnable {
Socket socket;
ClientData clientData;
public ThreadClientInFromServer(Socket socket, ClientData clientData) {
this.socket = socket;
this.clientData = clientData;
}
#Override
public void run() {
ObjectInputStream in;
ObjectOutputStream out;
out = clientData.getOut();
in = clientData.getIn();
while (!socket.isClosed()) {
try {
Object object = in.readObject();
clientData.updateData(object);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
SendRequestClient.java Only when i send this request it refresh and come the updates,notifications,etc
public void sendRequest(Request request) {
try {
out.writeObject(request);
out.flush();
out.reset();
} catch (IOException e) {
System.out.println("[ERROR] ON SEND REQUEST!");
return;
}
}
On Server (KEEPALIVETCP.java) for example, he doesnt receive.
public class KeepAliveTCP implements Runnable {
ServerModel serverModel;
public KeepAliveTCP(ServerModel serverModel) {
this.serverModel = serverModel;
}
#Override
public void run() {
Request request = new Request(null, Constants.ACK);
while (!serverModel.getSocket().isClosed()) {
try {
for (SocketModel clients : serverModel.getModelClientes()) {
if (clients.getNome() != null) {
clients.getOut().writeUnshared(request);
clients.getOut().flush();
}
}
sleep(5000);
watchWhoFails();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thanks in Advance!!!
EDIT : So I was trying to find a solution and come up with my cliente blocking the thread(ThreadClientInFromServer) when he uses scanner.next() on the menus(that user uses to browse on the application). So I dont really know how to solve this problem, if you guys know some solution for this!
Thanks.
I'm making Chatting-Room program using the Java Swing.
In the client side, I was saw that doesn't read message from the server side.
The writeUTF() method of the client side is very well and I'm checked readUTF and writeUTF on the server side, that was very well too.
I think the problem is code which does as "Receiver" on the client side.
In the run() method of Thread, The instance dis of the DataInputStream has continuously null value.
I'm so confusing.. Please give me some help.
The bellow is part of my client&server code.
Thanks!
Client code
RoomBackground.java
public class RoomBackground {
private static String socket_server = "127.0.0.1";
private static Socket chatSocket;
private static DataOutputStream dos;
private static DataInputStream dis;
private ChatReceiver chatReceiver;
public Socket getChatSocket() {
return chatSocket;
}
public static DataOutputStream getDos() {
return dos;
}
public RoomBackground() throws IOException {
chatSocket = new Socket(socket_server, 7777);
chatReceiver = new ChatReceiver();
chatReceiver.start();
dos = new DataOutputStream(chatSocket.getOutputStream());
dis = new DataInputStream(chatSocket.getInputStream());
dos.writeUTF(User.getUser().getUsername());
dos.flush();
}
class ChatReceiver extends Thread {
#Override
public void run(){
try {
# PROBLEM CODE..... Allways "dis is null"
System.out.println("dis is " + dis);
# This line never executed.
while(dis != null) {
# some codes.....
}
} catch (IOException e) {
e.printStackTrace();
System.out.println(e.toString());
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}
}
RoomFrame.java
public class RoomFrame extends JFrame{
private RoomBackground roomBackground;
public RoomFrame(int roomId) throws IOException {
chatField.addActionListener(new ActionListener() {
roomBackground = new RoomBackground();
#Override
public void actionPerformed(ActionEvent e) {
String msg = chatField.getText() + "\n";
try {
RoomBackground.getDos().writeUTF(msg);
# It works.
System.out.println("sent msg is " + msg);
} catch (IOException e1) {
e1.printStackTrace();
}
chatField.setText("");
}
});
}
}
Now server code.
Server Background.java
public class ChatReceiver extends Thread {
private DataInputStream in;
private DataOutputStream out;
public ChatReceiver(Socket chatSocket) throws IOException {
out = new DataOutputStream(chatSocket.getOutputStream());
in = new DataInputStream(chatSocket.getInputStream());
nick = in.readUTF();
addChatClient(nick, out);
}
#Override
public void run() {
try {
while(in!=null) {
chatMsg = in.readUTF();
# It works !
System.out.println("before send" + chatMsg);
sendMsg(chatMsg);
# It works too!
System.out.println("after send" + chatMsg);
}
}catch (IOException e) {
removeChatClient(nick);
}
}
}
When you are starting the ChatReceiver thread in the RoomBackground the dis object is not initialized yet, that is why it is null. One solution could be to initialize the dis variable in the ChatReceiver constructor.
Hello dear programmers ,
I am trying to make a tic tac toe game using android, my android application contains several activities, one of these activities can the allows client to send a message to the server asking if X user wants to challenge, if the user accepts the challenge the server messages me and we both move forward to another activity.
My server is running as a regular java code on my PC, this is my server code :
public class Server {
ServerSocket serverSocket;
ArrayList<ServerThread> allClients = new ArrayList<ServerThread>();
public static void main(String[] args) {
new Server();
}
public Server() {
// ServerSocket is only opened once !!!
try {
serverSocket = new ServerSocket(6000);
System.out.println("Waiting on port 6000...");
boolean connected = true;
// this method will block until a client will call me
while (connected) {
Socket singleClient = serverSocket.accept();
// add to the list
ServerThread myThread = new ServerThread(singleClient);
allClients.add(myThread);
myThread.start();
}
// here we also close the main server socket
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class ServerThread extends Thread {
Socket threadSocket;
String userName;
boolean isClientConnected;
InputStream input;
ObjectInputStream ois;
OutputStream output;
ObjectOutputStream oos; // ObjectOutputStream
public ServerThread(Socket s) {
threadSocket = s;
}
public void sendText(String text) {
try {
oos.writeObject(text);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
try {
input = threadSocket.getInputStream();
ois = new ObjectInputStream(input);
output = threadSocket.getOutputStream();
oos = new ObjectOutputStream(output);
userName = (String) ois.readObject();
isClientConnected = true;
System.out.println("User " + userName + " has connected");
while (isClientConnected) {
String singleText = (String) ois.readObject();
System.out.println(singleText);
for (ServerThread t : allClients)
t.sendText(singleText);
// oos.writeObject(singleText);
}
// close all resources (streams and sockets)
ois.close();
oos.close();
threadSocket.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
I use the communication between clients in only two activies, both activites contain the same connectUser() code :
public class MenuActivity extends Activity {
public static final String HOST = "10.0.2.2";
public static final int PORT = 6000;
static ConnectThread clientThread;
boolean isConnected;
static boolean isOnline = false;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
runOnUiThread(new Runnable() {
public void run() {
connectUser();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void connectUser() {
clientThread = new ConnectThread();
clientThread.start();
}
class ConnectThread extends Thread {
InputStream input;
OutputStream output;
ObjectOutputStream oos;
Socket s;
public void sendText(String text) {
try {
oos.writeObject(text);
System.out.println(text);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
try {
s = new Socket(HOST, PORT);
output = s.getOutputStream();
oos = new ObjectOutputStream(output);
oos.writeObject(un);
isOnline = true;
isConnected = true;
new ListenThread(s).start();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ListenThread extends Thread {
Socket s;
InputStream input;
ObjectInputStream ois;
public ListenThread(Socket s) {
this.s = s;
try {
input = s.getInputStream();
ois = new ObjectInputStream(input);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
while (isConnected) {
try {
final String inputMessage = (String) ois.readObject();
//do something with the message }
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
I use this code this code to send message to the server :
clientThread.sendText(user + " " + opponent + " play");
The problem is that when I create the connection at the first activity, then move to the second activity I create another connection , which means so far I am having two connections, same with other clients and then the server seems to return a timed out error.
My question is how to do a global client variable that is created once and can be used in each activity. I saw many suggestions like socket service or asyntask , but I need more direction and help
Thanks in advance.
Add a sub class of Application to your project and update application tag and add this class as android:name:
<application
android:name="com.your.app.MyApplication"
...
and then create a static reference to your Socket connection in MyApplication class:
private static Socket connection;
and then add a static method to access this object:
public static Socket getConnection() {
if( connection == null) {
// initialize connection object here
}
return connection;
}
Now you have a global object!
I have a a GPS receptor. I create a class to retrieve all the GPS data on my Eclipse Console.
(This is the code of makia42)
public class COM implements Runnable{
static Thread myThread=null;
static BufferedReader br;
static BufferedWriter wr;
static InputStreamReader isr;
static OutputStreamWriter osw;
static java.io.RandomAccessFile port;
public COM(){ /**Constructeur*/
myThread=new Thread(this);
}
public void start(){
try {
port=new java.io.RandomAccessFile("COM3","rwd");
port.writeBytes("\r\n");
port.writeBytes("c,31,0,0,5\r\n");
port.writeBytes("T,1000,1\r\n");
}
catch (Exception e) {
System.out.println("start "+e.toString());
}
myThread.start();
}
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
System.out.println(st);
}
}
public static void main(String[] args) {
COM temp= new COM();
temp.start();
}
}
I have another class which is a frame containing a button and a JTextArea. This class is in communication with my first class COM.
When i click the button, COM is starting and show me the data in my Eclipse Console.
But now, I'd like to show it on my JTextArea.
How can I do it ?
Best regards,
Tofuw
Take a moment to read about this pattern.
Make the Thread a Subject. Before starting register the instance of the class that contains the JTextArea as the Observer with the instance of the Thread. At the run() instead of printing on the console, use the notify(String);
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
System.out.println(st);
}
}
Change to
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
notifyObservers(st); //Pass the data to the observers.
}
}
EDIT:
I suppose you can rewrite the Thread to a simple class. It will render the program unresponsive while it reads, that's why you have a Thread. I suppose you can implement a cleaner way using Future<String>
public class GpsReader {
public class GenericGPSException extends Exception {
public GenericGPSException(String message, Throwable cause) {
super(message, cause);
}
}
public static void main(String[] args) {
// Example of usage
GpsReader gpsReader = new GpsReader();
String messageFromDevice;
try {
// Try read it
messageFromDevice = gpsReader.getCoordinate();
} catch (GenericGPSException e) {
// Error, what does it says?
messageFromDevice = e.getMessage();
}
JTextArea mockArea = new JTextArea();
// Show to user anything that comes to it.
mockArea.setText(messageFromDevice);
}
private boolean isReady;
private RandomAccessFile port;
public GpsReader() {
}
public String getCoordinate() throws GenericGPSException {
if (!isReady) {
try {
port = new RandomAccessFile("COM3", "rwd");
port.writeBytes("\r\n");
port.writeBytes("c,31,0,0,5\r\n");
port.writeBytes("T,1000,1\r\n");
isReady = true;
} catch (FileNotFoundException e) {
throw new GenericGPSException(
"Error at starting communication to Device ", e);
} catch (IOException e) {
throw new GenericGPSException(
"Error at starting communication to Device ", e);
}
}
try {
return port.readLine();
} catch (IOException e) {
throw new GenericGPSException("Error at reading the Device ", e);
}
}
}
class SomeUI
{
SocketMessageSender messageSender;
// ensure that its initialized ...
private void bSendMessageActionPerformed(java.awt.event.ActionEvent evt) {
try {
// TODO add your handling code here:
messageSender.sendMessage(jMessage.getText());
jMessage.setText("");
} catch (IOException ex) {
Logger.getLogger(TeKServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
ERROR: Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: Uncompilable source code - Erroneous sym type: bSendMessageActionPerformed
Why do you keep opening the socket and closing it on every button click. Create a class that allow you to keep the socket open for as long as your application run. The socket connection can be done when the application starts.You can try out the following class
public class SocketMessageSender
{
private String host;
private int port;
private DataOutputStream dos;
public SocketMessageSender(String host, int port)
{
this.host = host;
this.port = port;
}
// call when application starts
public void initConnection() throws IOException
{
InetAddress address = InetAddress.getByName(host);
Socket connection = new Socket(address, port);
dos = new DataOutputStream(connection.getOutputStream());
}
//call from button click
public void sendMessage(String message) throws IOException
{
if(dos != null)
{
dos.writeUTF(message);
dos.flush();
}
}
// call when application exits
public void closeConnection() throws IOException
{
if(dos!= null)
{
dos.close();
}
}
}
Hope it helps ...
Assume you have a class like
class SomeUI
{
SocketMessageSender messageSender;
// ensure that its initialized ...
private void bSendMessageActionPerformed(java.awt.event.ActionEvent evt) {
messageSender.sendMessage(jMessage.getText());
jMessage.setText("");
}
}
I think that the class signature should be something like this ....
public class MyPanel extends JPanel implements ActionListener
{
private SocketMessageSender messageSender;
private Message jMessage = new Message();// This is just a temp class, replace this with your class
public MyPanel()
{
messageSender = new SocketMessageSender("some host", 8080);
try
{
messageSender.initConnection();
}
catch(IOException e)
{
Logger.getLogger(MyPanel.class.getName()).log(Level.SEVERE, null, e);
}
}
#Override
public void actionPerformed(ActionEvent e)
{
try {
// TODO add your handling code here:
messageSender.sendMessage(jMessage.getText());
jMessage.setText("");
} catch (IOException ex) {
Logger.getLogger(MyPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Consider using ObjectOutputStream/ObjectInputStream and write object through sockets.
There are a lot of examples at java2s.com
Please mind that if you are writing same object multiple times, you will need to reset() stream before writing, and flush after it.