Support Wikipedia Follow My Heart: 一月 2012

2012年1月20日星期五

Comparing Different JUnit Parameterized Runners

This week I met a task, that is: I have one test case (with contains logistics) and multiple group of test data combinations. So I want to make use of JUnit Parameterized Test Function to test all and generate splendid report. How ever, when I invoke the standard Parameteried Tests in JUnit4, a problem occured:
The displaying name of each round test in the report is : [0], [1], [2] ….
All my collegues think this naming tradition of JUnit is meaningless. What we want is : test[A=a;B=b…], test[A=1;B=2…] …,  from which users can easily understand with what kind of value combination the test failed. I googled the problem, many people have the same requirement. From StackOverflow , someone already made a customized JUnit Test Runner “LabelledParameterized”, by which the displaying name of JUnit Result can be changed by users’ code. I download the source code, and test it. Good news is that it works in Eclipse (3.6) with Junit.jar (4.10). Bad news is that it does not work in Netbeans (7.1) nor ANT (by JUNIT/JUNIT REPORT Target).
So I have to keep finding. Then I found JUnitParams Project from Google Code. By which the displaying name is successfully replaced both in IDE (eclipse/netbeans) and command line mode (ANT). By the way, JUnitParams is not perfect yet, the displaying name will be mysterious if all your parameters are “String” type.
To Compare the differences of each Test Runner, I made a comparison project (wiht ANT build.xml). You can  download it from Here. Just unzip the code to local folder (without space in path name), and run the build.xml (Target “all”) from ANT. Here are some screen snapshots.
junit_compare
Result Comparison in Eclipse
2012-01-21_1229
2012-01-21_1236
Result Comparison in html Report (generated by ANT – JUnitReport)

2012年1月6日星期五

How to create Own “Update Center” for Netbeans / VisualVM Plug-in?

What is a “Update Center” and how it works?

The answer is very easy. It is kind of plug-in repository. Plug-in authors will release and save the new plug-in in certain update center, locating in some remote servers. The url of the Update Center (actually, it is the URL of the “updates.xml” file in the root of Update Center folder) can be registered in your software. Then, the next time your software checks the URL, read in the “updates.xml” which descripes what plug-in are available and their version information. If your “Update Center” finds that some your installed plugin has newer version, then you will see a hint note. If you permits updating, then the new plug-in will be downloaded and installed automatically.

VisualVM is a product utilizing the Netbeans Platform, so it is same to build update center for either Netbeans or VisualVM.

What is necessary for a “Update Center”?

It becomes clear that two things are important:

  1. there is an “updates.xml” file locating in the root folder of Update Center
  2. the available .nmb plug-in packages are also located in the Update Center. The location should be accessible by canonical path from the “updates.xml” file.

What is the format and content of such “updates.xml” file?

This question is trivial because acutally it is not designed for human read in my idea. If you insist on it, you can read the following sample from VisualVM Plugin Suites.

Sample Updates.xml

 


How to generate the necessary files automatically?


I suggest using Netbeans IDE to do this, because it already provides function to write “Updates.xml” file and package generated .nbm files. All you need is just to:



  1. Create a Module Suite, and add your plug-in into this suite.

  2. Right click the suite, choose “package as –> nbms” (some posts said the function name is “create nbms”). Or you can use ANT to run the “nbms” target of file “build.xml” of your suite. Then you can see a “update” folder is automaically created under your suite root. All your required files are inside this folder.

Note: sometimes, you may find impossible to create a separate module suite to contain your plug-in because it depends on other modules, which cannot be also copied into the new suite. In this case, maybe you need to add your own plug-in into the same suite, build the suite, and manually change the content of the “updates.xml” (delete useless “module” sections or “module group” sections).


How to publish the generated files as “Update Center” mode?


Since you have got the “update” folder in which all necessary files are generated (“updates.xml”, “*.nbm”,…), you need to put them into some place where is accessible by your software.


Here are some examples.



  1. If you put the folder in “C:\”, then you can open your software, registerr the auto update URL as “file:/C:/update/updates.xml”.

  2. You may also start the Windows IIS service (in windows platform) or any other kind of HTTP Server (like APACHE..), setting up the default website root address to the update folder. Then you may register the URL as “http://localhost/updates.xml”.

Finally, do not forget to notify your software to check available plug-ins if you want to see the changes immediately!

2012年1月3日星期二

Java RMI 学习笔记

在我看来,Java RMI 远远不是一个简单的网络点对点消息传递技术。RMI技术的精髓在于,在程序运行时动态地在网络上部署和转移资源(包括源代码和数据)。因此,对于RMI技术的用户来说,必须完成大量“繁琐”的资源/代码访问权限的设置工作,以保证RMI技术在使用时的安全性。因此对于仅仅追求网络信息的简单点对点传播功能的初级用户来说,我觉得RMI技术显然是“杀鸡用牛刀”,而且也太复杂了一点。

不过鉴于RMI技术的强大,还是很有必要钻研一下的。Oracle给点RMI技术的教程我觉得太初级了一些,我觉得为什么它并没有把RMI技术的设计和使用精髓讲清楚。因此,我抛砖引玉,尝试着从其他角度做一点补充。详细的blog和测试代码请参照英文版博客文章“My Java RMI Tutorial”.

首先,Java RMI的连接建立工作流程图。

图片1

第一步:远程的某一个对象,将自己注册到全局的RMI Naming Service里面。这样无论哪里的客户端,都可以有办法找到它的注册信息(包含真实的网络通信地址)。

图片2

第二步:某一个需要用到远程对象的客户端上线后,通过全局的RMI Naming Service查找目标对象的注册信息(根据注册名称)。

图片3

第三步:客户端获取远程对象的真实网络地址后,建立网络连接。从远程对象那边下载接口代理(Stub)。这样以后调用远程对象的方法时,所需要的手续等同于调用本地stub对象的方法。网络层的动作被成功屏蔽。

 

RMI技术的精髓在于“动态部署资源”,也就是说,在实际通信过程中,客户端(或者远程对象端)可以动态下载完成计算所需要的资源。举个例子:

  1. 客户端事先知道的仅仅是stub对象端接口的定义文件。具体在远程对象那边是哪个类实现了这个接口,客户端是不知道的。甚至客户端都没有这个类的代码。因此,在建立连接后,客户端会动态地从远程对象那边下载所需要的对象定义信息。
  2. 同样的道理,在调用stub对象的方法实现计算时,客户端负责提供参数,远程对象完成计算。事先远程对象并不需要知道参数是什么。甚至参数的具体代码远程对象可能也没有(有点可能仅仅是接口的定义)。这样在计算之前,远程对象端会自动从客户端下载参数的具体类代码。
  3. 可能的场景还有,当远程对象完成计算,返回结果时,所返回的对象的具体实现代码,可能客户端也是没有的。因此,客户端也可能动态地从远程对象端下载相关代码。

这种运行时的动态资源部署,涉及到安全性的问题。为了避免恶意软件入侵,RMI技术的使用者需要通过SecurityManager来指定自己的类在接入RMI网络时,自身的哪些资源可以被动态下载。这一块内容对于初学者来说很麻烦,但是却是RMI技术的设计重点。

My Java RMI Tutorial”的示例代码 中有3组例子,分别对应了上面列出的三种场景,在代码中书写清楚了在每种情况下需要如何设置SecurityManager来覆盖必须的文件访问路径。希望这些例子能对您的工作学习有所帮助。

My Java Remote Message Invocation (RMI) Turorial

Basically, Java RMI is one of the popular information sending technology in network environment. However, the main merit/point of Java RMI is "Dynamically Distributing Resources (including Source Code and Messages) around Network" than purely passing messages from one network node to the other. So I believe if you are new bee to network communication and what you want is purely network messaging function, it would be better to research on other technologies (like Socket Connection, RPC, and etc.)
Oracle provides RMI tutorial online, however, I think it only provides the most simplest example, which is far from enough to tell new bees what should be done, and why they must do this. So from now on, I will discuss the basic ideas of RMI and show some basic operation patterns. By adopting these examples, I believe you can clearly understand what you are doing, and why you do it.
The main idea of RMI is to "Dynamically distribute computing code and messages", so it becomes natural to think through the following ways:
  1. Users of RMI may not know which physical network address (like IP address) they should send message to, because the characteristic "Dynamic Distribution" is highly appreciated in RMI designment. So RMI applies Java "Naming" Service to disclaim and find target resources.
  2. Also, It is quite possible that the target node does not have the same copy of used classes/resources. So RMI still permits downloading of classes/resources dynamically. Therefore it becomes quite important to protect some credential resources against malicious downloading, RMI designers pay much attention in securities design. Nearly full package of Javax.Security is applied in RMI to assure the security and authentication.
Due to above consideration, users who want to use RMI must also follow its rules: using Java Naming Service to Declare/Find target Object, setting authentication configuration so that RMI can do valid downloading and data access. 
The general work flow of RMI can be depicted as follows:
图片1
Step 1: Registering Remote Object in the Naming Service.
wps_clip_image-12757
Step 2: Client gets Remote Object information from Naming Service.
wps_clip_image-15646
Step 3: Client setup connection with Remote Object, download Stub and finish configuration.
 
So let's have a look at where and what kind of Security policy should be applied. Security policy will be applied wherever downloading is happened. In the whole work flow, there are three occasions when downloading might happen.
wps_clip_image-11092
Possible Downloading Occasions

 

When Client "looks up" target remote object in the naming service:

The naming service replies the real Remote Object Network Address to the client. So Client could setup connection with the remote Object, and download stub for it. During this process, The System must provide enough access control authority to the following items. Code "RMI_Sample_1_Server/Client" is an example.
    1. Remote Object Side
      1. Remote Object class File
      2. Class which creates Stub
      3. Class which invokes Registry
    2. Client Side
      1. Class which invokes Registry
      2. Class which lookup "stub" in Registry

 

When Client invokes method of Remote Object (Stub):

The command and parameters will be sent to remote object by the stub. Then actual action will be done remotely. 
So if the remote object has enough definition (primitive types, implementation class file, etc.) of the attached parameters, nothing need to be downloaded. Code "RMI_Sample_1_Server/Client" is an example.
In contrast, if remote object does not have the definition (class file) of parameters, these definition will be downloaded from the client side. So in this occasion, the system must provide authorities to following items. Code "RMI_Sample_2_Server/Client" is an example.
  1. Remote Object Side
    1. Remote Object class File
    2. Class which creates Stub
    3. Class which invokes Registry
  2. Client Side
    1. Class which invokes Registry
    2. Class which lookup "stub" in Registry
    3. Parameter Implementation Class Files

When Remote Object returns the result of Method Invocation:

The result will be returned. So if the Client side has enough definition file (primitive type, implementation class file, etc.) to parse the returned object, nothing will be downloaded specially. Code "RMI_Sample_2_Server/Client" is an example.
In contrast, if Client side lacks enough information to parse the returned Object, it becomes necessary to download required information from the Remote Object Side. So the following items should have access control authority. Code "RMI_Sample_3_Server/Client" is an example.
  1. Remote Object Side
    1. Remote Object class File
    2. Class which creates Stub
    3. Class which invokes Registry
    4. Result Object Implementation Class Files
  2. Client Side
    1. Class which invokes Registry
    2. Class which lookup "stub" in Registry
 

RMI Important Notes

  1. Interface of Remote Object must Extends "java.rmi.remote"
  2. Methods in Remote Object (Interface) must throws "RemoteException"
  3. Any parameters/objects which need be transmitted by RMI must implements "Serializable"
  4. Security Manager must be setup in both Remote Object side and Client side.
 

Example Code

Download Link
CONTENTS:
    1. RMI_Common 
      1. Common tools applied in examples
      2. Build it, and copy rmi-tool.jar into lib folder of each example projects. Add it to build path.
    2. RMI_Sample_1_Server/Client
      1. Compile the source code into "bin" folder.
    3. RMI_Sample_2_Server/Client
      1. Compile the source code into "bin" folder.
      2. Copy RMI_Common/dist/rmi-type.jar into lib folder of the Client project. Add it to build path.
    4. RMI_Sample_3_Server/Client
      1. Compile the source code into "bin" folder. 
      2. Copy RMI_Common/dist/rmi-type.jar into lib folder of the Client project. Add to build path.