Ha salido la versrión final de JBoss 3.2.0
lunes, abril 14, 2003 at 10:30AM
j2ee
lunes, abril 14, 2003 at 10:30AM
lunes, abril 14, 2003 at 2:44AM
jh
domingo, abril 13, 2003 at 2:00AM
Fecha de creación: 08.04.2003
Revisión 1.0 (08.04.2003)
Antonio Calero
acalero AT iti DOT upv DOT es
|
El propósito del siguiente artículo es introducir los conceptos básicos
necesarios para desarrollar cualquier tipo de aplicación en Java
utilizando el modo Full-Screen (pantalla completa) disponible a partir
de la versión 1.4 del JDK de SUN. La mayoría de aplicaciones que
utilizan este modo son los videojuegos, pero eso no implica que no
se pueda utilizar en aplicaciones de ámbito general.
Para comprender el funcionamiento de este modo de pantalla veremos un ejemplo sencillo, el típico "Hola Mundo", pero en este caso utilizando una aplicación a pantalla completa. Una vez visto el ejemplo el paso de cualquier tipo de aplicación en Swing o AWT a pantalla completa es inmediato.
Este artículo está destinado tanto a usuarios noveles de Java como a usuarios avanzados. Espero que sea de gran ayuda tanto para unos como para otros.
A muchos programadores que hayan utilizado la API de Microsoft Direct X este concepto les resultará bastante familiar, para otros programadores quizás este concepto les sea totalmente nuevo. De una o de otra forma hay que decir que el modo exclusivo a pantalla completa es una potente característica del J2SE a partir de su versión 1.4 que permite al programador suspender el entorno de ventanas del sistema operativo para que el dibujado pueda ser aplicado directamente en la pantalla. Esto puede sonar un poco confuso pero veremos exactamente a que nos referimos a continuación.
En las aplicaciones Java con las interfaces gráficas tradicionales, AWT es el responsable de propagar los eventos de "pintar" del sistema operativo, a través del un hilo manejador de eventos, e invocando el método Component.paint de AWT siempre que sea necesario (redibujado de pantalla, al pasar el ratón por encima, etc.). Pues bien, en el modo exclusivo a pantalla completa, el dibujado se puede hacer activamente a través de la propia aplicación. Esto permite reducir gran cantidad de recursos que eran consumidos por el hilo de AWT, y que normalmente no son necesarios en este tipo de aplicaciones como puede ser un videojuego.
Utilizar este modo a pantalla completa en las interfaces gráficas tradicionales implica que se tendrá que limitar a la profundidad de color y al tamaño de pantalla que elija el usuario. Esto puede ser controlado por el programador a través de la clase DisplayMode, más adelante veremos como podemos utilizar esta clase para establecer el modo de pantalla que nosotros queramos.
Finalmente, muchas otras técnicas avanzadas, como por ejemplo page-flipping (que se tratará con profundidad en posteriores artículos) o visores estereoscópicos (sistemas que utilizan conjuntos separados de imágenes para cada ojo) requieren, en algunas plataformas, que una aplicación este principalmente en modo exclusivo a pantalla completa.
La gestión del modo exclusivo a pantalla completa de Java se hace a través de un objeto de la clase GraphicsDevice. Para obtener una lista de todos los dispositivos de pantalla (en sistemas multi-monitor puede que tengamos más de un dispositivo) se puede invocar el método getScreenDevices de la clase java.awt.GraphicsEnvironment (que representa a nuestro entorno gráfico de ventanas). Para el dispositivo primario por defecto se puede invocar directamente el método getDefaultScreenDevice.
Entonces lo primero que tenemos que hacer si queremos usar el modo a pantalla completa es obtener esa referencia al dispositivo gráfico que representará a nuestro monitor. Esto lo hacemos en nuestro código de la siguiente manera:
...
// Obtenemos la referencia al entorno de ventanas
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
// Obtenemos el dispositivo gráfico primario (por defecto)
GraphicsDevice gd = ge.getDefaultScreenDevice();
...
Una vez obtenida la referencia al dispositivo gráfico podremos invocar alguno de los métodos siguientes:
public boolean isFullScreenSupported()
Este método devuelve verdadero si el modo exclusivo a pantalla completa está disponible, es decir, si el hardware y el sistema operativo de la máquina tienen soporte para utilizarlo. En sistemas donde el modo exclusivo no esté disponible probablemente sea mejor ejecutar la aplicación en una ventana de tamaño fijo y predefinido que establecer una ventana a pantalla completa.
public void setFullScreenWindow(Window w)
Este método entra en el modo exclusivo a pantalla completa utilizando la ventana que se le pase como argumento. Si el modo exclusivo no esta disponible, la ventana se posiciona en el punto (0, 0) y se redimensiona hasta ajustarse completamente a la pantalla. Si utilizamos este método con un argumento nulo saldremos del modo exclusivo a pantalla completa.
Básicamente esto es todo lo que se necesita saber para empezar a utilizar el modo a pantalla completa (sencillo, ¿verdad?). Veamos un primer ejemplo con una clase muy básica, esto nos hará descubrir que aún es necesario algún que otro concepto...
Vamos a ir comentando en detalle todo aquello que nos vayamos encontrando en el código de la clase:
// AWT-SWING
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// DEFINICIÓN DE LA CLASE
public class HolaMundo extends JFrame {
Podemos ver que en primer lugar estamos importando los paquetes básicos de AWT y Swing por si se quisieran añadir botones, paneles, escuchadores de eventos, etc. Se presupone un mínimo conocimiento de Java con lo que supongo que estas primeras líneas todo el mundo las entenderá.
El primer dato importante a tener en cuenta está en la declaración de la clase, como podéis ver, la clase extiende de JFrame. Esto es obvio puesto que estamos implementando una interfaz gráfica y por tanto debemos hacer que nuestra clase herede de Window. En este caso eso se consigue heredando de JFrame, pero también podríamos haber heredado directamente de la clase Window, o también de la clase Frame. Cada uno puede tener una manera concreta de programar sus interfaces, así que aquí que cada uno herede de lo que cree oportuno, siempre que todo herede de la clase Window no habrá problema.
// ATRIBUTOS DE LA CLASE
// Referencia al dispositivo gráfico
private GraphicsDevice gd = null;
Definiremos un atributo de la clase con la referencia al dispositivo gráfico primario del sistema, que es en definitiva la que nos dará acceso al modo exclusivo a pantalla completa.
Continuemos viendo el código del constructor:
public HolaMundo() {
// Primero obtenemos una referencia al entorno gráfico de ventanas
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
// Obtenemos una referencia al dispositivo gráfico primario
gd = ge.getDefaultScreenDevice();
// Si no hay soporte adecuado lo mostramos por pantalla
if(!gd.isFullScreenSupported())
System.out.println("WARNING: No hay soporte.\n");
else
System.out.println("INFO: Detectado soporte\n");
try {
// Activamos el modo a pantalla completa
gd.setFullScreenWindow(this);
// Inicializamos toda la interfaz gráfica
initMainInterface();
}
catch(Throwable e) {
e.printStackTrace();
System.out.println("ERROR CRITICO: "+e.getMessage());
exit();
}
}//constructor
Bien, pues tal y como se comentó al principio obtenemos la referencia al entorno de ventanas y a partir de ella el dispositivo primario de gráficos. Una vez lo tenemos podemos comprobar si nuestro sistema tiene soporte para utilizar el modo exclusivo (no importa si no tiene, puesto que en ese caso se ejecutará en una ventana de tamaño la resolución actual del sistema). A continuación estableceremos el modo a pantalla completa e inicializaremos la interfaz gráfica con todos los elementos que queramos. No es tema de este artículo tratar las excepciones, además supongo que son de sobra conocidas por los que lean el artículo, basta decir que se captura cualquier excepción que se pueda generar y que se muestra la traza y se termina la aplicación invocando al método exit().
Veamos el código de los métodos nuevos que aparecen aquí, initMainInterface() y exit()
public void initMainInterface() throws Exception {
// WindowListener para cerrar la aplicación al cerrar la ventana
this.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(WindowEvent e) {
exit();
}
});
// Aqui añadimos una etiqueta en la "ventana" con la cadena HolaMundo
this.getContentPane().add(new JLabel("HOLA MUNDO!"));
this.setVisible(true);
}//initMainInterface
Este código no os debe parecer extraño si alguna vez habéis hecho alguna ventana con Java. En primer lugar establecemos un escuchador de eventos para cuando se cierre la ventana de la aplicación, en cuyo caso invocaremos el método exit. Después añadimos una etiqueta a nuestra ventana, y la hacemos visible.
Cómo podéis ver el código no cambia en absoluto al realizar la aplicación a pantalla completa (al menos no de momento y para las aplicaciones "normales"). Podríamos añadir cualquier tipo de componente que nos ofrece AWT o Swing y utilizarla en nuestra aplicación a pantalla completa sin ningún problema.
Por último veamos el código para salir de la aplicación:
public void exit() {
// salimos del modo a pantalla completa
gd.setFullScreenWindow(null);
// salimos de la aplicación
System.exit(0);
}//exit
Basta con salir del modo a pantalla completa (es necesario para no dejar el modo exclusivo más tiempo del que se debiera) y hacer un System.exit().
Pues con esto ya tenemos nuestra primera aplicación que utiliza el modo exclusivo a pantalla completa en Java. Es bastante sencillo, sin embargo, cuando probéis a ejecutar la aplicación os surgirán preguntas y comentarios como: "Muy bonito, ¿pero cómo especifico la resolución que yo quiera a pantalla completa?" "¿Cuáles son las mejoras que obtengo al hacer mi aplicación de esta manera?" "No da la impresión de que este en un modo a pantalla completa. Esto no creo que sirva de mucho." "El aspecto sigue siendo el mismo" "¿Con esto pretendes que haga un juego? Pues vaya...".
Tranquilos, este primer tutorial es muy básico y tampoco quería profundizar demasiado. Sólo quería mostrar la sencillez de Java para trabajar a pantalla completa (siempre que el sistema tenga soporte, claro). Este artículo pretende ser una pequeña introducción al tema y nada más. Puede que esta información a alguien ya le resulte suficiente para desarrollar alguna aplicación que necesite estar en "primer plano" por así decirlo (sin que se vea la barra de tareas de Windows o de Linux, o cosas así).
[1]
Código HolaMundo.java
Antonio Calero
Antonio Calero es Ingeniero en Informática y trabaja en el Instituto Tecnológico de Informática de la Universidad Politécnica de Valencia en el grupo de
Sistemas Distribuidos. Es un apasionado de la programación de videojuegos y a ellos intenta dedicar su poco tiempo libre, su mayor sueño sería terminar
el juego de rol que actualmente está desarrollando en Java con un grupo de amigos.
domingo, abril 13, 2003 at 2:00AM
Fecha de creación: 20.01.2003
Revisión 1.0 (20.01.2003)
Aitor García
|
Guía de iniciación rápida en el motor de persistencia Hibernate, escrita por Glen Smith[autor], y traducida al castellano por Aitor García[traductor]
Hibernate ofrece la Persistencia Relacional para Java, que para los no iniciados, proporciona unas muy buenas maneras para la persistencia de sus objetos de Java a y desde una base de datos subyacente. Más que ensuciar con SQL tus objetos y convertir consultas a y desde los objetos de primera magnitud, Hibernate puede preocuparse de todo ese maremágnum por ti. Tú utilizas solamente a los objetos, Hibernate se preocupa del SQL y de que las cosas terminan en la tabla correcta. ¿Limpio, eh?
Hibernate viene con una sensacional y amplia documentación. Esta guía es únicamente para proporcionar un arranque rápido en el aprendizaje de los fundamentos. Una vez que hayas visto esto, tendrás los fundamentos de la carga y almacenamiento de los objetos a la base de datos de tu elección, y podrás impresionar a tus amigos en el trabajo, o por lo menos mantener una conversación inteligente en tu grupo de usuarios local de Java.
Considera esto como una guía para el impaciente, si lo deseas. Una vez que estés feliz porque has hecho algún progreso y tengas un buen "feeling" con cómo funciona Hibernate, podrás explorar los trabajos más extensos que vienen con el paquete.
Hibernate es extremadamente expresivo y flexible, pero eso significa que es difícil hacerse una idea de cómo podría ser uso simplón de él. Aquí es adonde este documento interviene. No vamos a tratar transacciones, ni mapeos uno-a-muchos, o aún el uso de colecciones, pero no pasa nada porque la documentación de Hibernate cubre eso. Una vez que hayas vagado a través de este documento, estarás listo para lanzarte a las profundidades de todas estas buenas cosas.
Necesitarás una distribución de Hibernate. Estoy utilizando Hibernate 1.2, pero puede ser que desees trabajar con la copia más reciente del sitio de hibernate [1].
Hay varias maneras de acercarse al desarrollo con Hibernate. Aquí está el que estamos utilizando nosotros hoy, porque es probablemente el más simple de entender:
| Lista 1: Proceso de desarrollo con Hibernate |
Cuando te hagas mas experto, hay herramientas para autogenerar Beans del SQL o SQL de los Beans (e incluso plug-ins que generan el fichero de mapeo por ti), pero a vamos de hacerlo de la manera larga primero, para que no te distraiga ninguna magia innecesaria.
El ejemplo en el que vamos a trabajar es muy simple. Considera tener que desarrollar un subsistema básico para la gerencia de los usuarios de tu website. ¿Necesitaras una tabla de usuarios, no? Estoy pensando en algo como esto:
CREATE TABLE `users` (
`LogonID` varchar(20) NOT NULL default '0',
`Name` varchar(40) default NULL,
`Password` varchar(20) default NULL,
`EmailAddress` varchar(40) default NULL,
`LastLogon` datetime default NULL,
PRIMARY KEY (`LogonID`)
);
Estoy utilizando mySql, pero eres libre para utilizar cualquier clase de base de datos para la que tengas un driver JDBC. Tenemos una tabla de usuario con una identificación de la conexión, un nombre completo, una contraseña, un email y una ultima fecha de conexión. El paso siguiente es escribir un Java Bean para manejar un usuario dado.
Cuando tenemos un montón de Users en memoria, necesitaremos una clase Java para que los contenga. Hibernate trabaja vía reflection en los métodos de get/set de los objetos, así que necesitaremos "bean"-ificar los objetos que deseamos persistir (lo que no es algo muy grave porque ya que íbamos a usar beans de todos modos, verdad?). Luego escribamos una clase parecida a esta:
package dbdemo;
// ...
public class User {
private String userID;
private String userName;
private String password;
private String emailAddress;
private Date lastLogon;
public String getID() {
return userID;
}
public void setID(String newUserID) {
userID = newUserID;
}
// ... a bunch of other properties
// using getXXX() and setXXX() go in here...
public Date getLastLogon() {
return lastLogon;
}
public void setLastLogon(Date newLastLogon) {
lastLogon = newLastLogon;
}
}
En nuestro ejemplo arriba, hemos hecho los accessors (getID(), getLastLogon() ,etc
) publicos pero este no es un requisito de Hibernate - puede utilizar los métodos públicos, protegidos o incluso privados para persistir tus datos.
Ahora ya hemos conseguido nuestra tabla del SQL, y el objeto de Java que va a mapearse con ella. Todavía necesitamos una manera de decir a Hibernate cómo mapear uno con otro. Esto se logra a través de un archivo de mapeo. La manera más limpia (la más mantenible) es escribir un archivo de mapeo por objeto, y si lo nombras YourObject.Hbm.xml y lo pones en el mismo directorio que su objeto verdadero, Hibernate te hará las cosas incluso más fácil. Aquí está un ejemplo de cómo podría verse User.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping.dtd">
<hibernate-mapping>
<class name="dbdemo.User" table="users">
<id name="ID" column="LogonId" type="string">
<generator class="assigned"/>
</id>
<property name="userName" column="Name" type="string"/>
<property name="password" type="string"/>
<property name="emailAddress" type="string"/>
<property name="lastLogon" type="date"/>
</class>
</hibernate-mapping>
Miremos algunas líneas de nuestro fichero. La primera etiqueta de interés es la etiqueta class. Aquí mapeamos el nombre de la clase (en el paquete del dbdemo) a la tabla de usuarios en nuestra base de datos.
Obviemos la etiqueta id por un momento y hablemos de las etiquetas property. Un vistazo rápido mostrará que aquí es donde se está haciendo el trabajo importante. El atributo name es la característica en nuestro Bean, y column es el nombre del campo en nuestra base de datos. El atributo type es opcional (Hibernate utilizará reflection para conjeturar el tipo si tu no lo pones) - pero lo he puesto para que se viese de manera completa.
Bien. Volvamos a la etiqueta id. Quizás hayas sospechado que esta etiqueta tiene algo que ver con el mapeo de la clave primaria de la tabla. Tienes razón. La sintaxis de la etiqueta id es muy similar a la de las etiquetas de características que acabamos de ver. Mapeamos la característica del Bean (name) al campo de la base de datos(column).
La etiqueta embebida del generador le dice a Hibernate cómo debe producir la clave primaria (es bastante divertido que Hibernate te genere una, del tipo prefieras, pero necesitaras decirle cómo). En nuestro caso, lo fijamos a asignado, de manera que nuestro bean va a generar sus propias claves (después de todo el objeto del usuario necesitará siempre tener un UserID). Si quieres dejar que Hibernate genere las claves por ti, quizás te interesen clases como uuid.hex y uuid.string (Consulta la documentación para mas información).
Si consideras que esto del mapeo manual no es para ti, puedes hace que un plugin de tu IDE te eche una mano. Estoy utilizando uno para Eclipse llamado Hibernator[2]. O, si XDoclet[3] es más de tu preferencia, hay etiquetas de Hibernate para XDoclet que permiten que meter los mapeos directamente en el código fuente, y después autogenerar tu archivo de mapeo en tiempo de build. ¡Guay!
Todavía no le hemos dicho a Hibernate dónde encontrar nuestra base de datos. La manera más directa es proporcionar a Hibernate un fichero de las características, con los ajustes para las secuencias de la conexión, las contraseñas, etc. Si llamas a este archivo hibernate.properties y lo pones en el classpath, Hibernate lo tomará automagicamente (sic). El fichero tendría un aspecto como este:
hibernate.connection.driver_class = org.gjt.mm.mysql.Driver
hibernate.connection.url = jdbc:mysql://localhost/testdb
hibernate.connection.username = gsmith
hibernate.connection.password = sesame
Si has utilizado JDBC, éste te resultara familiar. En el ejemplo de arriba un driver de mysql, se conecta con la base de datos testdb en localhost, y utiliza el usuario y contraseña proporcionados. Hay un montón más de características que puedes ajustar para determinar cómo Hibernate tiene acceso a tu base de datos. De nuevo, consulta la documentación para más información detallada.
Todo el trabajo duro se ha hecho. Si ha ido todo bien hasta ahora, tendrás lo siguiente:
User.java - tu objeto Java a persistir
User.hbm.xml - tu archivo de Mapeo Hibernate
hibernate.properties tu archivo de propiedades con información sobre la conexión JDBC (Puedes hacer esto en el código si lo prefieres)
Una tabla Usuario en su base de datos
| Lista 2: Estado actual |
Hacer uso de Hibernate en tu código fuente es bastante directo. Ahí va la versión reducida:
Cree un objeto Datastore
Dile al Datastore el tipo de objetos que deseas almacenar
Crea una sesión a la base de datos de tu elección
Carga, guarda y consulta tus objetos
flush() tu sesión de vuelta a la base de datos
| Lista 3: Guía rápida de uso de Hibernate |
Vamos a mirar el código fuente para verlo todo mucho mas claro.
El objeto Datastore tiene conocimiento de todos los mapeos que existen entre los objetos de Java y la base de datos.
Datastore ds = Hibernate.createDatastore();
ds.storeClass(User.class);
Esto asume que tienes un User.hbm.xml en el mismo directorio que la clase user. Si decides llamar a tu archivo de otra manera, utiliza:
ds.storeFile("MyMappingFile.hbm.xml")
El objeto de sesión representa una conexión a su base de datos. Puedes proporcionar a Hibernate una sesión de JDBC que hayas creado a mano, pero soy perezoso, así que solo voy a proporcionarle a Hibernate el archivo de propiedades, y dejar que haga el trabajo por mí.
// Then build a session to the database
SessionFactory sf = ds.buildSessionFactory();
// or supply a Properties arg
Session session = sf.openSession();
He llamado a mi archivo de propiedades hibernate.properties y lo he puesto en mi classpath, pero si has llamado al tuyo de manera diferente (o quieres crear las propiedades en el código), entonces necesitaras proporcionar tu propio objeto de propiedades a buildSessionFactory().
Ahora solo tienes que usar los objetos de una manera Java. ¿Quieres almacenar un nuevo usuario en la base de datos? Seria algo así:
// Create new User and store them the database
User newUser = new User();
newUser.setID("joe_cool");
newUser.setUserName("Joseph Cool");
newUser.setPassword("abc123");
newUser.setEmailAddress("joe@cool.com");
newUser.setLastLogon(new Date());
// And the Hibernate call which stores it
session.save(newUser);
Como puedes ver, la gran ventaja de Hibernate es el poco código adicional a emplear. La mayor parte del tiempo solo te preocupas de tus objetos de negocio, y haces una sola llamada a Hibernate cuando todo esta preparado.
Pongamos por caso que deseas recuperar un objeto y sabes el UserID del usuario (ej. durante un proceso de la conexión a su sitio). Con una unica línea, pasando la clave ya lo tienes :
newUser = (User) session.load(User.class, "joe_cool");
El objeto usuario que has recuperado esta vivo! Cambia sus propiedades y se guardara en la base de datos en el próximo flush().
Incluso mejor , puedes consultar tu tabla y obtener una java.util.List de objetos vivos. Prueba con algo como esto:
List myUsers = session.find("from user in class dbdemo.User");
if (myUsers.size() > 0) {
for (Iterator i = myUsers.iterator(); i.hasNext() ; ) {
User nextUser = (User) i.next();
System.out.println("Resetting pass: "+ nextUser.getUserName());
nextUser.setPassword("secret");
}
}else {
System.out.println("Didn't find any matching users..");
}
Esta consulta devuelve toda la tabla . Normalmente querrás mucho mas control (ej. From user in class dbdemo.User where userID tenga algún valor especifico),de manera que harás algo como esto:
List myUsers = session.find("from user in class dbdemo.User where user.ID = ?","joe_cool", Hibernate.STRING);
Hay una gran abundancia de opción de consulta en la documentación, pero esto te da una idea de lo que Hibernate puede ofrecerte.
De vez en cuando tu sesión de Hibernate se hará flush() a si misma para mantener una correcta sincronización entre la BD y tus objetos en Memoria. Puedes querer liberar la conexión JDBC que Hibernate esta usando para lo cual normalmente harás:
// close our session and release resources
session.flush();
session.close();
Y eso es todo . ¡Bien hecho! Has creado objetos, los has guardado, y recuperado.¡Te sentirás feliz con esto!
Ahora que ya tiene cierto conocimiento de Hibernate, puede echar un buen vistazo a la extensa documentación que viene con el paquete. Hay un montón de funcionalidades que explorar como mapeo uno-a-varios, persistencia ordenada, nested collections, optimización y mucho más.
Disfruta! Y Buena Hibernación!
Y eso es todo lo que se me ha ocurrido (herencia, polimorfismo y diseño), por ahora me he quedado satisfecho, en la próxima entrevista ya tendré claro que contestar, pero espero que todo aquel que tenga nuevas ideas para el uso de interfaces me las haga llegar.
[autor] Web personal del autor,
http://glen.blog-city.com/
[traductor] Web personal del traductor,
http://freeroller.net/page/aitor
[1] Sitio web de Hibernate,
http://hibernate.sf.net
[2] Sitio web de Hibernator,
http://hibernator.sourceforge.net
[3] Sitio web de XDoclet,
http://xdoclet.sourceforge.net
Aitor García
Glen Smith
viernes, abril 11, 2003 at 11:23AM