Total Pageviews

2017/01/11

[Oracle VirtualBox] VT-x is not available

Problem
當我們參加教育訓練,從講師的硬碟 copy 上課用的 VirtualBox 到自己的電腦後,在啟動的時候發生錯誤,顯示 VT-x is not available 的錯誤訊息


How-to
解決步驟如下:
1. 重新啟動電腦 (restart your computer)
2. 按下 Esc,到 BIOS 進行設定 (press Esc during restarting computer process, then enter your BIOS configuation)
3. 將 Virtualization Technology (VTx) 的選項選取,重新啟動電腦即可 (Check Virtualization Technology (VTx) and Save, then restart your computer)




2017/01/10

[Oracle VirtualBox] 在 VirtualBox 中無法連上網路

Problem
當我啟動 VirtualBox 後,發現在 VirtualBox 中無法連上網路,但是在本機是可以連上網路的,此 VirtualBox 的網路設定如下:


How-To
網路要設定成橋接介面卡,並指定本機使用到的網路介面卡即可




2017/01/09

[Design Pattern] Factory Pattern

Assume I have a juice store, which provide apple juice, orange juice and kiwi juice. As I accept customer's order, I will make juice and deliver juice to customer.

Therefore, I will do make juice and deliver juice no matter which juices are ordered.
package albert.practice.designpattern.factory;

public interface Juice {
    void makeJuice();
    void deliverJuice();
}


Each juice will implement Juice interface, and implement its own logic in each class.
Here is apple juice:

package albert.practice.designpattern.factory;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class AppleJuice implements Juice {

    @Override
    public void makeJuice() {
      log.debug("making APPLE juice.");
    }

    @Override
    public void deliverJuice() {
        log.debug("deliver APPLE juice to customer.");
    }

}



Here is orange juice:

package albert.practice.designpattern.factory;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class OrangeJuice implements Juice {

    @Override
    public void makeJuice() {
        log.debug("making ORANGE juice.");
    }

    @Override
    public void deliverJuice() {
        log.debug("deliver ORANGE juice to customer.");        
    }

}



Here is kiwi juice:
package albert.practice.designpattern.factory;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class KiwiJuice implements Juice {

    @Override
    public void makeJuice() {
        log.debug("making KIWI juice.");
    }

    @Override
    public void deliverJuice() {
        log.debug("deliver KIWI juice to customer.");        
    }

}


I also create a fruit enumeration to tell which juice I will make:
package albert.practice.designpattern.factory;

public enum FruitEnum {
    APPLE, ORANGE, KIWI;
}


And I create a JuiceStore to process customers' order. The processOrder method is used to create apple, orange or kiwi object depends on customer's order.
package albert.practice.designpattern.factory;

public class JuiceStore {

    public static void main(String[] args) {
        JuiceStore test = new JuiceStore();
        test.processOrder(FruitEnum.KIWI);
        test.processOrder(FruitEnum.APPLE);
        test.processOrder(FruitEnum.ORANGE);
    }

    public void processOrder(FruitEnum fruit) {
        Juice juice = null;
        if (FruitEnum.APPLE == fruit) {
            juice = new AppleJuice();
        } else if (FruitEnum.ORANGE == fruit) {
            juice = new OrangeJuice();
        } else if (FruitEnum.KIWI == fruit) {
            juice = new KiwiJuice();
        }
        juice.makeJuice();
        juice.deliverJuice();
    }

}


It seems good so far. But if we would like to create object without exposing the if-else creating logic to client, we need to apply factory pattern to refactor the existing architecture.


Therefore, we need to create a JuiceFactory to generate object of concrete class based on given fruit.
package albert.practice.designpattern.factory;

public class JuiceFactory {

    public Juice getJuice(FruitEnum fruitEnum) {
        Juice juice = null;
        if (FruitEnum.APPLE == fruitEnum) {
            juice = new AppleJuice();
        } else if (FruitEnum.ORANGE == fruitEnum) {
            juice = new OrangeJuice();
        } else if (FruitEnum.KIWI == fruitEnum) {
            juice = new KiwiJuice();
        }
        return juice;
    }

}



We can see the updated JuiceStore class, the creating logic had been hide in JuiceFactory, we only need to tell JuiceFactory which fruit I would like to make:

package albert.practice.designpattern.factory;

public class JuiceStore {

    public static void main(String[] args) {
        JuiceFactory factory = new JuiceFactory();
        
        Juice apple = factory.getJuice(FruitEnum.APPLE);
        apple.makeJuice();
        apple.deliverJuice();
        
        Juice orange = factory.getJuice(FruitEnum.ORANGE);
        orange.makeJuice();
        orange.deliverJuice();
        
        Juice kiwi = factory.getJuice(FruitEnum.KIWI);
        kiwi.makeJuice();
        kiwi.deliverJuice();
    }
}


We can see JuiceStore asks JuiceFactory to create object based on its demands, and JuiceStore will use its object to make juice and deliver juice.




2017/01/08

[Redmine] Fail to Create Project via Rest API again!

Problem
I am using Redmine rest api to create project, and had checked the project identifier only allowed lower letter (a-z), numbers, dashes and underscores. But it still go wrong when I only provide numbers in project identifier:
1
2
3
4
5
org.springframework.web.client.HttpClientErrorException: 422 Unprocessable Entity
 at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:667) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:620) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]


How-to
According to this issue, the project identifier cannot accept number only although the document does not say it.

Therefore, we need to do one more check as we create project (you need to import org.apache.commons.lang.StringUtils class):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    private void checkProjectIdentifier(String identifier) {
        Pattern pattern = Pattern.compile("^[a-z0-9_=]*$");
        if (!pattern.matcher(identifier).matches()) {
            throw new RuntimeException("專案代碼僅允許使用小寫英文字母 (a-z), 阿拉伯數字, 虛線與底線");
        }
        
        if(StringUtils.isNumeric(identifier)) {
            throw new RuntimeException("專案代碼不可僅有數字");
        }
    }


Reference
[1] https://www.redmine.org/issues/5877

2017/01/07

[Redmine] Fail to Create Project via Rest API

Problem
I am using Redmine Rest API to create project, but I get this error message:
1
2
3
4
5
6
org.springframework.web.client.HttpClientErrorException: 422 Unprocessable Entity
 at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:667) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:620) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580) ~[spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
 at com.cht.commons.web.client.RestRequest.post(RestRequest.java:175) ~[cht-commons-web-client-0.3.0-SNAPSHOT.jar:0.3.0-SNAPSHOT]




How-To
This error results from the project identifier's limitation. 
I provide an illegal project identifier, so I fail to create project.



Owing to the Redmine Rest API cannot provide meaningful information for user, so I need to utilize regular expression to provide meaningful information when the project identifier is not legal.
1
2
3
4
5
6
    private void checkProjectIdentifier(String identifier) {
        Pattern pattern = Pattern.compile("^[a-z0-9_=]*$");
        if (!pattern.matcher(identifier).matches()) {
            throw new RuntimeException("僅允許使用小寫英文字母 (a-z), 阿拉伯數字, 虛線與底線");
        }
    }

    
    
Reference
[1] https://www.redmine.org/projects/redmine/wiki/Rest_Projects