Integrating Http requests in SFS2X Extensions

The need to communicate between an Extension and a remote server via HTTP/S is quite a common use case. Since SmartFoxServer already comes with embedded HTTP API we’re going to demonstrate how simple it is to integrate web requests in your server side code.

» Getting Started

Every SFS2X distribution comes with Apache’s HttpComponent libraries that provide a high level API for HTTP communication. The relative jar files are located under SFS2X/lib/ with these names:

  • httpclient-x.y.z.jar
  • httpcore-x.y.z.jar

The version numbers depend on the distribution of SFS2X and all you have to do is adding these two extra dependencies to your Extension project.

NOTE: if you’re new to developing server side code for SmartFoxServer we highly recommend this quick tutorial, to get started.

Let’s now take a look at a couple of examples to integrate the library in an SFS2X Extension.

» Example POST request

@Override
public void init()
{
	HttpClient httpclient = HttpClients.createDefault();
	HttpPost post = new HttpPost("http://my.domain.com/page.php");

	try 
	{
	    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
	    nameValuePairs.add(new BasicNameValuePair("Country","Greece"));
	    nameValuePairs.add(new BasicNameValuePair("City","Athens"));
	    
	    post.setEntity(new UrlEncodedFormEntity(nameValuePairs));

	    HttpResponse response = httpclient.execute(post);
	    BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
	    String line = "";
	    
	    while ((line = rd.readLine()) != null) 
	    {
	        System.out.println(line);
	    }

	} 
	catch (IOException e) 
	{
	    e.printStackTrace();
	}
}

At the top of our code we create an HttpClient object and we proceed with preparing the data we want to send. We’ll use the HttpPost class to wrap our key/value parameters which are stored in a regular List as NameValuePair objects.

Next, we proceed by url-encoding the parameters and setting them as the entity of the HttpPost instance. Finally we send the request via the httpclient.execute() method and read the response through a BufferedReader.

With this approach we’ll get back the HTML output sent by the server, so we will still need to be able to parse it correctly. A good approach to exchanging data between servers is to use JSON, rather than HTML which is a more document oriented markup.

We could also use different approaches:

  • Send POST data (key/value) and receive a JSON response
  • Send JSON data and receive a JSON response

Choosing which approach is best for you depends a lot on the use case, the complexity of the data being transferred and so on. Both are valid solutions.

» Example JSON request

Let’s now take a look at how to send and receive JSON data with a remote web server. For starters SmartFoxServer 2X already comes with a JSON coded library called json-lib-x.y.z.jar and found under the usual SFS2X/lib/ folder.

@Override
private void init()
{
        HttpClient httpclient = HttpClients.createDefault();
        CloseableHttpResponse response = null;

        HttpPost httpPost = new HttpPost("http://my.domain.com/page.php");
	
        // Create JSON data to send
        String jsonData = "{'value':20}";
        
        StringEntity requestEntity = new StringEntity
        (
                jsonData,
                ContentType.APPLICATION_JSON
        );
        
        httpPost.setEntity(requestEntity);
        HttpResponse rawResponse = (CloseableHttpResponse) httpclient.execute(httpPost);
        
        BufferedReader rd = new BufferedReader
        (
                new InputStreamReader(rawResponse.getEntity().getContent())
        );
        
        StringBuffer response = new StringBuffer();
        String line;
        while ((line = rd.readLine()) != null) 
        {
                response.append(line);
        }

        // Process Response
        JSONObject jso = JSONObject.fromObject(jsonStr);
}

The code is similar to the previous example. This time we also specify a different ContentType via the StringEntity class and then proceed with sending the request and reading back the response from the server.

» Performance Notes

The examples we have seen so far run synchronously, meaning that the current thread will block until the other side replies. This in turn means that if the remote server is laggy and we’re running many concurrent requests, we will end up with lots of waiting threads and ultimately poor scalability.

To avoid these issues it is always better to minimize the number of concurrent HTTP calls and also to make sure that the web server is “as close as possible” to SmartFoxServer 2X. Ideally they should run in the same private network, which drastically reduces the lag between the two machines.

Also, SmartFoxServer uses auto-load balancing thread pools so there’s no need to use custom threads or thread pools for HTTP calls. Only if your Extension makes heavy use of remote requests you will have to adjust the configuration accordingly.

If you’re interested in learning more about threading and performance, we highly recommend this article from the blog.

» Conclusion

Integrating HTTP calls in SFS2X Extensions is easily done since the necessary dependencies are already provided and thread management is automatic.

If you have more questions or doubts make sure to join the conversation in our support forums and let us know your feedback.