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();
} } }`
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;
}
}
}
Yes. All local variables inside methods are thread-safe. Class fields variables might be thread-safe or might be not. It is up to you. If rest controller has singleton scope (usually by default it has) that's mean that class fields are shared among the all requests.
So, technically you can use some shared lock object to synchonize on it. Try to do it. But it's better to do it in async mode. See Reverse Ajax Comet technique with long polling in this article.
Alternatively you might use Reverse Ajax with Websockets and send 'Transfer was received' back to client without any idle.
Related
I have write a simple method to post data to URL and consume the output. I hava tried multiple ways to consume the out put but no success yet:
public void postToUrl(final String theurl, final String query, final Callable<Void> myMethod){
String urlData="";
new Thread(new Runnable() {
#Override
public void run() {
try {
String urlData="";
String url=baseurl+ theurl + "/?" +query;
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true);
connection.connect();
InputStream response = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(response));
String line="";
while ((line = reader.readLine()) != null) {
urlData += line;
}
reader.close();
// How to consume urlData here?
// myMethod.call(); not accepts parameter
try {
myMethod.call(urlData);
}catch (Exception e){
e.printStackTrace();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}}
).start();
}
I have to wrap the method inside a runnable and can not expect a runnable method to return a value.
I tried to consume the output when it is ready inside the runnable but I need to call a third party method to pass the output. I found callable but it does not accept parameters.
I have read the accepted answer here but it needs to define a new class for every method.
I have read this Q/A but it suggest to define an interface instead of method that I believe is not the proper use of interface.
If this method is not the proper way to call and consume a url, how do you manage multiple client-server request in an application? Do you rewrite the codes above for every type of request? Do you really define a new class or new interface for every clien-server interactions?
I need to write a server for stock exchange in Java, the server will get many requests from couple of servers per second, my goal is to write this server and find out how many HTTP GET requests it can handle after executing couple of conditions and send a response in less then 100ms.
Each request contains a token that will be valid for 100ms.
My goal is to fetch data from cache (Redis/Memcached) using the request parameters, execute couple of O(1) conditions, send a response to the same server with the token and a boolean answer in max 100ms and save the request and response in a database (asynchronously).
This server will sit on AWS ec2 at the same region as the requesting servers.
Its needs to be written in Java, low level as it should be, btw, I come from Python/NodeJS world for the past 2 years.
I think its a classic producer-consumer design pattern.
Can anyone guide me to the technical parts ? like.. use "this' for handling requests (SocketInputStream), and use "that" for handling the queues, or maybe use "OpenMQ" framework ? monitor requests with "this" ? any reference for an implementation for similar problem ?
Update 1:
Thanks #mp911de, I saw LMAX (Disruptor), someone already invented the wheel but it feels like over-programming for now, I want to check how many 1k json object can be sent and response 100bytes back from simple ec2-server that run this java code I attached ? BTW, how many threads to put in Executors.newFixedThreadPool ?
public class JavaSimpleWebServer {
private static final int fNumberOfThreads = 100;
private static final Executor fThreadPool = Executors.newFixedThreadPool(fNumberOfThreads);
public static final int PORT = 81;
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(PORT);
while (true)
{
final Socket connection = socket.accept();
Runnable task = new Runnable() {
#Override
public void run() {
HandleRequest(connection);
}
};
fThreadPool.execute(task);
}
}
private static void HandleRequest(Socket s) {
BufferedReader in;
PrintWriter out;
String request;
try {
String webServerAddress = s.getInetAddress().toString();
System.out.println("New Connection:" + webServerAddress);
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
request = in.readLine();
System.out.println("--- Client request: " + request);
out = new PrintWriter(s.getOutputStream(), true);
// do some calculation
out.println(jsonResponse);
out.flush();
out.close();
s.close();
}
catch (IOException e) {
System.out.println("Failed respond to client request: " + e.getMessage());
}
finally {
if (s != null)
{
try {
s.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
I tried everything stack overflow has to offer on this common readLine problem. (sending \n, flushing out, changing to byte array style, becoming hermit, wrists )
I suspect in this case its a concurrency thing as Ispent well over 15 hours yesterday confirming that the only thing that isnt working is readline()!
I used loads of other versions like datareader with a byte array and making sure a \n got sent I even sent /ns just in case!
still my issue is the same, and I have ran out of ideas myself to solve the issue and have decided that somewhere, my problem is outside my understanding, just where? its got to be threading right?
I managed to get to read the socket to string that seemed to work so it IS blocking because reading the connection isnt working at all, the readline function is not the only way Ive had it as I said so in my snippets its not as developed as it has been but still the basic issue remains.
Please help, i dont know what the issue is
// So the main class initialises the socket objects and starts them in a thread, these work I get all sorts of flags letting me know that they are
void start_sockets() {
//if this is initiialised as a server and not a client
if (is_server) {
while (is_server) {
try {
System.out.println("listening for connection");
Sockject sj = new Sockject(server.accept());
sock_arr.add(sj);
System.out.println("server made connection ");
// once the connection is made the objects is started in a
// separate thread
new Thread(sock_arr.get(sock_arr.size() - 1)).start();
} catch (IOException e) {
}
}
} else { //else im running a client version of this class
// if the client socket isnt running in a thread, make it run
if (!running) {
new Thread(sj_client).start();
if (sj_client.sock.isConnected()) {
System.out.println("client thread connected to "
+ sj_client.sock.getLocalSocketAddress());
running = true;
}
}
}
}
//the inner class creates a socket object and puts it on an array or an object depending if the parent class is initialised to be a server or a client
class Sockject implements Runnable {
PrintWriter out;
BufferedReader in;
// a socket for processing
Socket sock;
// the constructor in this case initialises the input and output streams
Sockject(Socket s) {
sock = s;
try {
out = new PrintWriter(sock.getOutputStream());
in = new BufferedReader(new InputStreamReader(
this.sock.getInputStream()));
} catch (IOException e) {
close sockets
}
}
//tried variasions of this and similar, used data objects and been sennding /ns all over the shop
void recieve_data() throws IOException {
if (sock.isConnected()) {
if ((recieve = in.readLine()) != null) {
System.out.println("recieve says " + recieve);
}
}
}
// sends data to connection if it is cleared to send data
void send_data(String data) {
// send data called
if (clear_to_send == true) {
out.print(data);
out.flush();
clear_to_send = false;
}
}
#Override
public void run() {
while (threadloop ) {
try {
//code defo gets this far and with just send it keeps running forever so its defo recieve data thats the issue
send_data(send);
recieve_data();// <---I HATE YOU
} catch (IOException e) {
}
}
}
}
}
Now all of the above is ran in an instance of this class, in a thread of this class here these temporary functions are ran and are neversuccesfull
void servrecievex(){
System.out.println("NEVER GETS THIS FA THOUGH DOES IT");
for(int a = 0; a < net_flow.sock_arr.size(); a++){
if(net_flow.sock_arr.get(a).sock.isConnected()){
System.out.println("server recieve function");
net_flow.sj_client.clear_to_send = true;
net_flow.sock_arr.get(a).send_data("www /n \n");
System.out.println("RECIVEIFY!!!");
}
}
}
void clientsendx() {
net_flow.sj_client.clear_to_send = true;
net_flow.sj_client.send_data(Integer.toString(player1.posx) + "\n");
System.out.println("client sent stuff");
}
I am trying to write a Java program that should automatically download text from a website if and only if it gets updated. The problem I am running into is using only one HTTPURLConnection to do that because if i don't there will be billions of HTTPURLConnections to the web server since I am using a while(true) loop. Here is my work-in-progress, the getMsg() method receives a url and opens an HTTPURLConnection. Currently I am starting a new connection every time I have to read a line, which is not the most efficient way I am sure. How do I keep reading the same line with the same HTTPURLConnection?
// Starts a new URLConnection to "localhost/currentmsg.dat"
// Receives JSON string from the URLConnection
// Sets up a different variable for each object received from the URL for eg. if delete=1 means that the admin is requesting to delete a message from the screen.
import java.io.*;
import java.net.*;
import org.json.*;
import java.io.*;
import java.util.Scanner;
public class jListenerURL {
// Current arguments retrieved from the URL
private static int msgID = 0;
private static int aptID = 1; // Apartment ID of current device
private static int unitID = 3; // Unit ID of current device
static String message; // Message received from admin
static int delete; // Delete a message?
static int dmsgID; // What message to delete?
public static void jListener() {
URL url;
boolean keepGoing = true;
String msg = "";
try {
url = new URL("http://www.lotussmoke.com/msgtest/currentmsg.dat");
while (keepGoing) {
msg = getMsg(url);
JSONObject jObj = null;
try {
jObj = new JSONObject(msg);
}
catch (JSONException je) {
System.out.println("JSON Exception for message, try restarting terminal.");
}
int current = jObj.getInt("msgID");
int targetaptID = jObj.getInt("aptID");
int targetunitID = jObj.getInt("unitID");
// Keep listening, if the message changes meaning a different msgID then print that message
if (current!=msgID && targetaptID == aptID && targetunitID == unitID) {
msgID = jObj.getInt("msgID");
message = jObj.getString("message");
delete = jObj.getInt("delete");
dmsgID = jObj.getInt("dmsgID");
if (delete==1) {
// Delete a message
System.out.println("Delete msg ID? " + dmsgID);
continue;
}
System.out.println("Message ID: " + msgID);
System.out.println("Apartment ID: " + aptID);
System.out.println("Unit ID: " + unitID);
System.out.println("Message: " + message);
}
}
}
catch (MalformedURLException e) {
System.err.println();
}
}
public static void main(String args[]) throws Exception {
jListener();
}
private static String getMsg(URL url) {
HttpURLConnection con = null;
try {
con = (HttpURLConnection) url.openConnection();
} catch (IOException e1) {
e1.printStackTrace();
}
BufferedReader in = null;
String msg = "";
try {
in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String received;
while((received = in.readLine()) != null) {
//System.out.println(received);
msg = received;
}
in.close();
}
catch (IOException e) {
e.printStackTrace();
}
return msg;
}
}
Why don't you simply declare your HttpURLConnection object outside of your while loop ? It will then not open a connection at each call inside the loop.
HttpURLConnection cannot be reused, but it can reuse an open connection to the same server internally by setting the header Connection: keep-alive. It doesn't make sense if you connect to different servers, obviously.
One way to efficiently test whether there are changes, is to use If-Modified-Since header or the like If-Unmodified-Since, If-None-Match or If-Match (see HTTP Headers). In this case the web-server decides to deliver a new document if there are changes or just sends the response code 304 Not Modified without a body.
One last thing regarding the use of members (and especially static members): I'd refactor this code and the only item which would be left as static is static void main(). You can see the static members as some kind of global variables. Observing something like 'the connection is returning the same message' might be a effect of inappropriate exception handling and usage of static members.
I have written a java server and here is the code:
try
{
ss = new ServerSocket(8080);
while (true)
{
socket = ss.accept();
System.out.println("Acess given");
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//out = new PrintWriter(socket.getOutputStream(),true);
line = in.readLine();
System.out.println("you input is :" + in.readLine());
}
}
And an iphone application is the client and there is the code for it:
- (void)viewDidLoad {
[super viewDidLoad];
socket = [[LXSocket alloc]init];
if ([socket connect:#"10.211.55.2" port:8080]) {
NSLog(#"socket has been created");
}
else {
NSLog(#"socket couldn't be created created");
}
#try {
}#catch (NSException * e) {
NSLog(#"Unable to send data");
}
[super viewDidLoad];
}
-(IBAction)sendData{
[socket sendString:#"A\n"];
}
I am having 2 problems here: first is that the server is only reading the input once. The second is that when ever I try to output the data it doesn't output until I have called the method twice (clicked on the uibutton twice). Not sure what is happening here. What am I doing wrong?
You are creating a new reader everytime in your while loop. Instead move the code outside the while loop and block on the readLine() call.
socket = ss.accept();
in = new BufferedReader(new InputStreamReader(socket.getInputStream());
String line = "";
while ( true) {
line = in.readLine();
System.out.println("you input is :" + line);
if ( "Bye".equals(line) )
break;
}
Here is an example server side program.
Since alphazero posted the pattern, I will post a brief stripped down implementation:
This is the Server:
try {
ServerSocket ss = new ServerSocket(portNumber);
logger.info("Server successfully started on port " + portNumber);
// infinite loop that waits for connections
while (true) {
SocketThread rst = new SocketThread(ss.accept());
rst.start();
}
} catch (IOException e) {
logger.info("Error: unable to bind to port " + portNumber);
System.exit(-1);
}
The SocketThread is something like:
public class SocketThread extends Thread {
private Socket communicationSocket = null;
public SocketThread(Socket clientSocket) {
communicationSocket = clientSocket;
try {
input = new ObjectInputStream(communicationSocket.getInputStream());
} catch (IOException e) {
logger.info("Error getting communication streams to transfer data.");
try {
communicationSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public void run() {
boolean listening=true;
DataObject command = null;
while (listening) {
try {
Object currentObject = input.readObject();
if (currentObject != null
&& currentObject instanceof DataObject) {
command = (DataObject) currentObject;
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
// If we got to this point is because we received a request from
// the client
// we can exit the loop
listening = false;
}
}
}
}
Note: "DataObject" is just a custom class which could be more practical since you can read the Dataobject itself from the socket without worrying about how many bytes you are reading, etc. Only condition is that DataObject is flagged as Serializable.
Hope it helps.
Tushar,
The general pattern is this (almost java but pseudo-code):
while (server-socket is accepting new connections)
{
// The server-socket's job is to listen for connection requests
// It does this typically in a loop (until you issue server-shutdown)
// on accept the server-socket returns a Socket to the newly connected client
//
socket s = server-socket.accept-connection();
// various options here:
//
// typically fire off a dedicated thread to servie this client
// but also review NIO or (home-grown) connection-map/handler patterns
// the general pattern:
// create a dedicated thread per connection accepted.
// pass Socket (s) to the handler method (a Runnable) and start it off
// and that is it.
// Here we use the general pattern and create a dedicated
// handler thread and pass of the new connections' socket reference
//
Thread handler-thread = new Thread (handler-routine-as-runnable, s);
handler-thread.start();
}