Wednesday 30 March 2016

Volatile and double-checked locking

https://en.wikipedia.org/wiki/Singleton_pattern#Java_5_solution

This is a lazy initialization of singleton.

What does volatile do here?

1:  public final class SingletonDemo {  
2:    private static volatile SingletonDemo instance;  
3:    private SingletonDemo() { }  
4:    public static SingletonDemo getInstance() {  
5:      if (instance == null ) {  
6:        synchronized (SingletonDemo.class) {  
7:          if (instance == null) {  
8:            instance = new SingletonDemo();  
9:          }  
10:        }  
11:      }  
12:      return instance;  
13:    }  
14:  }  
Well, volatile ensures one thread can always read the up-to-date value of the variable updated by another thread.

What happens if we remove volatile?

OK, brain exercise time. Suppose two threads A and B come to this getInstance() method.

At time 100: Both A and B arrive at line 5
At time 101: A enters the synchronized block, B waits outside
At time 105: A exits the synchronized block at line 12
At time 106: B enters the synchronized block at line 7

Question: For thread B, is 'instance' equal to null now? Not necessarily without the volatile keyword. It might still seem to be null to B although it has in fact been assigned some value.

Next question: is there any advantage of using double-checked lock over the following implementation, which looks much neater.
1:  public final class SingletonDemo {  
2:    private static SingletonDemo instance = null;  
3:    private SingletonDemo() { }  
4:    public static synchronized SingletonDemo getInstance() {  
5:      if (instance == null) {  
6:        instance = new SingletonDemo();  
7:      }  
8:      return instance;  
9:    }  
10:  }  

I guess when the number of threads is high, the 2nd implementation is slower because of the synchronized keyword on the method. For the 1st implementation, once the object has been created, the synchronized block won't be executed at all.

Tuesday 29 March 2016

Builder pattern

Quick template code

 public class FullName {  
   private final String firstName;  
   private final String lastName;  
   public static class Builder{  
     private String firstName;  
     private String lastName;  
     public Builder(){}  
     public Builder firstName(String firstName){  
       this.firstName = firstName;  
       return this;  
     }  
     public Builder lastName(String lastName){  
       this.lastName = lastName;  
       return this;  
     }  
     public FullName build(){  
       return new FullName(this);  
     }  
   }  
   private FullName(Builder builder) {  
     firstName = builder.firstName;  
     lastName = builder.lastName;  
   }  
 }  

Client code

 FullName name = new FullName.Builder().firstName("Ming").lastName("Sun").build();  

Finalizer guardian

"Effective Java" Item 7: Avoid finalizer

In the last few paragraphs, a concept of 'Finalizer guardian' is introduced. It took me a while to get my head around it. So I would like to share my understanding.

When we override a class's finalize() method, it is important we call super.finalize(), because its super class may want to close some critical resources. However, people don't always remember to call super.finalize(). Here the finalizer guadian comes to rescue.

Let's have a look at an example. OK, here we forget to call super.finalize()

 public class FooSub extends Foo {  
   @Override  
   protected void finalize() throws Throwable {  
     System.out.println("FooSub garbage collected");  
   }  
 }  

But with finalizer Guardian, everything is still under control.

 public class Foo {  
   private CriticalResource criticalResource = new CriticalResource();  
   private final Object finalizerGuardian = new Object(){  
     @Override  
     protected void finalize() throws Throwable {  
       System.out.println("Critical resource closed");  
       criticalResource.close();  
     }  
   };  
   private static class CriticalResource implements Closeable{  
     public void close() throws IOException {  
     }  
   }  
 }  


 public static void main(String[] args) {  
     FooSub foo = new FooSub();  
     foo = null;  
     System.gc();  
   }  

Check the output

 Critical resource closed
 FooSub garbage collected 

Sunday 27 March 2016

jQuery Ready handler

<html>
  <head>
    <title>JQuery</title>
 <script src="script/jquery-1.12.2.js" type="text/javascript"></script>
 <script type="text/javascript">
   var $ = 'Hi!';
       jQuery(function(){
     alert('$ = ' + $);
   });     
 </script>
  </head>
  <body>Hi</body>
</html>
Since $ variable gets overridden here, the result is '$ = Hi!'

Now add a $ as a parameter

 <script type="text/javascript">
   var $ = 'Hi!';
       jQuery(function($){
     alert('$ = ' + $);
   });     
 </script>

The result is '$ is function (select, context)......'

Because $ is a local variable now. The global variable $ = 'Hi!' takes no effect.

Weak reference

What is weak reference?

To understand weak reference, first look at strong reference.

String s = new String("hello world");

This is strong reference. Only when s becomes null will the object 'new String("hello world")' become eligible for garbage collection.

 
Map strongMap = new HashMap();
Cat key = new Cat();
Object value = new Object();
strongMap.put(key, value);
key = null;
value = null;

The key in the map is also strong reference. Even though the key variable is set to null, the 'new Cat()' object cannot be garbage collected.
 
Map weakMap = new WeakHashMap();
Cat key = new Cat();
Object value = new Object();
weakMap.put(key, value);
key = null;
value = null;

Now that we put the key/value pair into a WeakHashMap, the 'new Cat()' object does become garbage collected once the key is set to null.

Here is a complete program to illustrate the difference.

First a utility class
 
private static class MyKey {
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("Gabage collected");
    }
}

StrongMap
public static void main(String[] args) {
    Map<MyKey, Object> strongMap = new HashMap<MyKey, Object>();
    for (int i = 0; i < 1000; i++){
       for (int j=0; j < 10000; j++){
            MyKey key = new MyKey();
            Object value = new Object();
            strongMap.put(key, value);
        }
    }
}
Output is OutOfMemory error

WeakMap
public static void main(String[] args) {
    Map<MyKey, Object> weakMap = new WeakHashMap<MyKey, Object>();
    for (int i = 0; i < 1000; i++){
       for (int j=0; j < 10000; j++){
            MyKey key = new MyKey();
            Object value = new Object();
            weakMap.put(key, value);
        }
    }
}

Output is tons of "Gabage collected" message and you don't see an OutOfMemory error.

Git integration with IntelliJ

So when right clicking the project in Intellij, and find 'Git' option is not on the menu, what to do?

Step 1, File - Settings - Version Control - Git, Check the 'Path to Git executable' is correct



Step 2: File - Settings - Plugins - Search 'git'. Check 'Git Integration' and 'Git Hub' are ticked.



Still cannot see the option? Maybe because your project has been previously using SVN as source control? So delete all the .svn and .idea folders and reimport the project.

Monday 14 March 2016

MySQL 中文乱码解决方案

修改my.ini,如果此文件不存在,就在MySQL安装目录下(e.g. D:\mysql-5.1.34-win32)建立此文件

[mysql] 
default-character-set=gbk
[mysqld] 
default-character-set=gbk

稍微解释一下,[mysql] default-character-set=gbk就是告诉MySQL,现在客户端传过来的SQL包含有中文字符。
而[mysqld] default-character-set=gbk就是把MySQL的数据库改为中文编码。
用以下命令可以清晰地看到效果:
mysql> show variables like 'char%';
+--------------------------+---------------------------------------+
| Variable_name                 | Value                                 |
+--------------------------+---------------------------------------+
| character_set_client         | gbk                                   |
| character_set_connection | gbk                                   |
| character_set_database   | gbk                                   |
| character_set_filesystem  | binary                                |
| character_set_results       | gbk                                   |
| character_set_server       | gbk                                   |
| character_set_system      | utf8                                  |
| character_sets_dir           | D:\mysql-5.1.34-win32\share\charsets\ |
+--------------------------+---------------------------------------+

重启MySQL服务器后,以后建立的数据库和表都可以接受中文。

值得一提的是,在修改my.ini之前建立的数据库和表还是不能接受中文。需要找到数据库的dt.opt文件,比方以前建立过
create database mydb;

那么在D:\mysql-5.1.34-win32\data\mydb下,修改dt.opt

default-character-set=gbk
default-collation=gbk_chinese_ci

再重启服务器就可以了。

关于表的话,当然也可以用Alter命令修改,但更简单的方法就是drop再create一次就完了。

如果用Hibernate连接,只要简单地作如下配置

<property name="connection.url">jdbc:mysql://localhost:3361/mydb</property>

并不需要加上?useUnicode=true&amp;characterEncoding=GBK

JDK6和JBoss 5.0.0.GA的不兼容问题

  今天研究EJB3的web service过程中,出现一些问题,解决后觉得挺有心得,所以记录下来,已供将来参考。

环境:
  JDK6, JBoss 5.0.0.GA,Eclipse Helios。JBoss整合在Eclipse中。

问题:
  客户端访问部署在JBoss中的web service时,出现以下异常
java.lang.UnsupportedOperationException: setProperty must be overridden by all subclasses of SOAPMessage
 at javax.xml.soap.SOAPMessage.setProperty(SOAPMessage.java:445)
......

分析:
  JDK6中提供了web service相关的jar包,但和JBoss并不兼容。从这个例子中来看,就是JDK提供了一个SOAPMessage的类,同时JBoss也提供了同名的类(显然,内容是不一样的)。JBoss本意是要加载自己的类,但JVM classloading的顺序就是先加载JDK自己的核心类,再加载server的类。没办法,就这样被JDK的类捷足先登了。所以解决思路就2个,一个就是去除JDK6的SOAPMessage的类,如果只剩下一个类,那JVM也无从选择了。另一个思路就是设法使JBoss的SOAPMessage的类加载在先。

解决方案1:
  为了去除JDK6的SOAPMessage的类,不可能说去把这个jar包删掉,可行的方法就是放弃JDK6,而使用JDK5,JDK5中是没有这个类的。但这样我们就无法使用JDK6中的新功能了,以这样的代价去解决这个问题并不能令人满意。

解决方案2:
  在JBoss的路径中,找出包含SOAPMessage的jar包——jbossws-native-saaj.jar,放入<JAVA_HOME>\jre\lib\endorsed目录中。(如没有这个目录,则自己建立)

  为什么要放在endorsed目录下呢?原来放在这个目录下的class是优先于JDK核心类先被加载的。举例来说,大家都知道String类是final,所以无法继承。但你如果就是铁了心了要改写这个String类,也是有办法的,就是把这个新写的类打包成jar文件后放入endorsed目录下,这样JVM就会优先加载你这个String类了。

  所以这样一来,JBoss的SOAPMessage类就先被加载,这样就解决了问题。

  但这种解决方案也是有问题的,人家JDK6开发出SOAPMessage这个包终归是有用意的,它或许跟JBoss不兼容,但可能就跟Glassfish兼容的很好,如果以后要在这个机器上跑2个服务器,该怎么办呢?

  以我的知识所及,本来是想不出第三种,也就是最好的解决方案。但我在论坛中,看到有些人在同样的环境下运行的很好,完全没有发生错误。这使我很疑惑,究竟我跟他们之间有什么区别呢?

  抱着试试看的态度,我将JBoss的启动改为Commond Line方式启动,也即是双击bin目录下的run.bat。然后调用web service客户端,居然毫无问题。经过反复试验后,证明JBoss在Eclipse中运行就会出错,而在Commond Line下启动就没问题。这不得不使我去探索这两种启动方法到底有什么区别,也终于使我研究出了——

解决方案3:
  在Eclipse中,修改JBoss启动的VM Arguments,默认的是-Dprogram.name=run.bat -server -Xms128m -Xmx512m -XX:MaxPermSize=256m,在下面再加一句话

  -Djava.endorsed.dirs="D:\jboss-5.0.0.GA\lib\endorsed" (假设JBOSS_HOME=D:\jboss-5.0.0.GA)

  这句话的意思就是告诉JVM,这次启动,你要把D:\jboss-5.0.0.GA\lib\endorsed当作你的endorsed目录来启动。在这里你完全可以猜出D:\jboss-5.0.0.GA\lib\endorsed目录下一定有jbossws-native-saaj.jar。

  这么做的好处就是让这个配置只应用于JBoss的启动上,甚至说是只限于这个JBoss Server的instance。我完全可以再建立一个JBoss server,不加上那个参数,那么新的JBoss server还是只会以默认的方式启动。

  说实话,为了找出两种JBoss启动的不同,费了我可大的劲了。最后我是把run.bat中的@echo off去掉,让它把执行的话一句一句打印出来,最后才找到了这句参数。而一旦找到了这句话,一瞬间我就豁然开朗了。

总结:
  通过这次问题处理,一是巩固了对endorsed目录的作用的理解(原先只是模模糊糊大概知道那么回事),二是知道了-Djava.endorsed.dirs=...的用法,三是对类加载的顺序有了进一步的了解。

Union order by

select .... union select ... order by后面可以跟什么

只可以跟两样东西

1. 数字N,1<=N<=列数
2. union左边的select clause里的字段,如果有别名,必须用别名,不可以再用原来的字段名。不可以用字符串。

一个例子说明第二点

select employee_id id, first_name, 'c', 'c' ca from employees
union
select employee_id, first_name f_name, 'c', 'c' from employees
order by ?

order by 3 可以
order by employee_id 不可以,因为这个字段有了别名,本来的字段名就不能用了
order by id 可以
order by first_name 可以
order by f_name 不可以,union右边select clause的字段根本不用看
order by 'c' 不可以,因为是字符串
order by ca 可以,因为是别名,不是字符串了
order by lower(first_name) 不可以,表达式一律不允许

Modify constraint

SQL expert (1z0-047)的题库里有这样一道题,我觉得挺有意思的。

The ORDERS table contains data and all orders have been assigned a customer ID. Which statement would add a NOT NULL constraint to the existing CUSTOMER_ID column?

A. ALTER TABLE orders ADD CONSTRAINT orders_cust_id_nn NOT NULL (customer_id);
B. ALTER TABLE orders MODIFY customer_id CONSTRAINT orders_cust_id_nn NOT NULL;
C. ALTER TABLE orders MODIFY CONSTRAINT orders_cust_id_nn NOT NULL (customer_id);
D. ALTER TABLE orders ADD customer_id NUMBER(6)CONSTRAINT orders_cust_id_nn NOT NULL;

粗一看觉得答案是A。D肯定是错的,因为customer_id这个字段已经存在了。觉得BC错是因为我压根就没见过MODIFY CONSTRAINT这种用法。不是只有drop和add constraint吗?

答案却是B。

这是套用了ALTER TABLE table MODIFY column CONSTRAINT constraint inline_constraint的用法。

https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_3001.htm#i2103924

A为什么错了?因为ADD CONSTRAINT的用法是ALTER TABLE table ADD CONSTRAINT constraint out_of_line_constraint。

inline_constraint和out_of_line_constraint有什么区别?

http://docs.oracle.com/cd/E11882_01/server.112/e41084/clauses002.htm#SQLRF52180

主要区别就在于out_of_line_constraint不支持NULL/NOT NULL。其他的什么PRIMARY KEY, UNIQUE, CHECK, FOREIGN KEY都支持,当然格式有点不一样。

关于C,其实MODIFY CONSTRAINT是有的,用法是ALTER TABLE table MODIFY CONSTRAINT constraint_state。什么是constraint_state?

就是INITIALLY IMMEDIATE/DEFERRED, ENABLE/DISABLE, VALIDATE/NOVALIDATE这些东西,所以这个用法套不上的。

Key preserved table

What does mean by key preserved table?

According to its definition: A table is key-preserved if every key of the table can also be a key of the result of the join. So, a key-preserved table has its keys preserved through a join.

Let's illustrate this by an example.
 
create table a (a_id number primary key);
create table b (b_id number primary key, a_id number,
  foreign key (a_id) REFERENCES a(a_id) on delete cascade);

create or replace view c as (
  select a.a_id, b.b_id from a,b where a.a_id = b.a_id
)

insert into a values (1);
insert into b values (2,1);
insert into b values (3,1);

select * from c;

The result is
 
A_ID B_ID
---------
1    2
1    3

Clearly A's primary key A_ID cannot be used as a primary key in the view, so table A is not a key preserved table. On the other hand, table B's primary key B_ID can be used as a primary key in the view, so table B is a key preserved table for this view C.

So what happens when you
 
delete from c;

is all the rows in table B are deleted.

Rules for updating a join view

http://docs.oracle.com/cd/E11882_01/server.112/e25494/views.htm#ADMIN11782