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'
Wednesday, December 22, 2010
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
Existen diversos ficheros de instalación. Multiidioma o Inglés y compresión zip o auto-instalador
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.
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"
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
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.
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
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");
}
}
}
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.
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.
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.
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.
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());
}
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());
}
Subscribe to:
Posts (Atom)