Showing posts with label concurrency. Show all posts
Showing posts with label concurrency. Show all posts

Tuesday, 4 March 2014

SocketProxyServer

I recently had a need to check out the communication between a client and a server, as well as act upon the contents. Now, I could have used a Network Sniffer to find that out, but it's hard to have a hook with a Network Sniffer and a Java program. Besides, the level of detail is a bit too high. I was only interested in what data is actually going over the line.

With this in mind, I set about to write my "socket proxy server".

The main reason for this "socket proxy server" is because I both do not control the client and the server, yet I wish to "be involved". One saving grace is that I can change the server IP address on the client.

I tested my socket proxy server by starting it as a proxy to a simple website.

java -cp socketproxy.jar com.tools.socketproxy.Main 8080 www.karchan.org 80

So, now I could connect to http://localhost:8080 and I would see the website provided.

Here is the communication as the socket proxy server saw it. First the messages as sent by the client.
received from client:{GET / HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:27.0) Gecko/20100101 Firefox/27.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: has_js=1
Connection: keep-alive
If-Modified-Since: Wed, 26 Feb 2014 16:26:34 +0000
If-None-Match: "1393431994"

}
Consequently the reply from the server.
received from server:{HTTP/1.1 200 OK
Date: Wed, 26 Feb 2014 16:29:04 GMT
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.3.3
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Last-Modified: Wed, 26 Feb 2014 16:29:04 +0000
Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0
ETag: "1393432144"
Link: </node/1>; rel="canonical",</node/1>; rel="shortlink"
X-Generator: Drupal 7 (http://drupal.org)
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8

26a5
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
  "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" version="XHTML+RDFa 1.0" dir="ltr"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:dc="http://purl.org/dc/terms/"
  xmlns:foaf="http://xmlns.com/foaf/0.1/"
...


The UML diagram above, shows the main Thread classes and how they relate to each other.

Dealing with multi-threaded programming is always hard and dangerous. In our case, the threads are provided by a fixed thread pool in the concurrency package of Java. I also had a List of Messages, so the list was created using Collections.synchronizedList(List list). What helps is that two connections cannot interfere with each other, making threading easier.

You can find the source code (Java 7) and javadoc in the references below.

Currently the functionality is limited, however it should be easy to extend.

For example, the current listener will only be called after the conversation has finished. This makes the current implementation unsuitable for directly interfering in the communication.

I required this socket proxy server for one of my private hobby projects. This will be the subject of one of my next blog posts. See [1].

References

Github - socketproxy repository
https://github.com/maartenl/socketproxy
Github - socketproxy javadoc
http://maartenl.github.io/socketproxy/javadoc/
[1] Google App Engine - First Try
http://randomthoughtsonjavaprogramming.blogspot.nl/2014/03/google-app-engine-first-try.html

Friday, 9 July 2010

Concurrency problems in jsp Pages

I'm so ashamed that I didn't notice this problem sooner, but apparently servlets (and, therefore, jsp pages too) are instanced and put into a pool for multithreaded use.

This has the very bad effect of messing with your class variables.

So, do NOT do the following:

<%!
// authentication && authorization

/* name of the current user logged in */
private String itsPlayerName;

private Logger itsLog = Logger.getLogger("mmud");
 
/* password of the current user logged in, unsure if used */
private String itsPlayerPassword = "";
 
/* sessionid/cookiepassword of current user */
private String itsPlayerSessionId;

private StringBuffer contents = new StringBuffer("");
%>

A JSP page is by default thread unsafe. This means that multiple requests, started in multiple threads for a specific JSP access the same Instance.

Do not make your JSP page threadSafe="true". It will become a performance nightmare.

If you are interested, the following is put in the javadoc of the javax.servlet.Servlet interface service method:

Servlets typically run inside multithreaded servlet containers that can handle multiple requests concurrently. Developers must be aware to synchronize access to any shared resources such as files, network connections, and as well as the servlet's class and instance variables.

Tuesday, 11 May 2010

ConcurrentModificationException occurred

Recently had a ConcurrentModificationException in a single threaded piece of code. That was weird. Luckily there are lots of resources (google is your friend) that tell you how to solve it.

Here's the offending piece of code.

Set<Orders> ordersToDelete = customer.getOrders();
        
for(Order order : ordersToDelete)
{
    order.setCustomer(null);
    customer.getOrders().remove(order);
    order.setCompany(null);
    genericCustomDAO.remove(order);
}
I thought about just "nulling" the Set in Customer, but that is not possible as hibernate wants to have references removed before attempting to remove the object itself. (yeah, I should look into the whole CascaseType.ALL thing sometime.)

The ugliest thing that you could do is of course make a copy of the set and then iterate over this new set, removing the items in the old set.

Now, if we only had access to the nice Iterator that the foreach loop above uses, things would be fine. But we do not, so it is time to grasp back to the ancient days where we had to write our own for-loops.

Iterator<Order> ordersToDelete = 
    customer.getOrders().iterator();
        
while (ordersToDelete.hasNext())
{
    Order order = ordersToDelete.next();
    order.setCustomer(null);
    // remove the item from the set by using the
    // remove method of the iterator
    order.setMeasure(null);
    ordersToDelete.remove();
    genericCustomDAO.remove(order);
}
Calling the remove on the iterator itself solves the problem for me.