I am running a server, and I have an arraylist of type Client
When a client connects through
ServerSocket.accept()
I pass the new Socket to the arraylists constructor. This is everything inside the constructor
this.add(new Client(Socket client));
My problem is when a client disconnects, it closes the Socket, but it doesn't delete its spot in the arraylist, and shift everything down one. So the arraylist is constantly growing bigger.
What can I do/use to fix this problem?
Sometimes I will run commands that will execute on all clients which is why I store the clients in an arraylist.
Is there a better alternative for storing clients in a server?
Update 1
The classes are in the beginning stages. Very little has been implemented. So far the HashMap option suggested in the answer works best for me. Thank you for your replies
Interesting problem.
You should use hash map here .. Add the client with object as value and use some key. Whenever you disconnect it, remove it from the map.
A good question could me what should be the key? may be the object reference (depends on your choice) or anything that is unique with respect to client object (there must be something, if not, you can generate it easily).
Map<Integer,Client> clientMap = new HashMap<Integer,Client>();
You should remove the Client from the ArrayList, the rest elements in the list will automatically shuffle upwards along the list.
//java.util.ArrayList.remove(Object) shifts any subsequent elements
// to the left (subtracts one from their indices).
Say,if the Client is Client A and the ArrayList is ArrayListA, then you should apply
ArrayListA.remove(ClientA);
But, the better approach would be to use HashMap to store client information as mentioned in Danyal Sandeelo's answer.
A lot of assumptions are made, for example I'm assuming you have a disconnect() method in your Client class. Please provide more details if you want a more accurate solution.
One way of doing it could be by passing a callback to your client so it removes itself from the ArrayList when it's done. Very rough implementation:
public class Callback {
private ArrayList<Client> clients;
public Callback(ArrayList<Client> clients) {
this.clients = clients;
}
public void remove(Client client) {
clients.remove(client);
}
}
Then pass the Callback when you instantiate the Client:
Callback callback = new Callback(list);
list.add(new Client(socket, callback));
Then call the remove() method of the callback. If the Client has a disconnect() method, then inside it you can do
public void disconnect() {
// bla bla
callback.remove(this);
}
This way the Client can clean up after itself when it needs to :)
If Client it's your own class, then you can try this one:
public class Client {
public final List<Client> clients;
public Client(List<Client> clients, Socket socketClient) {
this.clients = clients;
clients.add(this);
}
public void disconnect() {
clients.remove(this);
}}
List<Client> clients = new ArrayList<Client>();
new Client(clients, new Socket());
new Client(clients, new Socket());
new Client(clients, new Socket());
Related
ok, so i'm trying to implement rxJava2 with retrofit2. The goal is to make a call only once and broadcast the results to different classes. For exmaple: I have a list of geofences in my backend. I need that list in my MapFragment to dispaly them on the map, but I also need that data to set the pendingIntent service for the actual trigger.
I tried following this awnser, but I get all sorts of errors:
Single Observable with Multiple Subscribers
The current situation is as follow:
GeofenceRetrofitEndpoint:
public interface GeofenceEndpoint {
#GET("geofences")
Observable<List<Point>> getGeofenceAreas();
}
GeofenceDAO:
public class GeofenceDao {
#Inject
Retrofit retrofit;
private final GeofenceEndpoint geofenceEndpoint;
public GeofenceDao(){
InjectHelper.getRootComponent().inject(this);
geofenceEndpoint = retrofit.create(GeofenceEndpoint.class);
}
public Observable<List<Point>> loadGeofences() {
return geofenceEndpoint.getGeofenceAreas().subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.share();
}
}
MapFragment / any other class where I need the results
private void getGeofences() {
new GeofenceDao().loadGeofences().subscribe(this::handleGeoResponse, this::handleGeoError);
}
private void handleGeoResponse(List<Point> points) {
// handle response
}
private void handleGeoError(Throwable error) {
// handle error
}
What am I doing wrong, because when I call new GeofenceDao().loadGeofences().subscribe(this::handleGeoResponse, this::handleGeoError); it's doing a separate call each time. Thx
new GeofenceDao().loadGeofences() returns two different instances of the Observable. share() only applies to the instance, not the the method. If you want to actually share the observable, you'd have to subscribe to the same instance. You could share the it with a (static) member loadGeofences.
private void getGeofences() {
if (loadGeofences == null) {
loadGeofences = new GeofenceDao().loadGeofences();
}
loadGeofences.subscribe(this::handleGeoResponse, this::handleGeoError);
}
But be careful not to leak the Obserable.
Maybe it's not answering your question directly, however I'd like to suggest you a little different approach:
Create a BehaviourSubject in your GeofenceDao and subscribe your retrofit request to this subject. This subject will act as a bridge between your clients and api, by doing this you will achieve:
Response cache - handy for screen rotations
Replaying response for every interested observer
Subscription between clients and subject doesn't rely on subscription between subject and API so you can break one without breaking another
I need to add certain functionality to an existing ejb projects.
Specifically - the client info, such as IP addres, login credentials (who is connected) and client application name
My bean is a stateless, so I worry there is an issue with such an approach..
My client code currently has the following:
private static MySession getmySession() throws RemoteException {
if(mySession != null) return mySession; //mySession is a private variable
try {
Properties h = new Properties();
h.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
h.put(Context.PROVIDER_URL, serverUrl ); //t3://localhost
InitialContext ctx = new InitialContext(h);
mySessionHome home = (mySessionHome) ctx.lookup( "mySessionEJB" );
mySession = home.create();
return mySession;
} catch(NamingException ne) {
throw new RemoteException(ne.getMessage());
} catch(CreateException ce) {
throw new RemoteException(ce.getMessage());
}
}
Ideally, I would like my 'mySession' know about the client at the point it is returned.
If that may not be possible,
I would like to send a client info at the time a particular method of MySession is called.
Somewhere in this code
public static List getAllMembers() throws RemoteException, CatalogException
{
getMySession();
List list = mySession.getAllMembers() );
return list;
}
There are quite many such methods, so this is less desirable. but I will take it if it solves the task.
At the end of the day, when "getAllMembers()" executes on the server, I want to know particular info of which client has called it. (there can be many different, including webservices)
Thanks
First thing - what are you doing with the client information? If you're planning to use it for auditing, this sounds like a perfect use for Interceptors!
The EJB way to access user information is via the user's Principal, and there's no problem using this in a stateless bean. You may find that this doesn't get all the information you would like - this answer suggests getting the user IP isn't entirely supported.
I am working on a client - server application and I have the following problem.
In one class (Server), I have a static reference to an ArrayList called clients and a static getter getClientsArray(). In another class (ServerThread), I use the same ArrayList and I successfully modify it (add / delete clients).
For every client, I call the method getClientsArray() and get that ArrayList. The problem is that the ArrayList is empty here, in Client class. I check it every time I update it in ServerThread (after a client connects) and it should have something in it.
public class Server {
private static ArrayList<User> clients = new ArrayList<User>();
public static ArrayList<User> getClientsArray() {
return clients;
}
and somewhere I call: new ServerThread(sock, users).start();
}
public class ServerThread extends Thread {
private ArrayList<User> users;
public ServerThread(Socket client, ArrayList<User> users) {
this.client = client;
this.users = users;
}
if I modify users in this class, the changes will occur
}
public class Client extends JFrame {
private ArrayList<User> users;
public Client() {
initGraphics();
users = Server.getClientsArray();
System.out.println(users.size()); <- This line always writes 0!!
}
}
There is a simple rule defined by Brian Goetz in JCIP:
If multiple threads access the same mutable state variable without appropriate synchronization, your program is broken.
You have clients mutable state and you don't use any mean of synchronizing access to it.
Static variables are only global to one program instance. Here, you have at least two programs running; You have one server program, and at least one other client program. The clients and server do not share any common heap, or program variables, so the static list will only be seen by that program.
If you want to share the list, you will need to pass it through sockets or some other data transfer. This question, How to transfer objects over network using java, has a code example of how to pass objects through sockets.
I have such IDL interface:
interface User
{
string toString();
//..
};
interface Group
{
typedef sequence<User> Users;
Users getUsers();
};
When I translated it to C++ I got sth like this:
// ...
Group::Users* GroupImpl::getUsers()
{
// ..return sequence of 'User'-objects
}
On client side (written in Java) I want to show my users. I do sth like this:
public void showAllUsers()
{
User[] users = interface_obj.getUsers();
if(users.length != 0)
{
DefaultListModel model = new DefaultListModel();
for(int i=0; i<users.length; i++)
model.addElement(users[i]);
this.usersList.setModel(model);
}
}
this.usersList is a JList.
When I do this like I wrote, I see only IORs of my Users-object:
IOR :0123405948239481293812312903891208320131293812381023
IOR: 0092930912617819919191818173666288810010199181919919
and so on ...
How to make it that way, to see their toString(); representation in DefaultListModel? I dont want to do this:
model.addElement(users[i].toString());
thats not the point. When I use RMI instead of CORBA, model.addElement(users[i]); is exactly what I need cause I see users string representation.
But I need to use CORBA and store in DefaultListModel corba-user-objects, not strings. Please, help.
I guess that the toString() method of the stub doesn't actually call the toString() method of the remote CORBA object. Try using another method name (like getName()), and use a custom renderer which calls this method.
That said, is it really a good idea to model a User as a remote CORBA object? That will cause a lot or remote method calls just to display the names of the users, and thse method calls are basically out of your control, since the Swing components will make them. Shouldn't you use DTOs instead?
One way to do it would be to make a UserView class whose instances you'd put in the list model:
public class UserView {
private final User corbaUser;
public UserView(User corbaUser) {
this.corbaUser = corbaUser
}
#Override
public String toString() {
String ret = null;
// construct the string as you want here
return ret;
}
}
EDIT:
as pointed out by JB Nizet be careful with the code you put in toString() since it is called every time the list needs to be shown - or the showing of the freshest data might be exactly what you want.
On my Client/Server Desktop application. I have this problem of how I should properly code my JDBC class with my Models to ensure all persistence request can support concurrency. i.e., multiple models want to request update to its persistence counterpart simultaneously [without atmost delay].
The scenario goes like this. Following the classes located in the server application.
Persitence Package:
abstract class AbstractService {
// other fields
private final String tName, tId;
private final String sqlStatement;
public AbstractService(final String tName, final String tId) {
this.tName = tName;
this.tId = tId;
this.sqlStatement = ""; // SELECT statement
}
// java.sql.Connection() createConnection()
// methods
}
public class T1Service extends AbstractService {
private final String sqlDMLStatements;
public T1Service() {
super("t1", "t1Id");
this.sqlDMLStatements = ""; // other DML statements
}
// methods having return types of List<E>, Object, Boolean, etc.
// i.e., public List<E> listAll()
}
Communication class [Client class]
import java.net.*;
import java.io.*;
public class Client extends Observable{
private Socket socket;
private ObjectInputStream input;
private ObjectOutputStream output;
private Object message;
// Constructor
// Getters/Setters
// Other methods like open or close input/output
private class ReceiverRunnable implements Runnable
#Override
public void run() {
while(running) { // if socket is still open and I/O stream are open/initialized
try { message = input.readObject(); }
catch(Exception e) {}
finally { setChanged(); notifyObservers(); }
}
}
}
}
The Main Class [Server class]
import java.net.*;
public class Server {
private List<Client> clientList; // holds all active connections with the server
private T1Service t1Service
private class ConnectionRunnable implements Runnable {
#Override public void run() {
while(running) { // serverSocket is open
Client client = new Client(ServerSocket.accept(), /* other parameters */);
client.addObserver(new ClientObserver(client));
clientList.add(client);
}
}
}
private class ClientObserver implements Observer {
private Client client;
// Constructor
public void update(Observable o, Object arg) {
// Check the contents of 'message' to determine what to reply
// i.e., message.equals("Broadcast") {
// synchronized(clientList) {
// for(Client element : clientList) {
// element.getOutput().writeObject(replyObject);
// element.getOutput()..flush();
// }
// }
// i.e., message.equals("T1") {
// synchronized(t1Service) {
// client.getOutput().writeObject(t1.findAll());
// client.getOutput().flush();
// }
}
}
}
Since this is a Client/Server applcation, multiple request from the client are simultaneously feed to the server. The server process the request sending the appropriate reply to the approriate client. Note: All of the objects sent between Client & Server an instance of java.io.Serializable.
Having this kind of scenario and looking into the block of Server.ClientServer.update() we may have a performance issue or I should say a delay in processing the N client(s) request due to Intrinsic Locks. But since I have to the rules concurrency and synchronization to ensure that Server.T1Service won't get confused to the queue of N clients request to it. Here's are the questions:
According to the Item 1 of Effective Java - Second Edition regarding Static Factory, would this let me create a new class reference to the methods inside the classes of Persistence package?
Would each Client element inside List<Client> would form a concurrency issue having N client update their message field simultaneously triggering the ClientObsver.update() wherein the reference object(s) of this Observer is only a single instance in the parent class. I was avoiding creating multiple instance of T1Service due to memory concerns.
If we are going to go by the contents of Effective Java - Second Edition, how can I convert my persitence class in a way they can be read easily, easily instantiated, and support concurreny?
you may also want to review Actors, for example ones in Akka
basic idea of actors is avoiding of synchronization at all, using sending events. Akka will guarantee that one actor will never be invoked by two threads in parallel. So you may define actor, which does something with the global variables, and then simply send a message to it.
works like a charm usually :)
Is my theory of [Item 1] Static Factory correct?
Yes, you can use a static factory instead of constructors. Typically this is when you the construction logic is complex and shared between various subtypes to warrant a factory pattern. Additionally the factory may provide means for dependency injection outside of a DI framework.
Would it then solve the concurrency issue of the converted static factory global objects?
If you need to synchronize construction, then a static factory works well, just add synchronized to the method declaration on your factory methods. If you need to synchronize methods on the objects themselves then this will not help.
Is it advisable for me to convert to static factory if where dealing with concurrent access to a global object and where wanted real-time access to the methods of each global object?
As I answered above, it depends on what you are trying to achieve. For constructor synchronization use a factory.