Wednesday, December 15, 2010

Creacion de Web Service con GlassFish

Para la creación de Web Service dentro de GlassFish V3 es mucho mas fácil si cabe que con JBoss.


Para tal propósito he usado NetBeans 6.8. Si  no tenemos configurado el servidor de GlassFish en NetBeans, lo añadimios
Primer paso crear un proyecto Web Aplication. Dentro de él se crean una serie de carpetas y ficheros de configuración por defecto. Creamos nuestro Pojo al cual le añadimos la annotation @WebService en la definición del nombre de la clase.
Para desplegar el Web Service pulsamos deploy encima del proyecto y ya esta.

Si queremos ver el War, solo tenemos que ir a la vista de ficheros ir al fichero build.xml y pulsar sobre el la acción de dist

Tuesday, December 14, 2010

diferencia entre orquestacion y coreografía

Leyendo y leyendo, todavía no he encontrado ningún artículo que ponga claramente cual es la diferencia entre estos conceptos. Al final, creo que hemos sacado una conculsión que cualquiera que crea que es erronea que lo diga.
Un Web service debe ser un servicio de negocio. Este servicio (de negocio) tiene un conjunto de operaciones (operaciones informáticas) que hay que ejecutarlas para llevarlas a buen termino de este servicio de negocio. Por ejemplo, para hacer una compra en una Web, tienes un WS con un conjunto de operaciones (informáticas). Para realizar la compra tienes que llamar a las operaciones de buscar libro, seleccionar libro, introducir usuario,  y validar compra. Todas las operaciones son un servicio de negocio definidas dentra de un WS.

Para llevar a cabo la ejecucion de un WS y no de una sola de las operaciones, temenos que coordinar las llamadas entre cada una de las operaciones de los Web Services. La coordinacion de estas operaciones es la orquestación. Hay un director que regula cada una de las llamadas. Estas llamadas se pueden realizar con BPEL para dirigir el flujo, aunque existe un estandar de Oasis para tal fin  http://docs.oasis-open.org/ws-tx/wstx-wscoor-1.2-spec-os.pdf 

Si queremos realizar una composicion de WS distintos, por ejemplo, comprar un libro y enviarlo para regalo, debemos coordinar las distintas llamadas de los WS de negocio, el WS de compra, empresa A y el WS de la empresa de envío del regalo, empresa B.
Cuando queremos llamar a varios WS (distintos negocios) para hacer algun tipo de servicio compuesto, estas llamadas se realizan una detras de otras a través de un BPEL, por ejemplo. Esto es una coreografia. Cada uno de los servicios sabe como actuar, bailan de manera autónoma ( ya que se ha definido en la orquestación), colaboran para dar un servicio compuesto.

Friday, December 3, 2010

junit java eclipse bundle

Estoy realizando un bundle que incluye un conjunto de test con la configuracion de carpetas de maven

src/main/java -> codigo java del bundle
src/test/java -> codigo java de test del bundle

a la hora de compilar y publicar el bundle hay que hacer ciertas modificaciones en el fichero de build.properties

source.. = src/
source.miBundle.jar = src/main/java/,src/test/java
bin.includes = META-INF/,\
               lib/dependencias.jar,\
               miBundle.jar
 Ahora entonces solo hace falta ejecutar desde eclipse "junit para bundles" y ya esta

Friday, November 26, 2010

extraer modelReference de un SAWSDL con EasyWSDL

EasyWSDL es una herramienta para extraer información de los ficheros WSDL. Estos ficheros pueden estar en formato  WSDL 1.1 y WSDL 2.0. Si quieres extraer la información semantica de los WSDL es decir WSDL anotados semanticamente se usa la librería http://easywsdl.ow2.org/extensions-sawsdl.html

para extraer los interfaces, servicio operaciones y binding no hay problema, es trivial con la api que te da la libreria, pero para extraer la informacion de los tipos de datos compuestos es bastante dificultoso, ya que hay que realizar varias conversiones a tipos de clases propias de la api de la libreria.

como entender esta libreria me ha costado mucho os dejo este trozo de código.

  for(org.ow2.easywsdl.extensions.sawsdl.api.schema.Schema mischema: schemaSwdl){
            System.out.println("********** of mischema in \"" + mischema.getTargetNamespace() + "\" operation (previous adding): " + mischema.getModelReference().size());
            for(org.ow2.easywsdl.extensions.sawsdl.api.schema.Element schemaElement :mischema.getElements()){
                if (schemaElement instanceof org.ow2.easywsdl.extensions.sawsdl.impl.schema.ElementImpl ){
                    System.out.println("----Model??--"+((org.ow2.easywsdl.extensions.sawsdl.impl.schema.ElementImpl)schemaElement).getModel());
                    org.ow2.easywsdl.schema.org.w3._2001.xmlschema.TopLevelElement modelReference =(org.ow2.easywsdl.schema.org.w3._2001.xmlschema.TopLevelElement)
                        ((org.ow2.easywsdl.extensions.sawsdl.impl.schema.ElementImpl)schemaElement).getModel();

                    System.out.println("-----******------in \"" + modelReference+" -***-" +modelReference.getComplexType());
                    //lista d objetos XML que luego hay que transformarlos a cada uno de sus tipos de datos para sacar las referencias.
                    List <Object> objetos =modelReference.getComplexType().getSequence().getParticle();
                     for( Object datosVarios : objetos){
                         //si son de JABX que tiene que ser de este tipo de datos todos los objetos que me devuelven.
                         if(datosVarios instanceof JAXBElement) {
                                 //System.out.print("que objeto hay"+((JAXBElement) datosVarios).getValue().getClass());
                             //vuelvo a comprobar si su valor es de tipo de datos estandar del W3C
                                if (((JAXBElement) datosVarios).getValue() instanceof org.ow2.easywsdl.schema.org.w3._2001.xmlschema.Element) {
                                    //lo transformo a un tipo de dato XML
                                    org.ow2.easywsdl.schema.org.w3._2001.xmlschema.Element nodeXML =
                                        (org.ow2.easywsdl.schema.org.w3._2001.xmlschema.Element) ((JAXBElement) datosVarios).getValue();
                                   
                                    System.out.println("que objeto hay->>>>>>>>>>>>>>>>>>>>>>>>>"+nodeXML);//+"->"+element2.getName());
                                    //forma de transformar de un dato XML a un objeto abstracto que debe implementar el objeto SchemaElement necesario para construir SAWSLD,
                                    final AbsItfElement elementSemantic = new org.ow2.easywsdl.schema.impl.ElementImpl(
                                            nodeXML,
                                            ((org.ow2.easywsdl.schema.api.abstractElmt.AbstractSchemaElementImpl) schemaElement
                                                    ).getParent());
                                   
                                    if(elementSemantic instanceof SchemaElement){
                                        SAWSDLElementImpl sawsdlElement=  new org.ow2.easywsdl.extensions.sawsdl.impl.SAWSDLElementImpl((SchemaElement) elementSemantic);
                                        System.out.println("--dame el la anotacion del modelo-"+sawsdlElement.getModelReference());
                                    }else{
                                        System.out.println("que no es un tipo semantico"+nodeXML);//.getName());
                                    }
                                }
                            }
                     }
                     System.out.print("}Tipo Compuesto\n");
                }
            }
        }

Wednesday, November 10, 2010

Exportar e Importar plugins desde eclipse con sus dependencias

Llevo todo un día perdido intentando importar las dependencias de un bundle. Claro que no es un bundle que esta en un repositorio de eclipse con su xml de dependencias. Lo que quiero hacer es sacar solo la parte de un proyecto de un plugin de Eclipse.

La solucion la he encontrado en 
http://stackoverflow.com/questions/266935/deploying-a-newly-developed-eclipse-plugin

Lo bueno es que no sabia que con hacer un feature plugin y un site se soluciona. Una maravilla esto en eclipse.

Thursday, October 14, 2010

Envío de ficheros con WS usando jaxb

Siguiendo el tutorial anterior, vamos a comentar como se puede enviar un fichero. Filosóficamente, un Web service solamente debería se posible enviar datos en ascii, ya que cada uno bajo su plataforma implementa las funcionalidades de los WS sabiendo que son simplemente texto.

Para definir un Web service como comentaba en el anterior tutorial solamente definimos un pojo con la siguiente etiqueta
@WebService
public class SendFile{
}
después implementamos un método con los siguientes parámetros

public boolean send(
@WebParam(name="steamFile")
@XmlMimeType("application/octet-stream") DataHandler data,
@WebParam(name="nameFile") String  fileName,
@WebParam(name="extension")String  extension)
throws ReturnError {


try {
if(data.getInputStream().available()>0){
                            ///leer el fichero
                        }else{
                           throw new ReturnError ("fichero vacio");
                        }
} catch (IOException e) {

ReturnError err =new ReturnError ();
err.initCause(e);
throw err;
}
}


el objeto DataHandler  encapsula el tratamiento del fichero.

simplemente ahora generamos todo el código con wsgen, y generamos el cliente con wsimport.
lo desplegamos en nuestro servidor de aplicaciones favorito. y a jugar.




Wednesday, October 6, 2010

Creación de ws con JAXWS

Estoy maravillado por lo fácil que es crear un WS en java, nada de AXIS2 ni cosas por el estilo. Con JAXWS es casi trivial.

Te creas un interface, siempre viene bien definir un contrat, aunque no es necesario.

public interface ILeerSensor {
   public abstract int dameLaTemperatura(String nombreDelSensor) throws SensorError;

}

Implementas el servicio


import javax.jws.WebParam;
import javax.jws.WebService;



@WebService
public class LeerSensorImpl implements ILeerSensor {

    public int dameLaTemperatura(@WebParam(name="nombreDelSensor") String nombreDelSensor) throws SensorError{
      
       return Sensor.find(nombreDelSensor).getTemperatura();


    }
}


creamos el WS
ejecutas esta simple instrucción:
wsgen -cp src\main\java;target\classes  -d target/web-classes -verbose -r src\main\webapp\WEB-INF\wsdl -wsdl pais.compania.proyecto.server.ws.LeerSensorImpl

Con esto se genera la estructura para generar un WS. Luego hay que empaquetarlo en un war para publicarlo en el servidor Tomcat o JBoss.

creamos el cliente

wsimport -p pais.compania.proyecto.cliente.ws -s src\main\java -d target\classes http://ip:port/nombreDelWar/LeerSensorImpl?wsdl

Nos genera unas clases por cada servicio. Y solamente hay que usarlo.


Problemas que me he encontrado:

Problema:
Si generas varios WS con nombre de objetos reutilizados, estos objetos no son los mismos. Es decir, la clase SensorError, si se usa en varios WS, genera tantas clases como WS (no metodos) implementes. No se como usar solo uno, ya que uso distintos paquetes y da error de "cast". Además si quieres pasar como parámetro a un WS una clase que te ha devuelto otro WS tienes que convertir a mano estos objetos que a priori son iguales.

Solución: Hacer un Wrapper para cada tipo de objeto.


Problema:
Si al crear una interfaz pones como valor de retorno un objeto List,  y luego en la signatura de la implementación devuelves un ArrayList, que implementa un List, todo funciona menos al generarte el cliente que consume el servicio.

Solución:
Poner tal cual la implementacion del interfaz, es decir si decimos que devolvemos un List en la interfacedevolver un List en la signatura de la implementación.


Problema:
Al generar los WS y los clientes, se pierden los nombres de los parametros en los métodos del WS.
Solución
Hay que poner explicitamente  @WebParam(name="nombreDelSensor") si quieres que te salga en eclipse el nombre del parámetro.