Recetario SCDJWS

Ya soy Sun Certified Developer for Java Web Services. Y como es costumbre, procedo a contarles que tuve que hacer y dejar de hacer para agregar esta certificación a mi palmarés:

Como ya conté en un post anterior, yo compré dos vouchers de certificación allá por agosto del año pasado, aprovechando que estaban a mitad de precio. Los dos vouchers vencían en Junio, así que optimistamente comencé a estudiar para obtener la SCBCD, certificación que obtuve en marzo de este año.

Por mi dejadez y descuido, estuve sin tocar un libro de Java hasta finales de Junio, cuando recordé el voucher que tenía pendiente y lo próximo de su vencimiento. Sin tener otra alternativa, programé rendir el SCDJWS 5 el 11 de Junio, un día antes de su vencimiento.

Ahora, mi experiencia práctica en Web Services es bastante...básica. A lo mucho he hecho unos cuantos clientes de WS en Axis, y eso es todo; por lo que necesitaba empezar por lo básico, y empezar cuanto antes dado que tenía menos de 15 días.

Pero antes, unas precisiones sobre el examen. El SCDJWS 5.0 es un exámen bastante nuevo, y como tal no existen guías de certificación ni exámenes de ejemplo aún. Pero, para certificarse basta con 42%. A pesar de que la Web de Sun diga lo contrario, el passing score es de 42%. Créanme, así dice en mi report de Prometric y así dicen los foristas de Javaranch.

Volviendo al relato,entonces empecé mi preparación. Como mencioné no existe aún una guía para el exámen; así que buceando por la red, encontré el post de un tipo que había aprobado la versión beta del exámen, y que recomendaba leer SOA Using Java Web Services de Mark D. Hansen (aunque decía que no cubría todos los temas del exámen). Dado que era la única sugerencia que encontré (casi todo lo que encontré fue para la versión anterior del exámen), me dispuse a comenzar su lectura.

Sólamente leí dos capítulos, que produjeron unos cuantos posts. El libro es bastante bueno y completo, pero era demasiado contenido para un novato para mí. Sin embargo, el leer ese par de capítulos me dio una buena idea de lo que me esperaba (un sinnúmero de especificaciones por leer).

Entonces, recurrí a Amazon para buscar un libro de Web Services que cubra JAX-WS (la API en la que te evalúan) y que sea sencillo. Para mi sorpresa, habían poquísimos libros que tocaban JAX-WS (en efecto, el examen es bastante nuevo xD), pero entre los pocos listados uno prometía: Java Web Services: Up and Running de Martin Kalin.

El libro de Kalin estaba más orientado a mi perfil (newbie), y con lo que ya había leído en Hansen me fue iluminando poco a poco en el mundo de los Web Services. El libro didáctico y sencillo, y se apoya en bastante código fuente y ejemplos prácticos. Pero eso no basta para dar un exámen de certificación, así que estando al 80% dejé el libro, y me dispuse a buscar otra fuente.

La encontré en las SCDJWS 5 Study Notes de Ivan Krizsan. Iván había dado el exámen, lo había aprobado y comparte sus notas con el que quiera leerlas. El documento no tiene la didáctica de un libro, pero extrae de las especificaciones los puntos que vienen en el examen (cubre casi todos los objetivos). Este pdf si me lo leí completito; y terminando me dispuse a buscar preguntas de ejemplo para ver que tanto había asimilado.


Lastimosamente, no las encontré. El exámen es demasiado nuevo, por lo que todavía no salen simuladores, así que tuve que conformarme con preguntas de la versión anterior del examen, en los mocks de Actualtests. La versión anterior y la actual coinciden en muchos temas (WSDL, UDDI, XML Schema, JAXP, etc), por lo que traté de responder sólamente las preguntas que sabía podían venirme en el examen. Una buena selección de ellas pueden ubicarlas en el blog. Resolviendo las preguntas me di cuenta que andaba algo flojo en WSDL y XML, por lo que apoyé en J2EE Web Services de Richard Monson-Haefel para aclarar las cosas (este libro cubre los objetivos de la versión anterior, pero en temas de WSDL y XML los temas coinciden); y para entender mejor los patrones en los que te evalúan le di una repasadita a Core J2EE Patterns: Best Practices and Design Strategies de Deepak Alur,John Crupi y Dan Malks.

Todo eso lo hice en más o menos 13 días. Faltando ya tres días para el examen, me puse a repasar los temas en los que estaba flojo de la Guía SCDJWS 5 de Mikalai Zaikin; que tiene mejor cobertura de temas que la de Iván, pero por eso también es más extensa. El 9 de Junio detuve mi preparación, y me resigné a mi suerte.

Llegó el día del examen, el cúal rendí en Cibertec. El examen era de 65 preguntas, y la gran mayoría trataba de casos de aplicación prácticos. Eran preguntas del tipo: "En la empresa A, requieren una aplicación con tales requisitos no funcionales, y tienen tantas limitantes. ¿Que tecnología se debe usar?", aunque también estaban las de dominio del API y los estándares (aunque en minoría). Terminé el examen, y a la salida la misma señorita sonriente de la vez pasada me informaba que estaba certificado.

Todavía no tengo claro cúal será el siguiente paso. Tal vez podría ser el Certified Scrum Master, aprovechando el curso que se viene, o tal vez el Certified Software Development Associate de la IEEE. En cuanto me decida les aviso, hasta ese entonces planeo tomarme un descanso. Hasta otra!!

JAX-WS: Un cliente y un servidor

(Imagen : Rembrandt - La ascención de Cristo y María Magdalena)

Es hora de hacer un ejemplo, que ya estábamos demasiado "académicos". Se tendrá una clase de implementación Hello, que estará anotada como endpoint de web service mediante @WebService. Hello declara un sólo método denominado sayHello, anotado con @WebMethod. @WebMethod expone al método anotado a los clientes del Web Service. El método sayHello devuelve un saludo a los clientes, usando el nombre pasado como parámetro para armar el saludo. La clase de implementación define un constructor por defecto público, que no recibe argumentos (parámetros).

package helloservice.endpoint;

import javax.jws.WebService;

@WebService
public class Hello{
private String message = new String("Hello, ");

public void Hello(){}

@WebMethod
public String sayHello(String name){
return message + name + ".";
}
}


Ahora veamos al cliente. HelloClient es un programa Java stand-alone que accede al método sayHello de HelloService. Hace esta llamada a través de un port, un objeto local que actúa como proxy del servicio remoto. Este port es creado en tiempo de desarrollo por la herramienta wsimport, que genera artefactos portables de JAX-WS en base a un archivo WSDL.

AL invocar métodos remotos en el port, el cliente realiza lo siguiente:

Se utiliza la anotación javax.xml.ws.WebServiceRef para declarar una referencia a un web service. @WebServiceRef utiliza el elemento wsdlLocaltion para especificar el URI del WSDL del servicio desplegado

@WebServiceRef(wsdlLocation="http://localhost:8080/helloservice/hello?wsdl")
static HelloService service;


Se obtiene un proxy para el servicio, tambien conocido como port, al invocar getHelloPort en el service.

Hello port = service.getHelloPort();


El port implementa la SEI definida por el servicio.

Se invoca al método sayHello del port, pasándole al servicio un name.

String response = port.sayHello(name);


Aquí tenemos todo el código de HelloClient:

package simpleclient;

import javax.xml.es.WebServiceRef;
import helloservice.endpoint.HelloService;
import helloservice.endpoitn.hello;

public class HelloClient{
@WebServiceRef=(wsdlLocation="http://localhost:8080/helloservice/hello?wsdl")
static HelloService service;

public static void main(String[] args){
try{
HelloClient client = new HelloClient();
client.doTest(args);
}catch(Exception e){
e.printStackTrace();
}

}

public void doTest(String[] args){
try{
Hello port = service.getHelloPort();
String name;
if (args.length > 0){
name = args[0];
}else{
name = "No Name";
}
String response = port.sayHello(name);
System.out.println(response);

}catch(Exception e){
e.printStackTrace();
}
}
}


Basado en la Guía SCDJWS de Mikalai Zaikin

Creating a New ServiceBinding Object

El objeto JAXR ServiceBinding se corresponde con la estructura UDDI bindingTemplate, y representa la información técnica necesaria para acceder a un servicio. Puede tener cualquier número de specification links y sólamente un Access URI.

Un objeto ServiceBinding no tiene un nombre, pero casi siempre tendrá un accessURI, que es la dirección electrónica del servicio. Por ejemplo:

ServiceBinding binding = lifeCyclemngr.createServiceBinding();
service.addServiceBinding(binding);
binding.setValidateURI(false);
binding.setAccessURI("http://qwerty.org/iop");

Cuando se guarda un ServiceBinding en un registro UDDI, el registro verifica que el accessURI es un URL válido. La llamada al método setValidateURI(false) sobreescribe este comportamiento. Si se comenta esta línea y el URL especificado no existe, el programa lanzará una excepción indicando que la URL es inválida.

Entonces, la B es la alternativa de nuestra elección.

Pregunta tomada de ActualTests

Mapping JAXR to the UDDI Inquiry API


La Inquiry API de UDDI tiene básicamente dos tipos de operaciones SOAP: find_XXX y get_XXX. Las operaciones find_XXX se mapen directamente a métodos definidos en BusinessQueryManager, y muchas operaciones get_XXX definidas en la Inquiry API de UDDI están definidas implícitamente al navegar los objetos del infomodel.

La interfaz BusinessQueryManager define varios métodos findXXX() que se corresponden con las operaciopnes fin de la Inquiry API de UDDI.

Por lo que la alternativa B sería nuestra mejor opción.

Pregunta tomada de ActualTests

The RegistryObject Interface

La mayoría de interfaces definidas en el modelo de información de JAXR extienden de la interfaz javax.xml.registry.infomodel.RegistryObject. Esta interfaz define alrededor de tres docenas de métodos, de los cúales sólo algunos aplican a los tipos de datos UDDI.

La primera vez que se guardan RegistryObjects de ciertos tipos (como Organization y Concept) en un registro UDDI, se les asigna un UUID Key (Universally Unique Identifier) . Se puede obtener el key que el registro ha generado para un objeto invocando a getKey().

Esto con concuerda con la alternativa A y la alternativa B.

Pregunta tomada de ActualTests

Mapping JAXR to the UDDI Inquiry API

Es posible buscar por Organization, Service, ServiceBinding, ClassificationScheme y objetos Concept mediante el criterio classifications.

Paras buscar mediante Classification, es necesario instanciar la clase Classification, lo que significa que primero hay que encontrar su ClassificationScheme y despues crear una instancia de Classification. Al utilizar múltiples objetos Classification en este criterio, la búsqueda se conducirá como una búsqueda AND.

El parámetro de búsqueda classifications se corresponde con elemento de búsqueda UDDI categoryBag.

El objeto Organization es la raíz de una entrada de negocio UDDI. Representa una instancia de la estructura de datos UDDI businessEntity.

Un objeto Organization contiene un nombre de negocio y descripción, información de contacto, categoría de industria y valores de identificación, junto a una colección de cero o más objetos BusinessService, cada uno de los cúales representa un tipo de servicio electrónico (por lo general un Web Service o un sitio Web).

Lo que nos lleva a seleccionar la alternativa D.

Pregunta tomada de ActualTests

The Concept Information Object

En UDDI la estructura de datos tModel se utiliza para describir las especificaciones técnicas de un Web Service. Un TModel técnico puede hacer referencia a un documento WSDL, un documento de esquema XML, u otra especificación. En el caso de Web Services J2EE, un tModel técnico por lo general se refiere a un documento WSDL que describe un web Service.

En JAXR el objeto Concept representa un tModel técnico. Un objeto Concept se crea independientemente de un Organization y es referido por uno o más Web Services. Esto es útil cuando un tModel técnico hace referencia a un documento WSDL estándar.

Pregunta tomada de ActualTests

DataHandler

La clase DataHandler nos facilita en SAAJ el crear y agregar archivos adjuntos a mensajes SOAP. Cuando se agrega un adjunto a un mensaje SAAJ, el objeto adjuntado siempre es embebido por un objeto DataHandler. Esto puede ser oculto y ocurrir detrás del escenario, o puede hacerse explícitamente. Así:

AttachmentPart pdfAttach = message.createAttachmentPart();
FileDataSource file = new FileDataSource("manuscript.pdf");
DataHandler pdfDH = new DataHandler(file);
pdfAttach.setDataHandler(pdfDH);

La clase DataHandler puede ser instanciada para representar cualquier tipo de data: una imagen, un documento PDF, un Documento DOM, etc. DataHandler provee métodos para leer y escribir streams de data, acceder a tipos MIME de data y crear objetos Java que representen data en el stream.

Por lo que señalaríamos a la alternativa B como correcta.

Pregunta tomada de ActualTests

The SOAPHeader Type

El elemento Header de SOAP puede tener cero o más header blocks. En SAAJ, el tipo SOAPHeader representa al elemento Header, y el tipo SOAPHeaderElement representa un header block individual. SOAPHeader provee métodos para agregar, examinar y remover objetos SOAPHeaderElement, lo que agrega, examina o remueva header blocks de un documento SOAP.

Los receptores de SOAP pueden usar esta funcionalidad para acceder a todos los header blocks, header blocks asociados con un actor en particular, o los header blocks con mustUnderstand igual a true para un actor en particular. La clase SOAPHeader provee 5 métodos para examinar o extraer header blocks. La definición de la clase SOAPHeader es:

package javax.xml.soap;
import java.util.Iterator;

public interface SOAPHeader extends SOAPElement {
public SOAPHeaderElement addHeaderElement( Name name )
throws SOAPException;
public Iterator extractHeaderElements(String actor);
public Iterator examineHeaderElements(String actor);
public Iterator examineMustUnderstandHeaderElements(String actor);
public Iterator examinAllHeaderElements();
public Iterator extractAllHeaderElements();
}


Dicho esto, la alternativa A es la correcta.

Pregunta tomada de ActualTests

The SOAPElement Type

Los elementos específicos a la aplicación que no son parte del namespace XML de SOAP se representan mediante objetos del tipo SOAPElement. Este tipo puede representar cualquier elemento XML. Contiene métodos para acceder a elementos hijo, atributos, información del namespace y demás. Como cualquier elemento XML puede contener a otros elementos XML, un SOAPELement puede contener otros objetos SOAPElement. El tipo SOAPElement modela una estructura jerárquica que se corresponde con la estructura jerárquica de XML. El tipo SOAPElement es supertipo de otros tipos SOAP, incluyendo SOAPEnvelope, SOAPBody, SOAPBodyElement, SOAPHeader, SOAPHeaderElement y los elementos fault. El tipo Node es el supertipo de SOAPElement. El tipo SOAPElement se define así:

package javax.xml.soap;
import java.util.Iterator;

public interface SOAPElement extends Node, org.w3c.dom.Element {
public SOAPElement addAttribute(Name name, String value)
throws SOAPException;
public SOAPElement addChildElement(Name name) throws SOAPException;
public SOAPElement addChildElement(SOAPElement element)
throws SOAPException;
public SOAPElement addChildElement(String localName) throws SOAPException;
public SOAPElement addChildElement(String localName, String prefix)
throws SOAPException;
public SOAPElement addChildElement(String localName, String prefix,
String uri) throws SOAPException;
public SOAPElement addNamespaceDeclaration(String prefix, String uri)
throws SOAPException;
public SOAPElement addTextNode(String text);
public Iterator getAllAttributes();
public String getAttributeValue(Name name);
public Iterator getChildElements();
public Iterator getChildElements(Name name);
public Name getElementName();
public String getEncodingStyle();
public Iterator getNamespacePrefixes();
public String getNamespaceURI(String prefix);
public Iterator getVisableNamespacePrefixes();
public boolean removeAttribute(Name name);
public boolean removeNamespaceDeclaration(String prefix);
public boolean removeContents();
public void setEncodingStyle(String encodingStyle);
}


Entonces, la A se convertiría en nuestra alternativa.

Pregunta tomada de ActualTests

Working with SOAP Documents



SAAJ provee un número de interfaces que se pueden usar para construir un documento SOAP simple. Aquí tenemos el diagrama de herencia:




Un mensaje o documento SOAP es una instancia XML compuesta por elementos y atributos. Por conveniencia, cada parte de un documento SOAP tiene un tipo correspondiente SAAJ. El Envelope es representado por SOAPEnvelope, el Header es representado por SOAPHeader, el Body por SOAPBody y así sucesivamente. El tipo SOAPElement es utilizado para elementos específicos de la aplicación que no pertenecen al namespace de SOAP.

El supertipo de SOAPElement, y por consiguiente de todos sus subtipos, es Node. La interfaz Node nos provee de unos cuantos métodos útiles para navegar a través de un árbol jerárquico de elementos, remover nodos del árbol y marcar nodos para reciclaje.

Con lo que queda demostrado que la B es la opción válida.

Pregunta tomada de ActualTests

Creating a SOAP Message


MessageFactory es la factory principal de SAAJ. Con esta clase se comienza cada vez que se crea un SOAP Message.

La clase MessageFactory es abstracta y no puede ser instanciada. Mediante el método new Instance() se crea un objeto que pertenece a un subtipo de MessageFactory.

MessageFactory posee dos métodos createMessage(). El primero no recibe argumentos , y simplemente genera una instancia de SOAPMessage.

La parte MIME principal de un mensaje SwA es siempre el documento XML SOAP. Cuando el mensaje no tiene adjuntos, se puede usar simplemente los métodos getSOAPBody y getSOAPHeader de SOAPMessage para acceder a estos elementos del mensaje SOAP directamente. Por ejemplo:

MessageFactory msgFactory = MessageFactory.newInstance();
SOAPMessage message = msgFactory.createMessage();
message.getSOAPHeader().detachNode();
SOAPBody body = message.getSOAPBody();

Lo que encaja a la perfección con la alternativa D.

Pregunta tomada de ActualTests

JAXP

JAXP (Java API for XML Processing) permite a las aplicaciones parsear, transformar, validar y consultar documentos XML mediante un API que es independiente de una implementación de procesador XML particular. JAXP provee una capa conectable que permite a los vendedores proveer sus propias implementaciones sin introducir dependencias en el código de la aplicación. Usando este software, los desarrolladores de aplicaciones y herramientas pueden construir aplicaciones Java de soporte XML para e-commerce, integración de aplicaciones y publicación web.

JAXP es un componente estándar de la plataforma Java. Una implementación de JAXP 1.3 está incluida en J2SE 5.0 y una implementación de JAXP 1.4 está en Java SE 6.0.

Deducimos entonces que la A es la correcta.

Pregunta tomada de ActualTests

XSLT


XSLT (XML Stylesheet Language for Transformations) permite el escribir data XML en un archivo, convertir data XML a otros formatos y, junto con SAX, convertir data legacy a formato XML.

Funciones: Convertir data XML a otros formatos, y escribir data XML a archivos.

Capacidades: Dado un conjunto de instrucciones de transformación, convierte data en formato XML a otro formato.

Esto nos lleva a escoger la A.

Pregunta tomada de ActualTests

SAX

SAX (Simple API for XML Parsing) provee un mecanismo orientado a eventos, de acceso serial que procesa la data XML un elemento a la vez. SAX es un API push, lo que implica que el cliente implementa callbacks que son invocados para cuando cierta data ,como elementos, es encontrada al momento de parsear el documento.

SAX usa menos capacidad de procesamiento y de memoria, pero no nos da acceso al modelo de objetos completo de un documento XML. Es aplicable en aplicaciones del lado del servidor y de alta performance que filtran data.

SAX se orienta al procesamiento independiente del estado, donde el manejo de un elemento no depende del elemento anterior.

Por esto, la C es la correcta.

Pregunta tomada de ActualTests

SOAP over HTTP

Los códigos de éxito HTTP de nivel 200 son utilizados para indicar que un request SOAP fue recibido y procesado correctamente. Los códigos de éxito HTTP 200 OK y 202 Accepted son utilizados en Web Services.

200 OK: Cuando una operación SOAP genera un mensaje SOAP response, el código de respuesta HTTP para procesamiento exitoso es 200 OK. Este código de respuesta indica que el mensaje de respuesta no es un fault, y que contiene un mensaje SOAP response normal.

202 Accepted: Este codigo de respuesta significa que el request fue procesado exitosamente pero que no hay data SOAP de respuesta. Este tipo de operación SOAP es similar a los métodos Java que retornan void.

Aunque los mensajes SOAP One-Way son conceptualmente unidireccionales, cuando se solicita sobre HTTP siempre se envía una respuesta al emisor. Los mensajes SOAP One-way no devuelven SOAP Faults o resultados de algún tipo, por lo que el código de respuesta HTTP 202 Accepted indica sólamente que el mensaje llegó al receptor (no indica que el mensaje fue procesado con éxito)

Lo que nos lleva a seleccionar la alternativa A.

Pregunta tomada de ActualTests

EJB Endpoints

Es recomendable usar un EJB Endpoint cuando:

  • Ya tenemos un EJB stateless existente que se requiere exponer como Web Service
  • La lógica de negocio que utiliza el servicio se encuentra en la capa EJB, de modo que el endpoint y la lógica de negocio se mantengan en la misma capa.
  • Se requiere de los servicios de transacciones y seguridad que ofrece el contenedor EJB.
  • Se quiere tener un control de seguridad a nivel de método.
  • Se requiere de un contenedor que administre los accesos concurrentes a instancias del endpoint.

Entonces, la B es nuestra respuesta.

Pregunta tomada de ActualTests

The UDDI Inquiry API


UDDI requiere soporte de SOAP sobre HTTP. En efecto, las especificación UDDI requiere que los registros UDDI soporte una serie de operaciones de Web Service basadas en SOAP, llamadas el Programming API de UDDI. Estos mensajes SOAP utilizan el modo de messaging Document/Literal y estan descritas a detalle en el documento WSDL ubicado en la web de UDDI.org. Esto hace de UDDI un Web Service, como cualquier otro Web Service basado en SOAP y WSDL. Los Web Services de UDDI se dividen en dos API's basadas en WSDL y SOAP: la Inquiry API y la Publishing API. La Inquiry API se usa para buscar y leer data de un registro UDDI, mientras que la Publishing API se usa para agregar, modificar o eliminar data de un registro UDDI.

Lo que nos hace quedarnos con la C y la D.

Pregunta tomada de ActualTests

The UDDI Publishing API


Las organizaciones utilizan la Publishing API para agregar, modificar o eliminar información de un registro UDDI. Esta API perimite a las organizaciones el guardar sus propias estructuras businessEntity, businessService, bindingTemplate, tModel y publisherAssertion en un registro UDDI, y removerlas cuando sea necesario.

Como la Inquiry API, la Publishing API es un Web Service basado en el modo de messaging Document/Literal de SOAP, y es descrita mediante un documento WSDL. A diferencia de la Inquiry API, la Publishing API requiere que los operadores UDDI utilicen HTTPS (HTTP con SSL 3.0) para efectos de confidencialidad y como forma de autenticación. Además, cada mensaje (excepto el de login) debe incluir un token de autorización que es procesado por el registro UDDI al inicio de la sesión. Cada sesión tiene un token de autenticación único, que sólamente es válido durante la existencia de la sesión.

Entonces, la D es nuestra respuesta.

Pregunta tomada de ActualTests

The businessService and bindingTemplate Structures

El tipo complejo businessEntity declara un elemento businessServices, que puede contener uno o muchas estructuras de datos businessService. Cada businessService contiene uno o más entradas bindingTemplate. La relación entre la estructura businessService y la estructura bindingTemplate es similar a la relación entre los elementos service y port del WSDL: un businessService representa una agrupación de entradas bindingTemplate relacionadas. Un bindingTemplate describe un endpoint de WebService y representa la "huella técnica" de un Web Service. En otras palabras, lista todos los tipos tModel que describen un Web Service, que describen las especificaciones técnicas de un Web Service.

Por esto, la B es la correcta.

Pregunta tomada de ActualTests