Archivos del autor dbejar
Matar un proceso externo desde Java (por nombre, no por pid)
Recientemente nos hemos enfrentado a un problema en uno de nuestros proyectos.
Resulta que el servidor OpenOffice que usamos en ese proyecto para determinadas tareas, en algunas circunstancias se queda totalmente “tonto”. El proceso esta ahi, el servidor no hace crash, pero no responde a ninguna llamada.
Decidimos cortar por lo sano, y hacernos un daemon que chequease si el servidor estaba respondiendo. Si no responde, matamos el servidor, y lo rearrancamos.
No tiene mucho misterio el tema.
Pero nos enfrentamos a algo que nunca antes habiamos hecho: Como matar un proceso que no habiamos iniciado nosotros y del que unicamente sabiamos su nombre?
Bueno, buscando un poco en google, y sacando ideas de un foro aqui, y otro foro alli, llegamos a desarrollar esta funcion que quizas le sea de ayuda a alguien que tenga en el futuro un problema similar.
Por supuesto el daemon debe tener privilegios de nivel suficiente para ser capaz de acabar con el proceso a matar, en nuestro caso “soffice”.
private void matarSoffice() {
String osName = System.getProperty("os.name");
String cmd = "";
if(osName.toUpperCase().contains("WIN")){//S.O. Windows
cmd+="tskill soffice";
}else{//Solo ha sido probado en win y linux
cmd+="killall soffice";
}
Process hijo;
try {
hijo = Runtime.getRuntime().exec(cmd);
hijo.waitFor();
if ( hijo.exitValue()==0){
System.out.println("soffice matado con exito");
}else{
System.out.println("Incapaz de matar soffice. Exit code: " + hijo.exitValue()+"n");
}
} catch (IOException e) {
System.out.println("Incapaz de matar soffice.");
} catch (InterruptedException e) {
System.out.println("Incapaz de matar soffice.");
}
}
Hala pues,
La duda ecologica
Lo he hablado con algun compañero de viavansi.
Que es mas ecologico? Secarse las manos con papel, o con el secador de aire caliente?
Parece que hay cosas mas faciles como decidir si es mas ecologico usar una taza de ceramica, o un vaso de plastico? Pero, realmente esta tan claro??
Interesante articulo aparecido en tree-nation:
http://www.tree-nation.com/community/econews_comments.php?news_id=281
Por cierto, si no tienes un arbol en Niger, a que esperas? www.tree-nation.com
Una JSF universal
Un ejemplo de como simplificarnos la vida usando nuestras propias annotations.
Por la razon que fuese teniamos que crearnos un numero considerable pero finito de VOs con un numero tendiente a infinito de propiedades. Estos VOs a los que llamaremos FooData1VO, FooData2VO, … FooDataNVO; estos VOs , digo, iban a ser usados en JSFs en los que una lista del mismo FooDataXVO se representaria como una tabla, una tabla que a su vez seria exportable a excel.
Bien, tenemos dos formas de hacerlo. La normal o infernal, y la anotada o elegante y facil.
En la normal, nos creamos N VOs, N Controllers, y N JSFs.
En la version anotada que proponemos aqui necesitamos: N+1 VOs, 1 Controller universal, 1 JSF universal y 1 Annotation.
Lo primero que hacemos es crearnos nuestra anotacion java (annotation).
Para mas informacion sobre que y como y porque, os remito a mis ya viejos articulos Tu primera annotation chipas I y II:
http://xnoccio.com/62-tu-primera-annotation-chispas-i/
http://xnoccio.com/72-tu-primera-annotation-chispas-ii/
package com.viavansi.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.ElementType;
/**
* @author dbejar
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface WiseName{
String alias();
}
Este es un caso muy sencillito en el que unicamente le damos un nombre en lenguaje natural a una propiedad. Podriamos como en el caso real en el que desarrollamos esto, añadirle un booleano para distinguir entre propiedades exportables a excel, o un enum para hacer subconjuntos dentro del mismo VO. Pero estoy adelantando cosas…
A continuacion nos creamos una clase padre de nuestros VOs:
package com.viavansi.VO;
import java.lang.reflect.Field;
import com.viavansi.annotation.WiseName;
public abstract class FooDataSuperVO{
/**
* Devuelve una lista ordenada con todos los labels de los atributos marcados
* con la annotation WiseName
* @return
*/
public List<String>getWiseNamedLabels(){
List<String>aliases=new LinkedList<String>();
for (Field field : this.getClass().getDeclaredFields()){
WiseName nombreBonito=field.getAnnotation(WiseName.class);
if (nombreBonito==null) continue;
aliases.add(nombreBonito.alias());
}
return aliases;
}
/**
* Devuelve una lista ordenada con todos los nombres de los atributos marcados
* con la annotation WiseName
* @return
*/
public List<String> getWiseNamedProperties(){
List<String>propNames=new LinkedList<String>();
for (Field field : this.getClass().getDeclaredFields()){
WiseName nombreBonito=field.getAnnotation(WiseName.class);
if (nombreBonito==null) continue;
propNames.add(field.getName());
}
return propNames;
}
No requiere mucha explicacion, si se han leido y entendido mis articulos sobre Annotation. Basicamente con esas dos funciones por reflection obtenemos en una todas las propiedades anotadas, y en la otra el valor de la propiedad alias en esas anotaciones.
Ahora un ejemplo muy muy simple de uno de los VOs anotados:
package com.viavansi.VO;
public class FooData1VO extends FooDataSuperVO{
@NombreBonito(alias="1. Terrenos y bienes naturales")
private Double balActInmInvTerrYBienNat;
@NombreBonito(alias="2. Infraestructuras y bienes destinados al uso general")
private Double balActInmInvInfYVBienUsoGral;
//etc..
//Con sus geterts y setters
}
Ya estamos terminando.
Con estas anotaciones solo necesitamos una JSF. Una para todos los VOs. Y un unico controller tambien.
En el Controller introducimos un par de getters de la siguiente pinta:
/**
* Devuelve una lista ordenada con todos los nombres de los atributos marcados
* con la annotation WiseName
* @author cvillar,dbejar
*@return
*/
public List<String> getListNombresBonitosProperties(){
if (listaPaginas.getRegistros().get(0) instanceof FooData1VO){
return new FooData1VO().getWiseNamedProperties();
}else if (listaPaginas.getRegistros().get(0) instanceof FooData2VO){
return new FooData2VO().getWiseNamedProperties();
}//else if [....]
//N veces
}else if (listaPaginas.getRegistros().get(0) instanceof FooDataNVO){
return new FooDataNVO().getWiseNamedProperties();
}else{
log.error("Primer registro de listaPaginas no es de un tipo VO implementado");
return new LinkedList<String>();
}
}
/**
* Devuelve una lista ordenada con todos los labels de los atributos marcados
* con la annotation WiseNamed
* @author cvillar,dbejar
*@return
*/
public List<String> getListWiseNamedLabels(){
//Trivial. La misma idea que el metodo anterior.
}
Y finalmente nuestra JSF universal y super simplificada:
<v:dataTable id="data" var="fila" styleClass="display_table" controller="#{FooDataController}">
<c:forEach var="propiedad" items="#{FooDataController.listWiseNamedProperties}" varStatus="rowCounter">
<v:column property="#{propiedad}" label="${FooDataController.listWiseNamedLabels [rowCounter.index]} "/>
</c:forEach>
</v:dataTable>
Hala pues,
Serialicefa (Customiza tu Serializacion)
Segunda parte de Maldita Serializacion, la serie(lizacion) que causa sensa(liza)cion.
Como todos sabreis, no todos los objetos son serializables. Las instancias de Object, por ejemplo no son serializables. Y tampoco lo son los Thread, o los Socket.
Tambien sabreis todos que para Serializar un objeto que implemente una instancia de alguna clase no serializable, esta debe estar marcada como transient.
Lo que quizas no sea tan obvio es como sacar partido a lo explicado mi post anterior sobre serializacion. Como customizar nuestra serializacion, para que por ejemplo se rearranque un Thread al restaurar el objeto persistido.
El uso de writeObject y readObject como vimos anteriormente sobreescriben los comportamientos por defecto de la persistencia y restauracion de objetos por serializacion:
//Persistencia
//Dentro de try-catch
fos = new FileOutputStream(nombrefichero);
out = new ObjectOutputStream(fos);
out.writeObject(foo);
out.close();
//[...]
//Restuaracion
//Dentro de try-catch
fis = new FileInputStream(nombrefichero);
in = new ObjectInputStream(fis);
Foo foo = (Foo)in.readObject();
in.close();
Asi podemos hacer q nuestro foo al ser restaurado re-arranque determinado Thread:
private transient Thread t=new Thread(){
@Override
public void run() {
//Por ejemplo
MotorReglas.cache();
}
}
private void writeObject(ObjectOutputStream out) throws IOException{
//Escribe los campos no static ni transient de la clase actual en el stream.
//Debe ser llamado solo desde el metodo writeObject de la clase
//que esta siendo serializada.
//Lanza un NotActiveException si se llama desde otro lugar.
out.defaultWriteObject();
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
//Lee los campos que no son static ni transient
//de la clase actual en el stream.
//Debe ser llamado unicamente desde el metodo readObject
//de la clase que esta siendo deserializada.
//Lanza un NotActiveException si se llama de otra forma.
in.defaultReadObject();
// Aqui restauramos las instancias transitient
t.start();
}
Y por ultimo, para que seais auntenticas criaturas del renacimiento:
http://www.cefatoys.com/web/estaticosvideos/video01.html
Hala pues,
Maldita Serializacion
Lo de la serializacion es eso que usamos en Java para persistir un objeto. Basicamente hacemos que nuestra clase implemente: java.io.Serializable
Pero supongamos que en algun caso queremos que nuestra clase padre sea serializable, se pueda persistir, pero que la persistencia no sea heredada por alguna clase hija? O simplemente que queremos extender una clase existente en alguna libreria, que es serializable, pero no queremos que nuestra nueva clase lo sea.
Como detener la serializacion heredada?
Hay un truco bastante extraño para hacerlo asi:
Tenemos que declarar los metodos:
private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
Estos metodos, al ser privados no pueden ser llamados desde fuera, ni ser heredados, ni ser sobreescritos, ni basicamente nada, pero son accesibles para la maquina virtual.
En una clase que implemente Serializable estos metodos, de existir, son llamados por la JVM a la hora de persistir y recuperar el objeto.
Por tanto para detener la serializacion simplemente tenemos que implementar en aquellas clases donde no queremos serializacion esos dos metodos, y lanzar un NotSerializableException.
private void writeObject(ObjectOutputStream out) throws IOException
{
throw new NotSerializableException("Cerrado por vacaciones!");
}
private void readObject(ObjectInputStream in) throws IOException
{
throw new NotSerializableException("Cerrado por vacaciones!");
}
Sencillo pero extraño. Y util, en algunos escenarios.
Hala pues,
Mwahahaha!
[…] podría significar reescribir las leyes de la fisica….
… sí, sí, superinteresante, seguro….
¡Superlaser!
http://www.wired.com/gadgets/miscellaneous/magazine/15-12/st_antimatter
Debo parsear mi XML?
Llevo unos meses atrapado en una serie de proyectos [tremendamente aburridos] en los que me estoy enfrentando a problemas de velocidad de ejecucion y, sobre todo, de carga de memoria. Uno de esos dias en los que te sientes con fuerzas para cuestionar la filosofia de tu aplicacion que tiene meses de trabajo detras, me puse a buscar por ahi, a ver si daba con alguna explicacion razonable.
Y asi llegue a la pagina de los Sorensens y concretamente a este post: http://www.thesorensens.org/?p=14
Recomiendo la lectura de dicho articulo porque es muy interesante. Yo voy a ser bastante mas breve. Y probablemente para entender completamente este articulo, si se carecen de ciertos conocimientos, haya que leerse el otro.
Al parecer los parseadores de XML hacen uso de String.intern que resulta ser mucho mas eficiente a la hora de coparar Strings que un a.equals(b) caracter a carater; con String.intern esta comparacion es canonica. Desgraciadamente, para esta optimizacion de velocidad se hace uso del espacio Pergem de memoria.
Resulta que si bien mi caso no es tan extremo como el que tenia esta gente, si que me enfrento al parseo de un XML que puede llegar a ser de hasta 10Mb y cuyo XSD tiene 8600 lineas.
Es por esto que me enfrento a esos problemas de memoria. Tambien de velocidad, ya que el String.intern es mas eficiente que la comparacion caracter a caracter cuando tienes pocos Strings guardados en el pool, pero cuando este numero es masivo, el hecho de buscar los Strings en el pool es mas costoso que las comparaciones caracter a caracter.
La solucion que emplearon los Sorensens fue finalmente no usar parseadores de XML, ya que despues de todo no estaban parseando un XML real. En su lugar usaron expresiones regulares ganando espectacularmente en velocidad y uso de memoria.
En nuestro caso si se trata de XML reales, pero resulta que hay un 40% de los tags del XSD no los usamos en absoluto, y lo que nos sobra del XML es mas variable, pero en muchos casos ronda ese mismo porcentaje… quizas, despues de todo no necesitasemos parsear.
Probablemente ya sea tarde para plantearselo, pero si algun dia hay una segunda fase, quizas nos lancemos a reescribir esta parte del codigo. Si asi lo hacemos os comentaremos los resultados.
Hala pues,
Apatrullando la ciudad
Ha muerto el Fary…
Murió de un lamentable y doloroso cancer de pulmón cuando contaba con tan solo 70 años de edad en su casa madrileña.
Dios, hermano de Chuck Norris y Jack Bauer, al crear a la humanidad utilizó este algoritmo para los hombres:
Object o;
if (hombre.inAlturas(alto,mediano) || hombre.inAtractivos(guapisimo,pasable){
o=new Persona();
}
else{
o=new Fary();
}
Valga este post como cariñoso recuerdo.
Descanse en paz.
بسم الله
Aqui va una autentica frikada, a ver quien supera esta!
Puedo entender perfectamente que en el mundo friki se lleve mucho el estudio del japones.
Lo que ya se me escapa es porque los “autenticos” frikis se tiran a aprender idiomas absurdos como elfico, klingon, o verdurian, y abandonan la posibilidad de aprender idiomas cuanto menos tan complejos y fascinantes como el japones, pero a diferencia de los idiomas ficticios con una utilidad practica en el mundo real.
Los que nos hemos movido en las ofertas de trabajo internacionales sabemos que apenas hay demanda de ingenieros que hablen japones, y por supuesto ninguna de aquellos que hablan, o dicen hablar, elfico.
Tengo un amigo americano que vive actualmente en Singapore y esta encantado con que sus hijos hablen un chino fluido, ademas de español (el idioma de la madre) e ingles. Creo que esta fuera de toda discusion que el ingles es basico en el mundo de la tecnologia. Y tampoco hay duda de que para una carrera con proyeccion internacional el español es tambien muy muy util.
El chino es un idioma, de tremendo potencial, pero seamos realistas, es demasiado complejo como para estudiarlo a tu bola…. mejor te pones con Klingon, que nadie te va a decir que tu pronunciacion o entonacion es lamentable y no hay manera de saber que coño dices.
Quizas el idioma de amplio espectro [por poblacion, paises, y extension] mas sencillo de aprender para un europeo medio, es el Ruso. El alfabeto es muy sencillo, casi siempre tiene equivalencia directa con el romano, y su gramatica y proncunciacion son relativamente sencillas. Pero si uno mira a la situacion de los paises del Caucaso, o de Asia Central…. bueno, como que no parece que a medio plazo vayan a surgir grandes oportunidades de usar el ruso en un ambito tecnologico.
Que nos queda entonces? Pues nos queda el Arabe. Un idioma harto complejo, con tantas variantes como paises en los que se habla, y con fonemas en los que un español podria morir ahogado tragandose su propia lengua al intentar pronunciarlos. Y sin embargo tan fascinante y seductor como el japones. Y con, ya hoy en dia, una de alta a muy alta demanda de profesionales de IT capaces de hablarlo. Y encima muy bien gratificados.
Sin embargo encontrar buenos recursos on-line para dar tus primeros pasos solito en Arabe es muy dificil.
Bien, por si alguien quiere intentarlo, o al menos, inciarse, y quizas ser capaz descifrar algo escrito en arabe, aqui os dejo algunos enlaces:
La cancion del alfabeto, para ver la que se nos viene encima:
http://www.funwitharabic.com/song.htm
Una buena inciacion a conceptos basicos:
http://en.wikibooks.org/wiki/Arabic
Una fabulosa guia sobre como colocar la lengua y los labios para pronunciar correctamente las distintas letras:
http://afl.sakhr.com//freetour/menu/menu.html
Expresiones de uso comun hasta en paises donde el arabe no es la primera lengua:
http://arabic.speak7.com/islamic_expressions.htm
Por ultimo, mis dos emisoras on-line favoritas en arabe:
Mazaj radio, desde Jordania:
http://www.surfmusic.de/radio-station/mazaj-fm,8415.html
Radio Cairo:
http://www.surfmusic.de/radio-station/radio-cairo,5122.html
Hala pues,
Ya esta en la calle OpenSign v1.7.0
OpenOCES ha anunciado la release de su nueva version 1.7.0.
Desde aqui no podemos sino primero congratularnos y segundo sentirnos orgullosos de que uno de los nuestros sea el creador/colaborador de una de las nuevas funcionalidades incluidas en esta version:
Changes since v1.6.3:
- fixed access to Microsoft CryptoAPI keystore when IE runs in protected
mode on Microsoft Vista (bug #31)
- added a Java control panel keystore. Contributed by Félix García
Borrego
- explicitly specify source file encoding (bug #52)
http://www.openoces.org/pipermail/announce-development/2007-May/000041.html
Nuestro Felix es un crack!
Tenia que decirlo.
Categorías
Encuentra artículos a través de sus "tags"
Archivos mensuales
Encuentra artículos según el mes en el que fueron escritos.
- February 2010
- January 2010
- December 2009
- November 2009
- October 2009
- September 2009
- August 2009
- July 2009
- June 2009
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
- June 2007
- May 2007
- April 2007
- March 2007
- February 2007
- January 2007