Tutorial
En este tutorial aprenderemos como hacer un servicio web compuesto que recomienda robots para una determinada tarea, y a marcarlo semánticamente
Herramientas:
Nuestro primer paso será crear la Ontología que representa a los robots. Algunos de los conceptos básicos de una Ontología son las clases, las instancias y las propiedades, estas ultimas se dividen en propiedades de objetos y propiedades de datos; si tratamos de relacionar estos conceptos con el mundo de la programación orientada a objetos podemos ver las clases de una Ontología como clases de la programación, las propiedades de objetos como atributos que son punteros a otros objetos, las propiedades de datos como atributos de tipos de datos primitivos (String, int, float, etc.) y las instancias como instancias de una clase (Objetos)
Abrimos Protégé y creamos un nuevo proyecto tipo OWL / RDF Files
Luego nos pedirá una URI que será la dirección donde estará almacenada la Ontología, en este caso la guardaremos en glassfish por lo que la dirección será localhost
MejorRobotXSD.xsd
Herramientas:
- Protégé 3.2, disponible en: http://protege.cim3.net/download/old-releases/3.2/full/
- Netbeans, edición con Java EE y Glassfish, disponible en: http://netbeans.org/downloads/index.html
- Editor de texto, preferiblemente NotePad++, disponible en: http://notepad-plus-plus.org/
- Jena, disponible en: http://sourceforge.net/projects/jena/files/
- Owl-s API http://on.cs.unibas.ch/owls-api/download.html
Nuestro primer paso será crear la Ontología que representa a los robots. Algunos de los conceptos básicos de una Ontología son las clases, las instancias y las propiedades, estas ultimas se dividen en propiedades de objetos y propiedades de datos; si tratamos de relacionar estos conceptos con el mundo de la programación orientada a objetos podemos ver las clases de una Ontología como clases de la programación, las propiedades de objetos como atributos que son punteros a otros objetos, las propiedades de datos como atributos de tipos de datos primitivos (String, int, float, etc.) y las instancias como instancias de una clase (Objetos)
Abrimos Protégé y creamos un nuevo proyecto tipo OWL / RDF Files
Luego nos pedirá una URI que será la dirección donde estará almacenada la Ontología, en este caso la guardaremos en glassfish por lo que la dirección será localhost
Luego nos pedirá seleccionar un lenguaje, seleccionaremos OWL DL y luego le damos finish
En la pestaña OWL Classes creamos las clases, en OWL toda clase extiende de la clase Thing, los botones encerrados en el recuadro rojo de la imagen siguiente son en orden de izquierda a derecha: Crear una nueva subclase (Una clase que hereda de la clase que se encuentre seleccionada), crear clase hermana (Una clase que esta en el mismo nivel de jerarquía que la que esté seleccionada) y borrar clase
Así creamos diferentes clases que extienden de Robot: Androide, Zoomorfico, Poliarticulado, Movil e Hibrido; y una clase Dispositivo de la cual extienden: Comunicación, Energía, Extremidades, Motor, Sensor y Transporte, de cada una de ellas podemos crear mas subclases y así sucesivamente hasta crear una Ontología bien definida, para ver el funcionamiento del sistema de recomendación y la creación de los servicios web es suficiente con llegar hasta el nivel de jerarquía que se muestra en la imagen
Notemos que un Robot Híbrido puede ser cualquier combinación de los demás robots, por lo cual podemos modelar este hecho de tal forma que Híbrido extienda de todas sus clases hermanas, para esto diremos que tiene como superclases a Androide, Zoomorfico, Robot, Movil y Poliarticulado, nos aseguramos de cambiar a la vista de Propiedades (recuadro azul) y damos clic en agregar una clase (recuadro rojo) y luego seleccionamos toda las clases mencionadas anteriormente
Luego procederemos a crear las propiedades, a la clase robot le adicionaremos una propiedad de objeto llamada "dispositivos" y podrá contener todas las instancias de la clase dispositivos que tiene un robot. Como las clases Zoomorfico, Androide, etc. heredan de la clase Robot, también heredan sus propiedades, así que cualquier robot tendrá dispositivos. En el campo de Propiedades y Restricciones agregaremos una nueva propiedad de Objeto (recuadro rojo); notemos que para esta propiedad el dominio es la clase Robot y el rango es la clase Dispositivo.
En una Ontología podemos crear condiciones y restricciones, por ejemplo, podemos asumir que un robot dentro de sus dispositivos tiene que tener al menos uno de Energía, uno de Comunicación y un Motor. Para crear esta restricción seleccionamos la clase Robot y nos aseguramos de tener activada la vista lógica (recuadro azul), luego damos clic en el botón crear nueva restricción (recuadro rojo), seleccionamos la propiedad sobre la cual haremos la restriccion, en ese caso dispositivos, luego el tipo de restricciones, en este caso "SomeValuesFrom" y en el campo Filler tenemos varias herramientas para crear una expresión lógica, seleccionaremos el botón "Insert class" (recuadro verde) y seleccionamos la clase Comunicación:
Luego en el campo Filler presionamos el botón "and" (recuadro rojo) y luego insertamos una nueva clase, hasta crear la expresion que se muestra en la imagen
Así logramos crear una expresión lógica que obliga a que un Robot tenga al menos una fuente de Energía, un dispositivo de Comunicación y un Motor. Así podemos crear una serie de restricciones en cada uno de los subniveles de la jerarquía. Por ejemplo, podemos decir que un robot Móvil tiene que tener un GPS y un dispositivo de Transporte, además de la restricción heredada de la clase Robot, por lo que se vería algo como:
Crearemos propiedades de datos para cada uno de los dispositivos, vamos a la clase Wifi y creamos una nueva propiedad de datos (recuadro rojo), la cual llamaremos distancia, su rango es int (recuadro azul) y marcaremos la opción Functional (recuadro verde) la cual significa que esta propiedad podrá tener un único valor
Así crearemos una propiedad para cada uno de los dispositivos que indique alguna medición representable como un tipo de dato numérico.
Una vez terminada nuestra Ontología, guardamos el proyecto en File -> Save Project, seleccionaremos la ruta para guardar el proyecto (.pprj) y la Ontología (.owl)
Luego montaremos el archivo .owl al servidor de Glassfish, generalmente la carpeta del servidor es Carpeta del usuario -> .netbeans -> version -> config -> GF3 -> domain1 -> docroot . Allí crearemos una carpeta llamada Ontologías y pegaremos el archivo Robot.owl.
Ahora crearemos un archivo wsdl en NotePad++ por cada uno de los tres servicios atómicos. Estos se dividirán así:
- El primer servicio recibe un Array de Dispositivos y devuelve un objeto de la clase Paquete, el cual tiene dos atributos: Un Array de Robots y un array de Dispositivos, será el encargado de consultar en las Ontologías cuales instancias de la clase Robot tienen los dispositivos requeridos y devolverá dicha lista, notemos que no importa si la distancia del Wifi de un Robot A es 50m y dentro de mis requisitos está un Wifi de 80m, este servicio solo obtiene los robots que tengan los dispositivos sin importar sus propiedades de datos. El Paquete devuelto tiene como atributos el Array de robots obtenidos y el Array de dispositivos requeridos, los mismos que se ingresaron como parametro de entrada.
- El segundo servicio recibirá una clase Paquete y devolverá una clase paquete. Este servicio será el encargado de eliminar los demás dispositivos que no nos interesan para poder aplicar el algoritmo de la correlación de Pearson en el tercer servicio, ya que este necesita que los objetos a comparar tengan las mismas características en común, es decir, si requerimos un robot con Wifi, Brazo y un Motor y encontramos un Robot con Wifi, Motor, Brazo y Bluetooth debemos ocultar el ultimo dispositivo para trabajar con los que son necesarios. Así que este servicio eliminará los dispositivos que no son necesarios.
- El tercer servicio recibirá un Paquete y devolverá un Array de Robots, Aplicará la correlación de Pearson comparando cada robot con los valores de los dispositivos dados y luego los ordenará, dando así lugar a un Array con los robots que cumplen las caracteristicas solicitadas ordenados de forma tal que el primero es el que mas se parece al requerido.
Un buen tutorial sobre wsdl y servicios web es: http://www.ibm.com/developerworks/ssa/webservices/tutorials/ws-understand-web-services2/index.html
Aqui tenemos el .wsdl y el .xsd del primer servicio
DepuracionService.wsdl
DepuracionServiceXSD.xsd
Aqui tenemos el .wsdl y el .xsd del primer servicio
DepuracionService.wsdl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
Aqui tenemos el .wsdl y el .xsd del segundo servicio
ModificarCaracteristicasService.wsdl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
ModificarCaracteristicasServiceXSD.xsd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
Aqui tenemos el .wsdl y el .xsd del tercer servicio
MejorRobot.wsl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
MejorRobotXSD.xsd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
Ahora crearemos en Netbeans tres proyectos diferentes para cada uno de los proyectos, el poryecto debe ser tipo Java Web -> Web Application
El proyecto lo llamaremos "Depuracion", Luego en el proyecto crearemos un nuevo servicio a partir del WSDL, para ellos vamos a file -> new File, seleccionamos Web Services y luego Web Service from WSDL
Llamaremos al servicio "DepuracionService", seleccionamos un paquete donde se crearán las clases definidas en el .xsd y la direccion del wsdl
Creamos un nuevo paquete llamado "clases" y una clase llamada Main, la cual tendrá el siguiente código:
Jena es una API que nos permite extraer la información de una Ontología y utilizarla en Java.
Un tutorial sobre Jena se encuentra en: http://jena.sourceforge.net/ontology/index.html
Básicamente lo que hacemos es obtener la clase raíz de la Ontología, en este caso la clase Robot, se recorre las subclases y se obtienen las instancias de cada una de estas, luego podemos proceder a obtener las propiedades que cada instancia tiene y así comparar cada Robot con las condiciones dadas obteniendo los que cumplan con los requerimientos necesarios.
Este proyecto requiere importar la librería de Jena, por lo cual creamos una libreria en netbeans y agregamos todos los .jar que se encuentran en la carpeta lib del archivo descargado de Jena.
El código de la clase DepuracionService.java quedaría como sigue:
Similarmente crearemos otros dos proyectos, el segundo servicio llamado "ModificarCaracteristicas" y un servicio llamada "ModificarCaracteristicasService", el código de la clase Main.java y ModificarCaracteristicasService.java de se muestran a continuación
El tercer servicio lo llamamos "MejorRobot", a continuacion el codigo de la clase Main.java y de MejorRobotService.java
Asi tenemos los tres servicios atomicos programados, damos en cada uno clic derecho -> Deploy para ponerlos a correr en GlassFish
Luego procederemos a marcar cada uno de los servicios atómicos y a la composición del servicio web
Abrimos Protege y realizamos los pasos mencionados anteriormente.
Hacemos click en el botón que está dentro del marco rojo e importamos nuestra ontología de dominio.
Si señalamos la pestaña OWLClasses, podremos ver cada una de las clases de nuestra ontología importada.
Luego iremos menú en barra, señalamos project/configure y seleccionamos owlstab; de ésta manera estaremos importando el plug-in de owl-s editor para Protégé y a su vez la ontología para describir servicios web OWL-S.
Al realizar los pasos anteriores tendremos la siguiente vista en nuestro Protégé.
Para realizar el marcado semántico a nuestros servicios web, creamos una nueva instancia de la clase Process declarada en la ontología OWL-S como subclase de ServiceModel.
Observemos el marco rojo, con ese botón crearemos la instacia, luego aparecerá el cuadro que en la anterior imágen tiene como título Choose a Class. En este cuadro seleccionamos Atomic Process.
Luego creamos una nueva instancia de hasInput y tendrémos la siguiente vista.
Luego de darle un identificador a la entrada, especificamos su tipo de dato haciendo click en el botón amarillo con el símbolo de suma.
En nuestro caso señalamos la clase ArrayDispositivos, indicando que el servicio recibe una entrada de este tipo.
Para especificar las salidas, hacemos este mismo proceso pero creando una instancia de hasOutput.
Ahora, supondremos que hemos creado 3 procesos atómicos y crearémos un nuevo process pero señalaremos esta vez Composite Process, para indicar que este es compuesto.
Para realizar este paso es necesario tener instalado el software Graphviz para visualizar un esquema del servicio compuesto. Uno de los botones que tiene forma de rombo rosado, tiene una letra 'S', con este botón crearémos un sequence, ya que nuestro servicio compuesto se comporta como una secuencia.
Creamos varios Perform con el botón que tiene la 'P', un perform por cada atomic process.
Al crear un perform, en la pestaña properties, le damos un nombre al perform y seleccionamos el atomic process correspondiente.
En la siguiente imágen veremos como se especifica que la salida de un atomic process es exactamente la misma entrada del siguiente proceso.
Luego de realizar estos pasos con cada perform, nuestro esquema será de la siguiente manera.
Luego crearemos nuestro grounding, creando una instancia de WsdlGrounding, al crearla, aparecerá un recuadro rojo enmarcando a supportedBy, en la cual se debe especificar el servicio al cual se le está haciendo el grounding. Por el momento no será importante.
Crearemos una instancia de hasAtomicProcessGrounding y allí especificaremos todo acerca de la ubicación de ciertos elementos en el wsdl de cada servicio.
Vamos a tomar como ejemplo el servicio web ModificarCaracteristicasService. El wsdl en nuestro caso está ubicado en nuestro localhost, accediendo a él con la siguiente dirección: http://localhost:8080/ModificarCaracteristicas/ModificarCaracteristicasService?WSDL
Observemos ahora la siguiente imágen.
Cada elemento del wsdl será especificado utilizando la dirección de este último añadiendo # y el nombre del elemento en el wsdl.
Ejemplo: http://localhost:8080/ModificarCaracteristicas/ModificarCaracteristicasService?WSDL#Paquete
De esta manera estaríamos especificando, en este caso, que las salidas de el servicio son de tipo Paquete.
Posteriormente crearemos el serviceProfile, creando una instancia.
En este definiremos las entradas del servicio compuesto y las salidas, indicaremos el procesos que tiene, damos el servicio al cual pertenece, y de manera opcional darémos una breve descripción del servicio en texto.
Luego creamos una instancia de Service e indicamos añadiendo instancias en los respectivos recuadros, el grounding, el profile y el proceso compuesto.
Finalmente, salvámos nuestro proyecto, el cual generará un archivo .owl.
Para más detalles visita: http://owlseditor.semwebcentral.org/documents/tutorial.pdf
El proyecto lo llamaremos "Depuracion", Luego en el proyecto crearemos un nuevo servicio a partir del WSDL, para ellos vamos a file -> new File, seleccionamos Web Services y luego Web Service from WSDL
Llamaremos al servicio "DepuracionService", seleccionamos un paquete donde se crearán las clases definidas en el .xsd y la direccion del wsdl
Creamos un nuevo paquete llamado "clases" y una clase llamada Main, la cual tendrá el siguiente código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
Jena es una API que nos permite extraer la información de una Ontología y utilizarla en Java.
Un tutorial sobre Jena se encuentra en: http://jena.sourceforge.net/ontology/index.html
Básicamente lo que hacemos es obtener la clase raíz de la Ontología, en este caso la clase Robot, se recorre las subclases y se obtienen las instancias de cada una de estas, luego podemos proceder a obtener las propiedades que cada instancia tiene y así comparar cada Robot con las condiciones dadas obteniendo los que cumplan con los requerimientos necesarios.
Este proyecto requiere importar la librería de Jena, por lo cual creamos una libreria en netbeans y agregamos todos los .jar que se encuentran en la carpeta lib del archivo descargado de Jena.
El código de la clase DepuracionService.java quedaría como sigue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | WebService(serviceName = "DepuracionService", portName = "DepuracionServicePort", endpointInterface = "localhost._8080.depuracion.depuracionservice." + "DepuracionServicePortType", targetNamespace = "http://localhost:8080/Depuracion/DepuracionService", wsdlLocation = "WEB-INF/wsdl/DepuracionService/DepuracionService.wsdl")@ |
Similarmente crearemos otros dos proyectos, el segundo servicio llamado "ModificarCaracteristicas" y un servicio llamada "ModificarCaracteristicasService", el código de la clase Main.java y ModificarCaracteristicasService.java de se muestran a continuación
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | .*;modificarcaracteristicasservice |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | WebService(serviceName = "ModificarCaracteristicasService", portName = "ModificarCaracteristicasServicePort", endpointInterface = "localhost._8080.modificarcaracteristicas.modifi" + "carcaracteristicasservice.ModificarCaracteristicasServicePortType", targetNamespace = "http://localhost:8080/ModificarCaracteristicas" + "/ModificarCaracteristicasService", wsdlLocation = "WEB-INF/wsdl/ModificarCaracteristicasService" + "/ModificarCaracteristicasService.wsdl")@ |
El tercer servicio lo llamamos "MejorRobot", a continuacion el codigo de la clase Main.java y de MejorRobotService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | WebService(serviceName = "MejorRobotService", portName = "MejorRobotPort", endpointInterface = "localhost._8080.mejorrobot.mejorrobotservice." + "MejorRobotPortType", targetNamespace = "http://localhost:8080/MejorRobot/MejorRobotService", wsdlLocation = "WEB-INF/wsdl/MejorRobotService/MejorRobot.wsdl")@ |
Asi tenemos los tres servicios atomicos programados, damos en cada uno clic derecho -> Deploy para ponerlos a correr en GlassFish
Luego procederemos a marcar cada uno de los servicios atómicos y a la composición del servicio web
Abrimos Protege y realizamos los pasos mencionados anteriormente.
Hacemos click en el botón que está dentro del marco rojo e importamos nuestra ontología de dominio.
Si señalamos la pestaña OWLClasses, podremos ver cada una de las clases de nuestra ontología importada.
Luego iremos menú en barra, señalamos project/configure y seleccionamos owlstab; de ésta manera estaremos importando el plug-in de owl-s editor para Protégé y a su vez la ontología para describir servicios web OWL-S.
Al realizar los pasos anteriores tendremos la siguiente vista en nuestro Protégé.
Para realizar el marcado semántico a nuestros servicios web, creamos una nueva instancia de la clase Process declarada en la ontología OWL-S como subclase de ServiceModel.
Observemos el marco rojo, con ese botón crearemos la instacia, luego aparecerá el cuadro que en la anterior imágen tiene como título Choose a Class. En este cuadro seleccionamos Atomic Process.
Luego creamos una nueva instancia de hasInput y tendrémos la siguiente vista.
Luego de darle un identificador a la entrada, especificamos su tipo de dato haciendo click en el botón amarillo con el símbolo de suma.
En nuestro caso señalamos la clase ArrayDispositivos, indicando que el servicio recibe una entrada de este tipo.
Para especificar las salidas, hacemos este mismo proceso pero creando una instancia de hasOutput.
Ahora, supondremos que hemos creado 3 procesos atómicos y crearémos un nuevo process pero señalaremos esta vez Composite Process, para indicar que este es compuesto.
Para realizar este paso es necesario tener instalado el software Graphviz para visualizar un esquema del servicio compuesto. Uno de los botones que tiene forma de rombo rosado, tiene una letra 'S', con este botón crearémos un sequence, ya que nuestro servicio compuesto se comporta como una secuencia.
Creamos varios Perform con el botón que tiene la 'P', un perform por cada atomic process.
Al crear un perform, en la pestaña properties, le damos un nombre al perform y seleccionamos el atomic process correspondiente.
En la siguiente imágen veremos como se especifica que la salida de un atomic process es exactamente la misma entrada del siguiente proceso.
Luego de realizar estos pasos con cada perform, nuestro esquema será de la siguiente manera.
Luego crearemos nuestro grounding, creando una instancia de WsdlGrounding, al crearla, aparecerá un recuadro rojo enmarcando a supportedBy, en la cual se debe especificar el servicio al cual se le está haciendo el grounding. Por el momento no será importante.
Crearemos una instancia de hasAtomicProcessGrounding y allí especificaremos todo acerca de la ubicación de ciertos elementos en el wsdl de cada servicio.
Vamos a tomar como ejemplo el servicio web ModificarCaracteristicasService. El wsdl en nuestro caso está ubicado en nuestro localhost, accediendo a él con la siguiente dirección: http://localhost:8080/ModificarCaracteristicas/ModificarCaracteristicasService?WSDL
Observemos ahora la siguiente imágen.
Cada elemento del wsdl será especificado utilizando la dirección de este último añadiendo # y el nombre del elemento en el wsdl.
Ejemplo: http://localhost:8080/ModificarCaracteristicas/ModificarCaracteristicasService?WSDL#Paquete
De esta manera estaríamos especificando, en este caso, que las salidas de el servicio son de tipo Paquete.
Posteriormente crearemos el serviceProfile, creando una instancia.
En este definiremos las entradas del servicio compuesto y las salidas, indicaremos el procesos que tiene, damos el servicio al cual pertenece, y de manera opcional darémos una breve descripción del servicio en texto.
Luego creamos una instancia de Service e indicamos añadiendo instancias en los respectivos recuadros, el grounding, el profile y el proceso compuesto.
Finalmente, salvámos nuestro proyecto, el cual generará un archivo .owl.
Para más detalles visita: http://owlseditor.semwebcentral.org/documents/tutorial.pdf
...que experiencia para resumir esto de esta manera gracias...
ResponderEliminar