Javatadas
Blog de Alvaro Zabala

Monday January 19, 2004
Hibernate y Dynamic-Class
Pese a que muchos lo consideren excentricidades de "friky", estoy empezando a alegrarme mucho de tener este weblog.
Grascias a él recibo muchos correos de gente interesada en los mismos campos que yo (GIS, Java, POO, etc), y en algunos casos les puedo ayudar, y en otros ellos me ayudan a mi.
Además, algunos amigos que habían pedido mi rastro han contactado conmigo por este medio.
Me gustaría dar las gracias a Rafael Muñoz. Tras leer mi post sobre como tener modelos dinámicos de clases con Hibernate (creando varios SessionFactory), muy amablemente me ha hecho llegar el siguiente link:
foro de hibernate
Es un mensaje del foro de desarrolladores de Hibernate en el que Gavin King indica que en la version 2.2 de Hibernate se creará un elemento , de forma que con un solo SessionFactory, podremos tener diferentes instancias de una misma clase mapeadas en diferentes tablas (entidades) del modelo.
Gracias Rafael!
Por cierto, ¿Por qué no funcionan las réplicas del BLOG?
(2004-01-19 11:47:56.0)
Permalink

Saturday January 17, 2004
JAVA.NIO ¿Lo usa alguien en un entorno de producción?
A mi me está deparando sorpresas con la ultima version de JDK.
Estoy haciendo un servidor orientado a conexion, de forma que cuando un cliente se conecta se le crea una conexion dedicada, y se le atiende por ésta de forma instantanea.
Sería algo así:
[SERVIDOR PRINCIPAL]
ServerSocket serverSocket;
//... codigo de inicializacion, etc etc
while(seguir){
Socket socket = serverSocket.accept();
ConexionCliente conexion = new ConexionCliente(socket);// implementa Runnable
Thread threadDedicado = new Thread(conexion);
threadDedicado.start();
}//while
En fin, un servidor de toda la vida. Pero mas refinado, (esto es solo un snippet) porque USA LOS PAQUETES DE NUESTRO FRAMEWORK MVC. Es decir, las Acciones no devuelven estados ni ActionFordward ni nada por el estilo. Por supuesto, la conexion no recibe el socket directamente. En su lugar tenemos clases que envuelven al socket y aportan semantica, tratamiento de errores, TIMEOUTS, etc
[CONEXION]
Sería algo parecido a:
public void run(){
while(seguir){
try{
String actionId = socket.readUtf();
Action action = Mappings.getActionPool().get(actionId);
Form actionForm = Mappings.getForm(actionId);
Request actionRequest = new Request(socket, actionForm);
ActionResult result = action.execute(actionRequest);
View view = Mappings.getView(actionId);
view.renderView(result);
}catch(IOException io){
seguir = false;
}
}//while
}
Mientras el socket.readUtf() no tenga datos (el cliente no ha pedido nada), la conexion esta
bloqueada. Cuando el cliente cierre su socket, se produce un IOException, se detiene el bucle y se liberan todos los recursos de la conexion.
El problema de todo esto es que creo un thread por socket, así que conforme crezcan los clientes los recursos de servidor se disparan. Solucion: Patrón de diseño THREADPOOL y lecturas no bloqueantes
O eso creia. La idea es tener un Pool de Threads, y que N threads den servicios a todas las conexiones físicas (sockets). Todos los threads van quitando las conexiones de una cola (si esta vacía se suspenden hasta que otro thread no añada otra conexion) mirá si hay peticion (String action = socket.readUtf()), y si no la hay, con sockets no bloqueantes readUtf() devuelve nada luego ponemos la conexion al final de la cola y miramos en otra. ESTA NO ES LA SOLUCION. Para entornos atomicos tipo SERVIDOR WEB seguramente si. En este tipo de entorno, SE GASTA CANTIDAD DE CPU NADA MAS QUE VIENDO SI HAY ALGO. Espera activa.
Total, que tras ver esto, quise configurar los sockets a bloqueantes, y me he encontrado un bug muy curioso. CON JAVA.NIO UN CHANNEL OBTENIDO DE UN SOCKET BLOQUEANTE SE CONVIERTE EN NO BLOQUEANTE TRANSCURRIDO UN TIEMPO DIOS SABE POR QUÉ. Esto hace que las conexiones recorran el ciclo de while(seguir) a lo bestia. Y esto es porque el readString() ya no bloquea.
SOLUCIONES:
- He quitado channels y todo lo que tenga que ver con NIO. He vuelto, para el modelo de 1 cliente 1 conexion - 1 thread al java.net y java.io de antes
- Voy a mirar lo de la multiplexacion. Es una caracteristica de NIO que ya existian en los programas en C.
¿Alguien se ha encontrado este problema?
(2004-01-17 08:55:24.0)
Permalink

Friday January 09, 2004
Hibernate Tricks II
Resumiendo el anterior post:
-
Podemos tener modelos dinamicos de objetos con Hibernate gracias a los <dynamic-component>.
Ejemplo:
class Entity{
Long id;
Map entityAttrs;
}
Su correspondiente mapeo en hibernate sería:
<class>
<dynamic-component>
< property name="field1" colum="FIELD1" >
Y para añadir propiedades dinamicamente, tan solo hay que añadir properties al mapeo. El contenido del campo de la tabla se volcara dentro del Map con los valores especificados.
-
Podemos mapear una misma clase en diferentes tablas utilizando varios SessionFactory. En nuestro ejemplo, una EntityCollection se encargaria de recuperar/guardar Entity, y cada instancia de EntityCollection tendria su propia SessionFactory.
(2004-01-10 00:54:09.0)
Permalink
Hibernate Tricks
En nuestro proyecto estamos inmersos en el desarrollo de un servidor de datos espaciales (capas cartograficas).
Su arquitectura es un poco compleja, pero en ultima instancia es como un Servidor de Aplicaciones
montado sobre un gestor de base de datos.
Usamos servicios TCP/IP porque el rendimiento es crucial.
No hemos hecho pruebas con servidores de aplicaciones, pero creemos que no es necesario cargar con todo lo que acarrean. Además, en el sector GIS existen estándares propios: las comunicaciones no pueden ser IIOP, hay formatos llamados WKB (Well Known Binary Format), WKT (Well Known Text), GML, etc.
Aunque los datos cartograficos pueden ser tomados de ficheros, de otros servidores (arquitectura distribuida pura), la base de datos es ideal para casos transaccionales (muchas actualizaciones de datos procedentes de varios clientes).
La necesidad del servidor se basa en la implementación de logica de negocio :
-
si una provincia -poligono- esta formada por terminos municipales-poligonos-, si un termino cambia de provincia, la forma de la provincia cambia automaticamente.
-
si digitalizo una parcela catastral, no puede cortar a otras parcelas existentes en la bbdd (deben formar un mosaico que cubra perfectamente la supercie de catastro a la que pertenecen)
-
si quiero digitalizar una zona, y otra persona esta trabajando con ella, debo tener bloqueos a nivel de zona (superficies, rectangulos, etc)
etc.
Como estas cosas no te las dan las BBDD (o a nivel muy rudimentario, Oracle Spatial, PostGIS, etc), el servidor se hace necesario.
Utilizar Hibernate con esta forma de trabajar era complicado.
Hibernate esta basado en reflexion y en 1 clase - 1 tabla, pero para mi todas las capas cartograficas serán instancias de una misma clase (1 instancia - 1 tabla).
¿Por que? Cada vez que añada un origen de datos (capa rios, capa municipios, capa PGOU 2003, PGOU 2004, etc) no quiero tirar el servidor, hacer una nueva clase, mapearla y volverlo a levantar.
En su lugar, tengo la clase Layer. Pero cada instancia tiene que tirar de una tabla (PGOU_2003, PGOU_2004, RIOS, etc), y esto se llevaba mal con Hibernate. Ademas, cada tabla tiene campos comunes (columna geometrica con la geometria guardada en binario) y campos diferentes.
Por otro lado Hibernate te facilita la vida: transacciones, bloqueos, CRUD, caches en memoria, caches en disco, etc.
La solucion: crear SessionFactory dinamicamente. Cada instancia tendra su propio SessionFactory, y cada SessionFactory tendra un mapeo distinto de la clase Layer, que apuntara a una tabla distinta. Ese mapeo se puede leer de la configuracion, generar dinamicamente, o estar en un fichero xml. Cada Layer tendra su xml distintos.
El problema de que cada tabla tiene distintos campos se soluciona utilizando un [dynamic-component]. Es el equivalente Hibernate al Dynabean. En la clase se convierte en un Map, y tu en cada mapeo indicas las propiedades del component y el nombre de la columna de la tabla de donde las tiene que cojer.
Ventajas: tengo todo lo que Hibernate me ofrece. Y no es poco. Hibernate me ha quitado meses de programacion a bajo nivel del tipo "SELECT FOR UPDATE", etc, etc.
Ademas, si quiero añadir campos a las tablas lo puedo hacer sin tirar el servidor. Añadiendo un metodo para que se "refresque" el SessionFactory, este puede cambiar su mapeo en tiempo de ejecucion. Y el EHCache no veas como funcione. Macabo de ahorrar una de trabajo que no veas, si yo tuviera que hacer Caches multinivel (de memoria a disco), me hubiese muerto (pues a veces me interesan que las caches permanezcan al matar el servidor)
Inconveniente: Hay que ver la memoria que consume el SessionFactory. Tardo muchisimo en arrancar el servidor, porque si tengo 100 Layers tengo que hacer 100 mapeos de SessionFactory. Eso me preocupa. El servidor es rapido en servir, las comunicaciones las controlo, tengo transacciones y muchas cosas mas (LifeCycle, etc, Gracias Hibernate!!!), pero tarda endemoniadamente en arrancar, y consume mucha memoria.
Pero un SessionFactory por objeto es la unica forma que he encontrado de tener modelos dinamicos de objetos (este verano Al y yo comentamos el tema en nuestro blog) con Hibernate.
SE ACEPTAN SUGERENCIAS!!!!
(2004-01-09 19:35:01.0)
Permalink

Sunday January 04, 2004
2004...a ver que nos traes!! Pues eso. A ver que tal se porta.
Uno de mis buenos propositos para este año es cuidar un poco más este blog.
La verdad es que desde las vacaciones de verano (que lejos quedan :-( ) no he escrito casi nada.
Motivos hay, pero ya los comentaré en este foro en su momento.
Otros propositos:
- Subir un proyecto en que estamos embarcados a SourceForge.
- Crear una pagina propia para este proyecto.
- Escribir un libro que tiempo ha que tengo en mente.
Además, hemos montado un framework para hacer aplicaciones que quiero documentar, subir tambien
a sourceforge y enviar un articulo/tutorial a JavaHispano. La idea es simple: partiendo de un
framework MVC para web propio, al estilo de Structs, lo hemos extendido para desarrollar servicios tcp/ip
de elevado rendimiento. La productividad es elevada, pues las interfaces utilizadas son las mismas para los dos entornos.
¿Que por qué no RMI o SOAP?
RMI tiene un coste de aprendizaje alto, sobretodo si va ligado a EJB's y servidores de aplicaciones. Si no fuese ligado, romperiamos el MODELO UNICO de programacion, algo que hemos conseguido con el framework propio.
Además, la serializacion java no me parece un mecanismo de comunicacion eficiente. Supongamos un DBMS al estilo de Oracle: ¿alguien enviaría los registros de una consulta como objetos serializados?
SOAP: me parece un patatón.
Dicho el comentario al estilo de Ricardo Devis, maticemos. En cuanto a crear una plataforma interoperable, es excelente. XML y Http. ¿Que mas podemos pedir?. Para servicios dedicados que proporcionen grandes volumenes de datos casi en tiempo real, olvidémosnos de SOAP.
¿Para cuando todo esto? Esperemos que para pronto. Por lo pronto, hasta el 24 de enero voy a estar ocupado!
(2004-01-04 16:42:52.0)
Permalink
|
Para saber mas...
alvaro_zabala@hotmail.com
Calendar
| « January 2004 » | | Sun | Mon | Tue | Wed | Thu | Fri | Sat |
|---|
| | | | | 1 | 2 | 3 | | 5 | 6 | 7 | 8 | | 10 | 11 | 12 | 13 | 14 | 15 | 16 | | 18 | | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | | | | | | | | | Hoy |
Links
Navigation
Referers
Las visitas de hoy a la página: 21
|