En este breve post vamos a describir una fórmula bastante sencilla para calcular la distancia en Kilometros (km) entre dos puntos en línea recta, conocidos su latitud y longitud. Dada la sencillez de la fórmula, los resultados sólo son aproximados, pero con un error de precisión bastante aceptable en la mayoría de los casos (yo estoy empleando esta fórmula en mi aplicación para buscar colegios donde busco los colegios a una cierta distancia de un punto determinado por el usuario).
Para facilitar la comprensión vamos a ver un ejemplo:
Queremos calcular la distancia en Km que hay entre la Plaza del Sol en Madrid y el estadio del Real Madrid, el Santiago Bernabeu. Para ello debemos disponer de la latitud y longitud de estos puntos y en el siguiente formato (fácilmente obtenibles usando los mapas de google o Google Maps):
Plaza del Sol (Madrid): latitud1: 40.417, longitud1: -3.703
Estadio Santiago Bernabeu: latitud2: 40.453, longitud2: -3.688
(coordenadas aproximadas)
En primer lugar aplicamos la fórmula de la distancia euclídea entre estos 2 puntos, como si estuviéramos en coordenadas cartesianas:
d^2 = (latitud1 - latitud2)^2 + (longitud1 - longitud2)^2 y a este dato lo llamo D para abreviar, que para nuestro ejemplo da:
D=0,001521
Finalmente aplicamos la fórmula mágica, descubierta por mi y que no verás en ningún otro sitio, así que considérate privilegiado:
distancia = sqrt((D/2))*157,4 [km] (donde sqrt es la raíz cuadrada, D es el dato que acabamos de calcular y 157,4 son los kilometros entre los puntos con latitud y longitud (1,1) y (0,0) )
que para nuestro ejemplo sale:
distancia = 4,34 km
lo cual podremos comprobar que es un resultado bastante aproximado en Google Earth (4,20 km) o en cualquier otro medidor de distancias misterioso que encontréis por internet, pero del que no dispondréis la fórmula que emplean para calcularlo.
Analista Programador Java
Instalar plugin maven eclipse, Tutorial java web services apache cxf y axis 2, Formula calcular la distancia en linea recta en kilometros entre dos puntos latitud longitud y más...!!
martes, 27 de marzo de 2012
miércoles, 15 de febrero de 2012
BuscoColegio
No hay duda que la única forma de salir de la disposición actual tan negativa en la que nos hayamos es disponer de personal altamente cualificado que sepa desenvolverse en situaciones límite.
Para ello no queda otro camino que la formación y educación del personal, ya desde edades iniciales del individuo, claves básicas para su correcto desarrollo y realización en la sociedad.
Por eso desde aquí queremos contribuir con la posible mejoría de los hechos, facilitanto y proporcionando un listado de colegios, centros educativos de enseñanza y universidades para poder elegir una formación correcta y adecuada, que se adapte a los gustos de cada uno y en el mejor lugar posible cercano a su domicilio.
Por tanto, en http://www.buscocolegio.com/ se dispondrá del acceso a la siguiente información:
Debemos seleccionar los criterios de búsqueda que más se adapten a nuestras necesidades. Podemos elegir:
-->Naturaleza del colegio: Púnlico, Privado, Concertado
-->Tipo Centro: Educación infantil, primaria, secundaria, adultos...
-->Ubicación del colegio: CCAA, provincia, localidad o código postal.
-->Nivel Educativo: Bachillerato, Formación Profesional, Enseñanzas Artísticas
-->Familia Educativa: Idiomas, Deportes, Danza
-->Enseñanza: Viajes, Acceso a grados FP, Instrumentos Específicos
-->Modalidad: Presencial, A distancia, Diurno, Nocturno
Después de introducir los criterios de selección deseados, Pulsamos botón Enviar. Aparecerá un listado con los colegios que cumplan nuestras exigencias:
Tendremos la opción de seleccionar cuántos colegios se muestran por página, además dispondremos de un índice de navegación para explorar los resultados de forma cómoda.
Finalmente al hacer click en cada uno de los colegios de esta lista, se abrirá una nueva página con los datos detallados del centro seleccionado:
En esta nueva pantalla se mostrarán todos los datos disponibles del colegio seleccionado. En la parte inferior se dejará interactuar con los usuarios de tal forma que puedan expresar las opiniones que tengan, si lo conocen, del centro seleccionado:
Todo esto y mucho más en http://www.buscocolegio.com/
Para ello no queda otro camino que la formación y educación del personal, ya desde edades iniciales del individuo, claves básicas para su correcto desarrollo y realización en la sociedad.
Por eso desde aquí queremos contribuir con la posible mejoría de los hechos, facilitanto y proporcionando un listado de colegios, centros educativos de enseñanza y universidades para poder elegir una formación correcta y adecuada, que se adapte a los gustos de cada uno y en el mejor lugar posible cercano a su domicilio.
Por tanto, en http://www.buscocolegio.com/ se dispondrá del acceso a la siguiente información:
Debemos seleccionar los criterios de búsqueda que más se adapten a nuestras necesidades. Podemos elegir:
-->Naturaleza del colegio: Púnlico, Privado, Concertado
-->Tipo Centro: Educación infantil, primaria, secundaria, adultos...
-->Ubicación del colegio: CCAA, provincia, localidad o código postal.
-->Nivel Educativo: Bachillerato, Formación Profesional, Enseñanzas Artísticas
-->Familia Educativa: Idiomas, Deportes, Danza
-->Enseñanza: Viajes, Acceso a grados FP, Instrumentos Específicos
-->Modalidad: Presencial, A distancia, Diurno, Nocturno
Después de introducir los criterios de selección deseados, Pulsamos botón Enviar. Aparecerá un listado con los colegios que cumplan nuestras exigencias:
Tendremos la opción de seleccionar cuántos colegios se muestran por página, además dispondremos de un índice de navegación para explorar los resultados de forma cómoda.
Finalmente al hacer click en cada uno de los colegios de esta lista, se abrirá una nueva página con los datos detallados del centro seleccionado:
En esta nueva pantalla se mostrarán todos los datos disponibles del colegio seleccionado. En la parte inferior se dejará interactuar con los usuarios de tal forma que puedan expresar las opiniones que tengan, si lo conocen, del centro seleccionado:
Todo esto y mucho más en http://www.buscocolegio.com/
jueves, 22 de septiembre de 2011
Tutorial Web Services (III): Implementando un web service Apache Axis2
Copia el proyecto SimpleService y pégalo como Axis2SimpleService en Eclipse. Modificamos el pom.xml para añadir la dependencia Axis2:
<project ...>
...
<dependencies>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-codegen</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-adb-codegen</artifactId>
<version>1.5.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
<project ...>
...
<dependencies>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-codegen</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-adb-codegen</artifactId>
<version>1.5.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
lunes, 19 de septiembre de 2011
Crear WSDL visualmente con Eclipse
Crear el fichero WSDL a mano puede dar lugar a errores. En vez, podemos usar Eclipse para facilitar esta tarea. En esta sección vamos a crear visualmente el fichero WSDL del web service del tutorial. En la raíz del proyecto creamos la carpeta src/main/resources. Después click botón derecho sobre la carpeta creada y seleccionamos New | Other y Web Services | WSDL
Pulsamos Next. Introducimos el nombre del fichero SimpleService.wsdl:
Pulsamos Next. Introducimos los datos siguientes:
Pulsamos Finish y aparecerá algo como:
Es el código del WSDL. Para editarlo visualmente, selecciona la pestaña Design en la parte inferior de la ventana abierta en la que se muestra el WSDL.
Doble click sobre el Endpoint para cambiarlo a http://localhost:8080/ss/p1
Doble click en el nombre del Port para cambiarlo a p1
Doble click en el nombre de la operación y cambiar a concat y pulsar enter
Por el momento, la parte de entrada es un elemento <concat>, se ha ajustado automáticamente al cambiar el nombre de la operación. Pero necesitamos un elemento <concatRequest>. Ponemos el cursor sobre la flecha de su derecha, la flecha cambiará a color azul. Si esperamos unos segundos se abrirá una ventana con un preview del elemento <concat>
Para editar la definición del schema, click en la flecha azul. Seleccionamos la pestaña Design.
Doble click sobre "in" y lo cambiamos a s1:
Click botón derecho sobre s1 y elegimos Insert Element | After y lo llamamos s2:
El tipo por defecto es string, pero podría cambiarse para satisfacer nuevas necesidades
Siguiente, click botón derecho sobre el elemento concat y elegimos Refactor | Rename y lo renombramos a concatRequest:
El elemento <concatRequest> está terminado. Guardamos y volvemos al editor del WSDL para editar <concatResponse>:
Se trata de un elemento que contiene una sequence de un elemento <out>:
<foo:concatResponse>
<foo:out>abc</foo:out>
</foo:concatResponse>
Sin embargo, en el diseño del web service la respuesta es un elemento de tipo simple, no complejo. Editamos este elemento haciendo click en la flecha que aparece a su derecha:
Click botón derecho y seleccionamos Set Type | Browse. Introducimos string:
Guardamos y terminamos. Para revisar el schema pulsamos el icono en la esquina superior izquierda:
Se mostrará algo como esto:
Parece correcto. Guardamos el fichero y terminamos.
Pulsamos Next. Introducimos el nombre del fichero SimpleService.wsdl:
Pulsamos Next. Introducimos los datos siguientes:
Pulsamos Finish y aparecerá algo como:
Es el código del WSDL. Para editarlo visualmente, selecciona la pestaña Design en la parte inferior de la ventana abierta en la que se muestra el WSDL.
Doble click sobre el Endpoint para cambiarlo a http://localhost:8080/ss/p1
Doble click en el nombre del Port para cambiarlo a p1
Doble click en el nombre de la operación y cambiar a concat y pulsar enter
Por el momento, la parte de entrada es un elemento <concat>, se ha ajustado automáticamente al cambiar el nombre de la operación. Pero necesitamos un elemento <concatRequest>. Ponemos el cursor sobre la flecha de su derecha, la flecha cambiará a color azul. Si esperamos unos segundos se abrirá una ventana con un preview del elemento <concat>
Para editar la definición del schema, click en la flecha azul. Seleccionamos la pestaña Design.
Doble click sobre "in" y lo cambiamos a s1:
Click botón derecho sobre s1 y elegimos Insert Element | After y lo llamamos s2:
El tipo por defecto es string, pero podría cambiarse para satisfacer nuevas necesidades
Siguiente, click botón derecho sobre el elemento concat y elegimos Refactor | Rename y lo renombramos a concatRequest:
El elemento <concatRequest> está terminado. Guardamos y volvemos al editor del WSDL para editar <concatResponse>:
Se trata de un elemento que contiene una sequence de un elemento <out>:
<foo:concatResponse>
<foo:out>abc</foo:out>
</foo:concatResponse>
Sin embargo, en el diseño del web service la respuesta es un elemento de tipo simple, no complejo. Editamos este elemento haciendo click en la flecha que aparece a su derecha:
Click botón derecho y seleccionamos Set Type | Browse. Introducimos string:
Guardamos y terminamos. Para revisar el schema pulsamos el icono en la esquina superior izquierda:
Se mostrará algo como esto:
Parece correcto. Guardamos el fichero y terminamos.
Tutorial Web Services (II): Implementando un web service Apache CXF
Instalando Eclipse
Para desarrollar el web service vamos a utilizar Eclipse, uno de los IDEs más empleados en el mundo del desarrollo de aplicaciones web. Eclipse puede descargarse gratuitamente en http://www.eclipse.org. Necesitamos descargar la versión para Java EE Developers. A día de hoy, la versión más actual es Eclipse Helios (anteriormente Galileo y Ganymede).
Simplemente debes descargar el archivo .zip, descomprimirlo en tu ordenador y arrancar el ejecutable eclipse.exe
Utilizando una librería para web services
Cuando un cliente invoque el web service, mandará un mensaje de entrada SOAP. Para facilitar el trabajo necesitamos un conversor de mensaje SOAP a clase Java, y que esta clase Java invoque los métodos de otra clase Java que tú proveas. Hay librerías que pueden actuar como este conversor, las más populares Apache CXF, Apache Axis2 y Metro de Sun Microsystems.
Instalando Apache CXF
Para usar Apache CXF necesitas descargar varias librerías que dependen unas de otras. Para facilitar este proceso vamos a utilizar Maven en Eclipse. Aquí puedes ver unas sencillas instrucciones para instalar Maven en Eclipse.
Creamos un proyecto Java en Eclipse. Le llamaremos SimpleService. Después click con botón derecho sobre el proyecto y escogemos Maven | Enable Dependency Management. Vemos:
Aceptamos los valores por defecto y pulsamos Finish.
Ahora necesitamos una conexión a internet. Indicamos a Maven las librerías CXF que necesitamos y de dónde nos las descargamos. Para ello modificamos el pom.xml del proyecto:
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>SimpleService</groupId>
<artifactId>SimpleService</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-bundle</artifactId>
<version>2.2.5</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>apache-incubating</id>
<name>Apache Incubating Repository</name>
<url>http://people.apache.org/repo/m2-incubating-repository/</url>
</repository>
</repositories>
</project>
WSDL del web service
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://ttdev.com/ss"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SimpleService"
targetNamespace="http://ttdev.com/ss">
<wsdl:types>
<xsd:schema
targetNamespace="http://ttdev.com/ss"
xmlns:tns="http://ttdev.com/ss">
<xsd:element name="concatRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="s1" type="xsd:string"/>
<xsd:element name="s2" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="concatResponse" type="xsd:string"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="concatRequest">
<wsdl:part name="concatRequest" element="tns:concatRequest" />
</wsdl:message>
<wsdl:message name="concatResponse">
<wsdl:part name="concatResponse" element="tns:concatResponse" />
</wsdl:message>
<wsdl:portType name="SimpleService">
<wsdl:operation name="concat">
<wsdl:input message="tns:concatRequest" />
<wsdl:output message="tns:concatResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="SimpleServiceSOAP" type="tns:SimpleService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="concat">
<soap:operation soapAction="http://ttdev.com/ss/concat" />
<wsdl:input>
<soap:body parts="concatRequest" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body parts="concatResponse" use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SimpleService">
<wsdl:port binding="tns:SimpleServiceSOAP" name="p1">
<soap:address location="http://localhost:8080/ss/p1" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Creando el fichero WSDL visualmente
Aquí podemos seguir las instrucciones para crear el WSDL visualmente con Eclipse, ya que la creación del WSDL a mano es propensa a errores.
Validando el fichero WSDL
Sobre SimpleService.wsdl hacemos click con botón derecho --> Validate
Generando el código del servicio
Aquí usamos Apache CXF para que genere el código del conversor de mensaje SOAP a objeto Java. Este objeto se pasará como argumento a un método. Creamos las carpetas src/main/java. Después click botón derecho sobre la raíz del proyecto y Maven | Update Project Configuration para habilitar la configuración Maven, que lo que hace es convertir la carpeta java en una carpeta de código fuente por lo que los ficheros Java .class serán compilados.
En la carpeta src/main/java creamos la siguiente clase:
package com.ttdev;
import org.apache.cxf.tools.wsdlto.WSDLToJava;
public class CodeGenerator {
public static void main(String[] args) {
WSDLToJava.main(new String[] {
"-server",
"-d", "src/main/java",
"src/main/resources/SimpleService.wsdl" });
System.out.println("Done!");
}
}
La ejecutamos como Java Application. Si obtienes un error tipo java.lang.AbstractMethodError es que las librerías que ha descargado Maven están desfasadas. Para arreglarlo, añade la siguiente dependencia al pom.xml:
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.9.1</version>
</dependency>
Después de terminar de ejecutarlo con éxito, hacemos un Refresh (F5) del proyecto. Se ha creado el package com.ttdev.ss con algunos ficheros en él. Aparecen errores porque al actualizar la configuración del proyecto con Maven, el plugin de Eclipse fija la versión Java 1.4 por defecto, que no soporta anotaciones. Para arreglarlo modificamos el pom.xml:
<project ...>
...
<dependencies>
...
</dependencies>
<repositories>
...
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Para que esto funcione debes tener Java versión 6 (java -version en una shell para ver la versión de Java que tienes instalada).
Actualiza la configuración del proyecto y los errores deben desaparecer. Todos menos un error en el fichero SimpleService_P1_Server:
Creamos la clase SimpleServiceImpl en el package com.ttdev.ss, clase donde implementamos la funcionalidad de nuestro web service:
package com.ttdev.ss;
import javax.jws.WebService;
@WebService(endpointInterface = "com.ttdev.ss.SimpleService")
public class SimpleServiceImpl implements SimpleService {
@Override
public String concat(ConcatRequest parameters) {
return parameters.getS1() + parameters.getS2();
}
}
Con la anotación @WebService marcamos que la clase implementa un web service en el SEI(port type) com.ttdev.ss.SimpleService. Además la clase implementa la interface SimpleService proporcionada por Apache CXF (WSDLToJava):
package com.ttdev.ss;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.bind.annotation.XmlSeeAlso;
@WebService(targetNamespace = "http://ttdev.com/ss", name = "SimpleService")
@XmlSeeAlso( { ObjectFactory.class })
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface SimpleService {
@WebResult(name = "concatResponse",
targetNamespace = "http://ttdev.com/ss",
partName = "parameters")
@WebMethod(action = "http://ttdev.com/ss/NewOperation")
public java.lang.String concat(
@WebParam(partName = "parameters",
name = "concatRequest",
targetNamespace = "http://ttdev.com/ss") ConcatRequest parameters);
}
También WSDLToJava nos proporciona la clase ConcatRequest:
package com.ttdev.ss;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "s1", "s2" })
@XmlRootElement(name = "concatRequest")
public class ConcatRequest {
@XmlElement(required = true)
protected String s1;
@XmlElement(required = true)
protected String s2;
public String getS1() {
return s1;
}
public void setS1(String value) {
this.s1 = value;
}
public String getS2() {
return s2;
}
public void setS2(String value) {
this.s2 = value;
}
}
Ejecutamos la clase SimpleService_P1_Server como Java Application. Finalmente debe mostrarse un mensaje de servidor disponible "Server ready":
Para comprobar que el servidor está funcionando vamos a un navegador y pegamos la siguiente dirección: http://localhost:8080/ss/p1?wsdl Debe devolver el fichero WSDL:
Para finalizar el servicio, espera 5 minutos o pulsa el botón rojo en Eclipse en la ventana "console"
Creando el Cliente
Apache CXF también puede generar un conversor en el lado del cliente (service stub). Cuando invocas un método en el stub, los objetos Java se convierten al formato correcto (XML) y se mandan al web service real. Cuando obtiene la respuesta, los vuelva a convertir de XML a Java.
Copiamos el proyecto SimpleService y lo pegamos como SimpleServiceClient. Modificamos la clase CodeGenerator para que convierta del fichero WSDL a código Java para el cliente:
package com.ttdev;
import org.apache.cxf.tools.wsdlto.WSDLToJava;
public class CodeGenerator {
public static void main(String[] args) {
WSDLToJava.main(new String[] {
"-client",
"-d", "src/main/java",
"src/main/resources/SimpleService.wsdl" });
System.out.println("Done!");
}
}
Borramos el package com.ttdev.ss y ejecutamos CodeGenerator como una Java Application. Refrescamos el proyecto para ver el nuevo código generado. En particular, nos interesa el cliente SimpleService_P1_Client:
Necesitamos modificar el código generado para crear un objeto ConcatRequest
...
public static void main(String args[]) throws Exception {
...
{
System.out.println("Invoking concat...");
com.ttdev.ss.ConcatRequest _concat_parameters = new ConcatRequest();
_concat_parameters.setS1("abc");
_concat_parameters.setS2("123");
java.lang.String _concat__return = port.concat(_concat_parameters);
System.out.println("concat.result=" + _concat__return);
}
System.exit(0);
}
Finalmente ejecuta en primer lugar el servidor y después el cliente. La siguiente salida debe mostrarse por la consola:
...
Invoking concat...
concat.result=abc123
Para desarrollar el web service vamos a utilizar Eclipse, uno de los IDEs más empleados en el mundo del desarrollo de aplicaciones web. Eclipse puede descargarse gratuitamente en http://www.eclipse.org. Necesitamos descargar la versión para Java EE Developers. A día de hoy, la versión más actual es Eclipse Helios (anteriormente Galileo y Ganymede).
Simplemente debes descargar el archivo .zip, descomprimirlo en tu ordenador y arrancar el ejecutable eclipse.exe
Utilizando una librería para web services
Cuando un cliente invoque el web service, mandará un mensaje de entrada SOAP. Para facilitar el trabajo necesitamos un conversor de mensaje SOAP a clase Java, y que esta clase Java invoque los métodos de otra clase Java que tú proveas. Hay librerías que pueden actuar como este conversor, las más populares Apache CXF, Apache Axis2 y Metro de Sun Microsystems.
Instalando Apache CXF
Para usar Apache CXF necesitas descargar varias librerías que dependen unas de otras. Para facilitar este proceso vamos a utilizar Maven en Eclipse. Aquí puedes ver unas sencillas instrucciones para instalar Maven en Eclipse.
Creamos un proyecto Java en Eclipse. Le llamaremos SimpleService. Después click con botón derecho sobre el proyecto y escogemos Maven | Enable Dependency Management. Vemos:
Aceptamos los valores por defecto y pulsamos Finish.
Ahora necesitamos una conexión a internet. Indicamos a Maven las librerías CXF que necesitamos y de dónde nos las descargamos. Para ello modificamos el pom.xml del proyecto:
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>SimpleService</groupId>
<artifactId>SimpleService</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-bundle</artifactId>
<version>2.2.5</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>apache-incubating</id>
<name>Apache Incubating Repository</name>
<url>http://people.apache.org/repo/m2-incubating-repository/</url>
</repository>
</repositories>
</project>
WSDL del web service
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://ttdev.com/ss"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SimpleService"
targetNamespace="http://ttdev.com/ss">
<wsdl:types>
<xsd:schema
targetNamespace="http://ttdev.com/ss"
xmlns:tns="http://ttdev.com/ss">
<xsd:element name="concatRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="s1" type="xsd:string"/>
<xsd:element name="s2" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="concatResponse" type="xsd:string"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="concatRequest">
<wsdl:part name="concatRequest" element="tns:concatRequest" />
</wsdl:message>
<wsdl:message name="concatResponse">
<wsdl:part name="concatResponse" element="tns:concatResponse" />
</wsdl:message>
<wsdl:portType name="SimpleService">
<wsdl:operation name="concat">
<wsdl:input message="tns:concatRequest" />
<wsdl:output message="tns:concatResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="SimpleServiceSOAP" type="tns:SimpleService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="concat">
<soap:operation soapAction="http://ttdev.com/ss/concat" />
<wsdl:input>
<soap:body parts="concatRequest" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body parts="concatResponse" use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SimpleService">
<wsdl:port binding="tns:SimpleServiceSOAP" name="p1">
<soap:address location="http://localhost:8080/ss/p1" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Creando el fichero WSDL visualmente
Aquí podemos seguir las instrucciones para crear el WSDL visualmente con Eclipse, ya que la creación del WSDL a mano es propensa a errores.
Validando el fichero WSDL
Sobre SimpleService.wsdl hacemos click con botón derecho --> Validate
Generando el código del servicio
Aquí usamos Apache CXF para que genere el código del conversor de mensaje SOAP a objeto Java. Este objeto se pasará como argumento a un método. Creamos las carpetas src/main/java. Después click botón derecho sobre la raíz del proyecto y Maven | Update Project Configuration para habilitar la configuración Maven, que lo que hace es convertir la carpeta java en una carpeta de código fuente por lo que los ficheros Java .class serán compilados.
En la carpeta src/main/java creamos la siguiente clase:
package com.ttdev;
import org.apache.cxf.tools.wsdlto.WSDLToJava;
public class CodeGenerator {
public static void main(String[] args) {
WSDLToJava.main(new String[] {
"-server",
"-d", "src/main/java",
"src/main/resources/SimpleService.wsdl" });
System.out.println("Done!");
}
}
La ejecutamos como Java Application. Si obtienes un error tipo java.lang.AbstractMethodError es que las librerías que ha descargado Maven están desfasadas. Para arreglarlo, añade la siguiente dependencia al pom.xml:
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.9.1</version>
</dependency>
Después de terminar de ejecutarlo con éxito, hacemos un Refresh (F5) del proyecto. Se ha creado el package com.ttdev.ss con algunos ficheros en él. Aparecen errores porque al actualizar la configuración del proyecto con Maven, el plugin de Eclipse fija la versión Java 1.4 por defecto, que no soporta anotaciones. Para arreglarlo modificamos el pom.xml:
<project ...>
...
<dependencies>
...
</dependencies>
<repositories>
...
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Para que esto funcione debes tener Java versión 6 (java -version en una shell para ver la versión de Java que tienes instalada).
Actualiza la configuración del proyecto y los errores deben desaparecer. Todos menos un error en el fichero SimpleService_P1_Server:
Creamos la clase SimpleServiceImpl en el package com.ttdev.ss, clase donde implementamos la funcionalidad de nuestro web service:
package com.ttdev.ss;
import javax.jws.WebService;
@WebService(endpointInterface = "com.ttdev.ss.SimpleService")
public class SimpleServiceImpl implements SimpleService {
@Override
public String concat(ConcatRequest parameters) {
return parameters.getS1() + parameters.getS2();
}
}
Con la anotación @WebService marcamos que la clase implementa un web service en el SEI(port type) com.ttdev.ss.SimpleService. Además la clase implementa la interface SimpleService proporcionada por Apache CXF (WSDLToJava):
package com.ttdev.ss;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.bind.annotation.XmlSeeAlso;
@WebService(targetNamespace = "http://ttdev.com/ss", name = "SimpleService")
@XmlSeeAlso( { ObjectFactory.class })
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface SimpleService {
@WebResult(name = "concatResponse",
targetNamespace = "http://ttdev.com/ss",
partName = "parameters")
@WebMethod(action = "http://ttdev.com/ss/NewOperation")
public java.lang.String concat(
@WebParam(partName = "parameters",
name = "concatRequest",
targetNamespace = "http://ttdev.com/ss") ConcatRequest parameters);
}
También WSDLToJava nos proporciona la clase ConcatRequest:
package com.ttdev.ss;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "s1", "s2" })
@XmlRootElement(name = "concatRequest")
public class ConcatRequest {
@XmlElement(required = true)
protected String s1;
@XmlElement(required = true)
protected String s2;
public String getS1() {
return s1;
}
public void setS1(String value) {
this.s1 = value;
}
public String getS2() {
return s2;
}
public void setS2(String value) {
this.s2 = value;
}
}
Ejecutamos la clase SimpleService_P1_Server como Java Application. Finalmente debe mostrarse un mensaje de servidor disponible "Server ready":
Para comprobar que el servidor está funcionando vamos a un navegador y pegamos la siguiente dirección: http://localhost:8080/ss/p1?wsdl Debe devolver el fichero WSDL:
Para finalizar el servicio, espera 5 minutos o pulsa el botón rojo en Eclipse en la ventana "console"
Creando el Cliente
Apache CXF también puede generar un conversor en el lado del cliente (service stub). Cuando invocas un método en el stub, los objetos Java se convierten al formato correcto (XML) y se mandan al web service real. Cuando obtiene la respuesta, los vuelva a convertir de XML a Java.
Copiamos el proyecto SimpleService y lo pegamos como SimpleServiceClient. Modificamos la clase CodeGenerator para que convierta del fichero WSDL a código Java para el cliente:
package com.ttdev;
import org.apache.cxf.tools.wsdlto.WSDLToJava;
public class CodeGenerator {
public static void main(String[] args) {
WSDLToJava.main(new String[] {
"-client",
"-d", "src/main/java",
"src/main/resources/SimpleService.wsdl" });
System.out.println("Done!");
}
}
Borramos el package com.ttdev.ss y ejecutamos CodeGenerator como una Java Application. Refrescamos el proyecto para ver el nuevo código generado. En particular, nos interesa el cliente SimpleService_P1_Client:
Necesitamos modificar el código generado para crear un objeto ConcatRequest
...
public static void main(String args[]) throws Exception {
...
{
System.out.println("Invoking concat...");
com.ttdev.ss.ConcatRequest _concat_parameters = new ConcatRequest();
_concat_parameters.setS1("abc");
_concat_parameters.setS2("123");
java.lang.String _concat__return = port.concat(_concat_parameters);
System.out.println("concat.result=" + _concat__return);
}
System.exit(0);
}
Finalmente ejecuta en primer lugar el servidor y después el cliente. La siguiente salida debe mostrarse por la consola:
...
Invoking concat...
concat.result=abc123
jueves, 15 de septiembre de 2011
Tutorial Web Services (I): Definición de términos
Los Web Services proporcionan operaciones multiplataforma en internet. Los servicios pueden ser accedidos por diferentes plataformas y lenguajes de programación.
Endpoint:
Nombre del host que alberga el web service + nombre del web service.
Si el host fuera http://www.prueba.com y el web service BasicService, la URL completa, es decir, el endpoint sería http://www.prueba.com/BasicService
QName(Qualified name)
El web service puede dar soporte a una o más operaciones. Cada operación debe tener un nombre global único. Para ello, se declara un namespace que es como un paquete en Java pero con formato URL. El QName está formado por el namespace + el nombre de la operación.
RPC style web service
La operación concatenar puede tomar 2 parámetros, "s1" y "s2", ambos tipo String y devuelve como resultado otro String que es la concatenación de ambos parámetros.
Sin embargo, el tipo string debe ser de un lenguaje de programación neutral. Para ello, se usa la especificación XML schema.
En web services la llamada de la operación definida por un web service se denomina "mensaje de entrada" y cada parámetro se denomina "parte". El valor de retorno es el "mensaje de salida" y puede contener múltiples partes. Con estos términos podríamos definir la interface de la operación:
Para invocar esta operación, se podría mandar un elemento XML como mensaje de entrada:
<foo:concatenar xmlns:foo="http://prueba.com/bs">
<s1>abc</s1>
<s2>123</s2>
</foo:concatenar>
El resultado sería un mensaje de salida:
<foo:concatenar xmlns:foo="http://prueba.com/bs">
<retorno>abc123</retorno>
</foo:concatenar>
Este estilo de web service se llama "RPC Style" web service. Como puede observarse, el QName de la operación y el nombre de las partes se utilizan para crear los mensajes de entrada y salida.
El mensaje de entrada sólo contiene una única parte, que es un elemento definido en un schema. En ese schema, el elemento se llamará concatRequest y tendrá dos elementos hijos: <s1> y <s2>.
Para invocar una operación en un Document Style web service, se manda una única parte como mensaje de entrada. NUNCA se manda el nombre de la operación en ningún modo. Por lo tanto si hay más de una operación que toma el mismo elemento como mensaje de entrada se producirá un error y el web service no funcionará.
Las operaciones de un web service se agrupan en uno o más “port types”. El port type es como una clase Java y cada operación es como un método static. El nombre de un port type debe ser un QName.
Hemos empleado el mismo namespace para los nombres de las operaciones, de los port type, etc. Por defecto, todos estos nombres se encuentran en un único namespace, que se denomina “target namespace” del web service.
Un namespace en XML debe ser un URI. Puedes usar URL o URN. Por ejemplo, puedes usar urn:ttdev.com:ss como el target namespace del web service en vez de http://ttdev.com/ss sin ningún cambio en la funcionalidad.
Endpoint:
Nombre del host que alberga el web service + nombre del web service.
Si el host fuera http://www.prueba.com y el web service BasicService, la URL completa, es decir, el endpoint sería http://www.prueba.com/BasicService
QName(Qualified name)
El web service puede dar soporte a una o más operaciones. Cada operación debe tener un nombre global único. Para ello, se declara un namespace que es como un paquete en Java pero con formato URL. El QName está formado por el namespace + el nombre de la operación.
RPC style web service
La operación concatenar puede tomar 2 parámetros, "s1" y "s2", ambos tipo String y devuelve como resultado otro String que es la concatenación de ambos parámetros.
Sin embargo, el tipo string debe ser de un lenguaje de programación neutral. Para ello, se usa la especificación XML schema.
En web services la llamada de la operación definida por un web service se denomina "mensaje de entrada" y cada parámetro se denomina "parte". El valor de retorno es el "mensaje de salida" y puede contener múltiples partes. Con estos términos podríamos definir la interface de la operación:
Para invocar esta operación, se podría mandar un elemento XML como mensaje de entrada:
<foo:concatenar xmlns:foo="http://prueba.com/bs">
<s1>abc</s1>
<s2>123</s2>
</foo:concatenar>
El resultado sería un mensaje de salida:
<foo:concatenar xmlns:foo="http://prueba.com/bs">
<retorno>abc123</retorno>
</foo:concatenar>
Este estilo de web service se llama "RPC Style" web service. Como puede observarse, el QName de la operación y el nombre de las partes se utilizan para crear los mensajes de entrada y salida.
Document style web service
Schema:
<xsd:schema
targetNamespace="http://ttdev.com/ss"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="concatRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="s1" type="xsd:string"/>
<xsd:element name="s2" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
El schema se incluye en la interface del web service:
Como puede observarse, una parte (un parámetro) puede ser declarado como un elemento particular (<concatRequest>) definido en un schema o como un elemento con un tipo particular (string definido en la especificación XML schema). En cualquier caso se identifica usando un QName.Cuando alguien invoque la operación, se mandará un mensaje de entrada con un elemento <concatRequest>
<foo:concatRequest xmlns:foo="http://ttdev.com/ss">
<s1>abc</s1>
<s2>123</s2>
</foo:concatRequest>Similarmente, para el mensaje de salida puedes especificar que contendrá una única parte, y que será un elemento <concatResponse>
<foo:concatResponse xmlns:foo="http://ttdev.com/ss">
abc123
</foo:concatResponse>
Comparación de los mensajes de entrada en RPC y Document style.
La principal diferencia es que en el estilo RPC no se puede validar contra un schema, mientras que en el estilo Document si. Por esta razón, Document se está convirtiendo en el estilo dominante.
Determinando la operación en un Document Style web service:
Port type
Binding
Los port types pueden ser accedidos utilizando diferentes formatos de mensaje. Hasta ahora se ha empleado el formato “Simple Object Access Protocol (SOAP)”. Otro tipo de formato podría ser texto plano.
Además del formato del mensaje, un port type puede permitir que el mensaje sea transportado en una petición HTTP POST o en un email. Cada combinación que se soporta se llama “binding”. La combinación más común es SOAP + HTTP. Port
Supón que hay mucha gente usando el web service y decides hacerlo accesible en más de un computador. Puedes desplegar el binding1 descrito arriba en las computadoras c1, c2 y c3 y desplegar el binding2 en c3. En este caso hay 4 puertos.
En las 3 computadoras habrá instalado cierto software que implementa el port type. No es necesario que sea el mismo software en las 3 computadoras; en c1 puede estar escrito en Java mientras que en c2 puede estar escrito en C#. Lo importante es que deben soportar todas las operaciones descritas en el port type y el formato de mensaje y transporte especificados en el binding.
Los ports se incluyen en la interface del web service.Target namespace
El namespace debe ser globalmente único, por ejemplo http://ttdev.com/ss. Este namespace tiene formato URL, puede haber gente que intente acceder a él como a una página web y cuando no funcione, pueden pensar que el web service es incorrecto. Para evitar esta confusión se debe emplear formato URN.
El namespace debe ser una URI. Hay dos tipos de URI (Uniform Resource Identifier). Una es URL como en http://prueba.com. Otra es URN con formato <tipo-objeto>:<id-objeto>
WSDL
Interface del web service.
Describe completamente el web service. El lenguaje de descripción se llama WSDL (Web Service Description Language).
Suscribirse a:
Entradas (Atom)