Capitulo 4y5

12
Capitulo 4 Solución Use un bean de sesión sin estado con un dedicado, interfaz local de negocios para abstraer y encapsular las interacciones con el almacén de datos. Un grano sin int erf az sesión de vi suali zaci ón se puede utilizar también; la reali zación, sin embargo, es más difcil de reemplazar entonces. !a interfaz!ocal adicional permite una fácil sustitución de la implementación del bean y por lo tanto proporciona fe"ibilidad adicional. Una interfaz de negocio simplifes la prueba de la #$% fuera del recipiente. Un patrón #$% se reduce en un entorno &ava '' ( a una interfaz y una clase, con algunas anotaciones)'&* specifc. 'l bean de sesión no sólo es responsable de acceder y transformar los datos, pero para el mane+o de cone"iones de recursos y as. !os recursos necesarios por e+e mpl o, +av a".persistence.'ntit y-anage r o +av a" .s l.#ataSourc e/ deben inyectarse preferentemente; se reduce drásticamente la cantidad de código. 'l contenedor tie ne cuidado sobre la con cur rencia, ges tió n de recursos, y el alis tami ento de tran sacc ión de los recursos iny ecta dos. #eta lles )de 0ec urs os speci fc tal es como el nombr e de un proce di mie nto al mac en ado o las de los parámetros de entrada 1 salida tienen ue ser completamente encapsulado y no e"puesto a los clientes. 2o se necesita la introducción de una fábrica adicional. 's sólo aumentara la comple+idad y la cantidad de código de infraestructura. !a vista local de este fri+ol puede ser fácilmente inyectado a otros servicios con mecanismos estándar, se reuiere )no infraestructura personalizado. 'l #$% bean de sesión se anota con3r ansaction$ttribute 3r ansa ctio n$tt ribu te3 y pe.-$2#$3 %0 /, por lo ue tod os los méto dos #$% pueden ser invocados sólo en una transacción ya e"istente. !a transacción va a ser iniciado por los servicios ue utilizan el #$% para acceder a la persistencia. #ebido a ue el ob+etivo principal de la #$% es la estricta separación de los detalles de persistencia y la lógica de negocio, un #$% tiene ue ser invocado desde un componente lógica de negocio y no directamente de la presentación. Un intento de invocar un #$% directamente desde la capa de presentación es la indicación 50S3 ue es probablemente superfuous. Un servicio, o incluso servicio de fac6adas, probablemente 6acer un me+or traba+o en este caso. 0epensar 

Transcript of Capitulo 4y5

7/23/2019 Capitulo 4y5

http://slidepdf.com/reader/full/capitulo-4y5 1/12

Capitulo 4

Solución

Use un bean de sesión sin estado con un dedicado, interfaz local de negocios paraabstraer y encapsular las interacciones con el almacén de datos. Un grano sin

interfaz sesión de visualización se puede utilizar también; la realización, sin

embargo, es más difcil de reemplazar entonces. !a interfaz!ocal adicional permite

una fácil sustitución de la implementación del bean y por lo tanto proporciona

fe"ibilidad adicional. Una interfaz de negocio simplifes la prueba de la #$% fuera

del recipiente. Un patrón #$% se reduce en un entorno &ava '' ( a una interfaz y

una clase, con algunas anotaciones)'&* specifc.

'l bean de sesión no sólo es responsable de acceder y transformar los datos, pero

para el mane+o de cone"iones de recursos y as. !os recursos necesarios por e+emplo, +ava".persistence.'ntity-anager o +ava".sl.#ataSource/ deben

inyectarse preferentemente; se reduce drásticamente la cantidad de código. 'l

contenedor tiene cuidado sobre la concurrencia, gestión de recursos, y el

alistamiento de transacción de los recursos inyectados. #etalles)de 0ecursos

specifc tales como el nombre de un procedimiento almacenado o las de los

parámetros de entrada 1 salida tienen ue ser completamente encapsulado y no

e"puesto a los clientes.

2o se necesita la introducción de una fábrica adicional. 's sólo aumentara la

comple+idad y la cantidad de código de infraestructura. !a vista local de este fri+olpuede ser fácilmente inyectado a otros servicios con mecanismos estándar, se

reuiere )no infraestructura personalizado.

'l #$% bean de sesión se anota con3ransaction$ttribute

3ransaction$ttribute3ype.-$2#$3%0/, por lo ue todos los métodos #$%

pueden ser invocados sólo en una transacción ya e"istente. !a transacción va a

ser iniciado por los servicios ue utilizan el #$% para acceder a la persistencia.

#ebido a ue el ob+etivo principal de la #$% es la estricta separación de los

detalles de persistencia y la lógica de negocio, un #$% tiene ue ser invocado

desde un componente lógica de negocio y no directamente de la presentación. Unintento de invocar un #$% directamente desde la capa de presentación es la

indicación 50S3 ue es probablemente superfuous. Un servicio, o incluso servicio

de fac6adas, probablemente 6acer un me+or traba+o en este caso.

0epensar 

7/23/2019 Capitulo 4y5

http://slidepdf.com/reader/full/capitulo-4y5 2/12

'n un '&* 7 1 &ava '' ( ambiente ue usted no tiene ue usar la &#*C de ba+o

nivel para acceder a la base de datos más. 8uede utilizar el, pero potente lengua+e

genérico consulta &8$, as como S9! nativo a buscar no sólo los ob+etos

persistentes, pero también de transferencia de datos de ob+etos y tipos de datos

incluso primitivas de la base de datos. :ncluso es posible e+ecutar update y delete

sin utilizar la $8: de &#*C de ba+o nivel. !a $88 viene con el 'ntity-anager, ue

proporciona una funcionalidad genérica de acceso a datos. 'l acceso no puede

ser más sencillo. 'l 'ntity-anager puede inyectar directamente a cualuier bean

de sesión

Sin 'stado

3ransaction$ttribute 3ransaction$ttribute3ype.-$2#$3%0/

public class *oo<Service*ean implementa *oo<service =

8ersistenceConte"t

>7?

#escargar en @oAe*oo<.Com

em 'ntity-anager privado;

'l 'ntity-anager es ya una interfaz; su realización pertenece a la interfaz del

8roveedor de &8$ S8:/ y se puede intercambiar de forma declarativa sin cambiar 

el código

B8ersistencia ...

B2ombre persistence)unit DlibroD de tipo de transacción D&3$DE

B8roveedorE org.eclipse.persistence.+pa.8ersistence8rovider B1 proveedorE

...

-étodos 'ntity-anager son muy similares a las implementaciones #$% clásicos

C0U#/, e"cepto por el uso e"tensivo de los genéricos de &ava S' (

6ttp11+ava.sun.com1+Fse1>.(.G1docs1guide1language1generics.6tml / &ava S' ( y

as los genéricos no estaban disponibles en el momento &F''/.

'l 'ntity-anager ya es una abstracción y la encapsulación, por lo

desacoplamiento )furt6er no es necesario y sera incluso contraproducente. !a

abstracción del proveedor de servicios es permeable, como cualuier otra

abstracción, pero la situación #efinitivamente no va a me+orar con una capa

adicional de indirección.

7/23/2019 Capitulo 4y5

http://slidepdf.com/reader/full/capitulo-4y5 3/12

'l 'ntity-anager puede ser considerada como una implementación genérica de la

pauta #$%. Se puede utilizar como un #$% y se inyecta a los servicios e"istentes.

'l uso intensivo de lengua+e de consulta de la $88, sin embargo, se ve borrosa la

e"presividad de la lógica de negocio. !a creación de consultas puede ser 

fácilmente factorizar 6acia constructores)o consultas dedicado clases de utilidad.

!os servicios podran 6eredar la lógica pregunta de una clase abstracta también.

'n &ava '', el patrón #$% es opcional y ya no es la Hnica manera de acceder al

almacén de datos. 'ntity-anager como una abstracción es sufciente para la

mayora de los proyectos de softAare de la casa. 'n el desarrollo de productos,

sin embargo, un #$% dedicado como una capa adicional de abstracción podra

ser necesario. Sin embargo, la introducción de tal capa sin reuisito claro es

siempre sospec6as y debe +ustificarse al de los reuisitos duros.

'n resumen, en &ava '' I, un dedicado #$% es una e"cepción y no la regla. !a

#$% a menudo puede ser reemplazado con un 'ntity-anager inyectado en unServicio.

Convenciones

!a puesta en práctica concreta de la interfaz CrudService va a ser inyectado en el

cliente por e+emplo, un servicio/ por el contenedor. 'l #: 6izo la superfuous fábrica

de #$%. 3odas las estrategias de #$% sólo se componen de una interfaz de

negocio y su aplicación fri+ol un bean de sesión/. 'sta estructura es válida para

todas las estrategias de #$% y variaciones. $demás simplifcation con un bean de

sesión sin interfaz no es adecuado. Una inyección directa de la aplicación #$%

6ace ue las pruebas fuera del recipiente más difcil y la sustitución de la

aplicación casi imposible. !a 5igura > ilustra la estructura del patrón #$%.

>7J

#escargar en @oAe*oo<.Com

5igura >. !a estructura del patrón #$%

 $ #$% genérico se implementa una vez y reutilizarse de varios componentes. 8or 

lo tanto, debe ser colocado en un pauete genérico, por e+emplo

... KapplicationL .integration.dataservices

#$%s)#omain specifc debe residir en el componente de negocio relacionado, por 

e+emplo

K$pplicationL .boo<.dataservices

7/23/2019 Capitulo 4y5

http://slidepdf.com/reader/full/capitulo-4y5 4/12

o más corto

K$pplicationL .boo<.ds

8articipantes y 0esponsabilidades

M Cliente 'l cliente #$% se implementa generalmente como un bean de sesióncon o sin estado/ ue accede a la funcionalidad #$%. Utiliza la #$% llegar a un

cómodo acceso al almacén de datos. 'l cliente utiliza el #$% en el conte"to de su

realización lógica de negocio, por lo ue la #$% siempre se invoca en el conte"to

de una transacción activa. !a #$% se inyecta en el cliente por el contenedor. 'l

cliente es independiente de la realización especfica de la cone"ión almacén de

datos.

M #$% Un #$% se implementa como un bean de sesión sin estado y responsable

para la encapsulación de $8:s y tecnologas propietarias. 'sto incluye la

transformación de las e"cepciones )incluso propietarias encadenados ueridos.Un #$% proporciona un acceso cómodo y de alto nivel para el almacén de datos.

'leva el nivel de abstracción. 'n aras de la conveniencia y la disociación, la

principal responsabilidad de un #$% es la gestión de recursos y la conversión

entre la representación de datos de cada tecnologa, en ob+etos de dominio de

nivel superior. 'l acceso a los recursos de '' &ava estándar y su mane+o se

simplifica en gran medida por el contenedor, en caso de un bean de sesión se

utiliza para la aplicación. 'n caso &8$ se utiliza como almacén de datos, el

'ntity-anager toma la responsabilidad de la conversión de datos, mane+o de

cone"iones, y el alistamiento transacción.

M !os datos de la tienda almacén de datos es una totalmente integrada como

&8$/, estandarizado como &#*C, &C$/, o un recurso de propiedad ue se tiene

ue acceder para acceso a datos. $cceso &8$ ya viene con &ava '')

encapsulación adicional rara vez es necesaria. Siempre es una buena idea, >4G

#escargar en @oAe*oo<.Com

sin embargo, utilizar #$%s para encapsular el acceso a datos de propiedad y

desacoplar la lógica de dominio de la tecnologa patentada.

'strategias

3odas las estrategias apuntan a un mismo ob+etivo simplifcation de acceso a

datos y desacoplamiento pragmática del almacén de datos concreto. #ependiendo

de las necesidades specifc con el proyecto, este reuisito genérico puede

satisfacerse mediante diferentes implementaciones effciently.

7/23/2019 Capitulo 4y5

http://slidepdf.com/reader/full/capitulo-4y5 5/12

#$% genérico

!a firma de los métodos 'ntity-anager ya es genérico. !os métodos de resultados

de la +ava".persistence.9uery no pueden ser de tipo seguro, porue tienen ue

materializar un ob+eto de una fila dada con+unto de tipo desconocido. 'stos

métodos devuelven un solo ob+eto o un +ava.util.!ist de ob+etos, respectivamente.'l usuario de la clase de consultas tendrá ue emitir el resultado a una entidad

&8$ particular, de todos modos. !a implementación #$% devuelve sólo la lista

prima de ob+etos, )casting sigue siendo responsabilidad del cliente. 8ara todos los

otros métodos el tipo de retorno se infiere a partir del parámetro cuando sea

posible. 'sto 6ace ue el uso de la aplicación #$% genérico más conveniente.

!a interfaz CrudService no está contaminada con el ue $8: es sólo una simple

interfaz '&* limpio vie+o &ava 8o+i/. Contiene no sólo los sospec6osos 6abituales

tales como los métodos de crear, buscar, actualizar y eliminar/, pero algunos

fnders as. 'l siguiente fragmento muestra la interfaz de un #$% genérico.

Capitulo (

(

8atrones y Servicios infraestructurales

 $lgunos patrones son difciles de clasificar, ya ue pueden ser utilizados en cada

capa. 2o todos los patrones Htiles son relevantes para el cuadro más grande y

pueden ser omitidos en la descripción de la aruitectura. 'ste captulo cubre

dic6os patrones Htiles y difciles de clasificar y aHn as y servicios pHblicos,incluyendo

M Servicio de arranue

M Singleton

M localizador de 5ri+ol

M rastreador 3ema

M #ependencia e"tensor de inyección

M e"tractor de carga Htil

M aglutinante de 0ecursos

M Soporte de Conte"to

#escargar en @oAe*oo<.Com

7/23/2019 Capitulo 4y5

http://slidepdf.com/reader/full/capitulo-4y5 6/12

#escargar en @oAe*oo<.Com

 $rranue Servicio

'l &ava '' ( contenedor gestiona el ciclo de vida de los componentes

desplegados. *eans de sesión sin estado se crean principalmente en la demanda;

beans de sesión con estado se crean en la inyección o la bHsueda de tiempo.

&ava '' ( soporta una forma estandarizada para forzar el recipiente para

inicializar ellos en tiempo de inicio. Sin estado agrupación de sesiones de fri+ol es

mencionado en la especificación y disponible en la mayora de los servidores de

aplicaciones, pero la forma en cómo se confgured la piscina no está

estandarizado. Usted simplemente no puede depender de la e"istencia de a+ustes

tales como piscina de tamaNo inicial o)pool)size min en cada servidor de

aplicaciones. 2o 6ay manera estandarizada para 6acer cumplir un bean de sesión

para iniciar durante el despliegue.

8roblema

 $lgunos lógica y los servicios de infraestructura deben ser inicializado antes de la

e+ecución de la lógica de negocio real. 'stos servicios pueden ser costosos, lentos

o inestable por e+emplo, una fle confguración O-! podra ser mal formado/. 's

una buena estrategia para empezar ellos a la mayor brevedad posible. Sólo la

introducción de '&* 7.> proporcionó una solución estandarizada para el problema

de inicialización. 2i F." '&* ni '&* 7.G apoyaron de manera directa para forzar el

recipiente para comenzar beans de sesión en tiempo de despliegue, con la

e"cepción de la introducción de un servlet inicio.

5uerzas

M 2ecesita una manera portátil para iniciar los servicios con entusiasmo

M !a solución debe proporcionar ganc6os e"tensibles con la ue *eans de sesión

sin estado e"istentes se pueden inicializar.

Solución

!a solución a este problema dependientes de la versión '&* apoyado. $ntes de

'&* 7.> ue podra forzar la inicialización de ciertos componentes con un servlet.'n '&* 7.> se puede lograr el mismo con sólo dos anotaciones adicionales.

'&* 7.>

'l problema de inicio se resuelve en el '&* 7.> specifcation. Usted puede

inicializar los servicios directamente en el patrón Singleton, o incluso inyectar e

inicializar beans de sesión e"istentes para tal fin.

7/23/2019 Capitulo 4y5

http://slidepdf.com/reader/full/capitulo-4y5 7/12

Sólo anotar una clase con las anotacionesSingleton yStartup y desplegarla +unto

con sus servicios. 'sto obliga al contenedor para inicializar el bean en tiempo de

despliegue, como se muestra en el siguiente fragmento

Singleton

8uesta 'n -arc6a

public class ServiceStarter =

'&*

servicio '"istingService*ean privado;

8ostConstruct

pHblica %n:nitialize void / =

System.out.println DPD Q t6is.getClass / getSimple2ame / Q D8ostConstructD./;

service.please:nitialize /;

#escargar en @oAe*oo<.Com

R

R

'l contenedor inicializa el fri+ol, pero no invocará la lógica o los servicios de

negocio. 8uede forzar fácilmente el recipiente para invocar su ganc6o al designar 

el método de inicialización con la anotación8ostConstruct. 'ste método

%n:nitialize en el e+emplo a continuación/ se invoca +usto después de la

construcción de la ServiceStarter y la invocación de un constructor por defecto,

como se demuestra en el siguiente e+emplo

Sin 'stado

public class '"istingService*ean =

8ostConstruct

pHblica %n:nitialize void / =

System.out.println DPD Q t6is.getClass / getSimple2ame / Q D8ostConstructD./;

R

public void please:nitialize / =

7/23/2019 Capitulo 4y5

http://slidepdf.com/reader/full/capitulo-4y5 8/12

System.out.println DPD Q t6is.getClass / ... Q Dplease:nitialize /D/;

R

public String some*usiness!ogic / =

return Dola desde el granoD;

R

R

Usted puede poner la lógica de inicialización a la derec6a en el

método8ostConstruct del Singleton. 'n este punto la inyección de dependencias

ya se 6a realizado, por lo ue puede confiar en la e"istencia de los recursos

inyectados. :ncluso puede utilizar la ServiceStarter como envoltorio para inicializar 

beans de sesión comunes. Usted sólo tiene ue inyectar la referencia y recurrir a

cualuier método ue desee. 'sto a la larga va a forzar el recipiente para inyectar 

e inicializar el bean de sesión. #urante la inicialización del contenedor crea el bean

si no ya e"iste/; entonces e+ecuta el método8ostConstruct e invoca su método de

negocio. 'sto puede ser fácilmente reproducido con la muestra anterior; se genera

el siguiente resultado

PServiceStarter8ostConstruct

P'"istingService*ean8ostConstruct

P'"istingService*ean 8lease:nitialize /

Usted puede incluso infuencia del orden en ue Singletons dependientes

e+ecutarán el inicialización. 8ara demostrar esto, se puede introducir otro

Singleton, el inicializador

Singleton

public class :nicializador =

8ostConstruct

pHblica %n:nitialize void / =

System.out.println DPD Q t6is.getClass / getSimple2ame / Q D8ostConstructD./;

R

R

7/23/2019 Capitulo 4y5

http://slidepdf.com/reader/full/capitulo-4y5 9/12

FG?

#escargar en @oAe*oo<.Com

!a declaración de la dependencia a otra Singleton Se pueden dar con la

anotación#epends%n. 'sta anotación tiene un solo atributo de tipo String KL.

0epresenta los nombres de los granos ue tienen ue ser inicializado antes de la

clase anotada

Singleton

8uesta 'n -arc6a

#epends%n D:nicializadorD/

public class ServiceStarter =

'n este e+emplo, el inicializador se inicializa antes de la ServiceStarter

P:nitializer8ostConstruct

PServiceStarter8ostConstruct

P'"istingService*ean8ostConstruct

P'"istingService*ean 8lease:nitialize /

Solución para las versiones anteriores de '&*

2o 6ay manera estándar de 6acer cumplir la inicialización de los beans de sesión

'&* 7.> antes. 'l contenedor @eb, sin embargo, fue capaz de proporcionar esta

funcionalidad para Servlets durante los das &F''. 8ara inicializar un servicio,

usted tiene ue proporcionar un servlet con un método init sobrescribe como se

muestra en el siguiente fragmento

public class ServiceStarter e"tiende ttpServlet =

'&*

servicio :nfrastructureService privado;

T %verride

public void init / t6roAs Servlet'"ception =

System.out.println . DPD Q 36is.getClass / getSimple2ame / Q Dinit /D/;

t6is.service.dummy-et6od /;

7/23/2019 Capitulo 4y5

http://slidepdf.com/reader/full/capitulo-4y5 10/12

R

R

Sólo inyectar un bean de sesión de su elección en el servlet. Una inyección simple

no es suficiente para 6acer cumplir la creación del fri+ol; ue es el mismo problema

ue en el caso de laSingleton. !a invocación de cualuier método arbitrario, sin

embargo, 6ará ue el contenedor para inicializar el bean de sesión.

!a tarea ue ueda se confguring el servlet en el Aeb."ml o con anotaciones/,

ue comenzará durante el despliegue. 8ara ello, tendrá ue dar un valor, superior 

a cero, en la etiueta load)on)startup.

B@eb)appE

BServletE

BServlet)nameE ServiceStarter B1 servlet)nameE

BServlet)classE ... servicestarter.ServiceStarter B1 servlet)classE

B!oad)on)startupE > B1 load)on)startupE

B1 ServletE

B1 @eb)appE

'l valor infuences el orden más alto es el valor de inicialización, el anterior 

relativamente a los demás/ se inicializa un Servlet. 'l resultado es comparable ala anotación#epends%n. 'l despliegue de los resultados de servlet en la siguiente

salida

:nit PServiceStarter /

P:nfrastructureService8ostConstruct

FGJ

#escargar en @oAe*oo<.Com

P:nfrastructureService #ummy-et6od

0epensar 

0epensar no es necesario, pero refactorización es. Con la disponibilidad de '&*

7.> soporta su servidor de producción, se puede transformar sus servlets de inicio

e"istentes en los granos Singleton y des6acerse de las guerras superfuous.

7/23/2019 Capitulo 4y5

http://slidepdf.com/reader/full/capitulo-4y5 11/12

8articipantes y 0esponsabilidades

'l proceso se 6a iniciado ya sea por el servlet o un grano de Singleton, el motor de

arranue de servicio. 'n ambos casos, el recipiente inicia el proceso e invoca el

método init o8ostConstruct, respectivamente. !a inicialización se realiza ya sea en

los ganc6os de inicio directamente o delegada a los beans de sesión mediante lainvocación de métodos ficticias.

8ruebas

'l comportamiento apropiado de inicio sólo se puede probar durante el tiempo de

implementación. !as pruebas unitarias, sin embargo, se recomienda probar la

propia lógica de inicialización. Servicio de arranue es una e"cepción a la regla;

!as pruebas de carga y estrés son irrelevantes au.

#ocumentación

#e inicio de servicio es irrelevante para el cuadro más grande, por lo ue no debe

aparecer en los diagramas de descripción. 'n '&* 7.>, incluso se podra omitir 

&ava#oc, porue la responsabilidad de inicialización ya está bien documentada

con la anotaciónStartup.

Consecuencias

'l arrancador servicio me+ora el tiempo de e+ecución robustez del sistema de

arranue servicios crticos con impaciencia. 2o 6ay otros impactos sobre los

reuisitos no funcionales.

8atrones 0elacionados

'l arrancador servicio invoca los servicios e"istentes, 5ac6adas de servicio, o

puertas de enlace para 6acer valer su inicialización. 2o está relacionado con otros

patrones en cuanto a su responsabilidad. 'l Singleton, sin embargo, es

técnicamente idéntica a la de arranue de servicio.

F>G

#escargar en @oAe*oo<.Com

Semifallo

'l modelo de un Hnico subproceso de programación es una de las principales

caractersticas de los '&*. !a realización de la idea conduce a la eliminación de

instancias compartidas y el estado de los 6ilos. Cada petición del usuario es decir,

todos los 6ilos/ opera en una sola instancia de bean de sesión. Una instancia sólo

7/23/2019 Capitulo 4y5

http://slidepdf.com/reader/full/capitulo-4y5 12/12

se puede acceder por un 6ilo a la vez. *eans de sesión con estado son aHn más

restrictivas. 'llos no sólo tienen ue ser accesibles por un 6ilo de un tiempo, pero

cada solicitud tiene ue estar asociado con el mismo usuario.

8roblema

!a programación simplifed es e"celente para la escalabilidad y la programación

multi)core, pero 6ace ue la gestión de los recursos limitados duros. !a cantidad

de casos activos bean de sesión depende solamente del nHmero de solicitudes de

los usuarios paralelas y la propiedad de confguración servidor de aplicaciones.

Configuración del grupo, la confguración de má", tamaNo de la piscina min, y su

capacidad de cambio de tamaNo en particular, no están respaldados por la

especificación. 8or lo tanto, no es posible implementar un Singleton de una

manera portátil; puede no depender de la disponibilidad del parámetro má"imo

tamaNo de la piscina, ni en su comportamiento esperado.

 $demás, sin una instancia central, es imposible implementar un effcient de sólo

lectura cac6é. 'l almacenamiento en cac6é es especialmente interesante para los

datos maestros y confguración.

5uerzas

M !a solución tiene ue ser portable a través de servidores.