Search code examples
javaweb-servicesjava-threads

Can I use wait() in a RESTful webservice?


I have a RESTful webservice which I use for a server on NetBeans. This webservice should get many requests from clients (multiplayer game).

I'm still new to this topic but if I understand it right- every call from clients to my webservice is a thread safe - because every connection to the web service is on a different thread (all my variables are inside the webservice methods) is this true?

And this brings me to my question: Can I use wait(); inside a webservice method? let's say I'm waiting for two client connections, so the second connection will use notifyAll(); But since the webservice is not really a thread I don't know if it's possible to use these methods there? What should I use instead??

This is my webservice:

@Path("/w")
public class JSONRESTService {
    String returned;

    @POST
    @Consumes("application/json")
    @Path("/JSONService")
    public String JSONREST(InputStream incomingData) {
        StringBuilder JSONBuilder = new StringBuilder();
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(incomingData));
            String line = null;
            while ((line = in.readLine()) != null) {
                JSONBuilder.append(line);
            }

            returned = "transfer was completed";

            // This is what I'm trying to add but I know that I can't:

            // count is a static variable, every new connection will increase this value     

            // only one player is connected
            if (Utility.count == 1)    
                wait (); //wait for a 2nd player to connect to this webservice

            // 2nd player is connected to this webservice
            if (Utility.count == 2)
                notifyAll ();           // notify the 1st player

        } catch (Exception e) {
            System.out.println ("Error Parsing: - ");
            returned ="error";
        }
        System.out.println ("Data Received: " + JSONBuilder.toString ());
        return (returned);
    }
}

Client:

JSONObject jsonObject = new JSONObject("string");

// Step2: Now pass JSON File Data to REST Service
try {
    URL url = new URL("http://localhost:8080/w/JSONService");
    URLConnection connection = url.openConnection();
    connection.setDoOutput(true);
    connection.setRequestProperty("Content-Type", "application/json");
    connection.setConnectTimeout(5000);
    connection.setReadTimeout(5000);
    OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
    out.write(jsonObject.toString());
    out.close();

   //string answer from server:
    BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    StringBuffer sb = new StringBuffer("");
        String line="";
        while ((line = in.readLine()) != null) {
            sb.append(line);
            System.out.println("\n"+line);
    in.close();
} catch (Exception e) {
    System.out.println("\nError while calling JSON REST Service");
    System.out.println(e);
}

br.close();
} catch (Exception e) {
e.printStackTrace();
} } }`

Solution

  • You can always use wait() and notify() as it affects the thread the code is running on. Whether or not you should use it depends on the situation.

    If you want a queue of players then use a queue :)

    A little example I knocked up...

    @Path("/w")
    public class JSONRESTService {
    
        private static BlockingQueue<Player> queue = new ArrayBlockingQueue<>(999);
    
        @POST
        @Consumes("application/json")
        @Path("/JSONService")
        public String JSONREST(InputStream incomingData) {    
    
    
            Player thisPlayer = ...; // Get player from session or something
    
            System.out.println (thisPlayer.getName() + " starting...");
    
            try {
    
                if (queue.isEmpty()) {
                    System.out.println ("waiting for an opponent");
                    queue.add(thisPlayer);
                    synchronized (thisPlayer) {
                        thisPlayer.wait();
                    }
                } else {
                    System.out.println ("get next in queue");
                    Player opponent = queue.take();
                    opponent.setOpponent(thisPlayer);
                    thisPlayer.setOpponent(opponent);
                    synchronized (opponent) {
                        opponent.notify();
                    }
                }
    
                System.out.println (thisPlayer.getName() + " playing " + thisPlayer.getOpponent().getName());
    
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    
        static class Player {
    
            private String name;
            private Player opponent;
    
            Player (String name) {
                this.name = name;
            }
    
            public String getName() {
                return name;
            }
    
            public Player getOpponent() {
                return opponent;
            }
    
            public void setOpponent(Player opponent) {
                this.opponent = opponent;
            }
        }
    }