Tips de JAVA J2EE

5
Tips de JAVA - J2EE ¿Sabes qué es un pool de conexiones? (javaHispano) Las conexiones a cualquier medio ( base de datos relacional, sistemas legacy, etc. ) son un recurso caro. Normalmente existe un número limitado de conexiones que puede mantener abiertas un determinado servidor, dependiendo de su memoria, su potencia, del sistema al que estamos accediendo, etc. Muchos sistemas que actúan como servidores necesitan mantener una gran escalabilidad y por lo tanto no pueden arriesgarse a que se agoten las conexiones. ¿Qué se puede hacer? Un pool de conexiones soluciona esta técnica. Se trata de un conjunto limitado de conexiones que se reutilizan constantemente para dar servicio a los diferentes clientes. De este modo se aumenta la escalabilidad y también el rendimiento ya que no será necesario abrir las conexiones constantemente. Normalmente un pool de conexiones se inicializa con un número de conexiones determinado. Casi todos los servidores modernos traen normalmente pools de conexiones integrados, aunque crearse uno propio no es demasiado difícil. En un pool de conexiones cada una de éstas es utilizada por múltiples clientes diferentes. Los clientes abren la conexión, acceden al servicio a través de ella y por último cierran dicha conexión. Es importante que el cliente abra y cierre la conexión en cada acceso al servicio ya que si no la cerrase no la estaría devolviendo al pool y por lo tanto correríamos el riesgo de agotar los recursos del servidor. Un driver de base de datos puede ofrecer soporte de pools de conexiones si implementa la interfaz javax.sql.DataSource. Este soporte es optativo en JDBC 2.0 y obligatorio en JDBC 3.0 ¿Sabías que utilizar el PrintWriter que ofrece el objeto HttpServletResponse para generar contenido no siempre es la mejor opción? (javaHispano) En un Servlet normalmente la manera más típica de generar contenido es la siguiente: public void doGet(HttpServletRequest request, HttpServletResponse response) { PrintWriter out = response.getWriter(); out.println(...); out.write(...); } Esto tiene un inconveniente. Cada uno de los caracteres se codifican internamente de char a byte. Cuando el contenido que queremos mostrar ya se encuentra codificado ( por ejemplo ficheros, urls, datos de base de datos que hayamos cogido con métodos como resultSet.getAsciiStream() ) nos encontramos con que estamos realizando miles y miles de transformaciones redundantes que no aportan nada. Normalmente, en estos casos, es preferible utilizar streams para generar la salida. De este modo se realiza un transferencia directa de bytes a bytes sin realizar ninguna transformación. Jason Hunter, en el libreo Java Enterprise Best Practices de O'Reilly expone el ejemplo siguiente:

Transcript of Tips de JAVA J2EE

Page 1: Tips de JAVA J2EE

Tips de JAVA - J2EE

¿Sabes qué es un pool de conexiones?   (javaHispano) Las conexiones a cualquier medio ( base de datos relacional, sistemas legacy, etc. ) son un recurso caro. Normalmente existe un número limitado de conexiones que puede mantener abiertas un determinado servidor, dependiendo de su memoria, su potencia, del sistema al que estamos accediendo, etc.

Muchos sistemas que actúan como servidores necesitan mantener una gran escalabilidad y por lo tanto no pueden arriesgarse a que se agoten las conexiones. ¿Qué se puede hacer?

Un pool de conexiones soluciona esta técnica. Se trata de un conjunto limitado de conexiones que se reutilizan constantemente para dar servicio a los diferentes clientes. De este modo se aumenta la escalabilidad y también el rendimiento ya que no será necesario abrir las conexiones constantemente.

Normalmente un pool de conexiones se inicializa con un número de conexiones determinado. Casi todos los servidores modernos traen normalmente pools de conexiones integrados, aunque crearse uno propio no es demasiado difícil.

En un pool de conexiones cada una de éstas es utilizada por múltiples clientes diferentes. Los clientes abren la conexión, acceden al servicio a través de ella y por último cierran dicha conexión. Es importante que el cliente abra y cierre la conexión en cada acceso al servicio ya que si no la cerrase no la estaría devolviendo al pool y por lo tanto correríamos el riesgo de agotar los recursos del servidor.

Un driver de base de datos puede ofrecer soporte de pools de conexiones si implementa la interfaz javax.sql.DataSource. Este soporte es optativo en JDBC 2.0 y obligatorio en JDBC 3.0

¿Sabías que utilizar el PrintWriter que ofrece el objeto HttpServletResponse para generar contenido no siempre es la mejor opción?   (javaHispano) En un Servlet normalmente la manera más típica de generar contenido es la siguiente: public void doGet(HttpServletRequest request, HttpServletResponse response) { PrintWriter out = response.getWriter();out.println(...);out.write(...);}

Esto tiene un inconveniente. Cada uno de los caracteres se codifican internamente de char a byte. Cuando el contenido que queremos mostrar ya se encuentra codificado ( por ejemplo ficheros, urls, datos de base de datos que hayamos cogido con métodos como resultSet.getAsciiStream() ) nos encontramos con que estamos realizando miles y miles de transformaciones redundantes que no aportan nada.

Normalmente, en estos casos, es preferible utilizar streams para generar la salida. De este modo se realiza un transferencia directa de bytes a bytes sin realizar ninguna transformación.

Jason Hunter, en el libreo Java Enterprise Best Practices de O'Reilly expone el ejemplo siguiente: import java.io.*;import java.util.prefs.*;import javax.servlet.*;import javax.servlet.http.*; public class NoConversions extends HttpServlet { String name = "content.txt"; // Fichero a enviar public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String file = getServletContext( ).getRealPath(name); res.setContentType("text/plain"); OutputStream out = res.getOutputStream( );

Page 2: Tips de JAVA J2EE

returnFile(file, out); } public static void returnFile(String filename, OutputStream out) throws FileNotFoundException, IOException { InputStream in = null; try { in = new BufferedInputStream(new FileInputStream(filename)); byte[ ] buf = new byte[4 * 1024]; // 4K buffer int bytesRead; while ((bytesRead = in.read(buf)) != -1) { out.write(buf, 0, bytesRead); } } finally { if (in != null) in.close( ); } }}

Como resultado, utilizando un fichero de prueba de 2Mb se ha obtenido un aumento del rendimiento del 20% en Tomcat 3.x y del 50% en Tomcat 4.x.

¿Sabías que no conviene utilizar el modelo SingleThreadModel del API de Servlets y JSP?   (javaHispano) Los desarrolladores cuando crean JSPs y Servlets se enfrentan a un reto importante: como sincronizar el acceso de múltiples clientes.

Tradicionalmente se han considerado dos opciones: realizar la sincronización manualmente o implementar el modelo SingleThreadModel.

Cuando un Servlet o un JSP implementan el modelo SingleThreadModel el contenedor web garantiza que nunca habrá más de una petición accediendo a la misma instancia de Servlet o JSP.

Internamente esto se consigue de dos modos: creando una cola de peticiones para entrar a cada Servlet y JSP que implementen el modelo SingleThreadModel o creando un pool de instancias del Servlet de modo que se garantice que a cada instancia accede únicamente una petición.

La primera de las opciones supone una degradación importante de rendimiento por lo que normalmente se implementa la segunda. El problema surge en que con este segundo modelo múltiples peticiones accederan al mismo Servlet simultáneamente ( ojo, no a la misma instancia del Servlet ).

Esto es un problema muy grave ya que los desarrolladores pueden creer que no necesitan sincronizar los elementos compartidos a los que acceden ( por ejemplo bases de datos, variables críticas, etc. ) y sin embargo la realidad es que se está accediendo simultánemanete a dichos elementos desde diferentes instancias del Servlet.

Por lo tanto, la diferencia entre utilizar el modelo SingleThreadModel y no utilizarlo es mínima ya que sigue siendo necesario implementar el código de sincronización. Más importante aún, como hemos visto utilizar dicho modelo puede llevar a engaños y producir problemas de difícil depuración.

¿Sabes qué es un motor de persistencia?   (javaHispano) Nos referimos con el término de persistencia a la capacidad de un elmemento para hacerse persistente, es decir, a la capacidad de poder almacenar el estado de un elemento de modo que sea posible recuperarlo posteriormente.

Atendiendo a esta definición, un motor de persistencia es un sistema de desarrollo, también conocido como framework o librería, que nos permite hacer persistentes los elementos de nuestras aplicaciones o modelos. Estos elementos pueden ser objetos, tipos primitivos de datos, arrays, etc., mientras que la persistencia se puede realizar sobre múltiples destinos: bases de datos relacionales, bases de datos orientadas a objetos, sistemas legacy, etc.

Page 3: Tips de JAVA J2EE

Actualmente, esta definición resulta bastante limitada. Los motores de persistencia no sólo nos permiten hacer persistentes nuestros objetos, sino que también nos permiten realizar consultas complejas que nos ofrezcan jerarquías completas de objetos, realizan optimizaciones automáticamente, resuelven asociaciones y dependencias, etc.

La ventaja de utilizar un motor de persistencia es la sencillez del modelo de programación que promueven. Un programador ya no se tiene que preocupar de realizar consultas manuales con JDBC y simplemente utilizará las funciones que le ofrece el motor. Estas funciones además de realizar múltiples optimizaciones de rendimiento le garantizan que la aplicación será compatbible con todas las bases de datos que soporte el motor de persistencia que utilice el programador.

Por ejemplo. Con el motor de persistencia Hibernate guardar en base de datos una instancia de una clase Gato con sus n crías se reduciría a : Gato gato = new GatoDomestico();Gato cria = new GatoDomestico();...Set crias = new HashSet();crias.add(cria);gato.setCrias(crias);session.save(gato);

Casi todos los motores de persistencia utilizan ficheros de configuración (normalmente en XML) para definir la asociación entre las diferentes clases y almacenamiento secundario. Por otra parte, normalmente estas clases son generadas automáticamente a partir de estos ficheros de configuración por loq ue el desarrollador tampoco tiene que perder el tiempo creándolas.

Ejemplos de motores de persistencia son Hibernate, Castor o OJB

¿Sabes por qué en los EJB cuando accedemos a una referencia remota desde un EJB o desde un cliente tenemos que utilizar PortableRemoteReference. narrow(..)?   (javaHispano) EJB utiliza como protocolo de comunicación remoto RMI-IIOP. Este protocolo permite unir los mundos de Java (RMI) y CORBA (IIOP) de modo que un cliente en cualquier lenguaje pueda comunicarse con un Enterprise Java Bean escrito en Java.

Como CORBA es una plataforma que soporta múltiples lenguajes se nos presenta un problema. No todos los lenguajes de programación soportan el concepto de cast por lo que es imposible realizar automáticamente casts de objetos que provengan de RMI-IIOP a objetos Java. Con el método PortableObjectReference.narrow(objeto, clase) explicitamos que queremos transformar ese objeto a una instancia de la clase que le pasamos como parámetro.

Esto no deja de ser bastante molesto cuando estamos trabajando únicamente en entornos basados en Java pero es el precio de la interoperabilidad.

¿Sabes lo que es una DMZ?   (javaHispano) Una DMZ, también conocida como Demilitarized Zone o zona desmilitarizada, es un ordenador o una pequeña subred que se sitúa entre el exterior y una intranet empresarial. Está situada pues entre dos firewalls y su función es evitar accesos peligrosos desde el exterior. Además, sirve de puente entre la red interna e Internet recibiendo las peticiones de los empleados y redireccionandolas al lugar apropiado. La DMZ normalmente aloja las páginas web de la empresa. Estas páginas web no deberían acceder a datos sensibles de la compañía. Las bases de datos con datos realmente importantes deberían ser accesibles únicamente desde el interior de la red o a través de una red privada virtual.

¿Sabes qué es un EIS?   (javaHispano) El término EIS proviene de Enterprise Information System y se utiliza para referirse a cualquier sistema que proporciona una infraestructura para el soporte de la información de una empresa.

Un EIS ha de ofrecer una serie de servicios a sus clientes, exponiendose éstos a través de una serie de interfaces locales o remotas, es decir, el cliente normalmente puede trabajar

Page 4: Tips de JAVA J2EE

localmente al EIS o desde un puesto de su intranet o incluso desde fuera de ésta.

Ejemplos típicos de sistemas EIS son:

Sistemas ERP Sistemas de procesamiento de transacciones en mainframes Bases de datos heredadas

Normalmente los EIS ofrecen una API para el acceso externo desde otras aplicaciones. Esta API suele exponer los servicios más importantes de un EIS. Cada sistema y cada fabricante tiene sus propias APIs y estas son muy diferentes entre si por lo que la integración con múltiples sistemas EIS suele ser compleja. Java tiene un magnifico soporte de este tipo de sistemas gracias a la especificación JCA ( Java Connector Architecture ) que especifica un conjunto de interfaces estándar para acceder a cualquier tipo de sistemas EIS.