Monday, February 20, 2017

Java Sequence Generator which simulates Oracle DB Sequence Generator

There is a requirement in my recent project, to generate 11 digit long sequence number without any database. Interesting, we are so used to rely on database to generate sequence number. In Java programming world, there isn’t a convenient library to generate sequence number!?

Solution 1: UUID.randomUUID().
UUID is alpha numeric and UUID size is way bigger than 11 digits.

Solution 2: System.currentTimeMillis().
[1] System.currentTimeMillis() generates 13 digits.
[2] If we substring the left most 11 characters, we lose the accuracy.
[3] The sequence is not continuous.
[4] In the very fast machine and fast retrieval, it is possible to obtain repeated value.

Solution 3: System.currentTimeMillis() as init value and +1 subsequently.
In the high volume retrieval, +1 may outrun the speed of time, e.g. 20000 transactions per second. When program restart, the newly System.currentTimeMillis() init value might have been used previously.

Solution 4: Plain and basic +1 counter and save the value in local file. This ensures the uniqueness of sequence number and sequence number will resume when restart the program.
Issue: Too much file write will slow down the program.

Solution 5: Plain and basic +1 counter with cache, similar to Oracle sequence cache. When cache is used up, renew it and save the new cache value in local file.
Issue: When the program or server crashes, local file is not updated and we don’t know where the last sequence number.

Solution 6: Enhanced version 5. When program is restarted, sequence counter will start from previous cache.
Issue: This behavior is the same as Oracle sequence generator. Un-used sequence number is lost when program is restarted.

Solution 7: Enhanced version 6. With the help of Java ShutdownHock, we’ll save current and new cache value in the file. Local file will be updated when
1)Program is properly shutdown, ShutdownHock will store [Current count, current count].
2)When new cache is created, store [Current count, new cache]

So, when program is restarted, it will read the file and compare,
1)If Current count == current count, resume sequence number = Current count.
2)If Current count < new cache, it means program crashed previously. Sequence number will start from new cache + 1.

So far Solution 7 is quite good. It is clean and light-weight.
http://stackoverflow.com/questions/1186387/generating-9-digit-ids-without-database-sequence/42344842#42344842

Interesting observation is,
1) Many people would think until Solution 4, 5, 6 and got stuck.
2) When 1 person is working alone, it is not easy to get out of blind spot.
3) The best solution indeed is not known or given. The best solution is purified from questioning and brain-storming with a team of good colleagues.

Wednesday, August 24, 2016

Renew Tenancy Renewal Offer

From MY HDB PAGE, go
MY BUSINESS -> Industrial Properties -> Tenant

After completion, print out the following:
1. Acceptance Letter
2. Deed of Guarantee (print 2 pages to 1 front of back)
3. Company Resolution , must be on paper with company letter head.

The rest can be ignored.

Mail to:
Housing and Development Board
Industrial Properties Group
480 Lorong 6 Toa Payoh
HDB Hub East Wing 21st Storey,
Singapore 310480
Attn: xxx

Friday, February 05, 2016

Java 8 collections content order

It is observed that in Java 8, the content in Collections has different order than previous Java.

To compare the equality of content in two Collections, the safer strategy becomes:

1. Convert name=value pair to Collections.
http://stackoverflow.com/questions/13592236/parse-a-uri-string-into-name-value-collection

2. assertTrue(org.apache.commons.collections.CollectionUtils.isEqualCollection(Collection a, Collection b));
 

Tuesday, November 24, 2015

compile single executable jar file with maven

Reference: http://stackoverflow.com/questions/574594/how-can-i-create-an-executable-jar-with-dependencies-using-maven

There are 2 ways of doing it.

(1) To include other jars:

  
    
      
        org.apache.maven.plugins
        maven-shade-plugin
        
          
            package
            
              shade
            
          
        
        
          
            
              asia.wirecard.standalone.reconcile.ReconcileGUWID.App
            
          
          ${artifactId}-${version}-with-libs
        
      
    
  

The jar file itself contains all the classpath dependencies:
java -cp Target.jar com.package.target.App or
java -jar Target.jar

(2) To include extracted classes:

  
    
      
        maven-assembly-plugin
        
          
            
              asia.wirecard.standalone.reconcile.ReconcileGUWID.App
            
          
          
            jar-with-dependencies
          
        
        
          
            make-assembly 
            package 
            
              single
            
          
        
      
    
  

The jar file itself is executable:
java -jar Target.jar

Thursday, November 19, 2015

Java output raw http get post

The following shows how Java write raw http GET and POST request via socket.

// Break down destinationURL.
// Reference: http://docs.oracle.com/javase/tutorial/networking/urls/urlInfo.html
java.net.URL aURL = new java.net.URL(destinationURL);
String sProtocol = aURL.getProtocol();
String sHost = aURL.getHost();
int iPort = aURL.getPort();
if (iPort == -1) {
  if (sProtocol.equals("https")) {
    iPort = 443;
  } else {
    iPort = 80;
  }
}
String sPath = aURL.getPath();
String sQuery = aURL.getQuery();
if (sQuery == null) { sQuery = parameters; } else { sQuery = sQuery + "&" + parameters; }

// Create socket.
java.net.Socket clientSocket;
if (sProtocol.equalsIgnoreCase("https")) {
   clientSocket = SSLSocketFactory.getDefault().createSocket(sHost,iPort);
} else {
   clientSocket = new java.net.Socket(sHost,iPort);
}
clientSocket.setSoTimeout(Integer.parseInt(timeOut));
 
// Connect to server.
java.io.OutputStream output = clientSocket.getOutputStream();
//output.write(("GET " + sPath + "?" + sQuery + " HTTP/1.1\r\n").getBytes("UTF-8"));
//output.write(("Host: " + sHost + "\r\n").getBytes("UTF-8"));
//output.write("Connection: close\r\n".getBytes("UTF-8")); // So the server will close socket immediately.
//output.write("\r\n".getBytes("UTF-8")); // HTTP1.1 requirement: last line must be empty line.
output.write(("POST " + sPath + " HTTP/1.1\r\n").getBytes("UTF-8"));
output.write(("Host: " + sHost + "\r\n").getBytes("UTF-8"));
output.write(("Content-Type: application/x-www-form-urlencoded\r\n").getBytes("UTF-8"));
output.write(("Content-Length: " + sQuery.length() + "\r\n").getBytes("UTF-8"));
output.write(("Connection: close\r\n").getBytes("UTF-8")); // So the server will close socket immediately.
output.write(("\r\n" + sQuery).getBytes("UTF-8"));
output.flush();

java.io.InputStream in = clientSocket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String inputLine = "";
while ((inputLine = reader.readLine()) != null) {
   response.append(inputLine);
}
System.out.println("HTTP Response = [" + response + "]");

Dynamic way to compose http parameters:
http://stackoverflow.com/questions/4205980/java-sending-http-parameters-via-post-method-easily

String userpass = org.apache.commons.codec.binary.Base64.encodeBase64("username:password".getBytes("UTF-8"))

import java.io.*;
import java.net.*;
import java.util.*;

class Test {
    public static void main(String[] args) throws Exception {
        URL url = new URL("http://example.net/new-message.php");
        Map<String,Object> params = new LinkedHashMap<>();
        params.put("name", "Freddie the Fish");
        params.put("email", "fishie@seamail.example.com");
        params.put("reply_to_thread", 10394);
        params.put("message", "Shark attacks in Botany Bay have gotten out of control. We need more defensive dolphins to protect the schools here, but Mayor Porpoise is too busy stuffing his snout with lobsters. He's so shellfish.");

        StringBuilder postData = new StringBuilder();
        for (Map.Entry<String,Object> param : params.entrySet()) {
            if (postData.length() != 0) postData.append('&');
            postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
            postData.append('=');
            postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
        }
        byte[] postDataBytes = postData.toString().getBytes("UTF-8");

        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
        conn.setRequestProperty("Authorization", "Basic ${userpass}")        
conn.setDoOutput(true); conn.getOutputStream().write(postDataBytes); Reader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); for (int c; (c = in.read()) >= 0;) System.out.print((char)c); } }



 

Wednesday, October 14, 2015

Chrome DevTools

Usage of Chrome Dev Tools.

Thursday, August 28, 2014

strategies to write log file log4j on other server computer

1. Using log4j's SimpleSocketServer
http://stackoverflow.com/questions/15381559/easiest-way-to-send-files-to-a-server/15382152#15382152

In your server you can just start server with the following parameters:
java -cp log4j.jar org.apache.log4j.net.SimpleSocketServer 4712

Here is sample log4j.properties for the server:
log4j.rootLogger=debug, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

Here is sample log4j.properties for the client:
log4j.appender.SERVER=org.apache.log4j.net.SocketAppender
log4j.appender.SERVER.Port=4712
log4j.appender.SERVER.RemoteHost=loghost
log4j.appender.SERVER.ReconnectionDelay=10000

2. Using Linux / Ubuntu rsyslog
http://www.rsyslog.com/doc/master/configuration/modules/imudp.html

Step 1 vi /etc/rsyslog.conf

= = = = = = = Enable UDP (Tested not working) = = = = = = =
# specific ruleset for remote messages
$Ruleset udpremote
*.* /var/log/updremote.log
# switch back to default ruleset
$Ruleset RSYSLOG_DefaultRuleset

# provides UDP syslog reception
$ModLoad imudp
$InputUDPServerBindRuleset udpremote
$UDPServerRun 514

= = = = = = = Enable TCP = = = = = = =
# specific ruleset for remote messages
$Ruleset tcpremote
*.* /var/log/tcpremote.log
# switch back to default ruleset
$Ruleset RSYSLOG_DefaultRuleset

# provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerBindRuleset tcpremote
$InputTCPServerRun 10514

Step 2 service rsyslog restart

Here is sample log4j.properties for the client:
log4j.appender.SYSLOG=org.apache.log4j.net.SyslogAppender
log4j.appender.SYSLOG.SyslogHost=localhost
log4j.appender.SYSLOG.Facility=Local2
log4j.appender.SYSLOG.Header=true
log4j.appender.SYSLOG.layout=org.apache.log4j.PatternLayout
log4j.appender.SYSLOG.layout.ConversionPattern=[%X{ref}] %-5p %C{1}:%L %m%n