tag:blogger.com,1999:blog-50819689004136273312024-03-13T09:22:24.737-03:00OnJ2EEJ2EE y otras plataformas...Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.comBlogger20125tag:blogger.com,1999:blog-5081968900413627331.post-54086149368886120442010-02-19T12:31:00.001-03:002010-02-19T12:33:21.383-03:00Introducción a EJB 3.0<div style="text-align: justify;">Enterprise JavaBeans (EJB) es una plataforma para construir aplicaciones empresariales portables, reusables y escalables, utilizando el lenguaje de programación java. EJB permite a los desarrolladores de aplicaciones enfocarse en construir la lógica de negocio sin la necesidad de gastar tiempo en la construcción de código de infraestructura.</div><div style="text-align: justify;">Desde el punto de vista del desarrollador, EJB es una pieza de código java que se ejecuta en un ambiente de ejecución (runtime enviroment) denominado <i>contenedor EJB</i>.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Estándar Java EE</b></div><div style="text-align: justify;">EJB es una parte muy importante del estándar Java EE. EJB 3 es una especificación de una API abierta y publica, la cual es utilizada por diversas organizaciones para crear una implementación de un contenedor (container) o un proveedor de persistencia (JPA). El estándar EJB 3 es desarrollado por la <a href="http://jcp.org/">Java Community Process</a> (JCP), la cual está constituida por un grupo no exclusivo de individuos que guían los estándares Java.</div><div style="text-align: justify;">Por este motivo, EJB es soportado por un gran número de organizaciones independientes. Esto incluye tanto a las grandes corporaciones como <a href="http://www.oracle.com/">Oracle</a> e <a href="http://www.ibm.com/">IBM</a>, como también a los grandes grupos open source como <a href="http://www.jboss.org/">JBoss</a> y <a href="http://geronimo.apache.org/">Geronimo</a>.</div><div style="text-align: justify;">El alto grado y variedad de soporte de esta especificación se traduce en tres importantes ventajas para el desarrollador y compañías que trabajan con esta tecnología:</div><ol style="text-align: justify;"><li>No se encuentran a merced de los altos y bajos de una compañía o grupo de usuarios en particular.</li>
<li>Un gran número de personas tienen el interés (a corto, mediano y largo plazo) de mantener esta tecnología lo más competitiva posible.</li>
<li>Todos los proveedores de la especificación históricamente han competido agregando nuevas características (no estándar) a sus implementaciones.</li>
</ol><div style="text-align: justify;">Todos estos factores mantienen la especificación EJB en el camino de la evolución constante.</div><div style="text-align: justify;">El proveedor de persistencia está completamente separado del contenedor EJB 3.0, por este motivo, es abstraído a través de la Java Persistence API (JPA). Esto permite, en un proyecto, intercambiar la implementación del mismo sin cambiar ninguna línea de código. Existen organizaciones que brindan implementaciones de la JPA, para que el mismo pueda ser utilizado dentro de un contenedor completo Java EE, con contenedores web livianos (como <a href="http://tomcat.apache.org/">Tomcat</a>), o para utilizarlas dentro de aplicaciones Java SE. <a href="http://db.apache.org/jdo/">JDO</a>, <a href="http://openjpa.apache.org/">OpenJPA</a>, <a href="https://www.hibernate.org/">Hibernate</a> (de JBoss) y <a href="http://www.oracle.com/technology/products/ias/toplink/index.html">TopLink</a> (de Oracle) son algunas de las implementaciones más utilizadas. </div><div style="text-align: justify;">Ver <a href="http://java.sun.com/javaee/5/docs/tutorial/doc/">tutorial oficial de sun de Java EE 5</a>. </div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>EJB como un componente</b></div><div style="text-align: justify;">En el mundo de EJB 3, un componente no es más que un <a href="http://es.wikipedia.org/wiki/Plain_Old_Java_Object">POJO</a> (Plain Old Java Object) con cierta funcionalidad especial. La idea real detrás de los componentes es que permiten encapsular el comportamiento de la aplicación.</div><div style="text-align: justify;">Existen tres tipos de componentes EJB:</div><ul style="text-align: justify;"><li>Beans de sesión (session beans)</li>
<li>Beans manejados por mensajes (message-driven beans)</li>
<li>Entidades (entities)</li>
</ul><div style="text-align: justify;">Los session beans y message-driven bean (MDB) son utilizados para implementar la lógica de negocio en una aplicación EJB, y los entities son utilizados para la persistencia. Estos componentes pueden ser reutilizados en diferentes aplicaciones, lo que obliga a construirlos de una manera cuidadosa y planificada para permitir reutilizarlos.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>EJB como un framework</b></div><div style="text-align: justify;">Como ya se menciono, los componentes EJB están alojados en un contenedor. Ambos, los componentes (o EJB’s) junto con el contenedor, pueden ser vistos como un framework que provee servicios para el desarrollo de aplicaciones empresariales.</div><div style="text-align: justify;">El contenedor EJB provee servicios comunes a la mayoría de las aplicaciones del lado del servidor, como el manejo de estados de una aplicación, almacenamiento y obtención de la información desde una base de datos, manejo de transacciones, implementación de seguridad, procesamiento asincrónico, integración de sistemas, etc. Estos servicios están disponibles para los componentes EJB cuando los mismos son desplegados (deployed) en un contenedor EJB. De esta manera se permiten desarrollar aplicaciones profesionales en menor tiempo y enfocarse solo en la lógica de negocio.</div><div style="text-align: justify;">El contenedor provee los servicios a los componentes EJB a través de las anotaciones metadata (metadata annotations), estas son utilizadas para preconfigurar los componentes EJB especificando los tipos de servicios, los cuales son agregados cuando el contenedor despliega los mismos.</div><div style="text-align: justify;">Las metadata annotations (introducidas en Java 5), son seteos de propiedades que se aplican a una pieza de código, como un método o una clase. Este es un tipo de programación declarativa, en donde el desarrollador especifica que debe ser realizado y el sistema agrega el código necesario para realizarlo. Estas anotaciones permiten no depender de un archivo XML de configuración externo. De esta manera, los desarrolladores agregan los servicios declarativamente a los componentes EJB, es decir, las anotaciones transforman un simple <a href="http://es.wikipedia.org/wiki/Plain_Old_Java_Object">POJO</a> en un EJB.</div><div style="text-align: justify;">El framework EJB es un estándar de la tecnología java, el cual tiene una especificación abierta (administrada por la <a href="http://jcp.org/">Java Community Process</a>). EJB es soportado por un gran número de compañías y grupos de open source que proveen implementaciones de la especificación. Dichas implementaciones deben cumplir con la especificación, lo cual facilita la portabilidad de las aplicaciones a través de diferentes contenedores EJB.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Arquitecturas de capas y EJB</b></div><div class="separator" style="clear: both; text-align: justify;"><a href="http://3.bp.blogspot.com/_3WReUfj0UMk/S36qM5GHfYI/AAAAAAAAARI/VAC7CxTA9Kk/s1600-h/01.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/_3WReUfj0UMk/S36qM5GHfYI/AAAAAAAAARI/VAC7CxTA9Kk/s320/01.JPG" /></a></div><div style="text-align: justify;">La mayoría de las aplicaciones empresariales contienen un gran número de componentes. Para desarrollar este tipo de aplicaciones se puede seguir una arquitectura común o un principio de diseño (patrones). En una arquitectura con capas, los componentes son agrupados dentro de diferentes capas, cada una de estas delega trabajo a su capa por debajo.</div><div style="text-align: justify;">EJB permite construir aplicaciones utilizando dos arquitecturas de capas diferentes: la arquitectura tradicional de cuatro capas y el diseño manejado por el dominio (domain-driven design).</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Arquitectura de cuatro capas</b></div><div style="text-align: justify;">En esta arquitectura, la <i>capa de presentación</i> es responsable de renderizar la interfaz grafica del usuario (GUI) y manejar la entrada del usuario. La <i>capa de lógica de negocio</i> es el corazón de la aplicación y contiene flujo de trabajo (workflow) y lógica de procesamiento. La <i>capa de persistencia</i> provee una abstracción orientada a objetos (OO) de alto nivel de la capa de base de datos. La <i>capa de base de datos</i> consiste típicamente en un sistema de administración de bases de datos relacionales (RDBMS).</div><div style="text-align: justify;"><a href="http://4.bp.blogspot.com/_3WReUfj0UMk/S36qsLw_rLI/AAAAAAAAARQ/8kJ6tGfxTz4/s1600-h/02.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://4.bp.blogspot.com/_3WReUfj0UMk/S36qsLw_rLI/AAAAAAAAARQ/8kJ6tGfxTz4/s320/02.JPG" /></a>EJB da soporte para la capa de lógica de negocio y la capa de persistencia. Los session beans y MDB residen y utilizan los servicios de la capa de lógica de negocio. Por otro lado, los entities residen y utilizan los servicios de la capa de persistencia.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Domain-driven design</b></div><div style="text-align: justify;">El termino <a href="http://en.wikipedia.org/wiki/Domain-driven_design">domain-driven design</a> (DDD) enfatiza que los objetos de dominio deben contener lógica de negocios y no deberían ser solo una réplica (sin lógica) de las tablas de la base de datos. En EJB, los objetos de dominio son denominados entities (entidades).</div><div style="text-align: justify;">En versiones anteriores de EJB (como EJB 2), era casi imposible implementar un modelo de dominio real debido a que los beans no eran POJO’s y no soportaban muchas características OO, como la herencia y el polimorfismo. EJB 3 permite implementar la arquitectura DDD, debido a que las entidades son definidas a través de JPA (EJB 3 Java Persistence API), la cual soporta todas las características OO dado a que son POJO’s con simples anotaciones.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Session Beans</b></div><div style="text-align: justify;">Un session bean es invocado por un cliente con el propósito de realizar una operación específica de negocio. Es decir, puede ser utilizado para crear cualquier funcionalidad lógica de la aplicación. Existen dos tipos de session beans: <i>stateful </i>y <i>stateless</i>.</div><div style="text-align: justify;">Un <i>stateful session</i> bean almacena automáticamente el estado del bean entre diversas invocaciones de un cliente sin la necesidad de que el desarrollador deba escribir código adicional.</div><div style="text-align: justify;">Un <i>stateless session</i> bean no mantiene ningún estado y permite modelar servicios de aplicación que pueden ser completados en una sola invocación del cliente.</div><div style="text-align: justify;">Un session bean puede ser invocado tanto local como remotamente utilizando <a href="http://es.wikipedia.org/wiki/Java_Remote_Method_Invocation">Java RMI</a> (Remote Method Invocation). Un stateless session bean puede ser publicado como un web service.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Message-driven beans (MDB)</b></div><div style="text-align: justify;">Del mismo modo que los session beans, los MDB’s procesan lógica de negocio. Pero con la diferencia que los métodos de los mismos nunca son invocados directamente por un cliente. Los MDB’s son desencadenados por mensajes enviados a un servidor de mensajes, el cual activa el envío de mensajes asincrónicos entre componentes del sistema. MDB’s son utilizados típicamente para sistemas robustos de integración o procesamientos asincrónicos. <a href="http://www-01.ibm.com/software/integration/wmq/">IBM WebSphere MQ</a>, <a href="http://web.progress.com/es-ar/sonic/index.html">SonicMQ</a>, <a href="http://www.oracle.com/technology/sample_code/tech/dataint/index.html">Oracle Advanced Queueing</a> y <a href="http://www.tibco.com/">TIBCO</a> son algunos de los servidores de mensajes más utilizados.</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://2.bp.blogspot.com/_3WReUfj0UMk/S36q7Lfta-I/AAAAAAAAARY/ZkqQQFc1DN8/s1600-h/03.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="http://2.bp.blogspot.com/_3WReUfj0UMk/S36q7Lfta-I/AAAAAAAAARY/ZkqQQFc1DN8/s640/03.JPG" width="640" /></a></div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Java Persistence API (JPA)</b></div><div style="text-align: justify;">La persistencia dentro de EJB 3 es administrada por JPA. JPA permite persistir automáticamente los objetos Java utilizando una técnica denominada object-relational mapping (ORM). ORM es esencialmente el proceso de mapear la información contenida en los objetos Java hacia las tablas de base de datos utilizando una configuración.</div><div style="text-align: justify;">JPA define un estándar para:</div><ul style="text-align: justify;"><li>La creación de configuración metadata del ORM para mapear entidades hacia tablas relacionales.</li>
<li>La EntityManager API, una API estándar para realizar las operaciones CRUD (create, read, update y delete) de las entidades.</li>
<li>El lenguaje Java Persistence Query Language (JPQL), para realizar búsquedas y obtener información persistida de la aplicación.</li>
</ul><div style="text-align: justify;">Como se ha mencionado anteriormente, <i><b>desde que JPA estandariza los frameworks ORM para la plataforma Java</b></i>, se pueden utilizar productos como Hibernate ó TopLink como la implementación del proveedor de persistencia de una aplicación. Como JPA está completamente separado del resto del contenedor EJB 3, y en definitiva todas las operaciones se traducen a operaciones <a href="http://java.sun.com/javase/technologies/database/">JDBC</a>, esta tecnología de abstracción de ORM puede ser utilizada en ambientes Java SE.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Entities</b></div><div style="text-align: justify;">Las entidades son objetos Java que son persistidos dentro una base de datos. Es decir, son las representaciones OO de la información de la aplicación almacenada en la base de datos. La magia de las entidades se basa en las anotaciones metadata ORM, las cuales especifican la información de cómo las mismas deben ser mapeadas a la base de datos. Las entidades JPA soportan todos los tipos de relaciones y capacidades OO, incluyendo relaciones entre entidades, herencia y polimorfismo.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>EntityManager</b></div><div style="text-align: justify;">La interface EntityManager administra entidades en términos de proveer servicios de persistencia. Dicha interface, lee las anotaciones metadata de una entidad y realiza las operaciones de persistencia. Es decir, conoce el modo de agregar, actualizar, eliminar y obtener entidades de la base de datos (CRUD).</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Contenedores completos Java EE</b></div><div style="text-align: justify;">Un contenedor Java EE es un servidor de aplicaciones el cuál contiene un contenedor EJB 3, un contenedor web y otras API’s y servicios Java EE. Algunos ejemplos de contenedores Java EE completos son: <a href="http://www.oracle.com/technology/products/weblogic/index.html">WebLogic Server</a> (BEA), <a href="https://glassfish.dev.java.net/">GlassFish</a> (Sun Microsystems), IBM <a href="http://www-01.ibm.com/software/websphere/">WebSphere</a>, <a href="http://en.wikipedia.org/wiki/JBoss_application_server">JBoss Application Server</a> y <a href="http://www.oracle.com/global/lad/appserver/index.html">Oracle Application Server</a>.</div><div style="text-align: justify;">Algunos proveedores pueden ofrecer solo un contenedor web (como Tomcat) o proveedor de persistencia (como Hibernate).</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://4.bp.blogspot.com/_3WReUfj0UMk/S36rEXC-9wI/AAAAAAAAARg/oyDfkb71qJs/s1600-h/04.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="212" src="http://4.bp.blogspot.com/_3WReUfj0UMk/S36rEXC-9wI/AAAAAAAAARg/oyDfkb71qJs/s640/04.JPG" width="640" /></a></div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Otros beneficios de EJB 3</b></div><div style="text-align: justify;">Además de los beneficios expuestos anteriormente, EJB 3 ofrece:</div><ul><li style="text-align: justify;">Utilización de servicios EJB: Integration, Pooling, Thread-safety, State managment, Messaging, Transactions, Security, Interceptors, Remote Access, Web services, Persistence, Caching y performance.</li>
<li style="text-align: justify;">Modelo de programación simplificado, a través de la utilización de POJO’s (Plain Old Java Objects) y POJI’s (Plain Old Java Interfaces), a los cuales luego se le aplican configuraciones a través de las anotaciones para agregar servicios de la plataforma.</li>
<li style="text-align: justify;">Anotaciones en cambio de descriptores de despliegue (archivos XML).</li>
<li style="text-align: justify;">Inyección de dependencia en vez de JNDI lookups. Esto permite desacoplar el código de la aplicación del servidor, los lookups se convierten en una simple configuración a través de anotaciones.</li>
<li style="text-align: justify;">Estandarización de frameworks de persistencia (JPA).</li>
<li style="text-align: justify;">Componentes POJO más fáciles de testear a través de frameworks de testeo como JUnit o TestNG.</li>
<li style="text-align: justify;">Integración de EJB 3 con Spring, Spring con EJB 3 y Spring con JPA.</li>
</ul>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com0tag:blogger.com,1999:blog-5081968900413627331.post-32298564491567765432010-02-17T12:16:00.004-03:002010-02-17T12:28:15.008-03:00Sun Certified Business Component Developer (SCBCD)<div style="text-align: justify;">Luego de rendir mi <a href="http://onj2ee.blogspot.com/2010/02/indice-scwcd.html">certificación SCWCD</a> (el 23 de diciembre de 2009) me decidí a tomarme un tiempo de descanso durante enero de 2010. Una vez pasado dicho mes, comence lentamente a leer e investigar los temas tratados en la certificación SCBCD <a href="http://www.sun.com/training/catalog/courses/CX-310-091.xml">(CX-310-091)</a>, solo con el objetivo de ver por donde continuaría mi camino por aprender Java EE. Más que nada por la disyuntiva <em>"seguir el camino de las certificaciones o comenzar con alguno de los tantos frameworks existentes para trabajar con esta tecnología"</em>. En un principio supuse que lo más conveniente sería comenzar con algún framework de los más mencionados (Hibernate, Struts, Spring, etc), pero al leer los dos primeros capítulos del libro <em><strong>"EJB in Action"</strong></em> de Manning, me dí cuenta de que estaba equivocado.</div><div style="text-align: justify;">Por ese motivo fue que me decidí a comenzar a investigar lentamente sobre EJB 3.0, y en una vez que maneje los temas tratados voy a rendir la certificación SCBCD. A diferencia de las certificaciones anteriores que rendí (<a href="http://onj2ee.blogspot.com/2010/02/indice-scjp.html">SCJP</a> y <a href="http://onj2ee.blogspot.com/2010/02/indice-scwcd.html">SCWCD</a>) esta me la voy a tomar más tranquilo y la prepararé más despacio (más que nada porque dentro de poco comenzaré a trabajar para una empresa de software si todo sale bien).</div><div style="text-align: justify;">Como <a href="http://onj2ee.blogspot.com/2009/12/sun-certified-web-component-developer.html">ya se ha mencionado en este blog</a>, el programa de certificación de SUN (ahora de <a href="http://www.oracle.com/global/es/index.html">Oracle</a>) actualmente contiene ocho exámenes de certificación sobre la plataforma Java:</div><div style="text-align: justify;"></div><div style="text-align: justify;">- <a href="http://www.sun.com/training/certification/java/scja.xml">Sun Certified Java Associate (SCJA)</a></div><div style="text-align: justify;">- <a href="http://www.sun.com/training/certification/java/scjp.xml"><strike>Sun Certified Java Programmer (SCJP)</strike></a> listo</div><div style="text-align: justify;">- <a href="http://www.sun.com/training/certification/java/scjd.xml">Sun Certified Java Developer (SCJD)</a></div><div style="text-align: justify;">- <a href="http://www.sun.com/training/certification/java/scwcd.xml"><strike>Sun Certified Web Component Developer (SCWCD)</strike></a> listo</div><div style="text-align: justify;">- <a href="http://www.sun.com/training/certification/java/scbcd.xml">Sun Certified Business Component Developer (SCBCD)</a></div><div style="text-align: justify;">- <a href="http://www.sun.com/training/certification/java/scdjws.xml">Sun Certified Developer For Java Web Services (SCDJWS)</a></div><div style="text-align: justify;">- <a href="http://www.sun.com/training/certification/java/scmad.xml">Sun Certified Mobile Application Developer (SCMAD)</a></div><div style="text-align: justify;">- <a href="http://www.sun.com/training/certification/java/scea.xml">Sun Certified Enterprise Architect (SCEA)</a></div><div style="text-align: justify;"><br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://1.bp.blogspot.com/_3WReUfj0UMk/S3wA_Ad-uTI/AAAAAAAAAQ4/1vnFHDniFqI/s1600-h/certpathJava_SCBCD.gif" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" ct="true" height="126" src="http://1.bp.blogspot.com/_3WReUfj0UMk/S3wA_Ad-uTI/AAAAAAAAAQ4/1vnFHDniFqI/s400/certpathJava_SCBCD.gif" width="400" /></a></div><div style="text-align: justify;"><em>"Esta certifición está dirigida a desarrolladores de componentes EJB (Enterprise JavaBeans) encargados de diseñar, desarrollar, probar, implantar e integrar aplicaciones EJB. Para obtener la certificación, es preciso aprobar un examen. Los candidatos ya deben poseer el título de Programador Certificado en Sun (SCJP), en cualquiera de las ediciones."</em></div><div style="text-align: justify;"><a href="http://www.sun.com/training/certification/java/scbcd.xml">Extraído de la página oficial de Sun</a></div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><strong>Tutorial Java EE 5</strong></div><div style="text-align: justify;">Por otro lado les recomiendo el <a href="http://java.sun.com/javaee/5/docs/tutorial/doc/">tutorial oficial de sun de Java EE 5</a>. En dicho tutorial se cubren todos los temás de la tecnología J2EE 5. Por lo tanto pueden encontrar información de utilidad para las certificaciones SCWCD, SCBCD y SCDJWS. </div><div style="text-align: justify;">Más allá de esto, considero que este tutorial sirve también para brindarnos los materiales de estudio para esta tecnología, y a su vez, una manera ordenada de abordar los temas si no lo quieren realizar a través de las certificaciones.</div><div style="text-align: justify;">A través de este tutorial queda claramente reflejado el hecho de que es altamente recomendable conocer todos los temas en profundidad, antes de comenzar con un framework de desarrollo. Como ya mencione, <strong><em>es una fantástica guía para seguir en nuestro camino de aprendizaje de la plataforma</em></strong>.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><strong>Detalles del examen</strong><br />
<ul><li>Se rinde en: Centros autorizados por Prometric</li>
<li>Prerequisitos: Sun Certified Java Programmer (cualquier edición)</li>
<li>Tipo de examen: Multiple Choice, preguntas basadas en un escenario y Drag and Drop</li>
<li>Número de preguntas: 61</li>
<li>Puntaje de aprobación: 59% (36 of 61 preguntas)</li>
<li>Tiempo disponible: 145 minutos</li>
</ul></div><div style="text-align: justify;"><strong>Bibliografía</strong></div><div style="text-align: justify;"></div><div style="text-align: justify;">Actualmente estoy leyendo el libro "EJB in Action" de <a href="http://www.manning.com/panda/">Manning</a>, a continuación les dejo el link así pueden descargarlo: </div><ul><li><a href="http://scjp-preparacion.googlecode.com/files/Manning.EJB.3.in.Action.Apr.2007.pdf">Manning - EJB 3 in Action - Apr 2007</a></li>
</ul><div style="text-align: justify;">Bueno para finalizar les digo que estén atentos a este post (si les interesan los temas relacionados a la certificación SCBCD), ya que a medida de que voy investigando agregaré aca mismo cualquier otra información de utilidad o bibliografía que encuentre.</div>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com4tag:blogger.com,1999:blog-5081968900413627331.post-38521730399644733472010-02-15T16:35:00.002-03:002010-02-16T09:57:33.996-03:00eBooks SCJP<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="http://scjp-preparacion.googlecode.com/files/SCJP%20Sun%20Certified%20Programmer%20for%20Java%206.pdf" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" ct="true" src="http://3.bp.blogspot.com/_3WReUfj0UMk/S3qVzCmiDSI/AAAAAAAAAQw/vFKPXMvuYmw/s320/0071591060.jpg" /></a></div><br />
<br />
<br />
<br />
<br />
<br />
<a href="http://scjp-preparacion.googlecode.com/files/SCJP%20Sun%20Certified%20Programmer%20for%20Java%206.pdf">SCJP Sun Certified Programmer for Java 6.pdf</a><br />
<br />
<a href="http://scjp-preparacion.googlecode.com/files/SCJP_6_StudyGuide_Exam310-065_MGH_2008_CDROM%282%29.iso">CD ISO</a><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://scjp-preparacion.googlecode.com/files/TJAVA.pdf" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/_3WReUfj0UMk/S3mhwHzDSuI/AAAAAAAAAQo/Qc3xUu8hJE4/s320/tj.jpg" /></a></div><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<a href="http://scjp-preparacion.googlecode.com/files/TJAVA.pdf">Thinking In Java 4th Edition.pdf</a>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com2tag:blogger.com,1999:blog-5081968900413627331.post-46606302840026574562010-02-12T13:15:00.002-03:002010-02-19T12:32:49.468-03:00Indice SCBCD<b>Info General</b><br />
<ul><li><a href="http://onj2ee.blogspot.com/2010/02/sun-certified-business-component.html">Introducción y preparación del examen</a></li>
<li>Objetivos del examen</li>
<li>eBooks para descargar</li>
</ul><b>Recursos</b><br />
<ul><li><a href="http://onj2ee.blogspot.com/2010/02/introduccion-ejb-30.html">Introducción a EJB 3.0</a><b> </b></li>
</ul>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com0tag:blogger.com,1999:blog-5081968900413627331.post-91971153533423144802010-02-12T13:14:00.001-03:002010-02-16T09:50:35.896-03:00Indice SCWCD<b>Info General</b><br />
<ul><li><a href="http://onj2ee.blogspot.com/2009/12/sun-certified-web-component-developer.html">Introducción y preparación del examen</a></li>
<li><a href="http://onj2ee.blogspot.com/2009/12/objetivos-scwcd-cx-310-083.html">Objetivos del examen</a></li>
<li><a href="http://onj2ee.blogspot.com/2009/12/comprando-el-voucher-us-40.html">Comprando el voucher de certificación a solo u$s 40</a></li>
<li><a href="http://onj2ee.blogspot.com/2010/01/ebooks-scwcd.html">eBooks para descargar</a></li>
</ul><strong>Recursos</strong><br />
<ul><li><a href="http://onj2ee.blogspot.com/2009/12/introduccion-servlets.html">Introducción Servlets</a></li>
<li><a href="http://onj2ee.blogspot.com/2009/12/conceptos-basicos-servlets-y-jsp.html">Conceptos básicos (Servlets y JSP)</a></li>
<li><a href="http://onj2ee.blogspot.com/2009/12/servlet-technology-model.html">The Servlet Technology Model</a> ( <a href="http://onj2ee.blogspot.com/2009/12/codigo-servlet-technology-model.html">Ejemplos de código</a> ) <em>Objetivos sección 1</em></li>
<li><a href="http://onj2ee.blogspot.com/2009/12/structure-and-deployment-of-web.html">The Structure and Deployment of Web Applications</a> <em>Objetivos sección 2</em></li>
<li><a href="http://onj2ee.blogspot.com/2009/12/web-container-model-scwcd.html">The Web Container Model</a><em> </em>, <a href="http://onj2ee.blogspot.com/2010/01/web-container-model-filters-scwcd.html">Filters</a><em> Objetivos sección 3</em></li>
<li><a href="http://onj2ee.blogspot.com/2010/01/session-management.html">Session Management</a> <em>Objetivos sección 4</em></li>
</ul>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com2tag:blogger.com,1999:blog-5081968900413627331.post-65651741271795177932010-02-12T13:13:00.004-03:002010-04-26T00:31:20.879-03:00Indice SCJP<b>Info General</b><br />
<ul><li><a href="http://scjp-sun.blogspot.com/2009/07/preparacion-del-examen.html">Preparación del examen</a> </li>
<li><a href="http://scjp-sun.blogspot.com/2009/10/ya-soy-scjp.html">Rindiendo mi examen</a><b></b></li>
<li><a href="http://scjp-sun.blogspot.com/2009/10/diploma.html">Diploma de certificación</a><b></b></li>
<li><a href="http://onj2ee.blogspot.com/2010/02/ebooks-scjp.html">eBooks para descargar</a><b><br />
</b></li>
</ul><b> Recursos</b><br />
<ul><li><a href="http://scjp-sun.blogspot.com/2009/07/declaraciones-y-contro-de-acceso.html">Declaraciones y control de acceso</a> </li>
<li><a href="http://scjp-sun.blogspot.com/2009/07/orientacion-objetos.html">Orientación a Objetos</a><b> </b>( <a href="http://scjp-sun.blogspot.com/2009/07/ejemplos-de-codigo-orientacion-objetos.html">Ejemplos de código</a> )</li>
<li><b> </b><a href="http://scjp-sun.blogspot.com/2009/07/asignaciones.html">Asignaciones</a> ( <a href="http://scjp-sun.blogspot.com/2009/07/ejemplos-de-codigo-asignaciones.html">Ejemplos de código</a> ) </li>
<li><a href="http://scjp-sun.blogspot.com/2009/07/operadores.html">Operadores</a> ( <a href="http://scjp-sun.blogspot.com/2009/08/ejemplos-de-codigo-operadores.html">Ejemplos de código</a> )</li>
<li><a href="http://scjp-sun.blogspot.com/2009/08/clases-internas.html">Clases Internas</a> </li>
<li><a href="http://scjp-sun.blogspot.com/2009/08/almacenamiento-de-objetos-contenedores.html">Almacenamiento de objetos (Contenedores)</a> , <a href="http://scjp-sun.blogspot.com/2009/09/genericos-y-colecciones.html">Genéricos y Colecciones</a><a href="http://scjp-sun.blogspot.com/2009/08/almacenamiento-de-objetos-contenedores.html"><br />
</a></li>
<li><a href="http://scjp-sun.blogspot.com/2009/08/tratamiento-de-errores-mediante.html">Tratamiento de errores mediante excepciones</a> , <a href="http://scjp-sun.blogspot.com/2009/09/control-de-flujo-excepciones-y.html">Control de flujo, Excepciones y Assertions</a></li>
<li><a href="http://scjp-sun.blogspot.com/2009/08/cadenas-de-caracteres.html">Cadenas de caracteres</a> , <a href="http://scjp-sun.blogspot.com/2009/09/strings-io-formateo-and-parseo.html">Strings, I/O, Formateo, and Parseo</a></li>
<li> <a href="http://scjp-sun.blogspot.com/2009/09/clases-internas-resumen.html">Clases Internas</a></li>
<li><a href="http://scjp-sun.blogspot.com/2009/09/hilos-threads.html">Hilos (Threads)</a> </li>
<li><a href="http://scjp-sun.blogspot.com/2009/09/development.html">Development</a></li>
</ul><b>Revista JavaWorld</b> <br />
<ul><li><a href="http://scjp-preparacion.googlecode.com/files/JavaWorld%20-%20Revista%20Digital%20-%20SCJP%20Capitulo%201.pdf">Capítulo 1</a></li>
<li><a href="http://scjp-preparacion.googlecode.com/files/JavaWorld%20-%20Revista%20Digital%20-%20SCJP%20Capitulo%202.pdf">Capítulo 2</a></li>
<li><a href="http://scjp-preparacion.googlecode.com/files/JavaWorld%20-%20Revista%20Digital%20-%20SCJP%20Capitulo%203.pdf">Capítulo 3</a></li>
<li><a href="http://scjp-preparacion.googlecode.com/files/JavaWorld%20-%20Revista%20Digital%20-%20SCJP%20Capitulo%204.pdf">Capítulo 4</a></li>
<li><a href="http://scjp-preparacion.googlecode.com/files/JavaWorld%20-%20Revista%20Digital%20-%20SCJP%20Capitulo%205.pdf">Capítulo 5</a></li>
<li><a href="http://scjp-preparacion.googlecode.com/files/JavaWorld%20-%20Revista%20Digital%20-%20SCJP%20Capitulo%206.pdf">Capítulo 6</a></li>
<li><a href="http://scjp-preparacion.googlecode.com/files/JavaWorld%20-%20Revista%20Digital%20-%20SCJP%20Capitulo%207.pdf">Capítulo 7</a></li>
<li>Capítulo 8, 9 y 10 (Proximamente)</li>
</ul>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com29tag:blogger.com,1999:blog-5081968900413627331.post-37516905775598905422010-01-08T11:31:00.002-03:002010-01-08T11:34:05.287-03:00eBooks SCWCDLibros para realizar la preparación de la certificación SCWCD:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://scjp-preparacion.googlecode.com/files/Manning.SCWCD.Exam.Study.Kit.Java.Web.Component.Developer.Certification.2nd.Edition.May.2005.pdf" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/_3WReUfj0UMk/S0dBNP77A6I/AAAAAAAAAQI/1RhwGmxqtLc/s320/book_manning.jpg" /></a><br />
</div><br />
<br />
<br />
<br />
<br />
<a href="http://scjp-preparacion.googlecode.com/files/Manning.SCWCD.Exam.Study.Kit.Java.Web.Component.Developer.Certification.2nd.Edition.May.2005.pdf">Manning SCWCD Exam Study Kit - 2nd Edition - May 2005</a><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://scjp-preparacion.googlecode.com/files/OReilly.Head.First.Servlets.and.JSP.2nd.Edition.Mar.2008.pdf" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/_3WReUfj0UMk/S0dBZzqkYvI/AAAAAAAAAQQ/1UKGAC-cnoY/s320/book_oreily.jpg" /></a><br />
</div><br />
<br />
<br />
<br />
<a href="http://scjp-preparacion.googlecode.com/files/OReilly.Head.First.Servlets.and.JSP.2nd.Edition.Mar.2008.pdf">OReilly Head First Servlets & JSP - 2nd Edition - Mar 2008</a><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<span style="font-style: italic;">NOTA: El libro de MANNING esta creado para la versión CX-310-081. Sin embargo, recomiendo la lectura de este libro ya que fue de mucha utilidad para mí preparación. Ciertos temas se desarrollan con mayor profundidad (aunque muy teóricos) y brindan un mayor conocimiento de fondo.</span>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com8tag:blogger.com,1999:blog-5081968900413627331.post-21868606403245771492010-01-08T11:17:00.001-03:002010-01-08T11:20:03.469-03:00Session Management (SCWCD)<div style="text-align: justify;"><span style="font-weight: bold;">Objetivos: <br />
</span><span style="font-weight: bold;">Section 4: Session Management</span><br />
</div><div style="text-align: justify;"><span style="font-weight: bold;">4.1- </span>Write servlet code to store objects into a session object and retrieve objects from a session object.<br />
</div><div style="text-align: justify;"><span style="font-weight: bold;">4.2- </span>Given a scenario describe the APIs used to access the session object, explain when the session object was created, and describe the mechanisms used to destroy the session object, and when it was destroyed.<br />
</div><div style="text-align: justify;"><span style="font-weight: bold;">4.3- </span>Using session listeners, write code to respond to an event when an object is added to a session, and write code to respond to an event when a session object migrates from one VM to another.<br />
</div><div style="text-align: justify;"><span style="font-weight: bold;">4.4- </span>Given a scenario, describe which session management mechanism the Web container could employ, how cookies might be used to manage sessions, how URL rewriting might be used to manage sessions, and write servlet code to perform URL rewriting.<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><a href="http://onj2ee.blogspot.com/2009/12/objetivos-scwcd-cx-310-083.html">Ver todos los objetivos de SCWCD</a> <br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Las sesiones en el protocolo HTTP</b><br />
</div><div style="text-align: justify;">HTTP es un protocolo sin estado (stateless), cada petición al servidor web y su correspondiente respuesta es manejada como una transacción aislada. El servidor (HTTP) no tiene manera de determinar que una serie de peticiones provienen del mismo cliente.<br />
</div><div style="text-align: justify;">Las sesiones, en una aplicación web, se utilizan para asociar las peticiones con el cliente. Una sesión comienza cuando un cliente desconocido envía la primera petición (que requiera crear una sesión) a la aplicación web. La misma finaliza, cuando el cliente la termina explícitamente o cuando se expira el tiempo de vida de la sesión (debido a que no se ha recibido una petición en un tiempo determinado).<br />
</div><div style="text-align: justify;">La manera en que una aplicación web mantiene una sesión con el cliente es:<br />
</div><ul style="text-align: justify;"><li>Cuando el servidor web recibe la primera petición de un cliente, el servidor inicia una sesión y le asigna un identificador único.</li>
<li><i>El cliente debe incluir este identificador único en cada petición subsecuente. El servidor revisa el identificador y asocia la petición con su correspondiente sesión.</i><br />
</li>
</ul><div style="text-align: justify;">Existen dos formas de implementar el soporte para sesiones, <b>cookies </b>y la <b>sobreescritura de la URL</b>.<br />
</div><div style="text-align: justify;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/_3WReUfj0UMk/S0c-KrGCQJI/AAAAAAAAAPw/bvyrJmsTRjU/s1600-h/HttpSession.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://2.bp.blogspot.com/_3WReUfj0UMk/S0c-KrGCQJI/AAAAAAAAAPw/bvyrJmsTRjU/s400/HttpSession.jpg" /></a><br />
</div><div style="text-align: justify;"><b>javax.servlet.http.HttpSession</b><br />
</div><div style="text-align: justify;">La API de servlets abstrae el concepto de sesión a través de esta interface. <i>Cuando se inicia una sesión para un cliente, el contenedor de servlets instancia un objeto HttpSession</i>. Los distintos servlets pueden utilizar este objeto para almacenar información relacionada al usuario y de esta manera mantener el estado del mismo. Existe <b><i>un objeto HttpSession por cada sesión</i></b> (o usuario). El contenedor de servlets se encarga de asociar una petición con su correspondiente objeto de sesión.<br />
</div><div style="text-align: justify;">La interface javax.servlet.http.<b>HttpServletRequest </b>provee dos métodos para obtener la sesión:<br />
</div><ul style="text-align: justify;"><li>HttpSession <b>getSession </b>(boolean create): Devuelve el correspondiente objeto sesión, o si no existe ninguna sesión y el parámetro sesión es true, crea una nueva sesión.</li>
<li>HttpSession <b>getSession </b>(): Método equivalente a invocar getSession (true).<br />
</li>
</ul><div style="text-align: justify;">Métodos de la interface <b>HttpSession </b>para el manejo de sus atributos:<br />
</div><ul style="text-align: justify;"><li>void <b>setAttribute </b>(String name, Object value): Asocia el objeto pasado como parámetro a la sesión, y lo identifica a través del nombre.</li>
<li>Object <b>getAttribute </b>(String name): Devuelve el objeto asociado al nombre, o null en caso de no existir ninguno.</li>
</ul><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Manejando los eventos de sesión con las interfaces listener</b><br />
</div><div style="text-align: justify;">En una aplicación web, cuando ocurren eventos importantes, se pueden recibir las notificaciones correspondientes a los mismos a través de las interfaces listener. Se crea una clase que implemente la interface listener correspondiente, y el contenedor de servlets invocará los métodos apropiados sobre un objeto (de esta clase) cuando ocurra algún evento.<br />
</div><div style="text-align: justify;">La API de servlets define cuatro interfaces listener y dos eventos relacionados a las sesiones dentro de javax.servlet.http:<br />
</div><div style="text-align: justify;"><i><b>HttpSessionAttributeListener</b></i>: Permite recibir notificaciones cuando se agrega, reemplaza, o elimina un atributo de un objeto HttpSession. La clase se debe especificar en el archivo web.xml. El contenedor de servlets solo crea una instancia, sobre la cual se invocaran los métodos para todas las sesiones.<br />
</div><ul style="text-align: justify;"><li>void <b>attributeAdded </b>(HttpSessionBindingEvent sbe): Invocado cuando se agrega un atributo a una sesión.</li>
<li>void <b>attributeRemoved </b>(HttpSessionBindingEvent sbe): Invocado cuando se elimina un atributo.</li>
<li>void <b>attributeReplaced </b>(HttpSessionBindingEvent sbe): Invocado cuando se reemplaza un atributo.<br />
</li>
</ul><div style="text-align: justify;"><i><b>HttpSessionBindingListener</b></i>: <i>Esta interface es implementada por aquellas clases cuyos objetos necesiten recibir notificaciones de cuando ellos son agregados y eliminados de una sesión</i>. Esta clase no se especifica en el archivo web.xml. Cuando se agrega o elimina un objeto de una sesión, el contenedor revisa las interfaces que implementa. En caso de que el objeto implemente la interface HttpSessionBindingListener, el contenedor invoca el método correspondiente:<br />
</div><ul style="text-align: justify;"><li>void <b>valueBound </b>(HttpSessionBindingEvent event): Notifica al objeto que está siendo asociado a una sesión.</li>
<li>void <b>valueUnbound </b>(HttpSessionBindingEvent event): Notifica al objeto que está siendo desasociado de una sesión.<br />
</li>
</ul><div style="text-align: justify;"><i><b>HttpSessionListener</b></i>: Esta interface se utiliza <i>para recibir notificaciones de cuando una sesión se crea o se destruye</i>. La clase que implemente dicha interface debe ser especificada en el archivo web.xml. Se crea una nueva instancia de esta clase, por cada nueva sesión creada. Posee los métodos:<br />
</div><ul style="text-align: justify;"><li>void <b>sessionCreated </b>(HttpSessionEvent se): Se invoca cuando se crea una sesión.</li>
<li>void <b>sessionDestroyed </b>(HttpSessionEvent se): Se invoca cuando se destruye una sesión. Si dentro de este método se invoca el método getAttribute(), se lanza la excepción IllegalStateException.<br />
</li>
</ul><div style="text-align: justify;"><i><b>HttpSessionActivationListener</b></i>: (No se requiere para el examen) Esta interface se utiliza por los atributos de una sesión, <i>para recibir notificaciones de cuando la sesión está siendo migrada a través de JVM’s en un ambiente distribuido</i>. De esta manera, los atributos contenidos en una sesión no se pierden, más allá de que exista más de una JVM ejecutando la aplicación. Posee los métodos:<br />
</div><ul style="text-align: justify;"><li>void <b>sessionDidActivate </b>(HttpSessionEvent se): Se invoca justo después de que la sesión se activa.</li>
<li>void <b>sessionWillPassivate </b>(HttpSessionEvent se): Se invoca antes de desactivar la sesión.<br />
</li>
</ul><div style="text-align: justify;"><b>Cerrar sesiones</b><br />
</div><div style="text-align: justify;">La interface HttpSession provee el método:<br />
</div><ul style="text-align: justify;"><li>void <b>invalidate</b>(): Cierra una sesión y desenlaza todos los objetos asociados a ella. Lanza la excepción IllegalStateException si la sesión ya ha sido cerrada.</li>
</ul><div style="text-align: justify;"><b>Session timeout</b><br />
</div><div style="text-align: justify;">El protocolo HTTP no provee ninguna señal de la terminación de una sesión en el servidor. Por este motivo, cuando el usuario no realiza ninguna acción en un período de tiempo determinado, el servidor cierra dicha sesión.<br />
</div><div style="text-align: justify;">En el archivo web.xml, el elemento <b><session-timeout></b> contiene en <b>minutos </b>el tiempo de vida de una sesión. <i><b>Un valor 0 o menor significa que la sesión nunca expirará.</b></i><br />
</div><pre class="brush: xml;" id="sourceCode" name="sourceCode"><web-app …="">
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
</pre><div style="text-align: justify;">La interface <b>HttpSession </b>también posee los siguientes métodos:<br />
</div><ul style="text-align: justify;"><li>void <b>setMaxInactiveInterval </b>(int seconds): <i>Afecta solo a la sesión en la cual se invoca</i>. Las demás, mantienen el tiempo especificado en el archivo web.xml.</li>
<li>void <b>getMaxInactiveInterval </b>()<br />
</li>
</ul><div style="text-align: justify;">Existen dos inconsistencias entre estos modos de setear el timeout:<br />
</div><ol style="text-align: justify;"><li>El valor de elemento <b><session-timeout></b> se especifica <b>en minutos</b>, mientras que <b>setMaxInactiveInterval() en segundos</b>.</li>
<li>El valor <b>0 o menos</b> en el elemento <b><session-timeout></b> significa que <b>la sesión nunca expirará</b>, mientas que al método <b>setMaxInactiveInterval()</b> se le debe pasar <b>un valor negativo (no 0)</b> para conseguir el mismo comportamiento.<br />
</li>
</ol><div style="text-align: justify;"><br />
<b>Utilización de cookies</b><br />
En esta técnica, para enviar y recibir el identificador de una sesión, el contenedor de servlets utiliza los encabezados (headers) HTTP. <i>Cuando se devuelve la respuesta, el contenedor agrega un encabezado especial que contiene el identificador de sesión</i>. El cliente, el cual es típicamente un browser, extrae este encabezado especial, y lo almacena en la máquina local. Cuando se realiza <i>otra petición, el cliente agrega automáticamente un encabezado que contiene el identificador de sesión almacenado</i>. Este archivo almacenado se denomina cookie.<br />
Cuando las cookies se encuentran deshabilitadas, el browser ignora cualquier encabezado que contenga cookies, y consecuentemente no envía ningún encabezado con cookies en la petición.<br />
</div><div style="text-align: justify;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/_3WReUfj0UMk/S0c-VUJVF4I/AAAAAAAAAP4/ws2OC2-qBVo/s1600-h/ServletResponse.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://4.bp.blogspot.com/_3WReUfj0UMk/S0c-VUJVF4I/AAAAAAAAAP4/ws2OC2-qBVo/s400/ServletResponse.jpg" /></a><br />
</div><div style="text-align: justify;"><b>Sobreescritura de URL’s</b><br />
Esta alternativa permite añadir, dentro de una respuesta, el identificador de sesión en todas las URL’s. De esta manera, cuando el usuario interactúe con el sitio, enviará automáticamente su identificador de sesión como parte de la petición.<br />
Este mecanismo no es tranparente al desarrollador (a diferencia de las cookies). La interface <b>HttpServletResponse </b>provee los métodos:<br />
</div><ul style="text-align: justify;"><li>String <b>encodeURL </b>(String url): Devuelve la url con el identificador de sesión adjuntado.</li>
<li>String <b>encodeRedirectURL </b>(String url): Idem anterior, pero se utiliza junto con el método sendRedirect().<br />
</li>
</ul><i>Ambos métodos verifican si es necesario adjuntar el identificador</i>. Si la petición contiene un encabezado de cookie, entonces las mismas están habilitadas en el browser cliente, y la sobreescritura de la url no es necesaria.<br />
Se debe tener en cuenta que en la URL, el ID de la sesión se agrega luego del carácter ‘;’. Por ejemplo:<br />
http://localhost:8080/scwcd/LoginServlet;jsessionid=1C9B3BAE94BE88AD45AA54B2A8AC0246?user=matias<br />
Esto se debe a que <i>jsessionid es parte del path info de la petición, y no es un parámetro de la misma</i>. Este valor NO puede ser accedido a través del método HttpServletRequest.getParameter(“jsessionid”).<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/_3WReUfj0UMk/S0c-caLI-LI/AAAAAAAAAQA/jmDPGlBAhg8/s1600-h/HttpSession_Listeners.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/_3WReUfj0UMk/S0c-caLI-LI/AAAAAAAAAQA/jmDPGlBAhg8/s400/HttpSession_Listeners.jpg" /></a><br />
</div>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com0tag:blogger.com,1999:blog-5081968900413627331.post-26489406641054468532010-01-04T10:51:00.000-03:002010-01-04T10:51:30.705-03:00The Web Container Model - Filters (SCWCD)<div style="text-align: justify;"><span style="font-weight: bold;">Objetivos: <br />
</span><br />
</div><div style="text-align: justify;"><span style="font-weight: bold;">Section 3: The Web Container Model (FILTERS)<br />
</span><br />
</div><div style="text-align: justify;"><div style="text-align: justify;"><span style="font-weight: bold;">3.3- </span>Describe the Web container request processing model; write and configure a filter; create a request or response wrapper; and given a design problem, describe how to apply a filter or a wrapper.<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><a href="http://onj2ee.blogspot.com/2009/12/objetivos-scwcd-cx-310-083.html">Ver todos los objetivos de SCWCD</a><br />
</div><div style="text-align: justify;"><br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://3.bp.blogspot.com/_3WReUfj0UMk/S0HvAfiasSI/AAAAAAAAAPQ/c4ZpiKmoTE0/s1600-h/Filter_Grafico.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://3.bp.blogspot.com/_3WReUfj0UMk/S0HvAfiasSI/AAAAAAAAAPQ/c4ZpiKmoTE0/s400/Filter_Grafico.jpg" /></a><br />
</div><div style="text-align: justify;"><b>Que es un filtro (filter)?</b><br />
</div><div style="text-align: justify;">Para una aplicación web, un filtro es un componente web el cuál <i><b>“filtra” las peticiones y respuestas que se realizan entre en cliente y el servidor</b></i>. Estos filtros permiten monitorear los mensajes enviados antes de que los mismos alcancen su destino. <i>La existencia de un filtro es transparente tanto al cliente como también al recurso</i> (como puede ser un servlet).<br />
</div><div style="text-align: justify;">También se puede emplear una cadena de filtros, en la cual los filtros se ejecutan uno seguido de otro (en cadena). Un filtro permite procesar una petición y pasarla (la petición procesada) al siguiente filtro de la cadena. Similarmente, cada filtro se ejecutará en orden inverso procesando la respuesta antes de que sea devuelta al cliente.<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Como trabaja la filtración</b><br />
</div><div style="text-align: justify;">Cuando el contenedor de servlets recibe una petición a un recurso, se verifica la existencia de filtros asociados al recurso. <i>Si existe algún filtro asociado, el contenedor dirige la petición al filtro en vez de al recurso.</i> Luego de que el filtro procesa la petición, realiza una de las siguientes acciones:<br />
</div><ul style="text-align: justify;"><li>Genera la respuesta, por el mismo, y se la retorna al cliente.</li>
<li>Pasa la petición (modificada o no) al siguiente filtro de la cadena (si existe) o al recurso.</li>
<li>Dirige la petición a un recurso diferente.<br />
</li>
</ul><div style="text-align: justify;"><i>Cuando se devuelve la respuesta desde el recurso, esta atraviesa el mismo conjunto de filtros en orden inverso.</i> Cada filtro en la cadena puede modificar la respuesta.<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>La API de filtros (Filter API)</b><br />
</div><div style="text-align: justify;">Interfaces del paquete javax.servlet:<br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://3.bp.blogspot.com/_3WReUfj0UMk/S0HvtvGxE3I/AAAAAAAAAPY/MNYZQ0eSFe4/s1600-h/Filter.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://3.bp.blogspot.com/_3WReUfj0UMk/S0HvtvGxE3I/AAAAAAAAAPY/MNYZQ0eSFe4/s400/Filter.jpg" /></a><br />
</div><div style="text-align: justify;"><b>javax.servlet.Filter</b>: Todos los filtros deben implementar esta interface. Define tres métodos:<br />
</div><ul style="text-align: justify;"><li>void <b>init </b>(FilterConfig) throws ServletException: El contenedor de servlets invoca este método sobre una instancia solo una vez. <i>La implementación típica de este método es almacenar la instancia FilterConfig</i>, para luego ser utilizada. Este método es <b>una analogía </b>del método <b>init(ServletConfig)</b> de la interface Servlet.</li>
<li>void <b>doFilter </b>(ServletRequest, ServletResponse, FilterChain) throws ServletException, IOException: El contenedor de servlets invoca este método para cada petición que sea mapeada con un filtro. U<i>na implementación típica de una aplicación web, castea las instancias de ServletRequest y ServletResponse a sus correspondientes implementaciones del protocolo http</i>, para luego realizar el procesamiento por el cual se creó el filtro. Este método es <b>una analogía </b>del método <b>service(ServletRequest, ServletResponse) </b>de la interface Servlet.</li>
<li>void <b>destroy </b>(): El contenedor de servlets invoca este método para liberar los recursos del filtro y realizar tareas de limpieza, antes de que el mismo sea eliminado.<br />
</li>
</ul><div class="separator" style="clear: both; text-align: justify;"><a href="http://1.bp.blogspot.com/_3WReUfj0UMk/S0HwCY8MwII/AAAAAAAAAPg/ZlCL-oJdFbc/s1600-h/FilterChain.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://1.bp.blogspot.com/_3WReUfj0UMk/S0HwCY8MwII/AAAAAAAAAPg/ZlCL-oJdFbc/s400/FilterChain.jpg" /></a><br />
</div><div style="text-align: justify;"><b>javax.servlet.FilterChain</b>: El contenedor de servlets provee una implementación para esta interface y pasa una instancia de la misma al método doFilter() del filtro. Posee solo un método:<br />
</div><ul style="text-align: justify;"><li>void <b>doFilter </b>(ServletRequest, ServletResponse): Pasa la petición al próximo componente en la cadena, otro filtro o el recurso original.</li>
</ul><div class="separator" style="clear: both; text-align: justify;"><a href="http://2.bp.blogspot.com/_3WReUfj0UMk/S0HwKS-9zZI/AAAAAAAAAPo/1y0fieaXoqU/s1600-h/FilterConfig.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://2.bp.blogspot.com/_3WReUfj0UMk/S0HwKS-9zZI/AAAAAAAAAPo/1y0fieaXoqU/s400/FilterConfig.jpg" /></a><br />
</div><div style="text-align: justify;"><b>javax.servlet.FilterConfig</b>: El contenedor de servlets provee una implementación para esta interface. Al igual que ServletConfig, la instancia se pasa a través del método init(FilterConfig). Esta interface provee métodos para acceder a los parámetros de inicialización de un filtro, y algunos otros datos:<br />
</div><ul><li style="text-align: justify;">String <b>getFilterName </b>(): Devuelve el nombre del filtro especificado en el archivo web.xml.</li>
<li style="text-align: justify;">String <b>getInitParameter </b>(String): Devuelve el valor del parámetro especificado en el archivo web.xml.</li>
<li style="text-align: justify;">Enumeration <b>getInitParameterNames </b>(): Devuelve una instancia Enumeration con los nombres de los parámetros de inicialización definidos en el archivo web.xml.</li>
<li style="text-align: justify;">ServletContext <b>getServletContext </b>(): Devuelve la instancia de ServletContext asociada a la aplicación web.</li>
</ul><div style="text-align: justify;"><b>Clases del paquete javax.servlet:</b><br />
</div><ul style="text-align: justify;"><li>javax.servlet.ServletRequestWrapper</li>
<li>javax.servlet.ServletResponseWrapper<br />
</li>
</ul><div style="text-align: justify;"><b>Clases del paquete javax.servlet.http:</b><br />
</div><ul style="text-align: justify;"><li>javax.servlet.http.HttpServletRequestWapper</li>
<li>javax.servlet.http.HttpServletResponseWrapper<br />
</li>
</ul><div style="text-align: justify;">Estas últimas cuatro clases wrappers, funcionan de la misma manera. <i>Toman una petición o una respuesta </i>(ServletRequest o ServletResponse) <i>en su constructor y delegan todas las invocaciones de métodos a ese objeto</i>. <i>Esto permite extender estas clases y <b>sobrescribir cualquier método para personalizar un comportamiento</b>.</i><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Configurar un filtro</b><br />
</div><div style="text-align: justify;">Para definir un filtro en el archivo web.xml, se debe utilizar los elementos <b><filter></b> y <b><filter-mapping></b>. <br />
</div><div style="text-align: justify;"><!ELEMENT <b>filter </b>(icon?, filter-name, display-name?, description?, filter-class, init-param*) ><br />
</div><div style="text-align: justify;"><!ELEMENT <b>filter-mapping </b>(filter-name, (url-pattern | servlet-name)) ><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b><filter></b>: Cada elemento de este tipo, introduce un nuevo filtro en la aplicación web. Este elemento puede contener varios elementos más. Algunos opcionales como: <icon>, <display-name> y <init-param>. Otros obligatorios como:<br />
</div><ul style="text-align: justify;"><li><b><filter-name></b>: Define el nombre del filtro dentro del archivo de configuración.</li>
<li><b><filter-class></b>: Define la clase utilizada para instanciar el filtro.</li>
</ul><div style="text-align: justify;"><b><filter-mapping></b>: Al igual que <b><servlet-mapping></b>, este elemento asocia un filtro con un conjunto de URLs. Contiene los elementos:<br />
</div></div><div style="text-align: justify;"><ul style="text-align: justify;"><li><b><filter-name></b>: Identifica el filtro a asociar.</li>
<li><b><url-pattern></b>: Se utiliza para aplicar el filtro a las peticiones que concuerden con el patrón URL.</li>
<li><b><servlet-name></b>: Se utiliza para aplicar el filtro a todas las peticiones que se realicen al servlet asociado.<br />
</li>
</ul><div style="text-align: justify;"><i><b>Solo puede existir un subelemento <url-pattern> o <servlet-name>, dentro un mismo <filter-mapping>.</b></i><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Configurando cadenas de filtros</b><br />
</div><div style="text-align: justify;">Las <b>cadenas de filtros</b> pueden ser configuradas utilizando <b>múltiples </b>elementos <b><filter-mapping></b>. Cuando el contenedor de servlets recibe una petición, este busca todos los mapeos de filtros que concuerdan la URI con el patrón URL. Este se considera el <b>primer conjunto de filtros </b>a aplicar al recurso. Luego, se buscan todos los mapeos de filtros con el nombre del servlet correspondiente. Este se convierte en el <b>segundo conjunto de filtros</b> en la cadena de filtros. <b><i>En ambos conjuntos, el orden de los filtros se corresponde al orden de declaración de los mismos en el archivo web.xml.</i></b><br />
</div><div style="text-align: justify;"><i><b>El contenedor primero invoca a los filtros del primer conjunto antes que los del segundo.</b></i> <br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Ejecución de filtros</b><br />
</div><div style="text-align: justify;">Como la especificación de Servlets 2.4 permite invocar servlets de las siguientes maneras:<br />
</div><ul style="text-align: justify;"><li>Como un resultado del método <b>RequestDispatcher.forward</b>().</li>
<li>Como un resultado del método <b>RequestDispatcher.include</b>().</li>
<li>En páginas de error.<br />
</li>
</ul><div style="text-align: justify;"><i><b>Un filtro solo es invocado con peticiones entrantes (desde el cliente).</b></i> Pero el archivo web.xml permite especificar los modos de invocación de un filtro:<br />
</div><pre class="brush: xml;" id="sourceCode" name="sourceCode"><filter-mapping>
<filter-name>AccessLog</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
</pre><ul><li style="text-align: justify;">El elemento <filter-name> es obligatorio.</li>
<li style="text-align: justify;">Se debe usar un elemento <url-pattern> o <servlet-name>, no se pueden usar ambos dentro de un mismo elemento <filter-mapping>.</li>
<li style="text-align: justify;">Se pueden usar de 0 a 4 subelementos <dispatcher> dentro de un elemento <filter-mapping>.</li>
<li style="text-align: justify;">Por defecto (si no se especifica ningún subelemento <dispatcher>) <i><b>los filtros solo se aplican </b></i>para peticiones entrantes a la aplicación. Es decir, solo el valor <i><b>REQUEST es aplicado por defecto</b></i>. </li>
<li style="text-align: justify;"><i><b>Si el contenedor no puede encontrar el recurso solicitado por una petición, ningún filtro correspondiente a la misma se invoca. Los filtros solo se invocan si existe el recurso original.</b></i><br />
</li>
</ul></div>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com1tag:blogger.com,1999:blog-5081968900413627331.post-70392817110965289372009-12-30T13:29:00.001-03:002010-01-04T10:30:44.889-03:00The Web Container Model (SCWCD)<div style="text-align: justify;"><span style="font-weight: bold;">Objetivos: <br />
</span><br />
</div><div style="text-align: justify;"><span style="font-weight: bold;">Section 3: The Web Container Model</span><br />
</div><div style="text-align: justify;"><span style="font-weight: bold;">3.1- </span>For the ServletContext initialization parameters: write servlet code to access initialization parameters; and create the deployment descriptor elements for declaring initialization parameters.<br />
</div><div style="text-align: justify;"><span style="font-weight: bold;">3.2- </span>For the fundamental servlet attribute scopes (request, session, and context): write servlet code to add, retrieve, and remove attributes; given a usage scenario, identify the proper scope for an attribute; and identify multi-threading issues associated with each scope.<br />
</div><div style="text-align: justify;"><span style="font-weight: bold;"></span><br />
</div><div style="text-align: justify;"><span style="font-weight: bold;">3.4- </span>Describe the Web container life cycle event model for requests, sessions, and web applications;create and configure listener classes for each scope life cycle; create and configure scope attribute listener classes; and given a scenario, identify the proper attribute listener to use.<br />
</div><div style="text-align: justify;"><span style="font-weight: bold;">3.5- </span>Describe the RequestDispatcher mechanism; write servlet code to create a request dispatcher; write servlet code to forward or include the target resource; and identify and describe the additional request-scoped attributes provided by the container to the target resource.<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><a href="http://onj2ee.blogspot.com/2009/12/objetivos-scwcd-cx-310-083.html">Ver todos los objetivos de SCWCD </a> <br />
</div><div style="text-align: justify;"><br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://4.bp.blogspot.com/_3WReUfj0UMk/Szt72NpS8EI/AAAAAAAAAO4/HQ25w9aqqlg/s1600-h/ServletContext.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://4.bp.blogspot.com/_3WReUfj0UMk/Szt72NpS8EI/AAAAAAAAAO4/HQ25w9aqqlg/s320/ServletContext.jpg" /></a><br />
</div><div style="text-align: justify;"><b>Inicializando el objeto ServletContext</b><br />
</div><div style="text-align: justify;">Toda aplicación web tiene una instancia de javax.servlet.ServletContext. <i>El contexto es inicializado en el momento que la aplicación es cargada</i>. Existen parámetros de inicialización del contexto, los cuales se definen en el archivo web.xml dentro del elemento <b><context-param></b>. Cada parámetro de inicialización tiene los elementos <b><param-name></b> y <b><param-value></b>.<br />
</div><div style="text-align: justify;">La interface <b>ServletContext </b>permite a los servlets obtener los parámetros de inicialización (<b>del contexto</b>) a través de dos métodos:<br />
</div><ul style="text-align: justify;"><li>String <b>getInitParameter </b>(String name): Devuelve un String que contiene el valor del parámetro, devuelve null si el parámetro no existe.</li>
<li>java.util.Enumeration <b>getInitParameterNames </b>(): Devuelve un objeto Enumeration con los valores de los parámetros.<br />
</li>
</ul><div style="text-align: justify;">Para utilizar estos métodos, primero se debe obtener la instancia del objeto ServletContext. Este objeto esta contenido dentro de <b>ServletConfig</b>. Debido a esto, desde un servlet, <i>existen dos formas de obtener el objeto ServletContext</i>:<br />
</div><ul style="text-align: justify;"><li>getServletConfig().getServletContext()</li>
<li>getServletContext(): Debido a que GenericServlet implementa la interface ServletConfig.<br />
</li>
</ul><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Utilizando Listeners</b><br />
</div><div style="text-align: justify;">La especificación de servlets provee interfaces de listeners. Estas, reciben notificaciones cuando se producen eventos relacionados a la aplicación web. Para responder a estas notificaciones, se deben crear clases que implementen dichas interfaces, y especificar el nombre de la clase en el archivo web.xml. Entonces, el contenedor de servlets puede invocar los métodos apropiados sobre objetos de estas clases, cuando se producen los eventos.<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Agregando y quitando atributos</b><br />
</div><div style="text-align: justify;">Se pueden agregar atributos a los objetos de contexto (<b>ServletContext</b>), objetos de sesión (<b>HttpSession</b>) y objetos de petición (<b>ServletRequest</b>). Cada una de estas clases, contiene los mismos cuatro métodos para realizar las operaciones sobre los atributos:<br />
</div><ul style="text-align: justify;"><li>Object <b>getAttribute </b>(String name): Devuelve el objeto asociado con el nombre pasado como parámetro.</li>
<li>Enumeration <b>getAttributeNames </b>(): Devuelve un objeto Enumeration con los nombres de los atributos.</li>
<li>void <b>setAttribute </b>(String name, Object value): Asocia un objeto con el ámbito actual y lo identifica a través del nombre especificado.</li>
<li>void <b>removeAttribute </b>(String name): Elimina el atributo del ámbito.<br />
</li>
</ul><div style="text-align: justify;">Se debe tener en cuenta tres puntos importantes:<br />
</div><ul style="text-align: justify;"><li>Los atributos del objeto ServletRequest se resetean luego de cada petición, pero los atributos de sesión están disponibles para cualquier servlet que reciba una petición como parte de la sesión.</li>
<li>Cualquier atributo asociado con el contexto está disponible en todos los servlets de la aplicación.</li>
<li>Solo se puede asociar un atributo con un nombre.<br />
</li>
</ul><div style="text-align: justify;"><b>Escuchando los eventos sobre los atributos</b><br />
</div><div style="text-align: justify;">Cada ámbito (contexto, sesión y petición) provee diferentes eventos y listeners para realizar un seguimiento de sus atributos:<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Petición</b>: Para responder a los eventos de atributos de petición, se debe crear una clase que implemente la interface <b>ServletRequestAttributeListener</b>. Dicha interface provee los métodos:<br />
</div><ul style="text-align: justify;"><li>void <b>attributeAdded </b>(ServletRequestAttributeEvent ser): Invocado cuando se agrega un atributo.</li>
<li>void <b>attributeRemoved </b>(ServletRequestAttributeEvent ser): Invocado cuando se elimina un atributo.</li>
<li>void <b>attributeReplaced </b>(ServletRequestAttributeEvent ser): Invocado cuando se reemplaza un atributo.<br />
</li>
</ul><div style="text-align: justify;"><b>Sesión</b>: Para responder a los eventos de atributos de sesión existen tres interfaces: <b>HttpSessionAttributeListener</b>, <b>HttpSessionBindingListener </b>y <b>HttpSessionActivationListener</b>.<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Contexto</b>: Para recibir las notificaciones sobre los cambios en los atributos del contexto de una aplicación, se debe crear una clase que implemente la interface <b>ServletContextAttributeListener</b>, la cual provee los siguientes métodos:<br />
</div><ul style="text-align: justify;"><li>void <b>attributeAdded </b>(ServletContextAttributeEvent scae): Invocado cuando se agrega un nuevo atributo.</li>
<li>void <b>attributeRemoved </b>(ServletContextAttributeEvent scae): Invocado cuando se elimina un atributo.</li>
<li>void <b>attributeReplaced </b>(ServletContextAttributeEvent scae): Invocado cuando se reemplaza un atributo.</li>
</ul><div style="text-align: justify;"><b>Eventos y listeners del ciclo de vida de servlets</b><br />
</div><div style="text-align: justify;">La Servlet Specification 2.4 define tres interfaces para hacer esto posible:<br />
</div><div style="text-align: justify;"><b>javax.servlet.ServletContextListener</b>: Permite conocer cuando el servlet context se inicializa o se destruye:<br />
</div><ul style="text-align: justify;"><li>void <b>contextDestroyed </b>(ServletContextEvent sce): Invocado cuando se destuye el contexto.</li>
<li>void <b>contextInitialized </b>(ServletContextEvent sce): Invocado cuando se inicializa el contexto.<br />
</li>
</ul><div style="text-align: justify;"><b>javax.servlet.http.HttpSessionListener</b>: Esta interface contiene los mismos métodos y capacidades que ServletContextListener, pero provee notificaciones cuando se crea o destruye una sesión.<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>javax.servlet.http.HttpServletRequestListener</b>: Permite conocer cuando una petición se inicializa o se destruye:<br />
</div><ul><li style="text-align: justify;">void <b>requestDestroyed </b>(ServletRequestEvent sre): Invocado cuando se destruye una petición.</li>
<li style="text-align: justify;">void <b>requestInitialized </b>(ServletRequestEvent sre): Invocado cuando se inicializa una petición. </li>
</ul><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/_3WReUfj0UMk/Szt-UHuPyhI/AAAAAAAAAPA/UgHGJkGzLYw/s1600-h/ServletContext_Listeners.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/_3WReUfj0UMk/Szt-UHuPyhI/AAAAAAAAAPA/UgHGJkGzLYw/s400/ServletContext_Listeners.jpg" /></a><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/_3WReUfj0UMk/Szt-YubGbBI/AAAAAAAAAPI/4CcK0IQUCX8/s1600-h/ServletRequest_Listeners.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/_3WReUfj0UMk/Szt-YubGbBI/AAAAAAAAAPI/4CcK0IQUCX8/s400/ServletRequest_Listeners.jpg" /></a><br />
</div><br />
<div style="text-align: justify;"><b>Agregando listeners en el archivo web.xml</b><br />
</div><div style="text-align: justify;">El archivo de configuración posee el elemento <b><listener></b>. Dicho elemento especifica las clases que escuchan a los eventos de la aplicación. <i><b>Cada elemento <listener> posee uno y solo un elemento <listener-class></b></i>. El mismo contiene el nombre completo (incluido el paquete al que pertenece) de la clase que implementa alguna (o varias) interface listener.<br />
</div><pre class="brush: xml;" id="sourceCode" name="sourceCode"><listener>
<listener-class>
com.abc.MyServletContextListener
</listener-class>
</listener>
</pre><div style="text-align: justify;">En el archivo web.xml, no se especifica que clase tiene que ser utilizada para cada evento. <i>El contenedor de servlets es el encargado de revisar cada una de las clases, viendo cada una de las interfaces que implementa, y agregando una instancia a una lista de listeners.</i><br />
Se pueden implementar múltiples interfaces listeners en la misma clase. En este caso, se necesita solo un elemento <listener> en el archivo de configuración. El contenedor de servlets creará solo una instancia de la clase y enviará todas las notificaciones a esta instancia.<br />
</div><div style="text-align: justify;"><i><b>Los listeners de tipo HttpSessionBindingListener no se deben especificar en el archivo web.xml.</b></i><br />
<br />
<b>Archivo web.xml</b><br />
<!ELEMENT <b>web-app</b> <br />
(icon?, display-name?, description?, distributable?, context-param*, filter*, filter-mapping*, listener*, servlet*, servlet-mapping*, session-config?, mime-mapping*, welcome-file-list?, error-page*, taglib*, resource-env-ref*, resource-ref*, security-constraint*, login-config?, security-role*, env-entry*, ejb-ref*, ejb-local-ref*)><br />
<br />
<b>Objetos contenedores thread-safe</b><br />
Los contenedores <b><i>ServletContext y HttpSession no son Thread-safe</i></b>. Es decir, cuando se quiera manipular los atributos de estos contenedores es necesario sincronizar este código. De esta manera, antes de comenzar a realizar acciones como agregar, reemplazar o eliminar un atributo, se debe obtener la cerradura (lock) del contenedor para que ningún otro servlet pueda realizar estas acciones al mismo tiempo. Esta es la única manera de hacer que estos contenedores sean thread-safe. Otros modos como sincronizar el método service() (o algún otro método de servicio), o implementar la interface SingleThreadModel, no son utilizados porque solo permiten la ejecución de un solo thread sobre una instancia de un servlet. Lo cual, son técnicas que perjudican la performance de las respuestas.<br />
</div>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com0tag:blogger.com,1999:blog-5081968900413627331.post-71442351679214460582009-12-15T15:06:00.001-03:002009-12-15T15:08:37.146-03:00Sun liberó Java EE 6, Glassfish v3 y NetBeans 6.8<blockquote><div style="text-align: justify;">Java Enterprise Edition 6 (Java EE 6) era muy esperado y se liberó apenas se consiguió la aprobación de su especificación. <b>Junto con Java EE 6 llega Glassfish v3, el primer servidor ajustado a EE 6 y también llega el IDE (Integrated Development Environment) NetBeans 6.8, que también soporta a Java EE 6 completamente.</b><br />
Según Kevin Schmidt, director de productos y marketing en la unidad Application Platforms de Sun, destacó que “<b>Java EE 6 incorpora nuevos servicios como RESTful Web Services, inyección de dependencia y anotaciones agregadas para servlets, reduciendo así la cantidad de código que hay que escribir</b>.” Con la incorporación de Profiles, Java EE 6 es más extensible porque <b>los desarrolladores pueden apoyarse sólo en las partes de Java EE 6 necesarias para una aplicación determinada en lugar de usar toda la plataforma.</b> Por ejemplo, una tarea que requería 20 líneas de código distribuidas en varios archivos fuente, ahora se puede hacer con dos líneas de código en un mismo archivo fuente. El mismo criterio se utiliza en el armado de las aplicaciones, <b>reduciendo la cantidad de archivos requeridos para una aplicación empresarial</b>, lo cual abrevia notablemente el proceso de desarrollo en ciertas tareas.<br />
Si bien algunos miembros de JCP (Java Community Process) no gustan de la forma en que se completó Java EE 6, <b>es un proyecto en el que participaron 2700 personas (en el proceso JCP) y la especificación se completó satisfactoriamente.<br />
</b>Respecto a NetBeans 6.8, este IDE ahora tiene soporte completo a Java EE 6 y se pueden desarrollar aplicaciones para servidores de middleware que cumplen con Java EE . Este release tiene mayor soporte a PHP, como ocurrió con la versión 6.7. <b>Si bien NetBeans es principalmente un IDE Java, Sun ha ganado espacio en PHP y NetBeans 6.8 incluye soporte a PHP 5.3.<br />
</b>En cuanto a Glassfish v3, es el primer servidor de aplicaciones conforme a Java EE 6 y eso significa que aprobó el Java EE 6 Test Compatibility Kit. La versión anterior<b> Glassfish v3 Prelude, liberada en noviembre 2008 era, según Schmidt, un release que entregaba una plataforma modular para las tecnologías Web Java EE 5 en un runtime OSGi </b>(por OSGi Alliance, antes Open Services Gateway initiative). También tenía acceso temprano a algunas tecnologías Java EE 6 para que los desarrolladores las fueran probando y así acelerar la futura adopción. <br />
La versión Prelude sirvió para tener feedback y perfeccionar a <b>GlassFish v3, que es totalmente ajustado a Java EE 6, tiene runtime OSGi y el nuevo Java EE 6 Web Profile.<br />
Java EE 6 sigue siendo compatible retroactivamente</b>, como todas las versiones Java EE y tiene su correspondiente kit de prueba de compatibilidad. La suite de prueba tiene más de 60.000 tests para confirmar esa compatibilidad retroactiva.<br />
</div></blockquote><br />
<i><b>"Noticias del mundo de SUN"</b>, extraido de un email enviado por <a href="http://osum.sun.com/profile/EzeSinger">Ezequiel Singer</a>.</i><br />
Buenas noticias para la plataforma J2EE, ni bien termine de rendir la certificación SCWCD, me sumergiré en el mundo de Java EE 6.<br />
SaludosMatías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com1tag:blogger.com,1999:blog-5081968900413627331.post-7031154285623499572009-12-14T15:58:00.003-03:002009-12-14T16:11:14.868-03:00The Structure and Deployment of Web Applications (SCWCD)<div style="text-align: justify;"><span style="font-weight: bold;">Objetivos:</span><br />
<span style="font-weight: bold;">Section 2: The Structure and Deployment of Web Applications</span><br />
<span style="font-weight: bold;">2.1- </span>Construct the file and directory structure of a Web Application that may contain (a) static content, (b) JSP pages, (c) servlet classes, (d) the deployment descriptor, (e) tag libraries, (d) JAR files, and (e) Java class files; and describe how to protect resource files from HTTP access.<br />
<span style="font-weight: bold;">2.2- </span>Describe the purpose and semantics of the deployment descriptor.<br />
<span style="font-weight: bold;">2.3- </span>Construct the correct structure of the deployment descriptor.<br />
<span style="font-weight: bold;">2.4- </span>Explain the purpose of a WAR file and describe the contents of a WAR file, how one may be constructed.<br />
</div><div style="text-align: justify;"><br />
</div><a href="http://onj2ee.blogspot.com/2009/12/objetivos-scwcd-cx-310-083.html">Ver todos los objetivos de SCWCD </a><br />
<br />
<div style="text-align: justify;"><b>La estructura de directorios de una aplicación web</b><br />
</div><div style="text-align: justify;"><i>La especificación de Servlets de java determina la manera en que una aplicación web debe ser almacenada.</i> Es decir, <b><i>se define una estructura de directorios</i></b> para almacenar los recursos y archivos de una aplicación web.<br />
</div><div style="text-align: justify;">El servidor Tomcat posee un directorio llamado webapps, el cuál contiene todas las aplicaciones web alojadas en el servidor. Cada directorio contenido representa una aplicación, la estructura de directorios de cada aplicación esta estandarizada por la especificación de Servlets:<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>WEB-INF</b>: Almacena información necesaria para que el contenedor de servlets pueda iniciar la aplicación web. <i>Este directorio no es accesible por el cliente, pero si por la aplicación.</i> Contiene tres elementos:<br />
</div><ul style="text-align: justify;"><li><b>classes </b>(directorio): Almacena los <i>archivos class de servlets y archivos class comunes</i> necesarios para dar soporte a los servlets o JSP’s , si los mismos no están incluidos en un archivo JAR. Los archivos class se encuentran organizados acorde a sus paquetes. <i>En tiempo de ejecución, el contenedor de servlets agrega este directorio al classpath de la aplicación web.</i> </li>
<li><b>lib</b> (directorio): <i>Almacena todos los archivos <b>JAR</b></i><b> </b>utilizados por la aplicación, tanto de terceras partes como propios. <i>En tiempo de ejecución, el contenedor de servlets agrega todos los archivos JAR de este directorio al classpath de la aplicación web.</i> </li>
<li><b>web.xml</b>: Es el archivo de configuración de la aplicación (o descriptor de despliegue). Todas las aplicaciones web deben tenerlo. Contiene las declaraciones de los servlets y mapeos, propiedades, autorizaciones y restricciones de seguridad.<br />
</li>
</ul><div style="text-align: justify;"><i><b>Cuando se importa una clase, el contenedor primero intenta ubicarla dentro del directorio classes, en caso de no hallarla, se busca la definición de la misma dentro de algún archivo JAR del directorio lib.</b></i><br />
</div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/_3WReUfj0UMk/SyaFoQ6sgwI/AAAAAAAAAOo/eETi4ST45bU/s1600-h/WarStructure2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/_3WReUfj0UMk/SyaFoQ6sgwI/AAAAAAAAAOo/eETi4ST45bU/s640/WarStructure2.jpg" /></a><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/_3WReUfj0UMk/SyaGrRY4UwI/AAAAAAAAAOw/hSN94WFS9l8/s1600-h/WarStructure.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://2.bp.blogspot.com/_3WReUfj0UMk/SyaGrRY4UwI/AAAAAAAAAOw/hSN94WFS9l8/s320/WarStructure.jpg" /></a><br />
</div><div style="text-align: justify;"><b>El archivo web (WAR)</b><br />
</div><div style="text-align: justify;">Los archivos y recursos de una aplicación web pueden ser empaquetados dentro de un archivo JAR, a diferencia que el archivo debe tener la extensión .war en lugar de .jar. La extensión .war viene de las siglas <b>W</b>eb <b>AR</b>chive, y significa que el archivo deberá ser tratado de diferente manera que un archivo JAR. <i>El contenedor de servlets puede instalar el archivo WAR de una aplicación web sin una intervención manual.</i><br />
</div><div style="text-align: justify;">Dentro del archivo WAR, se crea un directorio llamado <b>META-INF</b>. Dicho directorio contiene el archivo <i><b>MANIFEST.MF, el cual permite declarar dependencias con librerías y clases</b></i>. Es decir, brinda un chequeo en tiempo de despliegue (deploy-time) para que el contenedor pueda verificar las librerías y clases que se necesitan para ejecutar la aplicación web correctamente. Esto permite que no sea necesario esperar hasta que un recurso sea solicitado, para verificar que existan todos los componentes de los que depende la aplicación.<br />
</div><br />
<div style="text-align: justify;"><b>La aplicación web por defecto (default web application)</b><br />
</div><div style="text-align: justify;">Junto a las aplicaciones web creadas por los usuarios, <i>el contenedor de servlets contiene una aplicación web por defecto</i>. Esta aplicación maneja todas las peticiones que no concuerdan con ninguna aplicación del usuario. En el servidor <b>Tomcat</b>, esta aplicación por defecto se encuentra dentro del directorio <i>webapps/ROOT</i>.<br />
</div><div style="text-align: justify;"><i>Esta aplicación web por defecto permite ejecutar JSP’s y servlets individuales</i>, como también contenido estático, sin empaquetarlos en una aplicación separada.<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>El archivo descriptor de despliegue web.xml (deployment descriptor file)</b><br />
</div><div style="text-align: justify;">El archivo <b>web.xml</b>, es un típico archivo XML que comienza con la línea: <?xml version="1.0" encoding="ISO-5589-1"><br />
</div><div style="text-align: justify;">Dicha línea especifica la versión de XML y el juego de caracteres que se utilizará en el archivo. La línea siguiente depende de la versión de especificación Servlet o JSP que se utilice.<br />
</div><div style="text-align: justify;">Nodos del archivo de configuración:<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><!ELEMENT <b>servlet</b> (icon?, <b>servlet-name</b>, display-name?, description?, <b>(servlet-class|jsp-file)</b>, init-param*, load-on-startup?, load-on-startup?, security-role-ref*) ><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><!ELEMENT <b>servlet-mapping</b> (servlet-name, url-pattern) ><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b><web-app></b><b><web-app></web-app></b>: Nodo raíz del archivo.<br />
</div><ul style="text-align: justify;"><li><b><servlet></servlet><servlet></b>: Define un servlet para una aplicación web.<br />
- <servlet-name><servlet-name>: <i>Define el nombre del servlet</i>. Este elemento es obligatorio, y el nombre del servlet <i>debe ser único en todo el archivo</i>. Desde la aplicación, el nombre del servlet se puede obtener a través del método javax.servlet.<b>ServletConfig.getServletName</b>(). Este nombre también se utiliza para definir el mapeo del servlet a una URL.<br />
- </servlet-name><b><servlet-class></b><servlet-name><b><servlet-class></servlet-class></b>: <i>Define el nombre de la clase utilizada por el contenedor de servlets para instanciar el servlet</i>. Este elemento es obligatorio. Esta clase, como todas las clases de las que dependa, deben estar disponibles desde el classpath de la aplicación web.<br />
- <b><init-param></init-param></b></servlet-name><b><init-param></b><servlet-name>: Este <i>elemento</i> es <i>utilizado para crear parámetros de inicialización del servlet</i>. No hay un límite en la cantidad de parámetros de un servlet, pero cada uno debe contener:<br />
* <b><param-name></param-name></b></servlet-name><b><param-name></b><servlet-name>: Contiene el nombre del parámetro de inicialización.<br />
* <b><param-value></param-value></b></servlet-name><b><param-value></b><servlet-name>: Contiene el valor del parámetro de inicialización.<b> </b></servlet-name></li>
<li><b><servlet-mapping></servlet-mapping><servlet-mapping></b>: Especifica que URL debe ser manejada por cada servlet. El contenedor de servlets utiliza el mapeo para invocar el servlet apropiado para una URL. Este elemento debe contener:<br />
- <b><servlet-name></servlet-name><servlet-name></b>: Contiene el nombre del servlet.<br />
- <b><url-pattern></url-pattern><url-pattern></b>: Contiene la cadena de caracteres que se va a asociar al servlet.</li>
<li><b><load-on-startup></load-on-startup><load-on-startup></b>: Permite especificar un número, el cual <i>indica si el servlet debe ser cargado en tiempo de despliegue </i>(deploy-time). Si posee un valor negativo, el servlet se cargará e inicializará al momento en que recibe la primera petición. <i>Si posee un número positivo, se indica al contenedor que inicialice automáticamente al servlet</i>, es decir, cuando el servidor arranca. <b><i>El valor se utiliza para determinar el orden de inicialización de los servlets</i></b>, aquellos servlets que posean un número menor se inicializarán anteriormente a aquellos que poseen números mayores. Si varios servlets poseen el mismo número en este elemento, el contenedor inicializará a los mismos por el orden en que se encuentran declarados en el archivo web.xml.<br />
</li>
</ul><div style="text-align: justify;"><b>Mapeando una URL a un Servlet</b><br />
</div><div style="text-align: justify;">El enrutamiento de una petición a un servlet es un proceso de dos pasos:<br />
</div><ol style="text-align: justify;"><li>El contenedor de servlets identifica la aplicación web a la que pertenece la petición.</li>
<li>Luego se localiza el servlet (perteneciente a la aplicación web) apropiado para manejar la petición.<br />
</li>
</ol><div style="text-align: justify;">Ambos pasos requieren que el contenedor servlets divida la URL de la petición en tres partes:<br />
</div><ul style="text-align: justify;"><li><b>Context path</b> (path de contexto): El contenedor de servlets intenta concordar la mayor parte posible de la URL con el nombre de una aplicación web disponible. Si no existen concordancia, se asocia la petición con la aplicación web por defecto.</li>
<li><b>Servlet path</b>: Luego el contenedor de servlets intenta concordar la mayor parte del resto de la URL con los mapeos de servlets definidos en el archivo web.xml de la aplicación web. Si no se encuentra ninguna concordancia, se retorna una página de error.</li>
<li><b>Path info</b>: Es el resto de información de la URL, es decir, el resto luego de haber determinado el servlet que manejará la petición. En caso de que la URL posea parámetros, el path info es todo el resto de la misma hasta la aparición del primer carácter ‘?’, el cual indica el comienzo de los parámetros.<br />
</li>
</ul><div style="text-align: justify;">La interface javax.servlet.http.<b>HttpServletRequest </b>provee tres métodos para obtener esta información: <b>getContextPath</b>(), <b>getServletPath</b>(), <b>getPathInfo</b>().<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Identificación del servlet path</b><br />
</div><div style="text-align: justify;">Una vez identificado el path de contexto, el contenedor de servlets sigue un algoritmo para determinar el servlet que manejará la petición. Este algoritmo verifica, en ciertos pasos ordenados, la concordancia de la URI con los mapeos de los servlets. Una vez hallada la concordancia el algoritmo finaliza. Los pasos son:<br />
</div><ul style="text-align: justify;"><li>El contenedor intenta coincidir la URI completa. En este caso, el path info es null.</li>
<li>Se intenta coincidir la URI recursivamente a través del separador / quitando elementos de atrás para adelante. Si hay una coincidencia, la parte que concuerda es el servlet path y la parte restante es el path info.</li>
<li>Si el último nodo de la URI contiene una extensión, el contenedor de servlets intenta encontrar un servlet que maneje todas las peticiones con esa extensión. En este caso, la URI completa es el servlet path, y el path info es null.</li>
<li>Si el contenedor sigue sin encontrar una coincidencia, envía la petición al servlet por defecto. Si no existe un servlet por defecto, se devuelve un mensaje de error.<br />
</li>
</ul><div style="text-align: justify;"><b>Especificación de páginas por defecto (o welcome files)</b><br />
</div><div style="text-align: justify;">A través del archivo web.xml se puede especificar las páginas por defecto de una aplicación web. El contenedor utiliza este archivo para todos los directorios de la aplicación. Es decir, no importa que directorio se solicite, el contenedor revisará la misma lista de welcome files especificada. Se devolverá el primer archivo de la lista que exista en el directorio.<br />
</div><div style="text-align: justify;">Se deben tener en cuenta los siguientes puntos, al especificar la lista de páginas por defecto:<br />
</div><ul><li style="text-align: justify;">No se utiliza una barra delante del nombre del archivo.</li>
<li style="text-align: justify;">Todos los archivos (<b><welcome-file></welcome-file><welcome-file></b>) deben estar dentro de un solo elemento <b><welcome-file-list><welcome-file-list></welcome-file-list></b>, es decir, tienen que estar dentro de la misma lista.</li>
</ul><pre class="brush: xml;" id="sourceCode" name="sourceCode"><web-app …>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
</pre><div style="text-align: justify;"><b>Especificación de páginas de error</b><br />
</div><div style="text-align: justify;">A través del web.xml también se pueden especificar las páginas de error por defecto de una aplicación web. Pueden existir diferentes páginas de error dependiendo del tipo de excepción generada, o dependiendo del código de error HTTP. Estas páginas de error se especificación por medio del elemento <b><page-error><page-error></page-error></b>. Puntos a tener en cuenta:<br />
</div><ul><li style="text-align: justify;">Los subelementos <b><exception-type></b> <b><exception-type></exception-type></b> y <b><error-code><error-code></error-code></b> no pueden ser utilizados conjuntamente dentro de un mismo elemento <b><page-error></b><page-error>.</page-error></li>
<li style="text-align: justify;">Se existen varias páginas de error con diferentes <b><exception-type></b><exception-type>, se intentará concordar la excepción generada con una declaración del mismo tipo, o el supertipo más cercano.</exception-type></li>
<li style="text-align: justify;">El atributo pageError de la directiva page (de las páginas JSP), permite sobrescribir la página de error especificada en el web.xml.</li>
</ul>Ejemplos:<br />
<pre class="brush: xml;" id="sourceCode" name="sourceCode"><web-app …>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/errorPageThrowable.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/errorPageException.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>notFoundError.jsp</location>
</error-page>
</web-app>
</pre><div style="text-align: justify;">En este ejemplo, si se produce una excepción de tipo RuntimeException, se ejecutará la página: errorPageThrowable.jsp. Pero si se lanza una excepción comprobada se ejecutará la página: errorPageException.jsp.<br />
</div><br />
<div style="text-align: justify;"><b>Definir referencias a EJB (Enterprise JavaBean)</b><br />
</div><div style="text-align: justify;">Si bien los componentes EJB no están dentro de los objetivos del examen, se debe saber cómo definir referencias a los mismos a través del web.xml. Existen dos tipos de referencias a EJB’s:<br />
</div><br />
Referencia a un <b>bean local</b>: <br />
<pre class="brush: xml;" id="sourceCode" name="sourceCode"><web-app …>
<ejb-local-ref>
<ejb-ref-name>ejb/Customer</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<local-home>com.example.CustomerHome</local-home>
<local>com.example.Customer</local>
</ejb-local-ref>
</web-app>
</pre>Referencia a un <b>bean remoto</b>:<br />
<pre class="brush: xml;" id="sourceCode" name="sourceCode"><web-app …>
<ejb-ref>
<ejb-ref-name>ejb/LocalCustomer</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<home>com.example.CustomerHome</home>
<remote>com.example.Customer</remote>
</ejb-ref>
</web-app>
</pre><div style="text-align: justify;"><b>Definir enviroment entry (JNDI)</b><br />
</div><div style="text-align: justify;">Al igual que la definición de referencias a EJB, para el examen es necesario saber cómo definir estas entradas en el archivo web.xml:<br />
</div><pre class="brush: xml;" id="sourceCode" name="sourceCode"><web-app …>
<env-entry>
<env-entry-name>rates/discountRate</env-entry-name>
<env-entry-type>java.lang.Integer</env-entry-type>
<env-entry-value>10</env-entry-value>
</env-entry>
</web-app>
</pre><div style="text-align: justify;">Se debe tener en cuenta que el elemento <env-entity-type> <env-entity-type> puede contener cualquier tipo que tome un solo String como parámetro en algún constructor, o un simple carácter. El valor debe ser pasado como un String, o un carácter si corresponde al tipo.</env-entity-type><br />
</div><br />
<b>Definir tipos MIME</b><br />
Se pueden configurar mapeos entre una extensión y un tipo MIME en el archivo web.xml: <br />
<pre class="brush: xml;" id="sourceCode" name="sourceCode"><web-app …>
<mime-mapping>
<extension>mpg</extension> <!-- No se debe incluir el punto “.” -->
<mime-type>video/mpeg</mime-type>
</mime-mapping>
</web-app>
</pre>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com0tag:blogger.com,1999:blog-5081968900413627331.post-68621079836421959932009-12-14T12:35:00.000-03:002009-12-14T12:35:06.930-03:00Código - The Servlet Technology Model<b>HttpServletRequest</b><br />
<pre class="brush: java;" id="sourceCode" name="sourceCode">package manning.cap_04;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
public class HeadersParametersServlet extends HttpServlet {
protected void service (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
PrintWriter out = res.getWriter();
String title = "HeadersParametersServlet";
out.println("<html>");
out.println("<head><title>"+title+"</title></head>");
out.println("<body>");
out.println("<h1>"+title+"</h1>");
out.println("<h2>HEADERS</h2>");
Enumeration headers = req.getHeaderNames();
while (headers.hasMoreElements()) {
String header = (String) headers.nextElement();
String value = req.getHeader(header);
out.println("<br> <b>"+header+"</b>: "+value);
}
out.println("<h2>PARAMETERS</h2>");
Enumeration parameters = req.getParameterNames();
while (parameters.hasMoreElements()) {
String parameter = (String) parameters.nextElement();
String value = req.getParameter(parameter);
out.println("<br> <b>"+parameter+"</b>: "+value);
}
out.println("</body>");
out.println("</html>");
}
} </pre><br />
<div style="text-align: justify;">El código anterior es un ejemplo el cuál muestra como iterar a través de los encabezados y parámetros de una petición. Es decir,se utilizan los métodos:<br />
</div><ul style="text-align: justify;"><li>HttpServletRequest.getHeaderNames()</li>
<li>HttpServletRequest.getParameterNames()</li>
</ul><div style="text-align: justify;">Ambos métodos devuelve un objeto Enumeration el cuál contiene todos los nombres de los encabezados y parámetros en la petición.<br />
</div><br />
<b>HttpServletResponse</b><br />
<pre class="brush: java;" id="sourceCode" name="sourceCode">package manning.cap_04;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.io.PrintWriter;
public class UsingHttpServletResponse extends HttpServlet {
public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // Puede ser protected o public
if ("yes".equals(req.getParameter("redirect")))
res.sendRedirect("GetImageServlet");
else if ("post".equals(req.getParameter("redirect")))
doPost(req, res);
res.setHeader("HeaderDePrueba", "valorDelHeader");
res.setIntHeader("IntHeader", 20438);
res.setDateHeader("Last-Modified", 1000000);
res.addHeader("HeaderDePrueba", "OtroValorDelHeader");
PrintWriter out = res.getWriter();
out.println("<h2>HEADERS</h2>");
Enumeration headers = req.getHeaderNames();
while (headers.hasMoreElements()) {
String header = (String) headers.nextElement();
String value = req.getHeader(header);
out.println("<br> <b>"+header+"</b>: "+value);
}
}
protected void doPost (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res.sendError(500, "Error en el servlet creado por Matías Emiliano Alvarez Durán!!!");
}
}
</pre><br />
<div style="text-align: justify;">Este otro ejemplo muestra la utilización del objeto HttpServletResponse. Se utilizan los métodos:<br />
</div><ul style="text-align: justify;"><li>HttpServletResponse.sendRedirect ()</li>
<li>HttpServletResponse.setHeader ()</li>
<li>HttpServletResponse.setIntHeader ()</li>
<li>HttpServletResponse.setDateHeader ()</li>
<li>HttpServletResponse.addHeader () </li>
<li>HttpServletResponse.sendError () <br />
</li>
</ul><div style="text-align: justify;">En la última parte del método doGet(), se itera sobre los headers de la petición para visualizar los valores seteados anteriormente. Es decir, este servlet debe ser invocado dos veces. En la primera invocación se setearan los headers: "HeaderDePrueba", "IntHeader", "Last-Modified" y "HeaderDePrueba", y se visualizarán los headers por defecto. En la segunda, se visualizarán los headers por defecto y los headers seteados por el servlet.<br />
</div><div style="text-align: justify;">En caso de que se realice una petición por el método POST, se devolverá al cliente un error 500 con un mensaje personalizado.<br />
</div><pre class="brush: java;" id="sourceCode" name="sourceCode">package manning.cap_04;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
public class GetImageServlet extends HttpServlet {
protected void service (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res.setContentType("image/jpeg");
File f = new File("../webapps/scwcd/WEB-INF/classes/manning/cap_04/image.jpg"); // Directorio por defecto: /bin del tomcat
byte[] bytearray = new byte[(int) f.length()];
FileInputStream fis = new FileInputStream(f);
fis.read(bytearray);
OutputStream os = res.getOutputStream();
os.write(bytearray);
os.flush();
}
}
</pre><div style="text-align: justify;">Por último, el servlet GetImageServlet, es un ejemplo de utilización del método HttpServletResponse.getOutputStream(). Dicho método retorna un objeto OutputStream, el cuál es utilizado para escribir un arreglo de bytes en el flujo de salida.<br />
</div><div style="text-align: justify;">En este caso, el código escribe los bytes de una imagen en el OutputStream. Una vez finalizada la escritura, se envía la información al cliente a través del método OutputStream.flush().<br />
</div>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com0tag:blogger.com,1999:blog-5081968900413627331.post-29683883729322093042009-12-14T12:01:00.004-03:002009-12-14T15:32:26.553-03:00The Servlet Technology Model (SCWCD)<div style="text-align: justify;"><span style="font-weight: bold;">Objetivos:</span><br />
<span style="font-weight: bold;">Section 1: The Servlet Technology Model</span><br />
</div><div style="text-align: justify;"><span style="font-weight: bold;">1.1- </span>For each of the HTTP Methods (such as GET, POST, HEAD, and so on) describe the purpose of the method and the technical characteristics of the HTTP Method protocol, list triggers that might cause a Client (usually a Web browser) to use the method; and identify the HttpServlet method that corresponds to the HTTP Method.<br />
<span style="font-weight: bold;">1.2- </span>Using the HttpServletRequest interface, write code to retrieve HTML form parameters from the request, retrieve HTTP request header information, or retrieve cookies from the request.<br />
<span style="font-weight: bold;">1.3- </span>Using the HttpServletResponse interface, write code to set an HTTP response header, set the content type of the response, acquire a text stream for the response, acquire a binary stream for the response, redirect an HTTP request to another URL, or add cookies to the response.<br />
<span style="font-weight: bold;">1.4- </span>Describe the purpose and event sequence of the servlet life cycle: (1) servlet class loading, (2) servlet instantiation, (3) call the init method, (4) call the service method, and (5) call destroy method.<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><a href="http://onj2ee.blogspot.com/2009/12/objetivos-scwcd-cx-310-083.html">Ver todos los objetivos de SCWCD </a><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Métodos HTTP</b><br />
</div><ul style="text-align: justify;"><li><b>GET</b>: Se utiliza para obtener recursos activos o pasivos, generalmente para archivos HTML o imágenes.</li>
<li><b>POST</b>: Se utiliza generalmente para enviar grandes cantidades de información, subir archivos binarios, o para enviar nombres de usuarios y contraseñas para que no sean vistas como partes de una URL. La información se envía en el cuerpo de la petición.</li>
<li><b>HEAD</b>: Es similar al método GET, salvo que solo devuelve los encabezados de respuesta y no devuelve ningún mensaje en el cuerpo. Se utiliza generalmente para determinar el estado de un recurso y verificar la fecha de última modificación.</li>
<li><b>TRACE</b>: Se utiliza para ver cuáles son los datos que se están enviando al servidor. De esta manera el cliente puede ver que es lo que envía al otro lado, es útil para realizar pruebas y para la resolución de casos.</li>
<li><b>PUT</b>: Se utiliza para guardar la información adjuntada en el cuerpo de la petición (similar a POST).</li>
<li><b>DELETE</b>: Se utiliza para indicar que se debe eliminar el recurso especificado con la URL.</li>
<li><b>OPTIONS</b>: Permite obtener una lista de los métodos HTTP, los cuales se pueden utilizar para responder a cierto recurso.</li>
<li><b>CONNECT</b>: Se utiliza para propósitos de tunneling (enrutamientos).<br />
</li>
</ul><div style="text-align: justify;"><b>Manejando peticiones HTTP en un HttpServlet</b><br />
Para cada método HTTP, existe un correspondiente método en la clase HttpServlet que tiene la signatura (donde doXXX depende del método HTTP):<br />
protected void doXXX (HttpServletRequest, HttpServletResponse) throws ServletException, IOException;<br />
</div><ul style="text-align: justify;"><li>GET: <b>doGet()</b></li>
<li>POST: <b>doPost()</b></li>
<li>HEAD: <b>doHead()</b></li>
<li>TRACE: <b>doTrace()</b></li>
<li>PUT: <b>doPut()</b></li>
<li>DELETE: <b>doDelete()</b></li>
<li>OPTIONS: <b>doOptions()</b></li>
</ul><div style="text-align: justify;"><b>Flujo de control del contenedor de servlets:</b><br />
</div><ol style="text-align: justify;"><li>El contenedor de servlets invoca el método de HttpServlet: service (<i>ServletRequest</i>, <i>ServletResponse</i>).</li>
<li>El método anterior invoca al método (sobrecargado en la misma clase): service (<i>HttpServletRequest</i>, <i>HttpServletResponse</i>).</li>
<li>El método anterior analiza la petición y dependiendo del método HTTP utilizado invoca el correspondiente método doXXX() del servlet.<br />
</li>
</ol><div style="text-align: justify;"><i>Es aconsejable no sobrescribir el método service()</i>, debido a que se pierde la funcionalidad de la clase HttpServlet. Se recomienda solo sobrescribir los métodos doGet() y doPost().<br />
Muchos de los componentes más importantes de la API de Servlets, incluyen las interfaces HttpServletRequest y HttpServletResponse. Es el contenedor de servlets el que provee las clases que implementan dichas interfaces.<br />
En caso de que se intente realizar una petición a un servlet, el cual no haya sobrescrito el método correspondiente (doGet() o doPost()) se devolverá un error 405 indicando dicha problemática. Es decir, si un servlet solo posee el método doGet(), al mismo solo se podrá acceder a través de este método HTTP y no otro (si se intenta se obtendrá el error 405).<br />
<br />
<b>Analizando las peticiones (javax.servlet.ServletRequest y javax.servlet.HttpServletRequest)</b><br />
Las interfaces ServletRequest y HttpServletRequest permiten analizar una petición. Proveen una vista de la información enviada desde el navegador. La interface ServletRequest provee métodos relevantes para cualquier protocolo, mientras que HttpServletRequest agrega otros específicos para el protocolo HTTP.<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><a href="http://4.bp.blogspot.com/_3WReUfj0UMk/SyZOkovN1JI/AAAAAAAAAOI/AiXoQa2YpBo/s1600-h/ServletRequest.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://4.bp.blogspot.com/_3WReUfj0UMk/SyZOkovN1JI/AAAAAAAAAOI/AiXoQa2YpBo/s400/ServletRequest.jpg" /></a><br />
</div><div style="text-align: justify;">Métodos pertenecientes a la interface <i><b>ServletRequest </b></i>para obtener los parámetros enviados por un cliente:<br />
</div><ul style="text-align: justify;"><li>String <b>getParameter </b>(String paramName): Devuelve el valor asociado al parámetro.</li>
<li>String[] <b>getParameterValues </b>(String paramName): Devuelve un arreglo de todos los valores asociados a un parámetro.</li>
<li>Enumeration <b>getParameterNames </b>(): Devuelve un objeto Enumeration con todos los nombres de los parámetros.<br />
</li>
</ul><div style="text-align: justify;">Métodos de <i><b>HttpServletRequest </b></i>para obtener los encabezados de un request (los headers son específicos del protocolo http):<br />
</div><ul style="text-align: justify;"><li>String <b>getHeader </b>(String headerName): Devuelve el valor asociado al encabezado.</li>
<li>Enumeration <b>getHeaders </b>(String headerName): Devuelve un objeto Enumeration con todos los valores asociados a un encabezado.</li>
<li>Enumeration <b>getHeadersNames </b>(): Devuelve un objeto Enumeration con todos los nombres de los encabezados.<br />
</li>
</ul><div style="text-align: justify;"><b>Enviando las respuestas (javax.servlet.ServletResponse y javax.servlet.http.HttpServletResponse)</b><br />
La interface ServletResponse provee métodos relevantes para cualquier protocolo, mientras que HttpServletResponse agrega otros específicos para el protocolo HTTP. Una instancia de HttpServletResponse funciona como la vía para que el servlet envíe información de vuelta al navegador.<br />
<br />
Métodos de la interface <i><b>ServletResponse</b></i>:<br />
</div><ul style="text-align: justify;"><li>PrintWriter <b>getWriter </b>(): Devuelve un objeto java.io.PrintWriter el cuál puede ser utilizado para enviar caracteres al cliente. Este objeto se utiliza extensivamente en los servlets para generar páginas dinámicas HTML.</li>
<li>ServletOutputStream <b>getOutputStream </b>(): Devuelve un objeto javax.servlet.ServletOutputStream el cual permite enviar archivos binarios al cliente. Dicho objeto hereda de java.io.OutputStream.</li>
<li>void <b>setContentType </b>(String type): Permite especificar el tipo MIME de la información que se devuelve en la respuesta de una petición. También se puede incluir la codificación de caracteres utilizada en la respuesta. Este método se debe invocar antes del método getWriter(), para así obtener un objeto PrintWriter con esta información seteada.<br />
</li>
</ul><div style="text-align: justify;"><a href="http://1.bp.blogspot.com/_3WReUfj0UMk/SyZPydDTayI/AAAAAAAAAOQ/BIxNlCdYUcA/s1600-h/ServletResponse.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/_3WReUfj0UMk/SyZPydDTayI/AAAAAAAAAOQ/BIxNlCdYUcA/s400/ServletResponse.jpg" /></a>Solo uno de los métodos getWriter() y getOutputStream() puede ser invocado en una instancia de un objeto ServletResponse. En caso contrario, la invocación al segundo método lanzará la excepción <b>IllegalStateException</b>.<br />
</div><div style="text-align: justify;"><br />
Existen cuatro capacidades importantes de la interface <i><b>HttpServletResponse</b></i>:<br />
- <b>Setear encabezados de respuesta</b>: Posee siete métodos para llevar a cabo esta funcionalidad:<br />
</div><ul style="text-align: justify;"><li>void <b>setHeader </b>(String name, String value)</li>
<li>void <b>setIntHeader </b>(String name, int value)</li>
<li>void <b>setDateHeader </b>(String name, long milisec)</li>
<li>void <b>addHeader </b>(String name, String value)</li>
<li>void <b>addIntHeader </b>(String name, int value)</li>
<li>void <b>addDateHeader </b>(String name, long milisec)</li>
<li>boolean <b>containsHeader </b>(String name)<br />
</li>
</ul><div style="text-align: justify;">- <b>Redireccionamiento de peticiones</b>: El método HttpServletResponse.<b>sendRedirect </b>(String location). Este método no puede ser invocado si la respuesta ya ha sido enviada al cliente, si se invoca se lanzará la excepción IllegalStateException. El método sendRedirect() no es transparente al navegador, el servlet envía un mensaje al navegador para que este obtenga el recurso en otra parte.<br />
- <b>Setear cookies</b>: El método HttpServletResponse.<b>addCookie </b>(Cookie cookie), permite agregar cookies a la respuesta del servlet.<br />
- <b>Enviar códigos de estado en la respuesta</b>: El protocolo HTTP define códigos de estado para las condiciones de error comunes. Todos los códigos están definidos como constantes en la interface HttpServletResponse. Esta interface también provee los métodos <b>sendError </b>(int status_code) y <b>sendError</b> (int status_code, String msg) los cuales envían un código de estado al cliente.<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Ciclo de vida de un Servlet</b><br />
Antes de que un servlet pueda dar servicio a los clientes, el contenedor de servlets debe realizar ciertos pasos:<br />
<br />
<b>1. Carga e instanciación de un servlet</b>: Cuando se inicia el contenedor de servlets, este revisa todos los archivos de configuración de todas las aplicaciones web que aloja. Cada aplicación web posee un web.xml el cual tiene una entrada por cada servlet que utiliza. El contenedor de servlets carga cada servlet a través de la instrucción: Class.forName(className).newInstance(). Es por esto que cada servlet debe tener un constructor público sin argumentos. En caso contrario, se lanza la excepción java.lang.InstantiationException envuelta dentro de una javax.servlet.ServletException.<br />
<b>2. Inicialización de un servlet</b>: Como los servlets se instancian a partir de un constructor sin argumentos (generalmente el por defecto), se utiliza el método init(ServletConfig) para realizar la inicialización de los datos del servlet. El contenedor de servlets luego de instanciar el servlet, invoca este método pasando como argumento un objeto ServletConfig. Dicho objeto contiene todos los parámetros de inicialización especificados en el xml de configuración (web.xml).<br />
<br />
La clase javax.servlet.GenericServlet posee dos métodos init(): uno con un parámetro de tipo ServletConfig y otro sin parámetros. El método init(ServletConfig) se encarga de guardar el objeto ServletConfig en el servlet e invoca el método init(). El método init() se puede sobrescribir libremente para realizar una inicialización específica. Si se sobrescribe el método init(ServletConfig) se debe incluir la invocación al método super.init(ServletConfig) para no perder la referencia al objeto ServletConfig (la cual se obtiene a través del método getServletConfig()).<br />
<br />
Generalmente el contenedor de servlets inicializa un servlet cuando recibe la primera petición. Si la inicialización realiza muchas tareas, el tiempo de respuesta del primer cliente va a ser muy malo. En los casos en donde esto es inaceptable, el archivo de configuración web.xml tiene la etiqueta <load-on-startup>, la cual especifica al contenedor de servlets que debe cargar e inicializar uno o más servlets automáticamente cuando el mismo se inicia. Estos dos tipos de carga e inicialización se denominan: carga perezosa (lazy loading) y precarga o preinicialización.<br />
<b>3. Dando servicio a las peticiones</b>: Cuando el contenedor de servlets recibe una petición, despacha la misma a una instancia de un servlet invocando el método Servlet.service(ServletRequest, ServletResponse).<br />
<b>4. Destruyendo un servlet</b>: Cuando el contenedor de servlets decide que un servlet ya no es necesario, él invoca el método destroy() sobre la instancia del servlet. Dicho método libera los recursos, y una vez que es invocado el servlet se encuentra fuera de servicio (el contenedor no puede volver a ejecutar el método service()). Antes de invocar este método, el contenedor de servlets espera a que se finalice la ejecución, por parte de todos los hilos en ejecución, del método service().<br />
<br />
Causas por las que el contenedor de servlets puede invocar el método destroy() sobre un servlet:<br />
</load-on-startup><br />
</div><ul style="text-align: justify;"><li>Si el servlet está funcionando lento sobre los recursos o ninguna petición ha llegado al servlet por un largo tiempo.</li>
<li>Si el contenedor de servlets mantiene un pool de instancias de servlets, puede crear y destruir las instancias.</li>
<li>Si el contenedor de servlets detiene sus servicios, es decir, si es apagado.<br />
</li>
</ul><div style="text-align: justify;"><b>5. Descargando un servlet</b>: Una vez destruida, la instancia del servlet puede ser eliminada por el garbage collector, en este caso se dice que el servlet ha sido descargado.<br />
</div><div style="text-align: justify;"><br />
<b>javax.servlet.ServletConfig</b><br />
Esta interface provee métodos solo para obtener los parámetros del archivo de configuración web.xml:<br />
</div><ul style="text-align: justify;"><a href="http://1.bp.blogspot.com/_3WReUfj0UMk/SyZQ6w2NBFI/AAAAAAAAAOY/vcyrp6wcyK0/s1600-h/ServletConfig.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://1.bp.blogspot.com/_3WReUfj0UMk/SyZQ6w2NBFI/AAAAAAAAAOY/vcyrp6wcyK0/s320/ServletConfig.jpg" /></a>
<li>String <b>getInitParameter </b>(String name): Devuelve el valor del parámetro.</li>
<li>Enumeration <b>getInitParameterNames </b>(): Devuelve un objeto Enumeration con todos los nombres de los parámetros.</li>
<li>ServletContext <b>getServletContext </b>(): Devuelve la instancia de ServletContext del servlet actual.</li>
<li>String getServletName (): Devuelve el nombre del servlet especificado en el archivo de configuración.<br />
</li>
</ul><div style="text-align: justify;"><b>javax.servlet.ServletContext</b><br />
Esta interface permite a los servlets obtener información sobre el ambiente en donde se están ejecutando. Toda aplicación web tiene una sola instancia de ServletContext, y la misma es accesible por todos los recursos activos de la aplicación. También se utiliza para compartir información entre servlets.<br />
Métodos de la interface:<br />
</div><ul style="text-align: justify;"><li>java.net.URL <b>getResource </b>(String path): Devuelve una instancia de URL del recurso que apunta el path. El path debe comenzar con un carácter ‘/’ el cuál especifica el directorio raíz de la aplicación web.</li>
<li>java.io.InputStream <b>getResourceAsStream </b>(String path): Es un atajo para obtener el InputStream de salida de un recurso. Es equivalente a getResource(path).openStream().</li>
<li>java.lang.String <b>getRealPath </b>(String relativePath): Devuelve el path absoluto del recurso, es decir, su path en el sistema de archivos.<br />
</li>
</ul><div style="text-align: justify;"><b>Compartiendo datos entre servlets</b><br />
Los servlets pueden compartir información a través de tres objetos contenedores. Los mismos difieren en la visibilidad de la información contenida.<br />
</div><ul style="text-align: justify;"><li>javax.servlet.<b>ServletRequest</b>: Puede compartir información con cualquier servlet que se ejecute en la misma petición.</li>
<li>javax.servlet.http.<b>HttpSession</b>: Puede compartir información con cualquier servlet solo mientras sea válida la sesión del cliente.</li>
<li>javax.servlet.<b>ServletContext</b>: Puede compartir información con cualquier servlet de la misma aplicación web.<br />
</li>
</ul><div style="text-align: justify;">Estos tres contenedores de información poseen los siguientes métodos para setear y obtener datos:<br />
</div><ul style="text-align: justify;"><li>Object <b>getAttribute </b>(String name): Devuelve el objeto almacenado o null.</li>
<li>Enumeration <b>getAttributeNames </b>(): Devuelve un objeto Enumeration que contiene los nombres de todos los atributos.</li>
<li>void <b>setAttribute </b>(String name, Object value): Agrega una pareja clave-valor al contenedor.</li>
<li>void <b>removeAttribute </b>(String name): Elimina el atributo en el contenedor.</li>
</ul><div style="text-align: justify;"><b>javax.servlet.RequestDispatcher</b><br />
Las interfaces javax.servlet.ServletContext y javax.servlet.ServletRequest poseen un método para obtener un objeto de tipo RequestDispatcher, el método es:<br />
<i><b>public RequestDispatcher getRequestDispatcher (String path)</b></i><br />
<br />
</div><div style="text-align: justify;">La interface RequestDispatcher posee dos métodos:<br />
</div><ul style="text-align: justify;"><li>void <b>forward </b>(ServletRequest request, ServletResponse response): Permite a un servlet procesar una petición parcialmente y luego pasar la petición a otro servlet para generar la respuesta final. Este método puede ser invocado solo si la respuesta no fue enviada, caso contrario se lanza la excepción IllegalStateException. Es completamente manejado en el servidor, a diferencia de HttpServletResponse.sendRedirect(String location).</li>
<li>void <b>include </b>(ServletRequest request, ServletResponse response): Permite incluir el contenido de otro recurso en la respuesta que está generando el recurso que invoca el método.<br />
</li>
</ul><div style="text-align: justify;">La interface ServletContext además provee un método que permite redireccionar peticiones a componentes especificando solo su nombre (el cuál se define en el archivo web.xml), en vez de utilizar una URI. Este método es:<br />
<b>public RequestDispatcher getNamedDispatcher (String name)</b><br />
<i>Existe una diferencia importante entre el método getRequestDispatcher() de ServletContext y ServletRequest. Al método getRequestDispatcher() de ServletRequest se le puede pasar un path relativo, mientras que al de ServletContext no. El path pasado al método de ServletContext debe comenzar con ‘/’.</i><br />
<br />
<b>Accediendo a los atributos de la petición con RequestDispatcher</b><br />
El servlet incluido o redireccionado puede acceder a la información de la petición original a través de diversos atributos. Los nombres de los atributos dependen de si se ha invocado el método forward() o include(), los mismos pueden ser:<br />
- include():<br />
</div><ul style="text-align: justify;"><li>javax.servlet.include.request_uri</li>
<li>javax.servlet.include.context_path</li>
<li>javax.servlet.include.servlet_path</li>
<li>javax.servlet.include.path_info</li>
<li>javax.servlet.include.query_string<br />
</li>
</ul><div style="text-align: justify;">- forward():<br />
</div><ul style="text-align: justify;"><li>javax.servlet.forward.request_uri</li>
<li>javax.servlet.forward.context_path</li>
<li>javax.servlet.forward.servlet_path</li>
<li>javax.servlet.forward.path_info</li>
<li>javax.servlet.forward.query_string<br />
</li>
</ul><div style="text-align: justify;">Los valores de estos atributos son los mismos que los métodos: <b>getRequestURI</b>(), <b>getContextPath</b>(), <b>getServletPath</b>(), <b>getPathInfo</b>() y <b>getQueryString </b>de la interface HttpServletRequest. Estos atributos se acceden como los atributos regulares, a través del método getAttribute().<br />
</div><div style="text-align: justify;"><br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://2.bp.blogspot.com/_3WReUfj0UMk/SyZTBpOzf9I/AAAAAAAAAOg/8iKNzcE7rfs/s1600-h/Servlet.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/_3WReUfj0UMk/SyZTBpOzf9I/AAAAAAAAAOg/8iKNzcE7rfs/s640/Servlet.jpg" /></a><br />
</div><div style="text-align: justify;"><b>RESUMEN</b> <br />
</div><div style="text-align: justify;"><i>Ciclo de vida de un Servlet y API</i><br />
</div><ul style="text-align: justify;"><li>El contenedor inicializa un servlet cargando su clase, invocando su constructor sin argumentos, e invocando el método init().</li>
<li>El método init() (el cual puede sobrescribir el programador) solo es invocado una vez en la vida del servlet, y siempre antes de que este pueda dar servicio a cualquier petición cliente.</li>
<li>El método init() brinda (al servlet) acceso a los objetos ServletConfig y ServletContext, los cuales el servlet necesita para obtener información sobre su propia configuración y la de la aplicación web.</li>
<li>El contenedor finaliza la vida de un servlet invocando su método destroy().</li>
<li>La mayoría del tiempo de vida de un servlet se pasa ejecutando el método service() para una petición de un cliente.</li>
<li>Cada petición a un servlet se ejecuta en un thread separado. Solo existe una instancia de una clase servlet en particular.</li>
<li>Los servlets deben extender (en su mayoría) de la clase javax.servlet.http.HttpServlet, es en esta clase abstracta en donde se sobrecarga el método service() para que tome como parámetros los objetos HttpServletRequest y HttpServletResponse.</li>
<li>HttpServlet extiende de la clase abstracta javax.servlet.GenericServlet, la cual implementa la mayoría de los métodos básicos del servlet.</li>
<li>La clase GenericServlet implementa las interfaces Servlet y ServletConfig.</li>
<li>Las clases servlets se encuentran en uno de los dos paquetes: javax.servlet y javax.sevlet.http.</li>
<li>Se puede sobrescribir el método init(), y se debe sobrescribir al menos un método de servicio (doGet(), doPost(), etc.).<br />
</li>
</ul><div style="text-align: justify;"><i>HTTP y HttpServletRequest</i><br />
</div><ul style="text-align: justify;"><li>Los métodos doGet() y doPost() de HttpServlet toman como argumentos los objetos HttpServletRequest y HttpServletResponse.</li>
<li>El método service() determina que método de servicio (doGet(), doPost(), etc.) se debe ejecutar basado en el método HTTP (GET, POST, etc.).</li>
<li>Las peticiones POST poseen un cuerpo, las peticiones GET no, aunque estas últimas pueden contener parámetros de petición en su URL.</li>
<li>Las peticiones GET son idempotentes (idempotent). Es decir, son capaces de ejecutarse múltiples veces sin causar ningún efecto en el servidor. </li>
<li>Las peticiones POST no son idempotentes. Por este motivo, se debe diseñar el código de manera que si el cliente manda una misma petición dos veces (por error), se pueda manejar de una manera correcta.<br />
</li>
</ul><div style="text-align: justify;"><i>HttpServletResponse</i><br />
</div><ul style="text-align: justify;"><li>Los objetos Response se utilizan para enviar información de respuesta al cliente.</li>
<li>Los métodos que más se utilizan en el objeto de respuesta HttpServletResponse son setContentType() y getWriter().</li>
<li>El método getWriter() permite realizar operaciones de escritura de HTML (u otro tipo de texto) en el flujo de salida.</li>
<li>En la práctica, se utilizan más las paginas JSP para enviar HTML de respuesta, pero los servlets se pueden utilizar para enviar información binaria (como el caso de archivos) al cliente.</li>
<li>El método para obtener un flujo de salida binario es getOutputStream().</li>
<li>El método setContentType() permite indicar al browser como debe manejar la información que se envía en la respuesta. Los valores típicos son: “text/html”, “application/pdf”, y “image/jpeg”.</li>
<li>Se pueden setear los encabezados de respuesta utilizando los métodos addHeader() y setHeader(). La diferencia entre ambos depende es lo que se encuentra seteado en los encabezados. Es decir, setHeader() reemplaza el valor del encabezado, mientras que addHeader() agrega un valor adicional al encabezado ya existente. En caso de que el encabezado no exista ambos métodos se comportan del mismo modo.</li>
<li>El método sendRedirec() redirige una petición hacia otro recurso. Enviando el código 301 al browser, el cual es el que realiza la redirección al recurso especificado en la respuesta HTTP. </li>
<li>No se puede invocar el método sendRedirect() una vez que la respuesta ya fue invocada al cliente. En caso de que se invoque el método en esta situación, se lanzará la excepción IllegalStateException.<br />
</li>
</ul>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com0tag:blogger.com,1999:blog-5081968900413627331.post-25690802030860303762009-12-10T19:39:00.004-03:002009-12-10T19:48:48.092-03:00Comprando el voucher a u$s 40<div style="text-align: justify;">Recién termine de realizar la compra del voucher para el examen de certificación SCWCD (212-083). Como ya comenté en un <a href="http://scjp-sun.blogspot.com/2009/10/ya-soy-scjp.html">post anterior</a>, los examenes del SAI tienen el prefijo 212:<br />
</div><div style="text-align: justify;"><br />
</div><blockquote>Al recibir mi voucher, me di cuenta que no era para el examen 310-065 si no para el 212-065 (y entre en pánico), pero luego de ver el sitio <a href="http://www.prometric.com/Sun/default.htm">Prometric</a> me encontré con la siguiente información que me tranquilizo:<br />
<br />
<blockquote><b><span style="font-style: italic;">"SAI Sun Certification Exams are denoted with a 212 prefix to signify that it is designated for SAI. There is no difference between the 212 and 310 exam series."</span></b><br />
</blockquote><br />
La única diferencia entre estos dos exámenes, es que el 212-065 se puede rendir solo en inglés. Cosa que me preocupo en un principio, pero después pensándolo en frío, después de haber realizado toda la preparación y ejercitación en inglés fue mejor haberlo rendido en inglés.<br />
</blockquote><div style="text-align: justify;"><br />
A continuación les dejo unas capturas de pantalla en donde voy mostrando los pasos para adquirir el voucher (como ya todos saben a solo u$s 40, gracias al descuento que otorga el SAI (Sun Academic Initiative) para los estudiantes de universidades afiliadas al programa).<br />
</div><div style="text-align: justify;"><br />
Si no conoces este programa o queres informarte más sobre él, te paso estos links para que puedas quitarte tus dudas:<br />
</div><div style="text-align: justify;"><b>* Sitio de la iniciativa SAI: </b><a href="http://www.sun.com/solutions/landing/industry/education/sai/index.jsp">http://www.sun.com/solutions/landing/industry/education/sai/index.jsp</a><br />
<b>* Acceso a cursos del SAI: </b><a href="http://sailearningconnection.skillport.com/">http://sailearningconnection.skillport.com/</a><br />
<b>* Datos para registrarse en el SAI:</b><br />
</div><div style="text-align: justify;">- Program name: SAI-Argentina<br />
- Program ID: tbwg1fq8<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">(Hacer click sobre las imágenes para agrandarlas) <br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Paso 1: </b>Si te acordas de tu <b>Program ID</b>, podes empezar desde el paso 4. En caso contrario, tenes que obtener el mismo desde la opción 'Personalizar' del menú superior.<br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://3.bp.blogspot.com/_3WReUfj0UMk/SyFyFWHytlI/AAAAAAAAANA/j-HNoNFVEco/s1600-h/voucher_01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/_3WReUfj0UMk/SyFyFWHytlI/AAAAAAAAANA/j-HNoNFVEco/s320/voucher_01.jpg" /></a><br />
</div><div style="text-align: justify;"><b>Paso 2: </b>Hacer click en la opción 'Actualizar perfil de usuario'.<br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://2.bp.blogspot.com/_3WReUfj0UMk/SyFyWzZvIJI/AAAAAAAAANI/7LahHeYd1Xc/s1600-h/voucher_02.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/_3WReUfj0UMk/SyFyWzZvIJI/AAAAAAAAANI/7LahHeYd1Xc/s320/voucher_02.jpg" /></a><br />
</div><div style="text-align: justify;"><b>Paso 3:</b> En esta pantalla se muestran los datos con los que te registraste al SAI. Tape mis datos porque seguramente nadie quiere regalarme un voucher, asique no los necesitan. La flecha roja indica el número que es el <b>Program ID</b>, les recomiendo copiarla (salvo que quieran poner a prueba su memoria).<br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://3.bp.blogspot.com/_3WReUfj0UMk/SyFydtzxl6I/AAAAAAAAANQ/04ivMxB1lp4/s1600-h/voucher_03.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/_3WReUfj0UMk/SyFydtzxl6I/AAAAAAAAANQ/04ivMxB1lp4/s320/voucher_03.jpg" /></a><br />
</div><div style="text-align: justify;"><b>Paso 4:</b> Luego, volver a la página del SAI. Hacer click en la opción (de la barra izquierda) 'SAI Certification Discount Vouchers'.<br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://4.bp.blogspot.com/_3WReUfj0UMk/SyFyjoKWw-I/AAAAAAAAANY/_SO5k2MyB-c/s1600-h/voucher_04.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/_3WReUfj0UMk/SyFyjoKWw-I/AAAAAAAAANY/_SO5k2MyB-c/s320/voucher_04.jpg" /></a><br />
</div><div style="text-align: justify;"><b>Paso 5:</b> Luego, se abre una ventana emergente la cuál nos solicita algunos datos. Entre estos, nos pide el <b>Program ID</b> y otros. En SAI-Program Name elijan el de su país. Y luego seleccionen el examen que desean rendir.<br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://4.bp.blogspot.com/_3WReUfj0UMk/SyFypw_10cI/AAAAAAAAANg/2vR6ZRtMeQs/s1600-h/voucher_05.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/_3WReUfj0UMk/SyFypw_10cI/AAAAAAAAANg/2vR6ZRtMeQs/s320/voucher_05.jpg" /></a><br />
</div><div style="text-align: justify;"><b>Paso 6:</b> Una vez que envian el formulario, el browser se redirige a la página del gateway <b>PayPal</b>. En caso de que no esten registrados, lo hacen y podrán abonar su voucher a solo u$s 40.<br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://3.bp.blogspot.com/_3WReUfj0UMk/SyFywVAC65I/AAAAAAAAANo/5_OzMJthsqw/s1600-h/voucher_06.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/_3WReUfj0UMk/SyFywVAC65I/AAAAAAAAANo/5_OzMJthsqw/s320/voucher_06.jpg" /></a><br />
</div><div style="text-align: justify;"><b>Paso 7:</b> Verifican los datos, y luego hacen click en 'Pagar Ahora'.<br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://2.bp.blogspot.com/_3WReUfj0UMk/SyFy2lnYXkI/AAAAAAAAANw/73TJCj58_Wg/s1600-h/voucher_07.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/_3WReUfj0UMk/SyFy2lnYXkI/AAAAAAAAANw/73TJCj58_Wg/s320/voucher_07.jpg" /></a><br />
</div><div style="text-align: justify;"><b>Paso 8:</b> Se les confirma el pago.<br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://2.bp.blogspot.com/_3WReUfj0UMk/SyFy6hykxAI/AAAAAAAAAN4/pKh85ZDp98A/s1600-h/voucher_08.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/_3WReUfj0UMk/SyFy6hykxAI/AAAAAAAAAN4/pKh85ZDp98A/s320/voucher_08.jpg" /></a><br />
</div><div style="text-align: justify;"><b>Paso 9:</b> Por último se los redirige al sitio de sun en donde encuentran la siguiente pantalla.<br />
</div><div class="separator" style="clear: both; text-align: justify;"><a href="http://2.bp.blogspot.com/_3WReUfj0UMk/SyFy_ykbDoI/AAAAAAAAAOA/yUCap-rzs3g/s1600-h/voucher_09.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/_3WReUfj0UMk/SyFy_ykbDoI/AAAAAAAAAOA/yUCap-rzs3g/s320/voucher_09.jpg" /></a><br />
</div><div style="text-align: justify;">En esta pantalla se les informa como deben comunicarse con SUN, para verificar su estado como estudiante. Es decir, debén enviar un email a la dirección especificada, adjuntando alguna documentación que valide que se encuentran estudiando en alguna universidad afiliada al programa. (Si quieren averiguar si su universidad se encuentra afiliada, comuniquense con alguna persona que trabaje en SUN, o envíen un email a la dirección <b>contact_sai@sun.com</b>)<br />
</div><div style="text-align: justify;">En mi caso, envié una fotografía digital de:<br />
</div><div style="text-align: justify;">- Mi libreta de estudiante<br />
</div><div style="text-align: justify;">- Un certificado de alumno regular<br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Bueno cualquier duda dejen comentarios.<br />
</div><div style="text-align: justify;"><b>EVITEN</b> mandarme emails a mi dirección consultandome por este proceso, ya que <b><i>la idea del blog es compartir las dudas y todo tipo de cosas</i></b>. Como no trabajo en SUN, esto lo hago solo para aquella gente que se presento con las mismas problemáticas con las que yo me encontre. Compartiendo las consultas y las respuestas podemos brindar más y mejor información.<br />
A través de los comentarios voy a compartir algunos emails que me enviaron realizando consultas. Esto lo voy a hacer con cualquier email que me envíen, que yo considere que tenga información útil para compartir en el blog.<br />
Saludos ;)<br />
</div>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com5tag:blogger.com,1999:blog-5081968900413627331.post-18511888848988441362009-12-08T14:00:00.002-03:002009-12-08T14:04:11.994-03:00Conceptos básicos (Servlets y JSP)<div style="text-align: justify;"><span style="font-weight: bold;">Que es una JavaServer Page (JSP)?</span><br />Una JSP es una página web que contiene código java a lo largo de etiquetas HTML. Cuando es accedida por un cliente, el código java dentro de la página se ejecuta en el servidor web, produciendo código HTML el cuál reemplaza el código java.<br /><span style="font-style: italic;">JavaServer Pages</span> es el nombre de la tecnología que permite combinar código java como un lenguaje de scripting con etiquetas HTML. Esta tecnología forma parte de la capa de presentación de la arquitectura <span style="font-weight: bold;">J2EE</span>. La especificación JSP está compuesta de etiquetas JSP que son embebidas en etiquetas HTML.<br /><br /><span style="font-weight: bold;">Diferencias entre Servlets y JSP’s</span><br />Los <span style="font-style: italic;">servlets </span>son extensiones del servidor y proveen una funcionalidad extra al servidor web, son utilizados como controladores de componentes (controlan la lógica de negocio). JSP son páginas web, con una estructura similar a las páginas HTML.<br />Una aplicación web consiste en una combinación de servlets y JSP’s:<br /></div><ul style="text-align: justify;"><li>JSP’s: se utilizan para la presentación visual.</li><li>Servlets: controlan la lógica de negocio.</li></ul><div style="text-align: justify;"><span style="font-weight: bold;">Que es una aplicación web?</span><br />Una aplicación web se construye con componentes web que realizan tareas específicas y son capaces de dar servicios. Una aplicación web es un conjunto de múltiples recursos (activos) servlets, JSP’s, (pasivos) archivos HTML, imágenes, y otros.<br />Una aplicación web se describe utilizando un archivo “descriptor de despliegue” (deployment descriptor). Es un documento xml llamado web.xml, el cual contiene la descripción de todos los componentes dinámicos de una aplicación web.<br /><br /><span style="font-weight: bold;">El protocolo HTTP</span><br />Un mensaje HTTP es cualquier petición que es enviada desde un cliente al servidor, o cualquier respuesta desde el servidor al cliente.<br /></div>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com2tag:blogger.com,1999:blog-5081968900413627331.post-44501088576984942632009-12-07T14:22:00.001-03:002009-12-09T11:51:03.273-03:00Introducción Servlets<span style="font-weight: bold;">Que es un servlet?</span><br />
<div style="text-align: justify;">Todos los servidores poseen dos grandes responsabilidades:<br />
</div><ul style="text-align: justify;"><li>Manejar las peticiones de los clientes (programación a nivel de sockets, extraer información de los mensajes de petición, implementar los protocolos cliente-servidor, etc.)</li>
<li>Crear una respuesta para devolverla al cliente.<br />
</li>
</ul><div style="text-align: justify;">La mejor manera de dar soporte a estas dos responsabilidades es dividir el código en dos ejecutables separados (por un lado el servidor en sí, y por otro las extensiones del mismo). En java las extensiones del servidor se desarrollan utilizando la API de Servlets, y estos módulos son denominados servlets.<br />
<br />
<span style="font-weight: bold;">Servlet Container (Administrador o Contenedor de Servlets)</span><br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/_3WReUfj0UMk/Sx-5L-tKdHI/AAAAAAAAAMw/iCy7AjIkWZw/s1600-h/servlet_container.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://3.bp.blogspot.com/_3WReUfj0UMk/Sx-5L-tKdHI/AAAAAAAAAMw/iCy7AjIkWZw/s320/servlet_container.jpg" /></a><br />
</div>Los servidores web utilizan un modulo separado para cargar y ejecutar los Servlets. Este modulo especializado (que se dedica a la administración de los servlets) es denominado Servlet Container. Cuando se realiza una petición a un servidor web, si el recurso solicitado es activo (un servlet o una JSP), el servidor delega la petición al servlet container. Si el recurso es pasivo (una página HTML, una imagen, etc.) es el servidor web (a través del sistema de archivos) el que se encarga de manejar la petición.<br />
<br />
El Servlet Container es parte del servidor web, pero este puede ser clasificado en tres tipos:<br />
</div><ul style="text-align: justify;"><li>Standalone: Son servidores web basados en Java. El servidor web y el servlet container son partes de un solo programa.</li>
<li>In-process: El servidor web y el servlet container son programas diferentes, pero el contenedor se ejecuta dentro del espacio de memoria del servidor web, como un plug-in.</li>
<li>Out-of-process: El servidor web y el servlet container son programas diferentes, pero el servidor web se ejecuta en un proceso mientas que el contenedor de servlets se ejecuta en un proceso distinto.<br />
</li>
</ul><div style="text-align: justify;"><span style="font-weight: bold;">La API de Servlets</span><br />
La API está dividida en dos paquetes:<br />
<br />
<span style="font-weight: bold;">javax.servlet</span>: Contiene las interfaces y clases genéricas de los servlets, que son independientes del protocolo.<br />
</div><ul style="text-align: justify;"><li>Interface java.servlet.<a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/Servlet.html">Servlet</a></li>
<li>Clase java.servlet.<a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/GenericServlet.html">GenericServlet</a></li>
<li>Interface java.servlet.<a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletRequest.html">ServletRequest</a></li>
<li>Interface java.servlet.<a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletResponse.html">ServletResponse</a><br />
</li>
</ul><div style="text-align: justify;"><span style="font-weight: bold;">javax.servlet.http</span>: Contiene la funcionalidad básica requerida por los servlets HTTP. Es decir, contiene las implementaciones específicas para el protocolo HTTP de las clases e interfaces del paquete java.servlet.<br />
</div><ul style="text-align: left;"><li>Clase java.servlet.http.<a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.html">HttpServlet</a>: Extiende de java.servlet.GenericServlet.</li>
<li>Interface java.servlet.http.<a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServletRequest.html">HttpServletRequest</a>: Extiende de java.servlet.ServletRequest.</li>
<li>Interface java.servlet.http.<a href="http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServletResponse.html">HttpServletResponse</a>: Extiende de java.servlet.ServletResponse.</li>
</ul>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com2tag:blogger.com,1999:blog-5081968900413627331.post-90072316770698157482009-12-07T14:12:00.001-03:002009-12-08T13:58:39.593-03:00Objetivos SCWCD CX-310-083<span style="background-color: rgb(230, 236, 249);" onmouseover="_tipon(this)" onmouseout="_tipoff()"><strong></strong></span><div style="text-align: justify;"><span style="font-weight: bold;">Section 1: The Servlet Technology Model</span><br /><br /><span style="font-weight: bold;">1.1- </span>For each of the HTTP Methods (such as GET, POST, HEAD, and so on) describe the purpose of the method and the technical characteristics of the HTTP Method protocol, list triggers that might cause a Client (usually a Web browser) to use the method; and identify the HttpServlet method that corresponds to the HTTP Method.<br /><span style="font-weight: bold;">1.2- </span>Using the HttpServletRequest interface, write code to retrieve HTML form parameters from the request, retrieve HTTP request header information, or retrieve cookies from the request.<br /><span style="font-weight: bold;">1.3- </span>Using the HttpServletResponse interface, write code to set an HTTP response header, set the content type of the response, acquire a text stream for the response, acquire a binary stream for the response, redirect an HTTP request to another URL, or add cookies to the response.<br /><span style="font-weight: bold;">1.4- </span>Describe the purpose and event sequence of the servlet life cycle: (1) servlet class loading, (2) servlet instantiation, (3) call the init method, (4) call the service method, and (5) call destroy method.<br /><br /></div><div style="text-align: justify;"><span style="font-weight: bold;">Section 2: The Structure and Deployment of Web Applications</span><br /><br /><span style="font-weight: bold;">2.1- </span>Construct the file and directory structure of a Web Application that may contain (a) static content, (b) JSP pages, (c) servlet classes, (d) the deployment descriptor, (e) tag libraries, (d) JAR files, and (e) Java class files; and describe how to protect resource files from HTTP access.<br /><span style="font-weight: bold;">2.2- </span>Describe the purpose and semantics of the deployment descriptor.<br /><span style="font-weight: bold;">2.3- </span>Construct the correct structure of the deployment descriptor.<br /><span style="font-weight: bold;">2.4- </span>Explain the purpose of a WAR file and describe the contents of a WAR file, how one may be constructed.<br /><br /></div><div style="text-align: justify;"><span style="font-weight: bold;">Section 3: The Web Container Model</span><br /><br /><span style="font-weight: bold;">3.1- </span>For the ServletContext initialization parameters: write servlet code to access initialization parameters; and create the deployment descriptor elements for declaring initialization parameters.<br /><span style="font-weight: bold;">3.2- </span>For the fundamental servlet attribute scopes (request, session, and context): write servlet code to add, retrieve, and remove attributes; given a usage scenario, identify the proper scope for an attribute; and identify multi-threading issues associated with each scope.<br /><span style="font-weight: bold;">3.3- </span>Describe the Web container request processing model; write and configure a filter; create a request or response wrapper; and given a design problem, describe how to apply a filter or a wrapper.<br /><span style="font-weight: bold;">3.4- </span>Describe the Web container life cycle event model for requests, sessions, and web applications;create and configure listener classes for each scope life cycle; create and configure scope attribute listener classes; and given a scenario, identify the proper attribute listener to use.<br /><span style="font-weight: bold;">3.5- </span>Describe the RequestDispatcher mechanism; write servlet code to create a request dispatcher; write servlet code to forward or include the target resource; and identify and describe the additional request-scoped attributes provided by the container to the target resource.<br /><br /></div><div style="text-align: justify;"><span style="font-weight: bold;">Section 4: Session Management</span><br /><br /><span style="font-weight: bold;">4.1- </span>Write servlet code to store objects into a session object and retrieve objects from a session object.<br /><span style="font-weight: bold;">4.2- </span>Given a scenario describe the APIs used to access the session object, explain when the session object was created, and describe the mechanisms used to destroy the session object, and when it was destroyed.<br /><span style="font-weight: bold;">4.3- </span>Using session listeners, write code to respond to an event when an object is added to a session, and write code to respond to an event when a session object migrates from one VM to another.<br /><span style="font-weight: bold;">4.4- </span>Given a scenario, describe which session management mechanism the Web container could employ, how cookies might be used to manage sessions, how URL rewriting might be used to manage sessions, and write servlet code to perform URL rewriting.<br /><br /></div><div style="text-align: justify;"><span style="font-weight: bold;">Section 5: Web Application Security</span><br /><br /><span style="font-weight: bold;">5.1- </span>Based on the servlet specification, compare and contrast the following security mechanisms: (a) authentication, (b) authorization, (c) data integrity, and (d) confidentiality.<br /><span style="font-weight: bold;">5.2- </span>In the deployment descriptor, declare a security constraint, a Web resource, the transport guarantee, the login configuration, and a security role.<br /><span style="font-weight: bold;">5.3- </span>Compare and contrast the authentication types (BASIC, DIGEST, FORM, and CLIENT-CERT); describe how the type works; and given a scenario, select an appropriate type.<br /><br /></div><div style="text-align: justify;"><span style="font-weight: bold;">Section 6: The JavaServer Pages (JSP) Technology Model</span><br /><br /><span style="font-weight: bold;">6.1- </span>Identify, describe, or write the JSP code for the following elements: (a) template text, (b) scripting elements (comments, directives, declarations, scriptlets, and expressions), (c) standard and custom actions, and (d) expression language elements.<br /><span style="font-weight: bold;">6.2- </span>Write JSP code that uses the directives: (a) 'page' (with attributes 'import', 'session', 'contentType', and 'isELIgnored'), (b) 'include', and (c) 'taglib'.<br /><span style="font-weight: bold;">6.3- </span>Write a JSP Document (XML-based document) that uses the correct syntax.<br /><span style="font-weight: bold;">6.4- </span>Describe the purpose and event sequence of the JSP page life cycle: (1) JSP page translation, (2) JSP page compilation, (3) load class, (4) create instance, (5) call the jspInit method, (6) call the _jspService method, and (7) call the jspDestroy method.<br /><span style="font-weight: bold;">6.5- </span>Given a design goal, write JSP code using the appropriate implicit objects: (a) request, (b) response, (c) out, (d) session, (e) config, (f) application, (g) page, (h) pageContext, and (i) exception.<br /><span style="font-weight: bold;">6.6- </span>Configure the deployment descriptor to declare one or more tag libraries, deactivate the evaluation language, and deactivate the scripting language. 6.7 Given a specific design goal for including a JSP segment in another page, write the JSP code that uses the most appropriate inclusion mechanism (the include directive or the jsp:include standard action).<br /></div><div style="text-align: justify;"><span style="font-weight: bold;"><br />Section 7: Building JSP Pages Using the Expression Language (EL)</span><br /><br /><span style="font-weight: bold;">7.1- </span>Given a scenario, write EL code that accesses the following implicit variables including pageScope, requestScope, sessionScope, and applicationScope, param and paramValues, header and headerValues, cookie, initParam and pageContext.<br /><span style="font-weight: bold;">7.2- </span>Given a scenario, write EL code that uses the following operators: property access (the . operator), collection access (the [] operator).<br /><br /></div><div style="text-align: justify;"><span style="font-weight: bold;">Section 8: Building JSP Pages Using Standard Actions</span><br /><br /><span style="font-weight: bold;">8.1- </span>Given a design goal, create a code snippet using the following standard actions: jsp:useBean (with attributes: 'id', 'scope', 'type', and 'class'), jsp:getProperty, jsp:setProperty (with all attribute combinations), and jsp:attribute.<br /><span style="font-weight: bold;">8.2- </span>Given a design goal, create a code snippet using the following standard actions: jsp:include, jsp:forward, and jsp:param.<br /><br /></div><div style="text-align: justify;"><span style="font-weight: bold;">Section 9: Building JSP Pages Using Tag Libraries</span><br /><br /><span style="font-weight: bold;">9.1- </span>For a custom tag library or a library of Tag Files, create the 'taglib' directive for a JSP page.<br /><span style="font-weight: bold;">9.2- </span>Given a design goal, create the custom tag structure in a JSP page to support that goal.<br /><span style="font-weight: bold;">9.3- </span>Given a design goal, use an appropriate JSP Standard Tag Library (JSTL v1.1) tag from the "core" tag library.<br /><br /></div><div style="text-align: justify;"><span style="font-weight: bold;">Section 10: Building a Custom Tag Library</span><br /><br /><span style="font-weight: bold;">10.1- </span>Describe the semantics of the "Classic" custom tag event model when each event method (doStartTag, doAfterBody, and doEndTag) is executed, and explain what the return value for each event method means; and write a tag handler class.<br /><span style="font-weight: bold;">10.2- </span>Using the PageContext API, write tag handler code to access the JSP implicit variables and access web application attributes.<br /><span style="font-weight: bold;">10.3- </span>Given a scenario, write tag handler code to access the parent tag and an arbitrary tag ancestor.<br /><span style="font-weight: bold;">10.4- </span>Describe the semantics of the "Simple" custom tag event model when the event method (doTag) is executed; write a tag handler class; and explain the constraints on the JSP content within the tag.<br /><span style="font-weight: bold;">10.5- </span>Describe the semantics of the Tag File model; describe the web application structure for tag files; write a tag file; and explain the constraints on the JSP content in the body of the tag.<br /><br /></div><div style="text-align: justify;"><span style="font-weight: bold;">Section 11: Java EE Patterns</span><br /><br /><span style="font-weight: bold;">11.1- </span>Given a scenario description with a list of issues, select a pattern that would solve the issues. The list of patterns you must know are: Intercepting Filter, Model-View-Controller, Front Controller, Service Locator, Business Delegate, and Transfer Object.<br /><span style="font-weight: bold;">11.2- </span>Match design patterns with statements describing potential benefits that accrue from the use of the pattern, for any of the following patterns: Intercepting Filter, Model-View-Controller, Front Controller, Service Locator, Business Delegate, and Transfer Object.<br /></div>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com0tag:blogger.com,1999:blog-5081968900413627331.post-76416825129713950982009-12-07T13:16:00.000-03:002009-12-07T14:10:52.983-03:00Sun Certified Web Component Developer (SCWCD)<div style="text-align: justify;">Actualmente me estoy preparando para rendir mi segunda certificación. SCWCD <a href="http://www.sun.com/training/catalog/courses/CX-310-083.xml">(CX-310-083)</a> (Sun Certified Web Component Developer) es uno de los tantos examenes de certificación de la plataforma JAVA creado por SUN. El <a href="http://www.sun.com/training/certification/java/index.xml">programa de certificación</a> de SUN actualmente contiene ocho exámenes de certificación sobre la plataforma Java:<br />- <a href="http://www.sun.com/training/certification/java/scja.xml">Sun Certified Java Associate (SCJA)</a><br /> - <a href="http://www.sun.com/training/certification/java/scjp.xml">Sun Certified Java Programmer (SCJP)</a><br /> - <a href="http://www.sun.com/training/certification/java/scjd.xml">Sun Certified Java Developer (SCJD)</a><br /> - <a href="http://www.sun.com/training/certification/java/scwcd.xml">Sun Certified Web Component Developer (SCWCD)</a><br /> - <a href="http://www.sun.com/training/certification/java/scbcd.xml">Sun Certified Business Component Developer (SCBCD)</a><br /> - <a href="http://www.sun.com/training/certification/java/scdjws.xml">Sun Certified Developer For Java Web Services (SCDJWS)</a><br /> - <a href="http://www.sun.com/training/certification/java/scmad.xml">Sun Certified Mobile Application Developer (SCMAD)</a><br /> - <a href="http://www.sun.com/training/certification/java/scea.xml">Sun Certified Enterprise Architect (SCEA)</a><br /><br /><a href="http://scjp-sun.blogspot.com/2009/07/introduccion-scjp.html">Ver temas relacionados a la certificación SCJP.</a><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_3WReUfj0UMk/Sx0suL0v1NI/AAAAAAAAAKo/e8sSDeR6goo/s1600-h/certpathJava_SCWCD.gif"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 400px; height: 127px;" src="http://3.bp.blogspot.com/_3WReUfj0UMk/Sx0suL0v1NI/AAAAAAAAAKo/e8sSDeR6goo/s400/certpathJava_SCWCD.gif" alt="" id="BLOGGER_PHOTO_ID_5412531499128837330" border="0" /></a><span style="font-style: italic;">"Está dirigida a desarrolladores que desean especializarse en las tecnologías JavaServer Pages y servlet utilizadas para crear servicios y contenidos dinámicos en la Web.</span> <span style="font-style: italic;">Para alcanzar esta certificación, los candidatos deben completar exitosamente un examen. Los candidatos ya deben poseer el título de Programador Certificado en Sun (SCJP), en cualquiera de las ediciones."</span><br /><a href="http://www.sun.com/training/certification/java/scwcd.xml">Extraído de la página oficial de Sun</a><br /><br />Antes de comenzar mi preparación nunca había programado en JavaEE, pero sí tenía muchos conocimientos en lenguajes y plataformas web. Esta plataforma es distinta a las demás, pero muchos en aspectos se asemeja a otros frameworks web de desarrollo.<br />Cuando comencé a investigar los objetivos del examen y bibliografía para prepararme, ví que casi toda la información en la web se refería a la versión CX-310-081 del mismo. Fue ahí donde me surgió la duda <span style="font-weight: bold;">¿Cuál es la diferencia entre estas dos versiones del examen?</span>. Luego de buscar en la web encontré este <a href="http://www.coderanch.com/t/176641/Web-Component-Certification-SCWCD/certification/About-SCWCD-exam">post</a> (en el sitio <a href="http://www.javaranch.com/">JavaRanch.com</a>). En dicha publicación, uno de los autores de la nueva versión del examen SCWCD explica las diferencias entre ambas versiones.<br /><br /><span style="font-style: italic;" class="postbody"><blockquote>First of all, the title of the exam is pure marketing fluff. The SCWCD5 exam has nothing to do with Java EE v1.5. This exam (CX-310-083) is merely an update of the old SCWCD exam (CX-310-081). No objectives were changed.</blockquote></span><br /><a href="http://www.coderanch.com/forums/user/profile/12795;jsessionid=8E76FCFC381DE8BE5777C3AC7A825228"><span class="gen">Bryan Basham</span></a> explica que el título de la nueva versión del examen un puro marketing. Los objetivos del mismo no han cambiado de la versión <span style="font-style: italic;" class="postbody">CX-310-081.</span><span class="postbody"> En resumen, </span>el examen es el mismo, por lo que se puede utilizar un libro destinado a la versión CX-310-081 para prepararse para la versión CX-310-083.<br /><br />En el sitio <a href="http://www.javaranch.com/">JavaRanch.com</a>, también encontré algunas <a href="http://faq.javaranch.com/view?ScwcdFaq">FAQ</a> que quitaron muchas de mis dudas. Al que le interese rendir el examen, le recomiendo leerlas atentamente.<br /><br /><span style="font-weight: bold;">Detalles del examen</span><br /></div><ul style="text-align: justify;"><li>Se rinde en: Centros autorizados por <a href="http://www.prometric.com/Sun/default.htm">Prometric</a></li><li>Prerequisitos: Sun Certified Java Programmer (cualquier edición)</li><li>Tipo de examen: Multiple Choice y Drag and Drop</li><li>Número de preguntas: 69</li><li>Puntaje de aprobación: 70% (49 de 69 preguntas)</li><li>Tiempo disponible: 180 minutos</li></ul><div style="text-align: justify;"><span style="font-weight: bold;">Bibliografía</span><br />Actualmente me estoy preparando para rendir el examen antes de que finalice el 2009. He utilizado (y lo sigo haciendo) dos libros muy completos para lelvar esto a cabo. Los dejo los links así pueden descargarlos:<br /></div><ul style="text-align: justify;"><li><a href="http://scjp-preparacion.googlecode.com/files/Manning.SCWCD.Exam.Study.Kit.Java.Web.Component.Developer.Certification.2nd.Edition.May.2005.pdf">Manning SCWCD Exam Study Kit - 2nd Edition - May 2005</a></li><li><a href="http://scjp-preparacion.googlecode.com/files/OReilly.Head.First.Servlets.and.JSP.2nd.Edition.Mar.2008.pdf">OReilly Head First Servlets & JSP - 2nd Edition - Mar 2008</a><br /></li></ul><div style="text-align: justify;"><span style="font-style: italic;">NOTA: El segundo pdf (Head First Servlets & JSP) esta creado para la versión CX-310-083. Sin embargo, también recomiendo la lectura del otro libro ya que fue de mucha utilidad para mí preparación. Ciertos temas se desarrollan con más profundidad (aunque muy teóricos) y brindan un mayor conocimiento.</span><br /><br />Bueno espero que les sea de utilidad esta información. En breve subiré algo de documentación en español (resumenes más que nada) que estoy utilizando para prepararme.<br />Saludos</div>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com6tag:blogger.com,1999:blog-5081968900413627331.post-26113710053239975332009-12-05T20:58:00.001-03:002009-12-05T21:02:41.364-03:00Introducción OnJ2EE<div class="main"> <div class="snap_preview"><p>Hola! Mi nombre es Matías Emiliano Alvarez Durán. Actualmente vivo en la ciudad de Mar del Plata (Argentina), lugar donde me crié y donde realice mis estudios. Estudié en la <a href="http://www.mdp.utn.edu.ar/" target="_blank">Universidad Tecnológica Nacional (centro de estudios Mar del Plata)</a>. En dicha institución, egresé de la carrera <a href="http://www.mdp.utn.edu.ar/tecnico-superior-en-sistemas-informaticos.php">Técnico Superior en Sistemas Informáticos</a> (por lo cuál, tengo el título intermedio <a href="http://www.mdp.utn.edu.ar/tecnico-superior-en-programacion.php">Técnico Superior en Programación</a>).</p> <p>Antes de comenzar la cursada del último año de la facultad, comence a trabajar para la empresa <a href="http://onj2ee.wordpress.com/de%20Universidad%20Tecnol%C3%B3gica%20Nacional" target="_blank">Rollpix S.A</a>. En dicha empresa trabaje alrededor de un año y medio. Luego, deje de trabajar porque realmente quería comenzar a introducirme en el mundo de Java. Así, fue que (luego de investigar mucho) me decidí a prepararme para rendir las certificaciones de esta tecnología. </p> <p>Junto con la preparación de mi certificación <a href="http://www.sun.com/training/certification/java/scjp.xml" target="_blank">Sun Certified Java Programmer</a> (SCJP), hice un <a href="http://scjp-sun.blogspot.com/" target="_blank">blog</a> en donde fuí comentando mis experiencias en dicho proceso. Luego de ver la buena respuesta del mismo, y al ver que tenía ganas de seguir publicando cosas relacionadas al mundo de java y la programación, decidí crear este blog. </p> <p>OnJ2EE es el nombre de este blog, pero en realidad este no se limita a esta plataforma. OnJ2EE fue uno de los tantos nombres que se pasaron por mi cabeza, y fue el que más me gusto.</p><p>Bueno sin más que decir me despido. En las próximas publicaciones comentaré un poco que ando estudiando.</p> <p>Saludos!</p> </div> </div>Matías Emiliano Alvarez Duránhttp://www.blogger.com/profile/14142095839415896610noreply@blogger.com0