Syntax highlighter header

Friday, 24 September 2021

Httpd mod_proxy throwing 503 error

Recently I was debugging an issue of Apache server throwing 503 when we are trying to connect to a nodeJS server running on port 5000. We had proxy setting correctly added into out httpd.conf

<IfModule mod_proxy.c>
    ProxyRequests Off
    SSLProxyEngine On

    <Proxy *>
            Order deny,allow
            Allow from 127.0.0.1
    </Proxy>

    <Location /nodeserver>
        ProxyPass http://localhost:5000
        ProxyPassReverse http://localhost:5000
    </Location>

</IfModule>

The server was throwing 503 error and we were not able to figure out the reason for it because node server was up and was responding to all requests at port 5000. But when we were trying to access it via Apache server it was throwing 503 error. 

After a lot of debugging we found that it was selinux which was preventing Apache server from connecting to node server at port 5000. Although Apache server was able to connect tomcat server running at port 8009. 

The reason of this selective behavior was that selinux defines some ports as http ports and httpd server is allowed to connect to those port. You can get a list of these ports by running following command.

$semanage port -l |grep http_port_t
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000

After changing port from 5000 to 9000 for our node server and changing mod_proxy setting in httpd.conf our application started working.


 

Wednesday, 8 September 2021

Tomcat 9 creates different sessions for different directories

Recently we were testing one application with tomcat 9.0.43 where one application path was starting with sso/ and one was starting with normal/. We were redirecting to normal/ path from sso/ path. We found that the values we set in HttpSession were missing in normal/ path. 

After a lot of debugging we found out that Tomcat 9 was creating two sessions for same client one for sso/ path and one for normal/ path. That is why values set in HttpSession were missing. I wrote following sample jsp file to demonstrate the behavior.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<body>
<%
	String sessionStr = request.getSession().toString();
%>
Session:<%=sessionStr%>

</body>
</html>

I placed the file at two locations. One under sso/index.jsp and one under normal/index.html and hit both of them from same browser and output was following.

SSO:    Session:org.apache.catalina.session.StandardSessionFacade@2ca7ac8e
Normal: Session:org.apache.catalina.session.StandardSessionFacade@4b992f7e

This problem looks like to be fixed in tomcat 9.0.54



Tuesday, 17 August 2021

Unable to make private java.lang.reflect.Proxy() accessible with JDK-17 in JUnit test using Ant

Recently I encountered the following error while executing Junit test case using Ant. My testcase uses EJBs from a wildfly 24 server. I am using jboss-client.jar file from same server in my testcase.

2021-08-17 16:39:30,450 2428  ERROR [com.tk20.ejb.api.util.EJBUtils] (main:[]) Unable to make private java.lang.reflect.Proxy() accessible: module java.base does not "opens java.lang.reflect" to unnamed module @
394df057
java.lang.reflect.InaccessibleObjectException: Unable to make private java.lang.reflect.Proxy() accessible: module java.base does not "opens java.lang.reflect" to unnamed module @394df057
        at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) ~[?:?]
        at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297) ~[?:?]
        at java.base/java.lang.reflect.Constructor.checkCanSetAccessible(Constructor.java:188) ~[?:?]
        at java.base/java.lang.reflect.Constructor.setAccessible(Constructor.java:181) ~[?:?]
        at org.jboss.marshalling.reflect.JDKSpecific$SerMethods.<init>(JDKSpecific.java:147) ~[jboss-client.jar:24.0.0.Final]
        at org.jboss.marshalling.reflect.SerializableClass.<init>(SerializableClass.java:84) ~[jboss-client.jar:24.0.0.Final]
        at org.jboss.marshalling.reflect.SerializableClassRegistry$1.computeValue(SerializableClassRegistry.java:62) ~[jboss-client.jar:24.0.0.Final]
        at org.jboss.marshalling.reflect.SerializableClassRegistry$1.computeValue(SerializableClassRegistry.java:59) ~[jboss-client.jar:24.0.0.Final]
        at java.base/java.lang.ClassValue.getFromHashMap(ClassValue.java:228) ~[?:?]
        at java.base/java.lang.ClassValue.getFromBackup(ClassValue.java:210) ~[?:?]
        at java.base/java.lang.ClassValue.get(ClassValue.java:116) ~[?:?]
        at org.jboss.marshalling.reflect.SerializableClassRegistry.lookup(SerializableClassRegistry.java:83) ~[jboss-client.jar:24.0.0.Final]
        at org.jboss.marshalling.reflect.SerializableClass.<init>(SerializableClass.java:76) ~[jboss-client.jar:24.0.0.Final]
        at org.jboss.marshalling.reflect.SerializableClassRegistry$1.computeValue(SerializableClassRegistry.java:62) ~[jboss-client.jar:24.0.0.Final]
        at org.jboss.marshalling.reflect.SerializableClassRegistry$1.computeValue(SerializableClassRegistry.java:59) ~[jboss-client.jar:24.0.0.Final]
        at java.base/java.lang.ClassValue.getFromHashMap(ClassValue.java:228) ~[?:?]
        at java.base/java.lang.ClassValue.getFromBackup(ClassValue.java:210) ~[?:?]
        at java.base/java.lang.ClassValue.get(ClassValue.java:116) ~[?:?]
        at org.jboss.marshalling.reflect.SerializableClassRegistry.lookup(SerializableClassRegistry.java:83) ~[jboss-client.jar:24.0.0.Final]
        at org.jboss.marshalling.river.RiverUnmarshaller.doReadNewObject(RiverUnmarshaller.java:1394) ~[jboss-client.jar:24.0.0.Final]
        at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:298) ~[jboss-client.jar:24.0.0.Final]
        at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:231) ~[jboss-client.jar:24.0.0.Final]
        at org.jboss.marshalling.AbstractObjectInput.readObject(AbstractObjectInput.java:41) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.remote.RemoteClientTransport.lookup(RemoteClientTransport.java:271) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.remote.RemoteContext.lambda$lookupNative$0(RemoteContext.java:190) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.NamingProvider.performExceptionAction(NamingProvider.java:222) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.remote.RemoteContext.performWithRetry(RemoteContext.java:100) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.remote.RemoteContext.lookupNative(RemoteContext.java:188) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.AbstractFederatingContext.lookup(AbstractFederatingContext.java:74) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.store.RelativeFederatingContext.lookupNative(RelativeFederatingContext.java:58) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.AbstractFederatingContext.lookup(AbstractFederatingContext.java:74) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.AbstractFederatingContext.lookup(AbstractFederatingContext.java:60) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.AbstractFederatingContext.lookup(AbstractFederatingContext.java:66) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.AbstractFederatingContext.lookup(AbstractFederatingContext.java:66) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.AbstractFederatingContext.lookup(AbstractFederatingContext.java:66) ~[jboss-client.jar:24.0.0.Final]
        at org.wildfly.naming.client.WildFlyRootContext.lookup(WildFlyRootContext.java:144) ~[jboss-client.jar:24.0.0.Final]

The reason of failure was traced to version of Ant which I was using version 1.9.15 of Ant. After upgrading Ant to version 1.10.11 the error was removed. Due to some reason with older version of Ant JDKSpecific class which was being used was compatible with JDK8 and not the one which is compatible with JDK9 or higher. After upgrading Ant to 1.10.11 it started picking right version of class and problem was fixed.

Please refer to my earlier post regarding similar  error faced while accessing EJB in wildfly 24 without involvement of Ant and JUnit.  https://blog.bigdatawithjasvant.com/2021/07/javalangreflectinaccessibleobjectexcept.html

Friday, 13 August 2021

Implementing rate limit on an API

Here I am going to discuss an interesting programming problem. How to implement rate limit for an API per customer. You need to implement a rate limit of 10 requests per second with allowing a bust of 50 API calls. It means if user was silent for some time then tokens will accumulate up to 50 tokens and after that they will get expired. Every call will consume one token. One token will get accumulated every 100 milliseconds. 

Following is the implementation of code with limit of 10 API calls per second and allowing a bust of 50 API calls.


import java.util.HashMap;

public class RateLimitting {
	
	HashMap<String, Bucket> rateLimits = new HashMap<>();
	
	public static class Bucket {
		int tokens;
		long lastAccessTime;
		
		public Bucket() {
			tokens = 50;
			lastAccessTime = System.currentTimeMillis();
		}
	}
	
	public String api(String user, String req) {
		Bucket r = rateLimits.get(user);
		if(r==null) {
			r = new Bucket();
			rateLimits.put(user, r);
		} else {
			long current = System.currentTimeMillis();
			if((current - r.lastAccessTime)/100 >=1) {
				r.tokens = (int) (r.tokens + (current - r.lastAccessTime)/100);
				if(r.tokens>50) {
					r.tokens = 50;
				}
				r.lastAccessTime = current;
			}
		}
		
		if(r.tokens<0) {
			// deny the request
			return null;
		}
		
		r.tokens--;
		
		// Process the request
		return "Success";
		
	}
} 

Implement power function without using multiplication

In this post I am going to discuss one interesting  programming question. You are supposed to write power function without using multiply operator. You are allowed to use division operator but not multiply.

This is a good question to show your skill at optimizing code and showing that you don't miss the corner cases. You can use multiple additions to simulate multiplication. You need to make sure that you use lest number of additions. For example if you are multiplying 5 with 5 then you don't add 5 four time, you can do it by adding three times. You add 5 with 5 to get 10 in one addtion, You add 10 with 10 in second addition and after that you add 5 in third addition to get answer as 25.

You can implement one function for multiplying two numbers and use that function in your power function. Here again you need to make least number of calls to multiply function. For example if you are calculating 5^5 then we can do it with three calls to multiply functions instead of 4 calls. You multiply 5 with 5 in first call to get 25. You multiply 25 with 25 in second call and multiply 625 with 5 in third call.

Following is the java code for this question:


public class PowerWithoutMul {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		int m = 4;
		int n = 4;
		
		System.out.println(pow(m, n));
		

	}
	
	static int pow(int m, int n) {
		int res = 1;
		if(n/2>0) {
			int temp = pow(m, n/2);
			res = mul(temp, temp);
		}
		if(n%2==1) {
			res = mul(res, m);
		}
		return res;		
	}
	
	static int mul (int m, int k) {
		int res = 0;
		if(k/2>0) {
			int temp = mul(m, k/2);
			res =  temp + temp;
		}
		
		if(k%2 == 1) {
			res = res + m;
		}
		return res;
	}

}