Friday, January 18, 2019

Custom Thread Pool for Schedule job in SpringBoot

By default, default thread pool is used for schedule job. Number of thread in this pool is small. If we have many scheduled tasks, they could be delayed. We need to declare a dedicated thread pool for scheduled tasks. Below is an example thread pool (pool size 8) in Spring Boot.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
 
import javax.annotation.PreDestroy;
 
@Configuration
public class CustomSchedulingConfigure implements SchedulingConfigurer {
 
    ThreadPoolTaskScheduler pool = new ThreadPoolTaskScheduler();
 
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        pool.setPoolSize(8);
        pool.initialize();
        pool.setThreadNamePrefix("CustomPool");
        scheduledTaskRegistrar.setTaskScheduler(pool);
    }
 
    @PreDestroy
    public void stop() {
        pool.shutdown();
    }
}

Friday, December 7, 2018

Send GET/POST request with Spring Framework

Add httpclient to dependency list
1
2
3
4
5
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.6</version>
</dependency>
Below is an HttpUtil to send GET/POST request using Spring RequestTemplate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RequestTemplate;
 
public class HttpUtil {
    private static final int DEFAULT_TIMEOUT = 1000;// 1second
    private static final HttpUtil INSTANCE = new HttpUtil();
    private RequestTemplate rest;
    private HttpComponentsClientHttpRequestFactory requestFactory;
 
    private HttpUtil() {
        requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setReadTimeout(DEFAULT_TIMEOUT);
        requestFactory.setConnectionTimeout(DEFAULT_TIMEOUT);
        rest = new RestTemplate(requestFactory);
    }
 
    public static HttpUtil getInstance() {
        return INSTANCE;
    }
     
    public <T> T get(String url, Class<T> responseClass) {
        return rest.getForObject(url, responseClass);
    }
     
    public <T> T post(String url, Object requestBody, Class<T> responseClass) {
        return rest.postForObject(url, requestBody, responseClass);
    }
     
}

Saturday, February 4, 2017

Gradle to Maven Convertion

Just need to add Maven plugin to build.gradle

1
apply plugin: 'maven'

Then run the command 'gradlew.bat install'

The pom file for maven build will be available under build/poms named 'pom-default.xml'

Copy the 'pom-default.xml' to build.gradle directory and rename to 'pom.xml'.

Now you can build project by maven command 'mvn clean install'

Indicate Java version

If the build is failed due to 'diamond operator is not supported in -source 1.5 (use -source 7 or higher to enable diamond operator)', you need to add 'maven-compiler-plugin' to the pom file and re-run command 'mvn clean install'

1
2
3
4
5
6
7
8
9
10
11
12
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>

Sunday, January 1, 2017

Java Post JSON data

GSON library is good tool to convert data to JSON format 1. Add GSON dependency, current latest version is 2.8.0
1
2
3
4
5
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.0</version>
</dependency>
2. The data sender util look like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
 
import com.google.gson.Gson;
 
public class HttpRequestSender {
 
    private static final Logger LOGGER = Logger.getLogger(HttpRequestSender.class.getName());
 
    public static int postJsonData(String url, Object data, int connectionTimeout, int readTimeout, StringBuffer response) {
        int responseCode = 0;
        Gson gson = new Gson();
        StringBuilder sb = new StringBuilder();
        sb.append("data=").append(gson.toJson(data));
        long startTime = System.currentTimeMillis();
        try {
            URL urlObj = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) urlObj.openConnection();
            conn.setConnectTimeout(connectionTimeout);
            conn.setReadTimeout(readTimeout);
            conn.setRequestMethod("POST");
            conn.setInstanceFollowRedirects(false);
            conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            conn.setRequestProperty("charset", "UTF-8");
            byte[] postData = sb.toString().getBytes("UTF-8");
            conn.setRequestProperty("content-length", postData.length + "");
            conn.setDoOutput(true);
            try (DataOutputStream wr = new DataOutputStream(conn.getOutputStream())) {
                wr.write(postData);
                wr.flush();
            }
            responseCode = conn.getResponseCode();
            if (response != null) {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
                    String line = reader.readLine();
                    while (line != null) {
                        response.append(line);
                        line = reader.readLine();
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "Error while posting data " + String.valueOf(data) + " to " + url, e);
        }
        LOGGER.log(Level.INFO, "Posted {0} to {1} took {2} ms", new Object[] { String.valueOf(data), url, (System.currentTimeMillis() - startTime) });
        return responseCode;
    }
}

How To Get Source IP Address from HttpServletRequest

The address of source of request is stored in the header of HttpServletRequest so it is simply to get it. If it is not available in header so we can get the RemoteAddress. Mark dependency to package javaee-web-api, current latest verion is 7.0
1
2
3
4
5
<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version>7.0</version>
</dependency>
The util look like:
1
2
3
4
5
6
7
8
9
10
public static String getSourceIPAddress(HttpServletRequest request) {
    String srcIPAddress = request.getHeader("X-FORWARDED-FOR");
    if (srcIPAddress == null) {
        srcIPAddress = request.getRemoteAddr();
    }
    if (srcIPAddress != null && srcIPAddress.contains(",")) {
        srcIPAddress = srcIPAddress.split(",")[0];
    }
    return srcIPAddress;
}

Saturday, December 24, 2016

An useful util to handle nested collection in Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
 
public class CommonUtil {
 
    public static <K, V, O extends V> V getAndCreateIfNotExist(K key, Map<K, V> map, Class<O> c) {
        V result = map.get(key);
        if (result == null) {
            synchronized (map) {
                result = map.get(key);
                if (result == null) {
                    try {
                        result = c.newInstance();
                    } catch (Exception e) {
                        throw new RuntimeException("Error in getAndCreateIfNotExist", e);
                    }
 
                    map.put(key, result);
                }
            }
        }
        return result;
    }
    // Test
    public static void main(String[] args) {
        Map<String, Set<String>> phoneNumbersPerName = new HashMap<>();
        String personName = "Alex";
        Set<String> phoneNumbers = getAndCreateIfNotExist(personName, phoneNumbersPerName, HashSet.class);
        phoneNumbers.add("01234567891");
        phoneNumbers.add("09090909090");
        System.out.println(phoneNumbersPerName);
        // {Alex=[09090909090, 01234567891]}
    }
}

An useful util to separate a list to multiple sublist in Java

Assume that you need to group/separate a List of object to multiple sublist with an specified size, below use should be useful.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.LinkedList;
import java.util.List;
 
public class CommonUtil {
    public static <T> List<List<T>> group(List<T> input, int bulkSize) {
        List<List<T>> result = new LinkedList<>();
        int from = 0;
        int to = bulkSize;
        int size = input.size();
 
        while (to < size) {
            result.add(input.subList(from, to));
            from = to;
            to += bulkSize;
        }
 
        if (from < size) {
            result.add(input.subList(from, size));
        }
        return result;
    }
 
}