A Continuous Test Runner for Java
When you changed any test case or java code which is covered by test cases, Infinitest will invoke the test case automatically for you!
Jersey can handle concrete data binding smoothly, however, for Polymorphic, it’s not very configurable.
e.g.:
IUser
DefaultUser, SGUser, CNUser
We need a web service, which accept POST request from Client side:
saveUser(IUser newUser)…
Nobody knows it’s a DefaultUser or SGUser, or CNUser, except Spring config XML. and there’re some ways to use Jersey do the deserialization.:
http://programmerbruce.blogspot.sg/2011/05/deserialize-json-with-jackson-into.html
However, I prefer to use “Simple” Data Binding from Jackson to do the mapping manually:
“Simple here just means that range of value types is limited to core JDK types”
Object root = mapper.readValue(src, Object.class); Map<?,?> rootAsMap = mapper.readValue(src, Map.class);
So in the saveUser() method, we can get the raw values and then initialize the instances with the help of Spring to make sure what we know and what we only need to know is ‘Interface’/Contract:
saveUser(Map<String, Object> json) {
(Cast) json.get(“key”);
}
1. Interface
几乎所有的Class都是某些Interface的实现, 但我从来没有认真考虑过接口应该怎么用, 用到什么程度.
举例说, 有接口IDatabase, 还有具体类DefaultDatabase, Oracle, DB2…
理论上, 除了配置文件/Factory中可能会用到具体实现, 初次之外, 就不应该在任何Class中使用具体实现!
但事实上, 尤其是在不假思索, 取名叫做DefaultDataBase时, 经常会使用DefaultDataBase而不是IDatabase…
2. SVN
模块/文件夹 需要重构+重新命名.
由于担心SVN出现莫名其妙的问题, 所以新建了文件夹, 然后将新的文件逐步复制进去.
所有文件的历史记录将丢失.
3. Exception
WebService的Exception应该继续抛出, 而不是处理. 这样客户端在收到Exception后可以进行后续处理, 譬如重定向到某一个错误页面.
“You can subtype a generic class or interface by extending or implementing it. The relationship between the type parameters of one class or interface and the type parameters of another are determined by the extends and implements clauses.”
http://docs.oracle.com/javase/tutorial/java/generics/inheritance.html
package com.liguoliang.core.dao; import java.util.List; import com.liguoliang.core.modle.Animal; public abstract class AbstractDAO <T extends Animal>{ protected T saveAnimal(T animal) { System.out.println("Save: " + animal.toString()); return animal; } protected abstract List<T> getList(); }
Sub class should follow the contract made by the super class: T extends Animal
Otherwise, got the Error: Bound mismatch: The type ** is not a valid substitute for the bounded parameter
package com.liguoliang.core.dao; import java.util.List; import com.liguoliang.core.modle.Dog; public class DogDAO<WhatEver extends Object> extends AbstractDAO<Dog> { public Dog saveDog(Dog dog) { return saveAnimal(dog); } @Override protected List<Dog> getList() { return null; } public WhatEver whatEver(WhatEver w) { return w; } }
今天写了段很挫的代码, 简单的来说就是这样:
public static void main(String[] args) { try { throwNewException(); } catch (Exception e) { System.out.println(e); System.out.println(e.getMessage()); } } private static void throwNewException() { Object test = null; // simulate the Spring injection Error. test.getClass(); throw new RuntimeException("UserName cannot be empty."); }
简直就是奇葩, 在做UnitTest时, 其中一个用例是throwNewException throw RuntimeException,
由于Spring注入失败, 导致抛出NullPointerException, 而后续代码依赖于RuntimeException的ErrorMesg, 一直拿不到ErrorMesg. 纠结半天, 原因如下:
1. 懒. 使用RuntimeException而不是创建对应的Exception类型;
2. 懒. 在Catch时, catch了Exception, 而且没有打印Exception, 也就是说, 拦截并隐藏了所有Exception!
3. 懒. Debug时懒得思考, 看到如下的输出:
java.lang.NullPointerException
null
就得出结论, Exception是Null的! WTF!! 然后就开始纠结是不是Spring的问题…
所以,
创建Exception类型, Capture具体Exception具体处理, 处理或是继续抛出Exception, 而不是隐藏,.
// Proudly powered by Apache, PHP, MySQL, WordPress, Bootstrap, etc,.