Resolvi dar um jeito no famoso NullPointerException, não em todo contexto de uma aplicação, mas especificamente em nossos beans (Classes com métodos GET e SET, padrão de nomenclatura javabean).
Através de AOP todo método getXXX que retornar um objeto com referência nula receberá uma nova instância do seu tipo de retorno.
PRÓS: Evita NullPointerExceptions e gera uma saída no console para que o programador esteja ciente que foi evitado uma exceção desse tipo ao invés de parar a aplicação e jogar uma pilha de erros pro JVM.
CONTRA: Pode gerar confusão na cabeça do programador, quando valores de saída forem diferentes daquilo que ele esperava.
Agora espero as críticas…rss…
[]'s
Fontes aspectJ
pointcut gettingValues(): execution(public * *.get*());
before():gettingValues(){
assinatura = thisJoinPoint.getSignature();
metodoGet = assinatura.getName();
tipoRetorno = assinatura.toLongString().split(" ")[1];
metodoSet = assinatura.getName().replace("get", "set");
nomeClasse = assinatura.toLongString().split(" ")[2];
Integer divisor = nomeClasse.lastIndexOf('.');
nomeClasse = nomeClasse.substring(0, divisor);
isNull = MorroniReflection.isNull(nomeClasse, metodoGet);
if(isNull){
System.out.println("####################### AspectJ (Inicio) #####################");
System.out.println("Evitando NullPointerException ");
System.out.print(" Classe: "+this.nomeClasse);
System.out.print(" Atributo: "+this.metodoGet.replace("get", "").toLowerCase() +"\n");
System.out.println("####################### AspectJ (Fim) ########################");
MorroniReflection.defaultValue(thisJoinPoint.getTarget(), metodoSet,tipoRetorno);
}
}
Fontes Reflection
public class MorroniReflection {
@SuppressWarnings("unchecked")
private static Class<?> classe = null;
private static Method metodo = null;
private static Object clazz = null;
/**
* Valida se um atributo possui referência nula
* dado o nome da classe (incluindo o pacote) e o
* nome do método get (padrão javaBeans) do atributo que será
* validado.
* <br />
* Exemplo sobre os parâmetros:
* <br />
* String className = "com.morroni.javabean.JavaBean";
* <br />
* String methodName = "getDescription";
*
* @param String className
* @param String methodName
* @return Boolean
*/
public static Boolean isNull(String className, String methodName) {
if(classe == null || clazz == null || metodo ==null){
try {
clazz = Class.forName(className).newInstance();
classe = Class.forName(className);
metodo = classe.getMethod(methodName);
if(metodo.invoke(clazz) == null){
limpaAtributos();
return true;
}else{
limpaAtributos();
return false;
}
} catch (Exception e) {
e.printStackTrace();
limpaAtributos();
return false;
}
}else{
limpaAtributos();
return false;
}
}
/**
* Define uma nova referência para o atributo recebido, dado
* o objeto em questão, o nome do método get (Padrão JavaBeans) do atributo e
* o tipo de retorno desse atributo.
*
* @param obj
* @param methodName
* @param tipoRetorno
*/
public static void defaultValue(Object obj, String methodName,String tipoRetorno) {
Method method = null;
Class<?> classeTipoRetorno = null;
try {
classeTipoRetorno = Class.forName(tipoRetorno);
method = obj.getClass().getDeclaredMethod(methodName, classeTipoRetorno);
if(tipoRetorno.contains("Long")){
method.invoke(obj,new Long(0));
}else if(tipoRetorno.contains("Double")){
method.invoke(obj,new Double(0));
}else if(tipoRetorno.contains("Integer")){
method.invoke(obj,new Integer(0));
}else if(tipoRetorno.contains("Character")){
method.invoke(obj,new Character('0'));
}else{
method.invoke(obj,classeTipoRetorno.newInstance());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Limpa os atributos do objeto do objeto em questão.
* Os atributos são do tipo static e por isso precisam
* que seu valor seja reiniciado manualmente.
*/
private static void limpaAtributos(){
classe = null;
clazz = null;
metodo = null;
}
}
