The Web Container Model (SCWCD)

0 comentarios
Objetivos:

Section 3: The Web Container Model
3.1- For the ServletContext initialization parameters: write servlet code to access initialization parameters; and create the deployment descriptor elements for declaring initialization parameters.
3.2- 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.

3.4- 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.
3.5- 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.



Inicializando el objeto ServletContext
Toda aplicación web tiene una instancia de javax.servlet.ServletContext. El contexto es inicializado en el momento que la aplicación es cargada. Existen parámetros de inicialización del contexto, los cuales se definen en el archivo web.xml dentro del elemento <context-param>. Cada parámetro de inicialización tiene los elementos <param-name> y <param-value>.
La interface ServletContext permite a los servlets obtener los parámetros de inicialización (del contexto) a través de dos métodos:
  • String getInitParameter (String name): Devuelve un String que contiene el valor del parámetro, devuelve null si el parámetro no existe.
  • java.util.Enumeration getInitParameterNames (): Devuelve un objeto Enumeration con los valores de los parámetros.
Para utilizar estos métodos, primero se debe obtener la instancia del objeto ServletContext. Este objeto esta contenido dentro de ServletConfig. Debido a esto, desde un servlet, existen dos formas de obtener el objeto ServletContext:
  • getServletConfig().getServletContext()
  • getServletContext(): Debido a que GenericServlet implementa la interface ServletConfig.

Utilizando Listeners
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.

Agregando y quitando atributos
Se pueden agregar atributos a los objetos de contexto (ServletContext), objetos de sesión (HttpSession) y objetos de petición (ServletRequest). Cada una de estas clases, contiene los mismos cuatro métodos para realizar las operaciones sobre los atributos:
  • Object getAttribute (String name): Devuelve el objeto asociado con el nombre pasado como parámetro.
  • Enumeration getAttributeNames (): Devuelve un objeto Enumeration con los nombres de los atributos.
  • void setAttribute (String name, Object value): Asocia un objeto con el ámbito actual y lo identifica a través del nombre especificado.
  • void removeAttribute (String name): Elimina el atributo del ámbito.
Se debe tener en cuenta tres puntos importantes:
  • 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.
  • Cualquier atributo asociado con el contexto está disponible en todos los servlets de la aplicación.
  • Solo se puede asociar un atributo con un nombre.
Escuchando los eventos sobre los atributos
Cada ámbito (contexto, sesión y petición) provee diferentes eventos y listeners para realizar un seguimiento de sus atributos:

Petición: Para responder a los eventos de atributos de petición, se debe crear una clase que implemente la interface ServletRequestAttributeListener. Dicha interface provee los métodos:
  • void attributeAdded (ServletRequestAttributeEvent ser): Invocado cuando se agrega un atributo.
  • void attributeRemoved (ServletRequestAttributeEvent ser): Invocado cuando se elimina un atributo.
  • void attributeReplaced (ServletRequestAttributeEvent ser): Invocado cuando se reemplaza un atributo.
Sesión: Para responder a los eventos de atributos de sesión existen tres interfaces: HttpSessionAttributeListener, HttpSessionBindingListener y HttpSessionActivationListener.

Contexto: 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 ServletContextAttributeListener, la cual provee los siguientes métodos:
  • void attributeAdded (ServletContextAttributeEvent scae): Invocado cuando se agrega un nuevo atributo.
  • void attributeRemoved (ServletContextAttributeEvent scae): Invocado cuando se elimina un atributo.
  • void attributeReplaced (ServletContextAttributeEvent scae): Invocado cuando se reemplaza un atributo.
Eventos y listeners del ciclo de vida de servlets
La Servlet Specification 2.4 define tres interfaces para hacer esto posible:
javax.servlet.ServletContextListener: Permite conocer cuando el servlet context se inicializa o se destruye:
  • void contextDestroyed (ServletContextEvent sce): Invocado cuando se destuye el contexto.
  • void contextInitialized (ServletContextEvent sce): Invocado cuando se inicializa el contexto.
javax.servlet.http.HttpSessionListener: Esta interface contiene los mismos métodos y capacidades que ServletContextListener, pero provee notificaciones cuando se crea o destruye una sesión.

javax.servlet.http.HttpServletRequestListener: Permite conocer cuando una petición se inicializa o se destruye:
  • void requestDestroyed (ServletRequestEvent sre): Invocado cuando se destruye una petición.
  • void requestInitialized (ServletRequestEvent sre): Invocado cuando se inicializa una petición.



Agregando listeners en el archivo web.xml
El archivo de configuración posee el elemento <listener>. Dicho elemento especifica las clases que escuchan a los eventos de la aplicación. Cada elemento <listener> posee uno y solo un elemento <listener-class>. El mismo contiene el nombre completo (incluido el paquete al que pertenece) de la clase que implementa alguna (o varias) interface listener.
<listener>
    <listener-class>
        com.abc.MyServletContextListener
    </listener-class>
</listener>
En el archivo web.xml, no se especifica que clase tiene que ser utilizada para cada evento. 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.
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.
Los listeners de tipo HttpSessionBindingListener no se deben especificar en el archivo web.xml.

Archivo web.xml
<!ELEMENT web-app
(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*)>

Objetos contenedores thread-safe
Los contenedores ServletContext y HttpSession no son Thread-safe. 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.

Sun liberó Java EE 6, Glassfish v3 y NetBeans 6.8

1 comentarios
Java Enterprise Edition 6 (Java EE 6) era muy esperado y se liberó apenas se consiguió la aprobación de su especificación. 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.
Según Kevin Schmidt, director de productos y marketing en la unidad Application Platforms de Sun, destacó que “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.” Con la incorporación de Profiles, Java EE 6 es más extensible porque 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. 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, reduciendo la cantidad de archivos requeridos para una aplicación empresarial, lo cual abrevia notablemente el proceso de desarrollo en ciertas tareas.
Si bien algunos miembros de JCP (Java Community Process) no gustan de la forma en que se completó Java EE 6, es un proyecto en el que participaron 2700 personas (en el proceso JCP) y la especificación se completó satisfactoriamente.
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. Si bien NetBeans es principalmente un IDE Java, Sun ha ganado espacio en PHP y NetBeans 6.8 incluye soporte a PHP 5.3.
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 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 (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. 
La versión Prelude sirvió para tener feedback y perfeccionar a GlassFish v3, que es totalmente ajustado a Java EE 6, tiene runtime OSGi y el nuevo Java EE 6 Web Profile.
Java EE 6 sigue siendo compatible retroactivamente
, 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.

"Noticias del mundo de SUN", extraido de un email enviado por Ezequiel Singer.
Buenas noticias para la plataforma J2EE, ni bien termine de rendir la certificación SCWCD, me sumergiré en el mundo de Java EE 6.
Saludos

The Structure and Deployment of Web Applications (SCWCD)

0 comentarios
Objetivos:
Section 2: The Structure and Deployment of Web Applications
2.1- 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.
2.2- Describe the purpose and semantics of the deployment descriptor.
2.3- Construct the correct structure of the deployment descriptor.
2.4- Explain the purpose of a WAR file and describe the contents of a WAR file, how one may be constructed.

Ver todos los objetivos de SCWCD 

La estructura de directorios de una aplicación web
La especificación de Servlets de java determina la manera en que una aplicación web debe ser almacenada. Es decir, se define una estructura de directorios para almacenar los recursos y archivos de una aplicación web.
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:

WEB-INF: Almacena información necesaria para que el contenedor de servlets pueda iniciar la aplicación web. Este directorio no es accesible por el cliente, pero si por la aplicación. Contiene tres elementos:
  • classes (directorio): Almacena los archivos class de servlets y archivos class comunes 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. En tiempo de ejecución, el contenedor de servlets agrega este directorio al classpath de la aplicación web. 
  • lib (directorio): Almacena todos los archivos JAR utilizados por la aplicación, tanto de terceras partes como propios. En tiempo de ejecución, el contenedor de servlets agrega todos los archivos JAR de este directorio al classpath de la aplicación web. 
  • web.xml: 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.
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.



El archivo web (WAR)
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 Web ARchive, y significa que el archivo deberá ser tratado de diferente manera que un archivo JAR. El contenedor de servlets puede instalar el archivo WAR de una aplicación web sin una intervención manual.
Dentro del archivo WAR, se crea un directorio llamado META-INF. Dicho directorio contiene el archivo MANIFEST.MF, el cual permite declarar dependencias con librerías y clases. 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.

La aplicación web por defecto (default web application)
Junto a las aplicaciones web creadas por los usuarios, el contenedor de servlets contiene una aplicación web por defecto. Esta aplicación maneja todas las peticiones que no concuerdan con ninguna aplicación del usuario. En el servidor Tomcat, esta aplicación por defecto se encuentra dentro del directorio webapps/ROOT.
Esta aplicación web por defecto permite ejecutar JSP’s y servlets individuales, como también contenido estático, sin empaquetarlos en una aplicación separada.

El archivo descriptor de despliegue web.xml (deployment descriptor file)
El archivo web.xml, es un típico archivo XML que comienza con la línea: <?xml version="1.0" encoding="ISO-5589-1">
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.
Nodos del archivo de configuración:

<!ELEMENT servlet (icon?, servlet-name, display-name?, description?, (servlet-class|jsp-file), init-param*, load-on-startup?, load-on-startup?, security-role-ref*) >

<!ELEMENT servlet-mapping (servlet-name, url-pattern) >

<web-app>: Nodo raíz del archivo.
  • <servlet>: Define un servlet para una aplicación web.
        - <servlet-name>: Define el nombre del servlet. Este elemento es obligatorio, y el nombre del servlet debe ser único en todo el archivo. Desde la aplicación, el nombre del servlet se puede obtener a través del método javax.servlet.ServletConfig.getServletName(). Este nombre también se utiliza para definir el mapeo del servlet a una URL.
        -
    <servlet-class>: Define el nombre de la clase utilizada por el contenedor de servlets para instanciar el servlet. 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.
        -
    <init-param>: Este elemento es utilizado para crear parámetros de inicialización del servlet. No hay un límite en la cantidad de parámetros de un servlet, pero cada uno debe contener:
              *
    <param-name>: Contiene el nombre del parámetro de inicialización.
              *
    <param-value>: Contiene el valor del parámetro de inicialización. 
  • <servlet-mapping>: 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:
        - <servlet-name>: Contiene el nombre del servlet.
        - <url-pattern>: Contiene la cadena de caracteres que se va a asociar al servlet.
  • <load-on-startup>: Permite especificar un número, el cual indica si el servlet debe ser cargado en tiempo de despliegue (deploy-time). Si posee un valor negativo, el servlet se cargará e inicializará al momento en que recibe la primera petición. Si posee un número positivo, se indica al contenedor que inicialice automáticamente al servlet, es decir, cuando el servidor arranca. El valor se utiliza para determinar el orden de inicialización de los servlets, 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.
Mapeando una URL a un Servlet
El enrutamiento de una petición a un servlet es un proceso de dos pasos:
  1. El contenedor de servlets identifica la aplicación web a la que pertenece la petición.
  2. Luego se localiza el servlet (perteneciente a la aplicación web) apropiado para manejar la petición.
Ambos pasos requieren que el contenedor servlets divida la URL de la petición en tres partes:
  • Context path (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.
  • Servlet path: 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.
  • Path info: 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.
La interface javax.servlet.http.HttpServletRequest provee tres métodos para obtener esta información: getContextPath(), getServletPath(), getPathInfo().

Identificación del servlet path
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:
  • El contenedor intenta coincidir la URI completa. En este caso, el path info es null.
  • 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.
  • 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.
  • 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.
Especificación de páginas por defecto (o welcome files)
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.
Se deben tener en cuenta los siguientes puntos, al especificar la lista de páginas por defecto:
  • No se utiliza una barra delante del nombre del archivo.
  • Todos los archivos (<welcome-file>) deben estar dentro de un solo elemento <welcome-file-list>, es decir, tienen que estar dentro de la misma lista.
<web-app …>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
</web-app>
Especificación de páginas de error
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 <page-error>. Puntos a tener en cuenta:
  • Los subelementos <exception-type> y <error-code> no pueden ser utilizados conjuntamente dentro de un mismo elemento <page-error>.
  • Se existen varias páginas de error con diferentes <exception-type>, se intentará concordar la excepción generada con una declaración del mismo tipo, o el supertipo más cercano.
  • El atributo pageError de la directiva page (de las páginas JSP), permite sobrescribir la página de error especificada en el web.xml.
Ejemplos:
<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>
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.

Definir referencias a EJB (Enterprise JavaBean)
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:

Referencia a un bean local:
<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>
Referencia a un bean remoto:
<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>
Definir enviroment entry (JNDI)
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:
<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>
Se debe tener en cuenta que el elemento <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.

Definir tipos MIME
Se pueden configurar mapeos entre una extensión y un tipo MIME en el archivo web.xml:
<web-app …>
    <mime-mapping>
        <extension>mpg</extension> <!-- No se debe incluir el punto “.”  -->
        <mime-type>video/mpeg</mime-type>
    </mime-mapping>
</web-app>

Código - The Servlet Technology Model

0 comentarios
HttpServletRequest
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>");
 }
} 

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:
  • HttpServletRequest.getHeaderNames()
  • HttpServletRequest.getParameterNames()
Ambos métodos devuelve un objeto Enumeration el cuál contiene todos los nombres de los encabezados y parámetros en la petición.

HttpServletResponse
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!!!");
 }
}

Este otro ejemplo muestra la utilización del objeto HttpServletResponse. Se utilizan los métodos:
  • HttpServletResponse.sendRedirect ()
  • HttpServletResponse.setHeader ()
  • HttpServletResponse.setIntHeader ()
  • HttpServletResponse.setDateHeader ()
  • HttpServletResponse.addHeader () 
  • HttpServletResponse.sendError ()
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.
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.
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();
 }
}
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.
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().

The Servlet Technology Model (SCWCD)

0 comentarios
Objetivos:
Section 1: The Servlet Technology Model
1.1- 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.
1.2- 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.
1.3- 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.
1.4- 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.


Métodos HTTP
  • GET: Se utiliza para obtener recursos activos o pasivos, generalmente  para archivos HTML o imágenes.
  • POST: 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.
  • HEAD: 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.
  • TRACE: 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.
  • PUT: Se utiliza para guardar la información adjuntada en el cuerpo de la petición (similar a POST).
  • DELETE: Se utiliza para indicar que se debe eliminar el recurso especificado con la URL.
  • OPTIONS: Permite obtener una lista de los métodos HTTP, los cuales se pueden utilizar para responder a cierto recurso.
  • CONNECT: Se utiliza para propósitos de tunneling (enrutamientos).
Manejando peticiones HTTP en un HttpServlet
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):
protected void doXXX (HttpServletRequest, HttpServletResponse) throws ServletException, IOException;
  • GET: doGet()
  • POST: doPost()
  • HEAD: doHead()
  • TRACE: doTrace()
  • PUT: doPut()
  • DELETE: doDelete()
  • OPTIONS: doOptions()
Flujo de control del contenedor de servlets:
  1. El contenedor de servlets invoca el método de HttpServlet: service (ServletRequest, ServletResponse).
  2. El método anterior invoca al método (sobrecargado en la misma clase): service (HttpServletRequest, HttpServletResponse).
  3. El método anterior analiza la petición y dependiendo del método HTTP utilizado invoca el correspondiente método doXXX() del servlet.
Es aconsejable no sobrescribir el método service(), debido a que se pierde la funcionalidad  de la clase HttpServlet. Se recomienda solo sobrescribir los métodos doGet() y doPost().
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.
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).

Analizando las peticiones (javax.servlet.ServletRequest y javax.servlet.HttpServletRequest)
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.


Métodos pertenecientes a la interface ServletRequest para obtener los parámetros enviados por un cliente:
  • String getParameter (String paramName): Devuelve el valor asociado al parámetro.
  • String[] getParameterValues (String paramName): Devuelve un arreglo de todos los valores asociados a un parámetro.
  • Enumeration getParameterNames (): Devuelve un objeto Enumeration con todos los nombres de los parámetros.
Métodos de HttpServletRequest para obtener los encabezados de un request (los headers son específicos del protocolo http):
  • String getHeader (String headerName): Devuelve el valor asociado al encabezado.
  • Enumeration getHeaders (String headerName): Devuelve un objeto Enumeration con todos los valores asociados a un encabezado.
  • Enumeration getHeadersNames (): Devuelve un objeto Enumeration con todos los nombres de los encabezados.
Enviando las respuestas (javax.servlet.ServletResponse y javax.servlet.http.HttpServletResponse)
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.

Métodos de la interface ServletResponse:
  • PrintWriter getWriter (): 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.
  • ServletOutputStream getOutputStream (): Devuelve un objeto javax.servlet.ServletOutputStream el cual permite enviar archivos binarios al cliente. Dicho objeto hereda de java.io.OutputStream.
  • void setContentType (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.
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 IllegalStateException.

Existen cuatro capacidades importantes de la interface HttpServletResponse:
- Setear encabezados de respuesta: Posee siete métodos para llevar a cabo esta funcionalidad:
  • void setHeader (String name, String value)
  • void setIntHeader (String name, int value)
  • void setDateHeader (String name, long milisec)
  • void addHeader (String name, String value)
  • void addIntHeader (String name, int value)
  • void addDateHeader (String name, long milisec)
  • boolean containsHeader (String name)
- Redireccionamiento de peticiones: El método HttpServletResponse.sendRedirect (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.
- Setear cookies: El método HttpServletResponse.addCookie (Cookie cookie), permite agregar cookies a la respuesta del servlet.
- Enviar códigos de estado en la respuesta: 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 sendError (int status_code) y sendError (int status_code, String msg) los cuales envían un código de estado al cliente.

Ciclo de vida de un Servlet
Antes de que un servlet pueda dar servicio a los clientes, el contenedor de servlets debe realizar ciertos pasos:

1.    Carga e instanciación de un servlet: 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.
2.    Inicialización de un servlet: 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).

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()).

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 , 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.
3.    Dando servicio a las peticiones: 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).
4.    Destruyendo un servlet: 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().

Causas por las que el contenedor de servlets puede invocar el método destroy() sobre un servlet:

  • Si el servlet está funcionando lento sobre los recursos o ninguna petición ha llegado al servlet por un largo tiempo.
  • Si el contenedor de servlets mantiene un pool de instancias de servlets, puede crear y destruir las instancias.
  • Si el contenedor de servlets detiene sus servicios, es decir, si es apagado.
5.    Descargando un servlet: 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.

javax.servlet.ServletConfig
Esta interface provee métodos solo para obtener los parámetros del archivo de configuración web.xml:
  • String getInitParameter (String name): Devuelve el valor del parámetro.
  • Enumeration getInitParameterNames (): Devuelve un objeto Enumeration con todos los nombres de los parámetros.
  • ServletContext getServletContext (): Devuelve la instancia de ServletContext del servlet actual.
  • String getServletName (): Devuelve el nombre del servlet especificado en el archivo de configuración.
javax.servlet.ServletContext
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.
Métodos de la interface:
  • java.net.URL getResource (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.
  • java.io.InputStream getResourceAsStream (String path): Es un atajo para obtener el InputStream de salida de un recurso. Es equivalente a getResource(path).openStream().
  • java.lang.String getRealPath (String relativePath): Devuelve el path absoluto del recurso, es decir, su path en el sistema de archivos.
Compartiendo datos entre servlets
Los servlets pueden compartir información a través de tres objetos contenedores. Los mismos difieren en la visibilidad de la información contenida.
  • javax.servlet.ServletRequest: Puede compartir información con cualquier servlet que se ejecute en la misma petición.
  • javax.servlet.http.HttpSession: Puede compartir información con cualquier servlet solo mientras sea válida la sesión del cliente.
  • javax.servlet.ServletContext: Puede compartir información con cualquier servlet de la misma aplicación web.
Estos tres contenedores de información poseen los siguientes métodos para setear y obtener datos:
  • Object getAttribute (String name): Devuelve el objeto almacenado o null.
  • Enumeration getAttributeNames (): Devuelve un objeto Enumeration que contiene los nombres de todos los atributos.
  • void setAttribute (String name, Object value): Agrega una pareja clave-valor al contenedor.
  • void removeAttribute (String name): Elimina el atributo en el contenedor.
javax.servlet.RequestDispatcher
Las interfaces javax.servlet.ServletContext y javax.servlet.ServletRequest poseen un método para obtener un objeto de tipo RequestDispatcher, el método es:
        public RequestDispatcher getRequestDispatcher (String path)

La interface RequestDispatcher posee dos métodos:
  • void forward (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).
  • void include (ServletRequest request, ServletResponse response): Permite incluir el contenido de otro recurso en la respuesta que está generando el recurso que invoca el método.
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:
public RequestDispatcher getNamedDispatcher (String name)
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 ‘/’.

Accediendo a los atributos de la petición con RequestDispatcher
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:
- include():
  • javax.servlet.include.request_uri
  • javax.servlet.include.context_path
  • javax.servlet.include.servlet_path
  • javax.servlet.include.path_info
  • javax.servlet.include.query_string
- forward():
  • javax.servlet.forward.request_uri
  • javax.servlet.forward.context_path
  • javax.servlet.forward.servlet_path
  • javax.servlet.forward.path_info
  • javax.servlet.forward.query_string
Los valores de estos atributos son los mismos que los métodos: getRequestURI(), getContextPath(), getServletPath(), getPathInfo() y getQueryString de la interface HttpServletRequest. Estos atributos se acceden como los atributos regulares, a través del método getAttribute().


RESUMEN
Ciclo de vida de un Servlet y API
  • El contenedor inicializa un servlet cargando su clase, invocando su constructor sin argumentos, e invocando el método init().
  • 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.
  • 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.
  • El contenedor finaliza la vida de un servlet invocando su método destroy().
  • La mayoría del tiempo de vida de un servlet se pasa ejecutando el método service() para una petición de un cliente.
  • Cada petición a un servlet se ejecuta en un thread separado. Solo existe una instancia de una clase servlet en particular.
  • 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.
  • HttpServlet extiende de la clase abstracta javax.servlet.GenericServlet, la cual implementa la mayoría de los métodos básicos del servlet.
  • La clase GenericServlet implementa las interfaces Servlet y ServletConfig.
  • Las clases servlets se encuentran en uno de los dos paquetes: javax.servlet y javax.sevlet.http.
  • Se puede sobrescribir el método init(), y se debe sobrescribir al menos un método de servicio (doGet(), doPost(), etc.).
HTTP y HttpServletRequest
  • Los métodos doGet() y doPost() de HttpServlet toman como argumentos los objetos HttpServletRequest y HttpServletResponse.
  • 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.).
  • Las peticiones POST poseen un cuerpo, las peticiones GET no, aunque estas últimas pueden contener parámetros de petición en su URL.
  • Las peticiones GET son idempotentes (idempotent). Es decir, son capaces de ejecutarse múltiples veces sin causar ningún efecto en el servidor. 
  • 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.
HttpServletResponse
  • Los objetos Response se utilizan para enviar información de respuesta al cliente.
  • Los métodos que más se utilizan en el objeto de respuesta HttpServletResponse son setContentType() y getWriter().
  • El método getWriter() permite realizar operaciones de escritura de HTML (u otro tipo de texto) en el flujo de salida.
  • 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.
  • El método para obtener un flujo de salida binario es getOutputStream().
  • 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”.
  • 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.
  • 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. 
  • 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.

Comprando el voucher a u$s 40

5 comentarios
Recién termine de realizar la compra del voucher para el examen de certificación SCWCD (212-083). Como ya comenté en un post anterior, los examenes del SAI tienen el prefijo 212:

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 Prometric me encontré con la siguiente información que me tranquilizo:

"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."

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.

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).

Si no conoces este programa o queres informarte más sobre él, te paso estos links para que puedas quitarte tus dudas:
* Sitio de la iniciativa SAI: http://www.sun.com/solutions/landing/industry/education/sai/index.jsp
* Acceso a cursos del SAI: http://sailearningconnection.skillport.com/
* Datos para registrarse en el SAI:
- Program name: SAI-Argentina
- Program ID: tbwg1fq8

(Hacer click sobre las imágenes para agrandarlas)

Paso 1: Si te acordas de tu Program ID, podes empezar desde el paso 4. En caso contrario, tenes que obtener el mismo desde la opción 'Personalizar' del menú superior.

Paso 2: Hacer click en la opción 'Actualizar perfil de usuario'.

Paso 3: 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 Program ID, les recomiendo copiarla (salvo que quieran poner a prueba su memoria).

Paso 4: Luego, volver a la página del SAI. Hacer click en la opción (de la barra izquierda) 'SAI Certification Discount Vouchers'.

Paso 5: Luego, se abre una ventana emergente la cuál nos solicita algunos datos. Entre estos, nos pide el Program ID y otros. En SAI-Program Name elijan el de su país. Y luego seleccionen el examen que desean rendir.

Paso 6: Una vez que envian el formulario, el browser se redirige a la página del gateway PayPal. En caso de que no esten registrados, lo hacen y podrán abonar su voucher a solo u$s 40.

Paso 7: Verifican los datos, y luego hacen click en 'Pagar Ahora'.

Paso 8: Se les confirma el pago.

Paso 9: Por último se los redirige al sitio de sun en donde encuentran la siguiente pantalla.

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 contact_sai@sun.com)
En mi caso, envié una fotografía digital de:
- Mi libreta de estudiante
- Un certificado de alumno regular

Bueno cualquier duda dejen comentarios.
EVITEN mandarme emails a mi dirección consultandome por este proceso, ya que la idea del blog es compartir las dudas y todo tipo de cosas. 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.
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.
Saludos ;)

Conceptos básicos (Servlets y JSP)

2 comentarios
Que es una JavaServer Page (JSP)?
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.
JavaServer Pages 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 J2EE. La especificación JSP está compuesta de etiquetas JSP que son embebidas en etiquetas HTML.

Diferencias entre Servlets y JSP’s
Los servlets 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.
Una aplicación web consiste en una combinación de servlets y JSP’s:
  • JSP’s: se utilizan para la presentación visual.
  • Servlets: controlan la lógica de negocio.
Que es una aplicación web?
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.
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.

El protocolo HTTP
Un mensaje HTTP es cualquier petición que es enviada desde un cliente al servidor, o cualquier respuesta desde el servidor al cliente.

Introducción Servlets

2 comentarios
Que es un servlet?
Todos los servidores poseen dos grandes responsabilidades:
  • 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.)
  • Crear una respuesta para devolverla al cliente.
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.

Servlet Container (Administrador o Contenedor de Servlets)

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.

El Servlet Container es parte del servidor web, pero este puede ser clasificado en tres tipos:
  • Standalone: Son servidores web basados en Java. El servidor web y el servlet container son partes de un solo programa.
  • 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.
  • 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.
La API de Servlets
La API está dividida en dos paquetes:

javax.servlet: Contiene las interfaces y clases genéricas de los servlets, que son independientes del protocolo.
javax.servlet.http: 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.
  • Clase java.servlet.http.HttpServlet: Extiende de java.servlet.GenericServlet.
  • Interface java.servlet.http.HttpServletRequest: Extiende de java.servlet.ServletRequest.
  • Interface java.servlet.http.HttpServletResponse: Extiende de java.servlet.ServletResponse.

Objetivos SCWCD CX-310-083

0 comentarios
Section 1: The Servlet Technology Model

1.1- 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.
1.2- 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.
1.3- 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.
1.4- 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.

Section 2: The Structure and Deployment of Web Applications

2.1- 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.
2.2- Describe the purpose and semantics of the deployment descriptor.
2.3- Construct the correct structure of the deployment descriptor.
2.4- Explain the purpose of a WAR file and describe the contents of a WAR file, how one may be constructed.

Section 3: The Web Container Model

3.1- For the ServletContext initialization parameters: write servlet code to access initialization parameters; and create the deployment descriptor elements for declaring initialization parameters.
3.2- 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.
3.3- 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.
3.4- 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.
3.5- 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.

Section 4: Session Management

4.1- Write servlet code to store objects into a session object and retrieve objects from a session object.
4.2- 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.
4.3- 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.
4.4- 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.

Section 5: Web Application Security

5.1- Based on the servlet specification, compare and contrast the following security mechanisms: (a) authentication, (b) authorization, (c) data integrity, and (d) confidentiality.
5.2- In the deployment descriptor, declare a security constraint, a Web resource, the transport guarantee, the login configuration, and a security role.
5.3- 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.

Section 6: The JavaServer Pages (JSP) Technology Model

6.1- 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.
6.2- Write JSP code that uses the directives: (a) 'page' (with attributes 'import', 'session', 'contentType', and 'isELIgnored'), (b) 'include', and (c) 'taglib'.
6.3- Write a JSP Document (XML-based document) that uses the correct syntax.
6.4- 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.
6.5- 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.
6.6- 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).

Section 7: Building JSP Pages Using the Expression Language (EL)


7.1- 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.
7.2- Given a scenario, write EL code that uses the following operators: property access (the . operator), collection access (the [] operator).

Section 8: Building JSP Pages Using Standard Actions

8.1- 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.
8.2- Given a design goal, create a code snippet using the following standard actions: jsp:include, jsp:forward, and jsp:param.

Section 9: Building JSP Pages Using Tag Libraries

9.1- For a custom tag library or a library of Tag Files, create the 'taglib' directive for a JSP page.
9.2- Given a design goal, create the custom tag structure in a JSP page to support that goal.
9.3- Given a design goal, use an appropriate JSP Standard Tag Library (JSTL v1.1) tag from the "core" tag library.

Section 10: Building a Custom Tag Library

10.1- 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.
10.2- Using the PageContext API, write tag handler code to access the JSP implicit variables and access web application attributes.
10.3- Given a scenario, write tag handler code to access the parent tag and an arbitrary tag ancestor.
10.4- 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.
10.5- 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.

Section 11: Java EE Patterns

11.1- 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.
11.2- 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.

Sun Certified Web Component Developer (SCWCD)

6 comentarios
Actualmente me estoy preparando para rendir mi segunda certificación. SCWCD (CX-310-083) (Sun Certified Web Component Developer) es uno de los tantos examenes de certificación de la plataforma JAVA creado por SUN. El programa de certificación de SUN actualmente contiene ocho exámenes de certificación sobre la plataforma Java:
- Sun Certified Java Associate (SCJA)
- Sun Certified Java Programmer (SCJP)
- Sun Certified Java Developer (SCJD)
- Sun Certified Web Component Developer (SCWCD)
- Sun Certified Business Component Developer (SCBCD)
- Sun Certified Developer For Java Web Services (SCDJWS)
- Sun Certified Mobile Application Developer (SCMAD)
- Sun Certified Enterprise Architect (SCEA)

Ver temas relacionados a la certificación SCJP.

"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. 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."
Extraído de la página oficial de Sun

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.
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 ¿Cuál es la diferencia entre estas dos versiones del examen?. Luego de buscar en la web encontré este post (en el sitio JavaRanch.com). En dicha publicación, uno de los autores de la nueva versión del examen SCWCD explica las diferencias entre ambas versiones.

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.

Bryan Basham 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 CX-310-081. En resumen, 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.

En el sitio JavaRanch.com, también encontré algunas FAQ que quitaron muchas de mis dudas. Al que le interese rendir el examen, le recomiendo leerlas atentamente.

Detalles del examen
  • Se rinde en: Centros autorizados por Prometric
  • Prerequisitos: Sun Certified Java Programmer (cualquier edición)
  • Tipo de examen: Multiple Choice y Drag and Drop
  • Número de preguntas: 69
  • Puntaje de aprobación: 70% (49 de 69 preguntas)
  • Tiempo disponible: 180 minutos
Bibliografía
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:
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.

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.
Saludos