Friday, February 25, 2011

jHMS thành dự án mã nguồn mở

Sau một thời gian xây dựng và triển khai thực tế, nhóm phát triển phần mềm quản lý phòng khám jHMS đã quyết định công bố mã nguồn mở của sản phẩm này tại sourceforge. Lý do chính của quyết định này là nhằm giúp cho ngày càng nhiều bệnh viện, phòng khám, đặc biệt là các vùng khó khăn có thể trang bị cho mình một công cụ quản lý tiên tiến nhằm quản lý chuyên môn tốt hơn.

Việc công bố mã nguồn mở này cũng sẽ tạo điều kiện cho các sinh viên và lập trình viên Java có điều kiện nghiên cứu một ứng dụng Java cụ thể phục vụ cho việc học của mình

Đây là phần mềm mã nguồn mở hoàn toàn miễn phí nên tất cả mọi cá nhân tổ chức đều có thể download về để sử dụng miễn phí và triển khai có thu phí.

Source code có thể được download từ đây: http://jhms.sf.net
(sử dụng svn)

Friday, January 7, 2011

Các thủ thuật Java

Gần đây tôi có đọc một cuốn sách về các thủ thuật Java có tên là: Effective Java. Tác giả cuốn sách lập luận rằng việc học Java từ các giáo trình truyền thống không thể đưa đến việc sử dụng Java một cách hiệu quả. Trái lại, có những mẹo, thủ thuật lập trình chỉ có thể có được sau nhiều năm kinh nghiệm sử dụng Java. Trong cuốn sách tác giả liệt kê khỏang 50 thủ thuật khác nhau phân theo nhiều nhóm: khởi tạo đối tượng, thread...

Tuy nhiên có một số thủ thuật khác mà theo cảm nghĩ của tôi có ích cho lập trình viên Java.

1. Dùng scanInterval khi sử dụng maven
ScanInterval giúp lập trình viên không phải restart lại mỗi khi thực hiện thay đổi trên file java. Tính năng này cũng tương tự như jRebel (commercial) nhưng lại hòan tòan có sẵn

2. Dùng Tomcat trong Eclipse
Việc này cũng có hiệu quả tương tự như dùng scanInterval trong maven vì Tomcat sẽ scan những thay đổi trong project và reupload những thay đổi này.

3. Remote debugger
Một ứng dụng không chạy trong eclipse nhưng vẫn có thể gọi debug trên eclipse. Tuyệt vời

4. Dùng netbean thay vì eclipse. Các ưu điểm của eclipse như gọn nhẹ, nhiều plugin hỗ trợ mọi người đều đã biết. Tuy vậy, để start 1 ứng dụng EJB trên eclipse thì quả thật phiền phức.

EJB được hỗ trợ tuyệt vời trên netbean với glassfish tích hợp. Bộ tài liệu tham khảo và các ví dụ giúp cho "tay mơ" nhất có thể làm quen với EJB dễ dàng.

Hơn thế nữa netbean hỗ trợ lập trình J2ME và PHP cũng rất tuyệt.

5. Security cho ứng dụng web
Hiện tại có 3 cách để hiện thực security cho 1 ứng dụng web:
- In house
- Web server security framework
- Spring security

Nguyên lý giản dị của security là kiểm tra xem người dùng hiện đang đăng nhập có hợp lệ không (authentication), và có đủ quyền để thực thi 1 chức năng nào đó không (authorization).
Để thực hiện điều này, ta chỉ cần chen 1 đọan code xác minh quyền và kiểm tra quyền. Đọan code này sẽ đọc thông tin của user đã đăng nhập từ trong biến session.

Như vậy tự xây dựng cơ chế security cho ứng dụng là đơn giản và dễ dàng hơn rất nhiều so với sử dụng 1 framework như Spring security hoặc là 1 web server. Tuy nhiên cách làm này bị cho là không decouple 2 logic khác nhau: xác thực quyền và thao tác nghiệp vụ. May mắn thay, servlet cung cấp 1 cơ chế tuyệt vời cho security đó là Servlet Filter. Xem blog sau để biết chi tiết: http://www.developer.com/security/article.php/3467801/Securing-J2EE-Applications-with-a-Servlet-Filter.htm

Wednesday, November 24, 2010

SSL on Tomcat

I have found a very nice Tutorial on making SSL on Tomcat.
http://techtracer.com/2007/09/12/setting-up-ssl-on-tomcat-in-3-easy-steps/

The only thing which needs a notice is that port SSL is now 443 instead of 8080. So, to try if you set up SSL successfully, you must open the url: https://localhost:443

However, this is only the self-sign certificate. You will need OpenSSL to create a true certificate or probably buy a comercial one from VeriSign.

More about this topic:
http://download.oracle.com/javaee/5/tutorial/doc/bnbxw.html
-----------------------
Setting up SSL on Tomcat is easy and you don’t have to do much for converting your web application to work with the Https protocol. But however, the problem you would find to set up SSL is the documentation available over the web. The documentation source is available on the Apache site but it starts off good and ends with a lot of confusion. Especially I was confused on the OpenSSL part where it says to use OpenSSL.
It might be good in a production environment to use OpenSSL but if you just want to test out SSL with Tomcat alone then it is more than enough to just have your JDK and Tomcat setups. So I would make you walk through the same steps which I did while getting SSL up and running and building a secured web app within a matter of minutes.
The things which I have used to setup SSL consists of:
JDK 1.6
Tomcat 6
Even though I have used the latest version I don’t see any problems which you might face in carrying out the same set of steps for JDK 1.5 which I am about to explain. JDK comes shipped with a keytool executable which is required to generate a keystore. The keytool can be found in the earlier version of JDK too. The 3 steps which would make you to get started with setting up SSL are:
Generating the Keystore file
Configuring Tomcat for using the Keystore file
Configuring your web application to work with SSL
Let’s get this party started now.
1. Generating the KeyStore file
The keystore file is the one which would store the details of the certificatesnecessary to make the protocol secured. Certificates contain the information as to who is the source from which you are receiving the application data and to authenticate whether it is the intended party or not. To make this keystore you would have to use the keytool. So open command prompt in Windows or the shell in Linux and type:
cd %JAVA_HOME%/bin on Windows
cd $JAVA_HOME/bin on Linux
You would land up in the Java bin directory. Now time to run the keytool command. You have to provide some parameters to the command as follows :
keytool -genkey -alias techtracer -keypass ttadmin -keystore techtracer.bin -storepass ttadmin
The highlighted words are the ones which you would have to change according to your requirements. But keep one thing in mind that both thekeypass and storepass passwords should be the same. The .bin file is actually your keystore file. It would now start a questionnaire. So fill in therelevant details accordingly. Look below for a reference as to what to answer for the questions.
What is your first and last name?[Unknown]: nitin paiWhat is the name of your organizational unit?[Unknown]: homeWhat is the name of your organization?[Unknown]: techtracerWhat is the name of your City or Locality?[Unknown]: mumbaiWhat is the name of your State or Province?[Unknown]: maharashtraWhat is the two-letter country code for this unit?[Unknown]: INIs CN=nitin pai, OU=home, O=techtracer, L=mumbai, ST=maharashtra, C=IN correct?[no]: yes
The command would then conclude. It would make a .bin file with the name you had provided inside the bin directory itself. In my case it wastechtracer.bin which was located in
C:\Program Files\Java\jdk1.6.0_02\bin\
Put the .bin file in the webapps directory of Tomcat. This is required to avoid the need to give an absolute path of the file in the next step.
2. Configuring Tomcat for using the Keystore file
Here we would be making some changes to the server.xml file inside tomcat to tell it to use the keystore which was created in the earlier step for configuring SSL. Open the file server.xml which can be found as:
/conf/server.xml
Now you have to modify it. Find the Connector element which hasport=”8443″ and uncomment it if already not done. Add two lines. The highlighted lines are the newly added ones.

You can notice that I have given the path to the keystoreFile property asrelative to tomcat bin directory because the startup command will look for the .bin file. Now all you have to do is start your server and check the working of SSL by pointing your browser to the URL to:
https://localhost:8443/
Now that you have your tomcat running in the SSL mode you are ready to deploy an application to test its working. You must note that still your tomcat can run in normal mode too at the same time i.e on port 8080 with http. So it is but obvious that any application deployed to the server will be running on http and https at the same time. This is something that we don’t want. We want our application to run only in the secured mode.
3. Configuring your web application to work with SSL
In order to do this for our test, take any application which has already been deployed successfully in Tomcat and first access it through http and https to see if it works fine. If yes, then open the web.xml of that application and just add this XML fragment before web-app ends i.e
securedapp/*CONFIDENTIAL
Explanation of the fragment is beyond the scope of this tutorial but all you should notice is that the /* indicates that now, any resource in your application can be accessed only with https be it Servlets or JSP’s. The termCONFIDENTIAL is the term which tells the server to make the application work on SSL. If you want to turn the SSL mode for this application off then just turn don’t delete the fragment. Just put the value as NONE instead ofCONFIDENTIAL. That’s it!
Conclusion
These were the 3 easy steps in which you can make Tomcat to work in the SSL mode and also it tells you how easily you can turn the SSL mode on and off. If you find any difficulty or are not clear on any of the above steps feel free to drop in your queries. If you like this tutorial it would be nice of you to drop in a comment of appreciation or feedback as to how this tutorial can be improved.

Sunday, November 21, 2010

Cài đặt 1 Single sign on server + Ldap

Single sign on (SSO) và Ldap là 1 chủ đề được thảo luận rất nhiều trong những năm qua. Nhiều người có suy nghĩ rằng việc thiết lập các hệ thống sử dụng single sign on và Ldap là công việc phức tạp , đòi hỏi chuyên môn cao. Tuy nhiên, với sự phát triển của các công nghệ mã nguồn mở, việc sở hữu SSO và Ldap đã trở nên rất dễ dàng. Cái khó nhất lại nằm ở chỗ: thiếu các tài liệu cập nhật về các công nghệ này. Bài viết này sẽ giới thiệu từng bước thực hiện các công việc trên.

1. Cài đặt Single sign on server:
Hiện tại, CAS (Central Authentication System - http://www.jasig.org/cas) là 1 phần mềm mã nguồn mở xuất sắc được dùng để thiết lập các Single sign on server. Phát triển trước tiên bởi ĐH Yale, từ năm 2008, được quản lý bởi nhóm yêu thích kiến trúc Java - JASIG.
Trên webpage của Jasig có 1 tutorial hòan chỉnh hướng dẫn các cài đặt CAS

Tuy nhiên, ở bước 10, thay vì property userName phải được đổi thành --> userDn
độc giả không chỉ nên tham khảo cho biết

2. Cài đặt Ldap server
Apache đã phát triển 1 phần mềm gọi là Directory Apache http://directory.apache.org/
Download và cài đặt phần mềm này
Chú ý: sau khi cài vào Control panel/administarive/service và start dịch vụ này lên
3. Now try the CAS by opening browser and type: http://localhost:8080/, it will redirect to a CAS login page. After login, all resources in http://localhost:8080 can be accessed.
-------------------------------
Prerequisites
Apache tomcat is installed and running
Java(JDK) is installed.
Instructions
Download Apache directory server from http://directory.apache.org/
Run the setup with all the defaults and test that the server is working on localhost using telnet:
Start->Run->telnet
In the telnet console, type the following: open localhost 10389
If you get a screen that lets you type, Apache Directory Server is configured properly
Download the CAS installation and find the war file e.g. \cas-server-$VERSION\modules\cas-server-webapp-$VERSION.war
Start the Tomcat server, e.g. $TOMCAT_HOME/bin/startup.bat.
Add the CAS war file, cas-server-webapp-3.2.1.war, to the webapps folder, $TOMCAT_HOME\webapps.
Confirm the following directory exists, which indicates a successful deploy, {{$TOMCAT_HOME\webapps\cas-server-webapp-$VERSION},
You may also examine the Tomcat stardard output log file for errors, $TOMCAT_HOME/logs/catalina.out.
Stop the tomcat server, e.g. $TOMCAT_HOME/bin/shutdown.bat.
Add the following to the pom.xml file in the META-INF folder, $TOMCAT_HOME\webapps\cas-server-webapp-$VERSION\META-INF\maven\org.jasig.cas\cas-server-webapp:

${project.groupId}
cas-server-support-ldap
${project.version}

Edit $TOMCAT_HOME\webapps\cas-server-webapp-$VERSION\WEB-INF\deployerConfigContext.xml as follows:
Add the following bean LDAP authentication:
class="org.jasig.cas.adaptors.ldap.util.AuthenticatedLdapContextSource">



ldap://localhost:10389










Remove the demo authentication handler, org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler, from the authenticationHandlers property of the org.jasig.cas.authentication.AuthenticationManagerImpl bean.
Add the LDAP fast bind authentication handler:




Add the cas-server-support-ldap-$VERSION.jar from the CAS installation to $TOMCAT_HOME\webapps\cas-server-webapp-$VERSION\WEB-INF\lib.
Start tomcat and confirm there are no errors in the $TOMCAT_HOME\logs\catalina.out log.
Open a browser to the URL http://localhost:8080/cas-server-webapp-$VERSION/ and authenticate with the following credentials, admin/secret.










Tuesday, October 26, 2010

Proxy. Loại: Structure. Độ khó: Cao

Proxy tiếng Anh có nghĩa là người được ủy nhiệm. Khi việc khởi tạo 1 đối tượng mất nhiều thời gian ví dụ như đọc file từ ổ đĩa hoặc load file từ Internet, chương trình sẽ tạo 1 file giả. Đến khi cần sử dụng thực sự file này thì lúc đó file có thể đã được load xong. Ví dụ như ở trình duyệt, khi load 1 trang web trình duyệt sẽ hiện các image holder trước sau đó mới lấp nội dung ảnh vào.
Xem xét ví dụ sau đây:
Ta có lớp trừu tượng Graphic với 2 phương thức load và draw. Lớp Image hiện thực lớp Graphic. Lớp ProxyImage cũng hiện thực lớp Graphic. Do load Image có thể mất nhiều thời gian nên ta tạo lớp ImageProxy để có sẵn đối tượng một cách nhanh chóng:

abstract class Graphic {
public abstract void load();
public abstract void draw();
}

public class Image extends Graphic {

private String filename;

public Image(String filename) {
this.filename = filename;
load();
}

public void draw() {
System.out.println("Drawing...");
}

public void load() {
System.out.println("Loading...");
}

}

public class ProxyImage extends Graphic {

private String filename;
private Graphic image;

public ProxyImage(String filename) {
this.filename = filename;
}

public void draw() {
if (image==null) image = new Image(filename);
image.draw();
}

public void load() {

}
}

public static void main(String[] args) {
Graphic image1 = new ProxyImage("file1.jpg");
Graphic image2 = new ProxyImage("file2.jpg");

image1.draw();
image2.draw();
}




Facade. Loại: Structure. Độ khó: Trung bình

Facade, đọc là fei sơ, có ý nghĩa như 1 bộ khung. Ví dụ như trong 1 máy tính sẽ có các bộ phận khác nhau như CPU, RAM, Harddrive. Khi bật nút power, các đối tượng như CPU, RAM, và Hard drive sẽ tự động thực hiện các công việc của mình.

public class Computer {

private CPU cpu;

private RAM ram;

private HardDrive hardDrive;

public Computer() {
cpu = new CPU();
ram = new RAM();
hardDrive = new HardDrive();
}
public void start()
{
cpu.boot();
ram.load();
hardDrive.read();
}
}

public class CPU {

void boot()
{
System.out.println("Booting CPU");
}
}

public class RAM {

void load()
{
System.out.println("Load memory from RAM");
}
}

Test:
public static void main(String[] args)
{
Computer facade = new Computer();
facade.start();
}



Composite. Loại Structure. Độ khó: Trung bình

Composite ám chỉ 1 lớp tổng hợp. Ví dụ 1 thư mục sẽ có 1 thư mục cha và nhiều file. Hay 1 nhân viên sẽ có 1 người quản lý và nhiều người dưới quyền. Ví dụ sau đây hiện thực cấu trúc đó:

public class Directory {

private Directory directory;
private File[] files;

public Directory(File[] files) {
super();
this.files = files;
}
public Directory(Directory directory, File[] files) {
super();
this.directory = directory;
this.files = files;
}
boolean isDirectory()
{
return files != null;
}
boolean isFile()
{
return files ==null;
}

public Directory getDirectory() {
return directory;
}

public void setDirectory(Directory directory) {
this.directory = directory;
}

public File[] getFiles() {
return files;
}

public void setFiles(File[] files) {
this.files = files;
}

}

Decorator. Loại: Structure. Độ khó: Thấp

Decorator là trang trí. Decorator cho 1 class nghĩa là thêm thuộc tính hoặc hành vi, hoặc mở rộng hành vi cho lớp đó mà không dùng subclass.

Ví dụ có lớp Number với phương thức in ra số ngẫu nhiên
public class Number {

public void print()
{
System.out.println(new Random().nextInt());
}
}

public class Decorator
{
public Decorator() {
System.out.println("This is random number: ");
new Number().print();
}
}
public static void main(String[] args)
{
Decorator decorator = new Decorator();
}




Prototype. Loại: Creation. Độ khó: Thấp

Prototype theo tiếng Anh là mẫu vật. Dựa trên mẫu vật mà người ta copy ra nhiều đối tượng khác có cùng tính chất và hành vi. Java hỗ trợ 1 interface Cloneable với phương thức clone.
public class Complex implements Cloneable {

int[] nums = {1,2,3,4,5};
public Object clone() {
try {
return super.clone();
}catch(CloneNotSupportedException cnse) {
System.out.println(cnse.getMessage());
return null;
}
}

int[] getNums() {
return nums;
}

}

public static void main(String[] args)
{
Complex complex1 = new Complex();
Complex copy = (Complex)complex1.clone();

complex1.getNums()[3] = 10000;

for(int i = 0; i < copy.getNums().length; i++)
System.out.println(copy.getNums()[i]);
}

Singleton. Loại: Creation. Độ khó: Dễ

Lúc mới học lập trình Java, tôi rất lười sử dụng từ khóa new để tạo mới class, có lẽ do ảnh hưởng của phương pháp lập trình thủ tục. Không ngờ sau khi làm quen với Java, tôi phát hiện ra rằng việc dùng static và final đôi khi có lợi: đó là lớp static chỉ có 1 và chỉ 1 instance mà thôi.

public class Singleton {

private static final Singleton INSTANCE = new Singleton();

public Singleton() {
}

public static Singleton getInstance()
{
return INSTANCE;
}

public String sayHello()
{
return "This method is called by only 1 instance";
}

public static void main(String[] args)
{
System.out.println(Singleton.getInstance().sayHello());
}
}

Monday, October 25, 2010

Abstract Factory. Loại: Creation. Độ khó: Trung bình

Abstract Factory trừu tượng hơn Factory 1 mức. Thay vì chỉ cần 1 interface Factory, pattern này đòi hỏi thêm 2 lớp Factory hiện thực interface này. Ví dụ interface Factory có 1 phương thức là createButton(), 2 lớp hiện thực là WindowFactory và MacFactory. Hai lớp này sẽ trả về lần lượt 2 đối tượng là WindowButton và MacButton tương ứng. Trong đó WindowButton và MacButton lần lượt là 2 lớp hiện thực của interfact Button.

Code mẫu:
public interface Button {
void paint();
}

public class OSXButton implements Button{
public void paint() {
System.out.println("Draw OSX button");
}
}

public class WindowButton implements Button {
public void paint() {
System.out.println("Drawing Window button");
}
}

public interface Factory {
Button createButton();
}

public class WindowFactory implements Factory {

public Button createButton() {
return new WindowButton();
}
}

public class OSXFactory implements Factory {
public Button createButton() {
return new OSXButton();
}
}

Chạy test:
public static void main(String[] args) {
Factory factory = new WindowFactory();
Button button = factory.createButton();
button.paint();
}

Factory. Loại: Creation. Độ khó: Trung bình

Factory là 1 nhà máy sản xuất. Ý tưởng đưa ra là 1 nhà máy có thể sản xuất ra nhiều loại đối tượng khác nhau tùy theo yêu cầu đầu vào.
Ví dụ, ta có lớp Namer có 2 thuộc tính: First Name và Last Name. Tùy theo văn hóa từng nước mà thứ tự của First Name và Last Name sẽ xuất hiện khác nhau. Giả sử ta có 2 lớp con của Namer là FirstNameFirst và LastNameFirst. Hai lớp này sẽ căn cứ vào chuỗi tên truyền vào, bóc tách ra họ, tên, sau đó gán vào 2 thuộc tính firstName và lastName.

public class Namer {
protected String firstName;
protected String lastName;
}

public class LastFirst extends Namer {

public LastFirst(String fullName) {
int i = fullName.indexOf(",");
if(i>0)
{
lastName = fullName.substring(0,i);
firstName = fullName.substring(i+1, fullName.length());
}
else
{
lastName = fullName;
firstName = "";
}
}
}


public class FirstFirst extends Namer {

public FirstFirst(String fullName) {

int i = fullName.indexOf(" ");
if (i > 0) {
firstName = fullName.substring(0, i + 1);
lastName = fullName.substring(i, fullName.length());
} else {
lastName = fullName;
firstName = "";
}
}

}

Ta dùng 1 factory ở đây để trả về đối tượng phù hợp căn cứ vào dữ liệu đầu vào:
public class FactoryNamer {

public Namer getNamer(String enterText)
{
if(enterText.indexOf(",")>0)
return new LastFirst(enterText);
else
return new FirstFirst(enterText);
}
}


Lập trình phần mềm điều khiển bằng VB6

VB6 đã outdated từ lâu và thay bằng .NET. Tuy nhiên, với các ứng dụng điều khiển, VB6 vẫn còn đất sống bởi vì nó không đòi hỏi cấu hình máy tính cao, dễ lập trình, và bảo trì.
RS232 hay còn gọi là cổng COM hay cổng tuần tự là loại cổng thường được dùng trong các thiết bị cần giao tiếp với máy tính. Ưu điểm của nó là đơn giản, rẻ tiền. Nhược điểm của nó là tốc độ truyền và khoảng cách.

Sau đây là đoạn code mẫu lấy dữ liệu từ 1 máy đo và lưu trữ dữ liệu thu được vào máy tính.

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)


Private Sub Command4_Click()
Dim downloadedData, data As String
If MSComm1.PortOpen = False Then MSComm1.PortOpen = True

Dim i As Integer
i = 5
Do While data <> "" Or i > 1
MSComm1.Output = "D"

Sleep 3000

data = MSComm1.Input

downloadedData = downloadedData & data
i = i - 1

Loop

Open "C:\data_from_awa.txt" For Output As #1

Write #1, downloadedData

Close #1

End

End Sub

Wednesday, October 20, 2010

Iterator. Loại: Behavioral. Độ khó: Thấp

Iterator là một dạng vòng lặp. Đối với 1 danh sách các đối tượng không đồng nhất nhau thì việc đưa vào các danh sách như List, Sort, Map sẽ giúp cho việc duyệt qua danh sách dễ dàng mà không cần quan tâm đến sự hiện diện bên trong của danh sách.

Ví dụ có interface Employee và 2 class hiện thực là HourlyEmployee - nhân viên làm theo giờ và RegularEmployee - nhân viên lãnh lương tháng.

interface Employee {

double earnings();

}

public class HourlyEmployee implements Employee {

private double salaryPerHour;

private String name;

public HourlyEmployee(double salaryPerHour, String name) {
super();
this.salaryPerHour = salaryPerHour;
this.name = name;
}

public double earnings() {
// TODO Auto-generated method stub
return 40*salaryPerHour;
}

public String toString() {
return name;
}
}

public class HourlyEmployee implements Employee {

private double salaryPerHour;

private String name;

public HourlyEmployee(double salaryPerHour, String name) {
super();
this.salaryPerHour = salaryPerHour;
this.name = name;
}


public double earnings() {
return 40*salaryPerHour;
}


public String toString() {
return name;
}

}

Sử dụng pattern này:

public static void main(String[] args)
{
List list = new ArrayList();

list.add(new HourlyEmployee(30, "Petter"));

list.add(new RegularEmployee(20000000, "Mary"));

Iterator itr = list.iterator();

while(itr.hasNext())
{
Employee em = (Employee)itr.next();
System.out.println(em + " earns "+em.earnings());
}

}


Command. Loại: Behavioral. Độ khó: Trung bình

Command nghĩa là ra lệnh. Sĩ quan chỉ huy gọi là commander, người này không làm mà chỉ ra lệnh cho người khác làm. Như vậy, phải có người nhận lệnh và thi hành lệnh (receiver).

Bây giờ ta lấy ví dụ sau. Bóng đèn Light có 2 phương thức switchOn và switchOff.

class Light()
{
void switchOn(){
System.out.println("Switch light on");
}

void switchOff(){
System.out.println("Switch light off");
}
}

Tuy vậy, để giống trong quân đội, ta làm 1 interface tên là Command không trực tiếp tắt bật đèn mà chỉ ra lệnh cho bóng đèn bật tắt.

interface Command(){
void execute();
}

Ta hiện thực interface này bằng 2 class: CommandOff và CommandOn

class CommandOff(){
Light light;
public CommandOff(Light light){
this.light = light;
}

public void execute(){
light.switchOff();
}
}


class CommandOn(){
Light light;
public CommandOn(Light light){
this.light = light;
}

public void execute(){
light.switchOn();
}
}

Bây giờ đã đóng gói các command này vào trong 1 bộ điều khiển gọi là Remote Control

class RemoteControl(){

private Command command;

public setCommand(Command command){
this.command = command;
}

public void pressButton(){
command.execute();
}

Sử dụng remote control này như sau:
public static void main(String[] args){

RemoteControl rc = new RemoteControl();

Light light = new Light();
Command c1 = new CommandOff(light);
Command c2 = new CommandOn(light);

rc.setCommand(c1);
rc.pressButton();

rc.setCommand(c2);
rc.pressButton();

}

Như vậy, ta có thể truyền bất cứ command nào vào Remote control để yêu cầu thực hiện. Khi đó, yêu cầu thực hiện đã được đóng gói vào trong 1 object như mô tả trong GoF book:

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations


Adapter - Loại: Creation - Độ khó: trung bình

Adapter nôm na là một bộ chuyển đối. Laptop cũng cần adapter để chuyển từ điện AC sang DC. Đi nước ngoài thì phải xem họ xài ổ cắm tròn hay dẹt, 3 chấu hay 2 chấu. Nếu không phải mua adapter.
Vậy adapter là 1 bộ chuyển đổi dùng để kết nối 2 hay nhiều thiết bị khác nhau lại.

Bây giờ xét ví dụ sau đây: mỗi loài động vật có tiếng kêu khác nhau, chó sủa, bò rống, vượn hót, chim kêu.

public class Cow {

public void roar()
{
System.out.println("o o o o o");
}

}

public class Dog {

public void bark()
{
System.out.println("gau gau gau gau");
}
}

Ta cần 1 interface AnimalAdapter để có thể phiên dịch tiếng nói tất cả động vật

public interface AdapterAnimal {

public void say();

}

Để hiện thực interface này ta cần có AdapterCow và AdapterCat.

public class AdapterCow implements AdapterAnimal {

Cow cow = new Cow();
public void say(){
cow.roar();
}
}

public class AdapterCat implements AdapterAnimal {

Dog dog= new Dog();
public void say(){
dog.bark();
}
}

Bây giờ, ta sử dụng Adapter này:

public static void main(String[] args)
{
AdapterAnimal[] aas = {new AdapterCow(), new AdapterDog()};

for(AdapterAnimal aa: aas)
{
aa.say();
}

}

Ta thấy: nhờ có AdapterAnimal mà việc cho các loài động vật khác nhau cùng lúc lên tiếng trở nên dễ dàng.


Design pattern trong Java

Design pattern là một thuật ngữ nổi tiếng trong hướng đối tượng. Tuy nhiên, design pattern cũng khá khó hiểu. Có hơn 200 pattern trong đó khoảng 24 pattern là phổ biến nhất. Để lấy chứng chỉ SCJD chỉ cần biết khoảng 3,4 mẫu gì đó. Còn để lấy được SCEA thì cần biết hết 24 mẫu. Design pattern cũng được ứng dụng trong .NET, Ruby....

Các framework mã nguồn mở sử dụng design patterns rất nhiều. Chúng ta có thể nhận dạng chúng thông qua cách đặt tên ví dụ: Proxy, Adapter, Singleton, Prototype....

Trong quá trình nghiên cứu design pattern tôi nảy sinh ý định viết 1 loại bài tóm tắt lại những cái đã học được. Tài liệu trên Internet về design pattern thì rất nhiều nhưng để hiểu design pattern cần có các ví dụ tốt. Tôi sẽ trình bày các ví dụ này kèm theo mỗi pattern. Ví dụ được tổng hợp từ nhiều nguồn khác nhau


Wednesday, September 1, 2010

Crazy hibernate again

Hibernate có quá nhiều phương thức và cách hành xử khác nhau, rất khó đoán trước

Ví dụ:
Thao tác bằng session
Session session = getSession();
try{
session.saveOrUpdate(serviceParamValue);
session.close();
}
catch(Exception e)
{
e.printStackTrace();
}

Thao tác bằng Hibernate
getHibernateTemplate().saveOrUpdate(serviceParam);

Khi dùng session đối tượng sẽ lập tức được cập nhật vào db. Trong khi nếu dùng hibernateTemplate thì phải đợi hết session dữ liệu mới được commit

Tuy nhiên, khi update 1 đối tượng nếu dùng session dữ liệu sẽ không được cập nhật

Chưa tìm được lý do

Thursday, August 12, 2010

Bộ nhớ heap của Java

Làm quen với Java lâu nhưng ít người để ý bộ nhớ heap của Java trong khi nó đóng vai trò rất quan trọng trong việc bảo đảm hiệu suất làm việc của Java.
Bộ nhớ heap là gì?
Bộ nhớ heap chính là bộ nhớ dùng để lưu trữ các đối tượng được tạo ra trong 1 chương trình Java. Như vậy nếu kích thước bộ nhớ quá nhỏ trong khi số lượng đối tượng được tạo ra lớn hơn dẫn đến tràn bộ nhớ.
Ví dụ cụ thể, bộ nhớ heap mặc định của Java là 64MB. 1 chương trình Java có 1 đối tượng với khoảng 10 thuộc tính kiểu String với độ dài trung bình là 50 ký tự, 1 ký tự 2 bytes như vậy khoảng 100 bytes. Nhân với 10 thuộc tính là 1MB. Nếu chương trình khởi tạo 1 danh sách khoảng 100 đối tượng như vậy lượng bộ nhớ cần dùng là 100MB, chương trình sẽ lập tức bị tràn bộ nhớ.
Có thể thấy khả năng dẫn đến tràn bộ nhớ là rất cao, đặc biệt đối với các chương trình Java lớn.

Cách khắc phục
Giải pháp là tăng bộ nhớ heap. Nói tuy đơn giản nhưng để thực hiện khá phức tạp vì mỗi 1 chương trình Java có cách thiết lập kích thước bộ nhớ heap khác nhau. Có ít nhất 3 cách chỉnh kích thước heap:
- Trong biến môi trường, tạo mới hoặc hiệu chỉnh giá trị của biến có tên JAVA_OPTS. Ví dụ, JAVA_OPTS = -Xms256m -Xmx256m
Xms256m: kích thước khởi tạo của heap là 256 Mb
Xmx256m: kích thước cực đại của heap là 256Mb
- Trong control panel, mở Java Control panel và hiệu chỉnh Runtime Java Environment theo thông số -Xmx256m
- Đối với file jar: java -Xms256m -Xmx256m your_program.jar
- Đối với jetty: vào bin mở file jetty-service.conf và chỉnh như sau:
wrapper.java.initmemory=1024m
wrapper.java.maxmemory= 1024m

Với các ứng dụng khác như Tomcat, Eclipse, Jboss có thể tham khảo cách thiết lập heap size tạo đây















Thursday, July 15, 2010

Học gì ở J2EE nâng cao?

Để có thể xây dựng những ứng dụng có qui mô lớn trong Java, những kiến thức trong phần J2EE nền tảng là chưa đủ. Một trong những khía cạnh quan trọng của các ứng dụng này là cho phép chia nhỏ ứng dụng thành các module nhỏ hơn. Theo lý thuyết, modular design sẽ giúp làm giảm bớt độ phức tạp của ứng dụng. Việc giảm độ phức tạp của hệ thống sẽ làm cho việc phát triển cũng như bảo trì hệ thống trở nên dễ dành hơn nhiều. Có nhiều cách tiếp cập modular design trong Java như: portal, OSGI, và home-made modular design.

1. OSGI có thể coi là một cách tiếp cận chính thống trong modular design. Được đề xuất bởi Sáng kiến giao tiếp mã nguồn mở, OSGI đã có sự phát triển đáng kể từ lúc xuất hiện. Spring cũng đã hỗ trợ OSGI. Tuy nhiên nhược điểm của OSGI là sự phức tạp của nó. Việc thiếu vắng các tài liệu sử dụng cũng là lý do khiến OSGI không phổ biến.

2. Portal cũng là 1 cách tiếp cận modular. Tuy nhiên, portal thích hợp với các trang web dạng như Joomla hơn là phát triển 1 ứng dụng quản lý.

3. Home-made modular design: so với 2 cách tiếp cận trên đây có vẻ là cách phù hợp nhất. Sở hữu một kiến trúc modular đáp ứng chính xác các yêu cầu quản lý đồng thời duy trì sự đơn giản ở mức độ nhất định đó là các lợi thế của các tiếp cận này.

Hai vấn đề cần giải quyết:
Home-made modular design cần phải giải quyết được 2 vấn đề sau:
- Thứ nhất, đó là khả năng chia sẻ kết nối dữ liệu giữa các module, đồng thời cho phép sự phụ thuộc lẫn nhau giữa các file hibernate mapping
- Thứ hai, khả năng đóng gói nhiều module thành 1 file war lớn. File war chung này sẽ giúp chia sẻ session giữa các module.

Các vấn đề này đều đã được nghiên cứu và thử nghiệm tại JDTC. Tham gia khóa học J2EE nâng cao bạn hoàn toàn có khả năng làm chủ các kiến thức này.