sobre apache-cxf

Buenas, voy a escribir un poco sobre apache-cxf, hay que decir que para mi, es la implementación de referencia si quieres crear un servicio asíncrono como es un servicio web.

Para usarlo tendremos que poner en el pom.xml las siguientes dependencias:

<!– motor servicios web–>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-core</artifactId>
<version>${cxf.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-javamail_1.4_spec</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-activation_1.1_spec</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>

<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>${cxf.version}</version>
</dependency>

donde ${cxf.version} esta declarado en la parte de los properties tal que así:

<properties>
<cxf.version>[2,)</cxf.version>
<spring.version>3.0.6.RELEASE</spring.version>
<servlet.version>2.5</servlet.version>
<hibernate-annotations.version>3.4.0.GA</hibernate-annotations.version>
<hibernate-commons-annotations.version>3.3.0.ga</hibernate-commons-annotations.version>

<hibernate-core.version>3.3.1.ga</hibernate-core.version>
<hsqldb.version>1.8.0.7</hsqldb.version>
<junit.version>4.4</junit.version>
<netbeans.hint.deploy.server>gfv3ee6</netbeans.hint.deploy.server>
</properties>

asumiendo que useis maven, claro está,  si no lo usais, empezad ya!

Una vez que tenemos esto preparado, a la hora de compilar maven nos traerá los jar necesarios para empezar a trabajar.

Para tener un servicio web usando cxf tenemos que pensar en diseñar primero una interfaz con los métodos que queremos exponer y un fichero que implemente esta interfaz.

La interfaz:

package com.aironman.core.cxf.service;

import com.aironman.core.exceptions.StoreException;
import com.aironman.core.pojos.Items;
import javax.jws.WebService;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/*
Interfaz del endpoint del WS
* @author Alonso Isidoro Roman
*
*/
@WebService
@Path(“/StoreService”)
public interface StoreService
{
/*
* este ws se invoca de la forma siguiente:
* //http://localhost:8080/CoreTienda/StoreMT/StoreService/logOut/LEGAJO1
//http://localhost:8080/CoreTienda/StoreMT/StoreService/logIn/LEGAJO1/pass1/LAT/LON
o

//https://localhost:8181/CoreTienda/StoreMT/StoreService/logOut/LEGAJO1*/

@GET
@Path(“logIn/{h}/{p}/{lat}/{lon}”)
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
boolean logIn(@PathParam(“h”) String hash
,@PathParam(“p”) String pass
,@PathParam(“lat”) String lat
,@PathParam(“lon”) String lon) throws StoreException;

@GET
@Path(“logOut/{h}”)
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
boolean logOut(@PathParam(“h”) String hash) throws StoreException;

@GET
@Path(“addItemToCart/{h}/{i}”)
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
boolean addItemToCart(@PathParam(“h”) String hash
,@PathParam(“i”) String isbn) throws StoreException;

@GET
@Path(“deleteItemFromCart/{h}/{i}”)
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
boolean deleteItemFromCart(@PathParam(“h”) String hash
,@PathParam(“i”) String isbn) throws StoreException;

@GET
@Path(“confirmCart/{h}/{p}”)
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
boolean confirmCart(@PathParam(“h”) String hash
,@PathParam(“p”) String pass) throws StoreException;
@GET
@Path(“getDescriptionItem/{i}”)
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
String getDescriptionItem(@PathParam(“i”) String isbn) throws StoreException;

@GET
@Path(“getItem/{h}/{i}”)
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
Items getItem(@PathParam(“h”) String hash
,@PathParam(“i”) String isbn) throws StoreException;
}

He declarado 7 métodos, voy a usar GET para el transporte de datos, @Path sirve para indicar como se invoca al método @Consumes y @Produces son anotaciones que indican como quiero que se mande y reciba la información, en este caso JSON, pero si queremos xml habría que usar MediaType.APPLICATION_XML. @PathParam es una etiqueta que ya no es necesario poner, pues como usamos GET y RESTFUL, las invocaciones se hacen sin usar parámetros &h=MIVALOR. Ahora es /localhost:8080/ miApp/getItem/ITEM1 mucho mas bonito y sobre indexable por google de una forma mucho mas eficaz que usando la anterior forma.

Ahora la implementacion. Recordad, es un fichero al que podremos inyectarle mediante spring lo que mas nos convenga y que debe implementar la interfaz anteriormente descrita.

/**
*
*/
package com.aironman.core.cxf.service;

import com.aironman.core.exceptions.StoreException;
import com.aironman.core.pojos.Items;
import com.aironman.core.service.CoreService;
import javax.jws.WebService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

/***
* implementacion del Endpoint del WS
* @author alonso
*/
@Service(“storeServiceMT”)
@WebService(endpointInterface = “com.aironman.core.cxf.service.StoreService”)
public class StoreServiceMultiThreadImpl implements StoreService {

private static final Log log = LogFactory.getLog(StoreServiceMultiThreadImpl.class);
@Autowired
private CoreService coreService;

public StoreServiceMultiThreadImpl(){
if (log.isDebugEnabled()){
log.info(“CONSTRUCTOR SIN tipo StoreServiceMultiThreadImpl…”);
}
}

/***
* Metodo que hace el logIn al sistema
* @param email
* @param pass
* @param lat
* @param lon
* @return true OK false KO
* @throws StoreException
*/
public boolean logIn(String hash,String pass, String lat,String lon) throws StoreException
{
if (log.isDebugEnabled()){
StringBuffer sbInit = new StringBuffer(“Init StoreServiceMultiThreadImpl.logIn. hash: “)
.append(hash)
.append(” pass: “).append(pass);
log.info(sbInit);
}
boolean retorno = this.getCoreService().logIn(hash, pass, lat, lon);
if (log.isDebugEnabled()){
StringBuffer sbEnd = new StringBuffer(“End StoreServiceMultiThreadImpl.logIn. hash: “)
.append(hash)
.append(” pass: “).append(pass)
.append(” retorno: “).append(retorno);
log.info(sbEnd);
}

return retorno;
}

/**
Metodo que hace el logout del sistema. deja el campo activo de la persona encontrada a false
* Estos dos metodos logIn y logOut son exactamente iguales en las dos implementaciones, por lo que debo hacer que StoreAdminImpl y StoreImpl
* hereden una clase base que contenga estos dos metodos.
* @param email
* @return
* @throws StoreException
*/
public boolean logOut(String hash) throws StoreException
{
if (log.isDebugEnabled()){
StringBuffer sbInit = new StringBuffer(“Init StoreServiceMultiThreadImpl.logOut. hash: “)
.append(hash);
log.info(sbInit);
}
boolean retorno = this.getCoreService().logOut(hash);
if (log.isDebugEnabled()){
StringBuffer sbEnd = new StringBuffer(“End StoreServiceMultiThreadImpl.logOut. hash: “)
.append(hash)
.append(” retorno: “).append(retorno);
log.info(sbEnd);
}

return retorno;
}

/*
Metodo que se encarga de añadir un item dado su isbn en el carrito del usuario idUsuario identificado en el sistema
* @param email el identificador del usuario logado en el sistema que quiere añadir en su carrito el producto identificado por el isbn
@param isbn el identificador del producto
**/
public boolean addItemToCart(String hash, String isbn) throws StoreException
{
if (log.isDebugEnabled()){
StringBuffer sbInit = new StringBuffer(“Init StoreServiceMultiThreadImpl.addItemToCart. hash: “)
.append(hash)
.append(” isbn: “).append(isbn);
log.info(sbInit);
}
boolean retorno = this.getCoreService().addItemToCart(hash, isbn);

if (log.isDebugEnabled()){
StringBuffer sbEnd = new StringBuffer(“End StoreServiceMultiThreadImpl.addItemToCart. hash: “)
.append(hash)
.append(” isbn: “)
.append(isbn)
.append(” retorno: “).append(retorno);
log.info(sbEnd);
}
return retorno;
}

/***
* Metodo que se encarga de borrar de la lista de la compra del usuario el item identificado por el isbn
* @param hash el hash del usuario
* @param isbn
* @return
* @throws StoreException
*/
public boolean deleteItemFromCart(String hash, String isbn) throws StoreException
{
if (log.isDebugEnabled()){
StringBuffer sbInit = new StringBuffer(“Init StoreServiceMultiThreadImpl.deleteItemFromCart. hash: “)
.append(hash)
.append(” isbn: “).append(isbn);
log.info(sbInit);
}
boolean retorno = this.getCoreService().deleteItemFromCart(hash, isbn);
if (log.isDebugEnabled()){
StringBuffer sbEnd = new StringBuffer(“End StoreServiceMultiThreadImpl.deleteItemFromCart. hash: “)
.append(hash)
.append(” isbn: “)
.append(isbn)
.append(” retorno: “).append(retorno);
log.info(sbEnd);
}

return retorno;
}
/***
* METODO que se encarga de confirmar el carro del usuario
* @param hash que representa al usuario
* @param passConfirm el pass que coonfirma la compra
* @return true si OK, false KO
* @throws StoreException
*/
public boolean confirmCart(String hash,String passConfirm) throws StoreException
{
if (log.isDebugEnabled()){
StringBuffer sbInit = new StringBuffer(“Init StoreServiceMultiThreadImpl.confirmCart. hash: “)
.append(hash)
.append(” passConfirm: “).append(passConfirm);
log.info(sbInit);
}
boolean retorno = this.getCoreService().confirmCart(hash, passConfirm);
if (log.isDebugEnabled()){
StringBuffer sbEnd = new StringBuffer(“End StoreServiceMultiThreadImpl.confirmCart. hash: “)
.append(hash)
.append(” passConfirm: “)
.append(passConfirm)
.append(” retorno: “).append(retorno);
log.info(sbEnd);
}

return retorno;
}

public String getDescriptionItem(String isbn) throws StoreException
{
if (log.isDebugEnabled()){
StringBuffer sbInit = new StringBuffer(“Init StoreServiceMultiThreadImpl.getDescriptionItem. isbn: “)
.append(isbn);
log.info(sbInit);
}
String description = this.getCoreService().getDescriptionItem(isbn);
if (log.isDebugEnabled()){
StringBuffer sbEnd = new StringBuffer(“End StoreServiceMultiThreadImpl.getDescriptionItem. isbn: “)
.append(isbn)
.append(” description: “).append(description);
log.info(sbEnd);
}

return description;
}

/*
Este metodo va a traerte el item y va a meterlo en la lista de la compra de la persona que lo ha solicitado
*/
public Items getItem(String hash,String isbn) throws StoreException
{
if (log.isDebugEnabled()){
StringBuffer sbInit = new StringBuffer(“Init StoreServiceMultiThreadImpl.getItem. isbn: “)
.append(isbn)
.append(” hash: “)
.append(hash);
log.info(sbInit);
}
Items item = this.getCoreService().getItem(hash, isbn);
if (log.isDebugEnabled()){
StringBuffer sbEnd = new StringBuffer(“End StoreServiceMultiThreadImpl.getItem. isbn: “)
.append(isbn)
.append(” hash: “)
.append(hash)
.append(” item: “).append(item);
log.info(sbEnd);
}

return item;
}
/**
* @return the coreService
*/
public CoreService getCoreService() {
return coreService;
}

/**
* @param coreService the coreService to set
*/
public void setCoreService(CoreService coreService) {
this.coreService = coreService;
}

}

Como podeis ver, la implementacion del servicio web tiene inyectado otra interfaz que gestionará el core del sistema, de forma que tenemos un acoplamiento débil entre la capa del servicio web y el core. Si un día nos aburrimos o encontramos una implementación mejor sobre servicios web, pues solo tendremos que inyectar esta interfaz a una nueva implementación.

Saludos gente,

 

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s