jueves, 12 de agosto de 2010

Samsung Galaxy S i9000

Bueno, finalmente he cambiado de móvil a un Samsung Galaxy S i9000 (Movistar). En los últimos tiempos he pasado de un Samsung Omnia i900 (Vodafone) con wm 6 y 6.5 a un HTC Magic (Vodafone) con android 1.5, 1.6, y 2.1.

Es otro mundo, un salto casi tan grande que pasar de WM 6.x a Android.

Iré poniendo a modo de guía todos los cambios que pueda necesitar, que los necesita (al menos el de movistar), aunque es fácil encontrarlos en otras páginas.

Los siguientes posts, ganar permisos de superusuario (root), parchearlo para mitigar el lag, etc.

martes, 13 de julio de 2010

Disponible el código fuente del ejemplo de Servicios Web con Apache CXF y Spring

Bueno, al fin está disponible el código fuente del ejemplo utilizado en los tres posts publicados hasta el momento sobre Servicios Web con Apache CXF y Spring. Es algo muy básico pero como guía no está mal del todo.

Puedes descargarlo de aquí.

Hasta el momento la serie de posts consta de tres entregas,
  • Cómo consumir un Servicio Web Apache CXF desde GWT
  • Añadiendo cabeceras SOAP a tus Servicios Web con Apache CXF
Momento en el que actualizaré el código fuente.

domingo, 11 de julio de 2010

Cómo probar tus Servicios Web con Apache CXF

Una vez hemos creado el servidor y el cliente con Apache CXF y Spring, vamos a preparar una aplicación web con el WS que nos haga de entorno de pruebas.

Como comentamos en el primero de los posts de la serie, el módulo svc-ws contendrá los ficheros necesarios para montar la aplicación. Así, situado en, src/main/webapp/WEB-INF tendremos el web.xml y el ws-ctx.xml.

Para el caso de ws-ctx.xml vemos,

 <?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint
id="servicio"
implementor="#servicioImpl"
address="/Servicio" />
</beans>


y un trozo de web.xml sería,

      <context-param>  
<param-name>contextConfigLocation</param-name>
<param-value>classpath:emilio/escobar/svc-ctx.xml
WEB-INF/ws-ctx.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>


Pero la magia está en el pom.xml,

 <?xml version="1.0"?>  
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>svc</artifactId>
<groupId>emilio.escobar</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>svc-ws</artifactId>
<packaging>war</packaging>
<name>SVC :: WS</name>
<dependencies>
<dependency>
<groupId>emilio.escobar</groupId>
<artifactId>svc-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>2.5.6.SEC02</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>2.5.6.SEC02</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-core</artifactId>
<version>2.1</version>
<exclusions>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-simple</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-local</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.1</version>
<exclusions>
<exclusion>
<artifactId>spring-web</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-common-utilities</artifactId>
<version>2.1</version>
<exclusions>
<exclusion>
<artifactId>spring-beans</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-context</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>2.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>svc-ws</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>failsafe-maven-plugin</artifactId>
<version>2.4.3-alpha-1</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>7.0.1.v20091125</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<webAppConfig>
<contextPath>/svc-ws</contextPath>
</webAppConfig>
<stopKey>foo</stopKey>
<stopPort>9999</stopPort>
<connectors>
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<port>9000</port>
<host>0.0.0.0</host>
</connector>
</connectors>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>


Los plugins failsafe-maven-plugin y jetty-maven-plugin son los encargados de arrancar el contenedor y de ejecutar los tests de integración.

Para este ejemplo he preparado un pequeño test que no hace gran cosa. Simplemente carga el contexto con el cliente,

 <?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<jaxws:client id="servicioClient"
serviceClass="emilio.escobar.api.Servicio"
address="http://localhost:9000/svc-ws/Servicio" />
</beans>


y lo ejecuta. El código del test,

 public class ServiceWSIT {  
private static final String MEMORY_PATH = "emilio/escobar/wsclictx.xml";
private static final String[] MEMORY = {MEMORY_PATH};
private static ConfigurableApplicationContext context;
private Servicio servicio;
@BeforeClass
public static void loadContext() {
context = new ClassPathXmlApplicationContext(MEMORY);
}
@AfterClass
public static void shutdown() {
context.close();
}
@Before
public void setUp() {
this.servicio = getBean(Servicio.class);
}
@Test
public void test() {
assertNotNull(servicio);
}
@Test
public void methodTest() {
final String nombre = "it-test";
final ParametroDTO param1 = new ParametroDTO();
param1.setKey("param1");
param1.setValue("1");
final ParametroDTO param2 = new ParametroDTO();
param2.setKey("param2");
param2.setValue("2");
final EntradaDTO entrada = new EntradaDTO();
entrada.setNombre(nombre);
entrada.setParametros(Lists.newArrayList(param1, param2));
final List<String> salida = servicio.operacion(entrada);
assertNotNull(salida);
assertTrue(salida.size() == 3);
assertEquals(nombre, salida.get(0));
assertEquals("param1-1", salida.get(1));
assertEquals("param2-2", salida.get(2));
}


Por último, a lo largo de la semana publicaré el enlace a la descarga del código utilizado hasta el momento.

lunes, 5 de julio de 2010

Servicios Web con Apache CXF / Spring / Maven (Cliente)

Ya hemos visto lo fácil que es montar el servicio web con Spring y CXF. Bien, el cliente es aún más sencillo.

 <jaxws:client id="servicioClient"   
serviceClass="emilio.escobar.api.Servicio"
address="http://localhost:9000/test-ws/Servicio" />


Luego sólo hay que solicitarlo como el resto de beans.

Sigue quedando pendiente subir los ficheros del proyecto pero lo haré en breve.

miércoles, 30 de junio de 2010

Servicios Web con Apache CXF / Spring / Maven (Servidor)

Desde hace unos meses vengo trabajando con servicios web y la verdad es que cada vez es más sencillo. Para montarlos usamos, Java 6, Maven 2.2.1, Spring Framework, Apache CXF, JAX-WS y JAXB.

El proyecto maven

Me voy a decantar en este momento por un proyecto multimódulo que contenga,

svc-api, con las interfaces del servicio y los dto.
svc-server, con la implementación del servicio.
svc-ws, módulo de tipo war con la declaración del servicio.

¿Por qué lo organizo así? Pues porque me aporta gran facilidad a la hora de desplegar el servidor y el cliente, sin más.

La interfaz del servicio

Un ejemplo simple de un servicio web que tiene una única operación que recibe un dto y devuelve una lista de cadenas es, para uno de los dto implicados,

 package emilio.escobar.api;

import java.io.Serializable;

import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="entrada")
public class EntradaDTO implements Serializable {
private static final long serialVersionUID = -1266514434540369282L;
private String nombre;
private List parametros;

@XmlElement(name="nombre")
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
@XmlElement( name="parametro" )
@XmlElementWrapper( name="parametros" )
public List getParametros() {
return parametros;
}
public void setParametros(List parametros) {
this.parametros = parametros;
}
}

la interfaz,

 package emilio.escobar.api;

import java.util.List;

import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;

@WebService
@XmlSeeAlso({EntradaDTO.class, ParametroDTO.class})
public interface Servicio {
@WebResult(name = "resultados")
List operacion(@WebParam(name = "entrada") EntradaDTO entrada);
}


y la implementación,

 package emilio.escobar.impl;

import java.util.List;
...

public class ServicioImpl implements Servicio {
List operacion(EntradaDTO entrada) {
...
}
}


Los ficheros de configuración

Como usamos Spring Framework y Apache CXF la configuración del servidor la hacemos en dos líneas,

 <id="servicioImpl" class="emilio.escobar.impl.ServicioImpl" />    <id="servicioWS" implementor="#servicioImpl" address="/Servicio" />  
En próximos post continuaré construyendo el ejemplo completo y adjuntaré todos los ficheros necesarios para probarlo.

Quedan pendientes cómo construir el cliente, cómo probarlo, cómo añadir elementos a la cabecera SOAP, y cómo usarlos desde GWT.

viernes, 4 de junio de 2010

GeNews estrena web

Ha pasado algo de tiempo pero la espera ha merecido la pena, GeNews estrena web. Desde un punto de vista práctico recomiendo una pasada por el vídeo donde se describen sus características principales.

GeNews es un desarrollo de la empresa andaluza Isotrol.

Por último, recordaros que existe un grupo en linkedIn y un canal en Vimeo.

miércoles, 28 de abril de 2010