Wednesday, December 22, 2010

Creación de un producto a partir del eclipse

Eclipse te permite extender la funcionalildad añadiendo plugins. Si quieres hacer una solucion (terminología de .NET), producto en Eclipse, es muy fácil.

Primero debes tener correctamente resueltas las dependencias de los plugins. Es muy posible que tu plugin use otros plugins. Si te falta alguna dependencia el producto no se generará.

Pulsamos botón derecho sobre nuestra plugin de eclipse New->Product configuration
Insertamos un nombre de fichero de configuracion y 
seleccionamos en el wizard * use a launch configuration 

En el apartado de Testing pulsamos el link de Synchronize y correguimos los posibles errores. Si nos da un error de  "The plug-in 'org.eclipse.platform' is not in the workspace and cannot therefore be modified. Please import it into your workspace and retry."

Para correguir este error simplemente se importa el plugin en el workspace con la opcion de import ->   Plug-in Development -> plug-ins and fragments. Se muesta una lista de plugins, de la cual seleccionamos 'org.eclipse.platform'

GlassFish V3 Linux:

Para instalar GlassFish en Linux es muy fácil. Existe un manual aqui http://dlc.sun.com/pdf/821-1756/821-1756.pdf

Existen diversos ficheros de instalación. Multiidioma o Inglés  y compresión  zip o auto-instalador

Instalar la última versión de JDK correspondiente.

Autoinstalador
Descargarte la version de Oracle GlassFish Server 3.0.1.sh
Si no tienes un sistema de x-windows, da error al no encontrar las fuentes tipográficas. Puedes usar la instalación en silent mode junto con un fichero de respuestas para la configuración.
Descargarte la version de Oracle GlassFish Server 3.0.1.sh estableces los permisos de ejecución y sigues los pasos.
No he conseguido instalarlo con el auto-instalador. Así que he optado por el formato zip

Multiidioma

En la versión multiidioma al desplegar un War, me muestra un error. premature end of file. Es un error relacionado con el analizador lexico de XML. No he conseguido solucionarlo.

http://www.oracle.com/us/products/middleware/application-server/oracle-glassfish-server/index.html

Así que la única opción que me ha funcionado ha sido Ingles en formato zip.
ogs-3.0.1.zip

Tuesday, December 21, 2010

GlassFish V3 Linux: process already using the admin port 4848

-- In English

when I run  glassfishv3 in linux trhow this error

glassfishv3/glassfish/bin# ./asadmin start-domain domain1
 

There is a process already using the admin port 4848 -- it probably is another instance of a GlassFish server.



I havent any port open try -> netstat -tlunp 
I thought, is this a problem IPV6? no 

the problem that  the file /etc/host  havent PC name with IP
add this line in the file.

ip_PC name_PC
192.144.168.2 miserver


This works




--In spanish.

Al lanzar glassfishv3 en linux recibo este error

glassfishv3/glassfish/bin# ./asadmin start-domain domain1
 

There is a process already using the admin port 4848 -- it probably is another instance of a GlassFish server.



Evidentemente no tengo ningún puerto en uso netstat -tlunp 

Pensaba que era problema del soporte de IPV6, pero tampoco.

Así, ¿que cual es el problema?
El problema es que en el fichero /etc/host no esta definido en nombre del equipo con su ip
así que simplemente hay que añadir

ip_del_equipo nombre_del_equipo
192.144.168.2 servidor


Ya está funcionando.







Friday, December 17, 2010

eclipse jet

El JET es la creacion de unas plantillas para la generacion de clases fuentes java, para la creacion de ficheros de texto, parecido al velocity, en el ejemplo creamos XML.
A partir de un formato similar al JSP, se generar los ficheros fuentes java.
El fichero plantilla de JET es parecido a esto con la extension xmljet
. Esto genera un fichero .java para la creacion de ficheros XML
<%@ jet
    package="pais.empresa.proyecto.modulo"
    class="NombreClaseGenerada"
    skeleton="generator.skeleton" %>

<% String variable = (String) parametro1; %>
//fichero XML a generar
<xml><dato><%= variable%>"</dato></xml>



Para pasar parametros hay que incluir otra plantilla de ficheros generator.skeleton (en formato java) que se agregará como cabecera a cada uno de nuestras plantillas JET  para generar los ficheros fuentes.

public class CLASS {

     public String generate(String parametro1) {
         return "";
     }
}

Donde CLASS es sustituido por el JET por el parametro que hemos puesto en la plantilla JET en el apartado de  class="NombreClaseGenerada"

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.







Monday, September 27, 2010

patron Factory

Llevando el mantenimiento de una aplicacación. Me comentaron cambiar el envío de los datos, estos datos son un conjunto de ficheros que se tienen que enviar entre 2 computadores. Antes se realizaba a través de un FTP pero ahora se realizaza con rutas locales de red. Todos sabemos que el día de mañana es posible que te digan que lo dejaras como estaba antes. Pues habrá que dejarlo preparado.

Como el envío de los ficheros no está centralizado, es decir, esta disperso en toda la apliacion, y no tienes una clase que centraliza este envío, (yo no lo hice) tienes que deditacte a bucar, modificar y probar todo el código de tu aplicación.
Como solucion propongo el centralizarlo y además de crear un interfaz para el envio de fichero común. Que no sepa el usuario que tipo de envio esta realizarndo. Se envía y punto. Todo ello configurable en un fichero properties

//generamos un interface comun a todas las clases de transporte
public interface TransportFile {
 
   void connect() throws SocketException, IOException;
   void copyFile(String str_rutaOrigen, String str_rutaDestino) throws IOException;
   void disconnect() throws IOException;
   void get(String str_rutaLocal, String str_rutaRemota) throws IOException;
   boolean isConnected();

}
//implementamos cada uno de los metodos de envio de fichero, FTP, unidades de red, etc
 public class LocalFile implements TransportFile{

}
 //creamos una factoria que crea la implementación que necesitemos
public class FactoryTransportFile {

    public FactoryTransportFile(String ftpDireccion,String ftplogin,String ftppassword){
    }
    public TransportFile create(){

    }
}

Pros de esta solución:
No tienes que rehacer todo tu código. solamente donde generas el patron factoria.
Esta preparado para cambiar a otro tipo de métod de transporte de ficheros.

Tuesday, September 21, 2010

gestión de la memoria a través de ficheros

Realizando el mantenimiento de una aplicación, que utiliza un fichero temporal para la copia entre directorios de un FTP, he descubierto un método para mejorar el proceso sin crear ficheros temporales.  Esto es el NIO. Para mí completamente nuevo, pero por lo que he podido leer esta disponible desde la versión 1.4 de JVM.

Con NIO puedes utilizar la memoria como si fuera un fichero. Ya no tienes por que que crearte un byte buffer[], simplemente usas un fichero que se mapea en la memoria, en mi caso lectura y escritura, y te mueves por su contenido, y puedes ir realizando marcas leyendo datos escribiendo, etc.

static int length = 0x01FFFFFF; 

MappedByteBuffer inOut = new RandomAccessFile("fileMemory.dat", "rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, length);


//Borra la zona de memoria
inOut.clear();

DataInputStream dis = new DataInputStream(...);

while (dis.available() != 0) {
    inOut.put(dis.readByte());
}
inOut.rewind();//pone el puntero del fichero al inicio

for(;contadorBufferFichero>0;contadorBufferFichero--) {
    dos.writeByte(inOut.get());
}