Cómo hacer encuestas con SURVEY MONKEY

SurveyMonkey es una excelente herramienta para levantar información en una investigación de mercados o para hacer una pequeña encuesta. Sus funcionalidades son muy atractivas, pues solo basta con indicar que tipo de encuesta queremos hacer y la herramienta nos dará los diversos tipos de preguntas a utilizar.

Si aun no tienes una cuenta, aquí te dejamos un breve instructivo  en video para que lo puedas hacer (es tan sencillo que te demorará menos de un minuto registrarte) y luego te dejamos otro video tutorial para que puedas empezar a hacer tus encuestas.

Ten presente que los ejemplos que hemos desarrollado obedecen a un perfil de usuario con una cuenta gratuita.

Exitos con tu encuesta, si tienes dudas o consultas escríbenos en la opción de comentarios que encontrarás al final de esta publicación.


Instructivo para crear encuestas en survey mokey



Esperamos que este tutorial para crear encuestas usando survey monkey haya sido fácil de comprender.


Encuentra más de 300 casos de estudio de marketing, administración y gestión empresarial en http://www.facebook.com/EBlogDeRaffo
Recuerda que también puedes seguirnos en twitter como @rtrucios


Te invitamos a compartir nuestros contenidos con tus colegas y así hacer crecer nuestra comunidad



Ambiente externo en las organizaciones - Dominio ambiental y entorno

El entorno de una organización se puede comprender si se analiza su dominio en los sectores externos. El dominio de una organización es el campo de acción ambiental escogido. Es el territorio que una organización toma para ella respecto de productos, servicios y mercados atendidos. El dominio define el nicho de la organización y los factores externos con los cuales interactuará para alcanzar sus metas. Por ejemplo, AT&T la pone en contacto con clientes, competidores, proveedores y reglas y regulaciones gubernamentales.
El entorno comprende varios sectores o subdivisiones del ambiente externo que contienen elementos similares. Se pueden analizar diez sectores para cada organización: industria, materias primas, recursos humanos, recursos financieros, mercados, tecnología, condiciones económicas, gobierno, aspectos socioculturales e internacionales.


Ambiente externo en las organizaciones - Dominio ambiental y entorno

Adaptación a la incertidumbre ambiental
La incertidumbre ambiental representa una importante contingencia para la estructura organizacional y los comportamientos internos. Una organización que se halla en un entorno sin incertidumbre se manejará y controlará de un modo diferente a una organización que se encuentra en un entorno incierto en lo referente a los puestos y departamentos, diferenciación e integración organizacional, procesos de control, imitación institucional, y la planeación y proyección del futuro. Las organizaciones deben tener el ajuste correcto entre la estructura interna y el entorno externo.

Tipos de organización: sistemas mecánicos y orgánicos
Otra respuesta a la incertidumbre del entorno es la cantidad de estructura y controles formales impuestos sobre los empleados. Burns y Stalker sostienen que cuando el ambiente externo es estable, la organización interna se caracteriza por reglas, procedimientos y una clara jerarquía de autoridad. Por otro lado, las organizaciones son formales, centralizadas y la mayor parte de las decisiones se toma en la cima. A este tipo de organización lo llamaron sistema de organización mecánica.
En los entornos que cambian con rapidez, la organización interna es mucho más suelta, de libre flujo y adaptable. Las reglas y  regulaciones frecuentemente no estaban escritas o, si lo estaban, se desconocían.  La gente tiene que encontrar su camino en el sistema para entender lo que tiene que hacer. La jerarquía de autoridad no es clara y la  autoridad de toma de decisiones está descentralizada. Esto lo que se denomina sistema de organización orgánico.

Mecánica
Las tareas se desglosan en partes especializadas y separadas.
Las tareas se definen rígidamente
Hay una estricta jerarquía de autoridad y control;  existen muchas regla.
El conocimiento y el control de las tareas se centralizan en la parte superior de la organización.
La comunicación es vertical.

Orgánica
Los empleados contribuyen a la tarea común del departamento.
Las tareas se ajustan y redefinen por medio del trabajo en equipo.
Hay menos jerarquía de autoridad y control; existen pocas reglas.
El conocimiento y control de las tareas están en cualquier parte de la organización.
La comunicación es horizontal

Control de recursos ambientales
En respuesta a la necesidad de recursos, las organizaciones tratan de mantener un equilibrio entre los vínculos con otras organizaciones y su dependencia. Las organizaciones mantienen este equilibrio mediante esfuerzos para modificar, manipular o controlar otras organizaciones. Para sobrevivir, la organización focal, a menudo, trata de alcanzar y cambiar o controlar elementos del ambiente.

Estrategias organizacionales para controlar el ambiente externo:

Establecimiento de vínculos interorganizacionales
Control del dominio ambiental
1. Propiedad
1. Cambio de dominio
2.Contratos, negocios conjuntos regulación
2. Actividad política
3. Consejos de administración entrelazados
3. Asociaciones industriales
4. Reclutamiento de ejecutivos
4. Actividades legítimas
5. Publicidad, relaciones públicas




Tecnología al nivel de la organización
Las tecnologías al nivel de la organización son de dos tipos: de manufactura y de servicios. Las primeras incluyen procesos tradicionales de manufactura y nuevos sistemas de manufactura basados en computadora.

La tecnología de manufactura
El estudio de Woodward, una socióloga industrial inglesa, fue realizado en las organizaciones donde se recolectó datos prácticos sobre las características de la tecnología, estructura de la organización y  sistemas de administración. Ella encontró claras relaciones entre la tecnología y la estructura en las organizaciones de alto desempeño.  Sus conclusiones son tan claras que los gerentes pueden analizar   sus organizaciones en las mismas dimensiones de tecnología y estructura. Además, la tecnología y la estructura pueden alinearse con la  estrategia organizacional para satisfacer las necesidades cambiantes y brindar nuevas ventajas competitivas.

La tecnología de servicios
Difieren de manera sistemática de las tecnologías de fabricación. Las tecnologías de servicio se caracterizan por resultados intangibles y participación directa del cliente en el proceso de producción. Las empresas de servicio no tienen las tecnologías fijas basadas en máquinas que existen en las organizaciones de manufactura; de aquí que el diseño de la organización también sea diferente con mucha frecuencia.

Tecnología departamental
Las dimensiones de diversidad y análisis forman la base de cuatro categorías principales de las tecnologías departamentales: rutinaria, artesanal, de ingeniería y no rutinaria.

Rutinarias
Se caracterizan por poca diversidad de tareas y el uso de procedimientos objetivos computacionales. Las tareas están formalizadas y estandarizadas. Los ejemplos incluyen una línea de montaje de automóviles y un departamento de cajeros de banco.

Artesanales
Se caracterizan por una corriente de actividades bastante estable, pero el proceso de conversión no es analizable o no es bien comprendido. Las tareas requieren una extensa  capacitación y experiencia, porque los empleados reaccionan a factores intangibles a partir de la sabiduría, intuición y experiencia. Aunque los avances en las tecnologías de máquina parecen haber reducido el número de tecnologías artesanales en las organizaciones, todavía existen unas cuantas, por ejemplo los ingenieros de hornos siderúrgicos continúan mezclando el acero con base en la intuición y experiencia.

De ingeniería
Tiende a ser compleja porque hay una variedad sustancial en las tareas desempeñadas. Sin embargo, las diversas actividades, generalmente, se manejan sobre la base de fórmulas, procedimientos y técnicas establecidas. Los empleados suelen consultar un cuerpo de conocimientos bien desarrollados para el manejo de problemas. Las tareas de ingeniería y de contabilidad, a menudo, corresponden a esta categoría.

No rutinarias
Ofrecen una amplia diversidad de tareas y el proceso de conversión  no  es  analizable  o  no  se  comprende  bien.  En las tecnologías no rutinarias, se dedica mucho esfuerzo al análisis de problema y de actividades. La investigación básica, la planeación estratégica y otro trabajo que incluye nuevos proyectos y problemas inesperados pertenecen a la categoría no rutinaria.
Comprender la variedad y los análisis de una tecnología le indica a uno el estilo de administración, la estructura y el proceso que deben caracterizar a ese departamento. Las tecnologías rutinarias se caracterizan por una estructura mecánica y las tecnologías no rutinarias, por estructuras orgánicas. Aplicar el sistema de administración equivocado a un departamento resultará en insatisfacción y menor eficiencia.


Diseño departamental
Una vez que se identifica la naturaleza de la tecnología de un departamento, puede determinarse la estructura apropiada. De esta manera, la tecnología departamental tiende a relacionarse con un racimo de características departamentales, como el nivel de habilidades de los empleados, la formalización y los patrones de comunicación. Existen patrones definidos en la relación entre la tecnología de la unidad de trabajo y las características estructurales, que se asocian con el desempeño departamental.
Por otro lado, los departamentos difieren entre sí y pueden categorizarse de acuerdo con su tecnología de flujo de trabajo. Los procedimientos estructurales y de administración difieren con base en  la tecnología departamental. Es así que los ejecutivos deben diseñar sus departamentos de manera que puedan cumplir los requerimientos basados en la tecnología. Los problemas de diseño son más visibles cuando es obvio que el diseño no concuerda con la tecnología. Los estudios han concluido que cuando las características de estructura y comunicación no reflejan la tecnología, los departamentos tienden a ser menos efectivos. Esta situación origina que los empleados no pueden comunicarse con la frecuencia necesaria para resolver problemas. Algunas veces tienen que desviarse de reglas mal colocadas para comportarse como es necesario para ajustarse a la tecnología.


Tecnología avanzada de información
Las organizaciones han pasado rápidamente de la época de la computadora a la época de la información, resultado de la revolución de los microprocesadores.
Los aspectos de la tecnología avanzada de información más significativos para la administración son los sistemas de información ejecutiva, el software para trabajo en equipo y la automatización del flujo de trabajo. Un sistema de información ejecutiva usa la tecnología de computación para apoyar las necesidades de información de los altos ejecutivos. Por ejemplo, el director general de Duracell  pudo usar su computadora personal para comparar el desempeño de las fuerzas de trabajo en Estados Unidos y en ultramar. Su computadora  produjo  una  brillante  tabla  en  colores  mostrando las
diferencias en productividad. Al investigar más datos, descubrió que los vendedores en ultramar gastaban demasiado tiempo llamando a tiendas pequeñas, lo que impulsó una decisión para servir estas tiendas pequeñas en forma menos costosas. Los sistemas de información ejecutiva tienen la capacidad de apoyar decisiones no rutinarias, como la estrategia de una compañía y las reacciones ante la competencia.

El software para trabajo en equipo permite interactuar a los empleados que están en una red mediante sus computadoras personales. La forma más simple de esta tecnología es el correo electrónico, que comunica una PC con otra. Otros programas más complicados permiten que numerosos empleados se comuniquen al mismo tiempo. Por ejemplo, un equipo podría sentarse alrededor de  una mesa de conferencia, o incluso permanecer en sus oficinas separadas, mientras cada uno usa su terminal de computadora por cuyo conducto se registran los comentarios de otros miembros. Todos los participantes pueden ver lo mismo en sus pantallas, con lo cual se eliminan barreras de comunicación en las reuniones de grupo, lo que facilita la participación de la información.

La automatización del flujo de trabajo permite que las redes de computadoras envíen automáticamente documentos, como facturas, solicitudes de comprobación o indagaciones de los clientes para su procesamiento a la ubicación correcta. Por ejemplo, un informe de gastos puede llenarse en una computadora que revisa los detalles, alerta al gerente apropiado para la revisión, luego imprime el cheque y notifica al empleado por correo electrónico del lugar donde puede recogerlo. La automatización del flujo de trabajo permite que todo el procedimiento se complete vía computadora, sin que un empleado tenga que manejar un documento en papel.
Algunas organizaciones emplean la nueva tecnología solo para reforzar jerarquías rígidas, centralizar la toma de decisiones y hacer rutinario el trabajo. Sin embargo, en su mayor parte, las organizaciones exitosas la emplean para descentralizar y su impacto se siente en los procesos de la administración, en el diseño de las organizaciones y en la cultura en el sitio de trabajo.

Finalmente, muy a menudo  nos preguntamos cuál sería el impacto de la tecnología avanzada de información en la estructura administrativa, en ese sentido, lo mas rescatable sería:

Estructuras de organización más planas
Mayor centralización o descentralización
Mejor coordinación
Tareas menos limitadas
Mayor proporción de profesionales en el personal



Encuentra más casos de estudio de marketing, administración y empresas exitosas en http://www.facebook.com/EBlogDeRaffo
Recuerda que también puedes seguirnos en twitter como @rtrucios


Te invitamos a compartir nuestros contenidos con tus colegas y así hacer crecer nuestra comunidad

Sistemas de información en la cadena de suministro y sus procesos con proveedores - Administración de sistemas de información

Hoy en día, crear y afianzar relaciones con los proveedores se ha convertido en una tarea muy importante dentro de la gestión de la cadena de suministros, en la que ahora no sólo están involucradas las áreas logísticas de las organizaciones. 

Es así, que el uso y administración de las tecnologías de la información en las empresas, ha ganado una importante participación desempeñando un rol muy destacado automatizando procesos, ahorrando tiempo, mejorando la relación "proveedor-cliente" e intercambiando información en tiempo real dentro de un ambiente colaborativo.

En ese sentido, si es que no lo hemos podido notar, el poder transformar un proceso dentro de nuestra empresa o transformar procesos en varias empresas mediante tecnologías basadas en el uso de herramientas que proporciona el internet, es la definición más cercana al "e business"

Por tanto, como primer paso en nuestra gestión de la cadena de suministros, analizaremos como mejorar nuestros procesos dentro de la planificación de compras considerando como principal protagonista de nuestra gestión de abastecimiento y reaprovisionamiento a nuestro socio estratégico de negocios también conocido como PROVEEDOR.

Bajo la premisa que en nuestra función de compras debemos desarrollar e implementar la estrategia de compras, hacer seguimiento de actividades y medir objetivos les presento a continuación la primera sesión de Sistemas de información en la Cadena de Suministro y sus procesos con proveedores.





Sistemas de información en la cadena de suministro y sus procesos con proveedores from Rafael Trucios Maza


Sistemas de información en la cadena de suministro y sus procesos con proveedores - Administración de sistemas de información (Sesión 1) - Rafael Trucíos Maza


Si buscas casos de estudio, artículos y herramientas para la gestión de empresas y alta dirección la respuesta la tienes en http://rafaeltrucios.blogspot.com/

Síguenos también en Facebook y Twitter

TEORIA DE LA ORGANIZACIÓN Y NIVELES DE ANÁLISIS - Diseño organizacional

La teoría de la organización identifica variables y ofrece modelos para que los gerentes sepan diagnosticar y explicar lo que sucede y así pueden organizarse a fin de alcanzar una eficacia más alta.

Es una forma de ver y analizar las organizaciones con más precisión y profundidad de lo que se podría hacer de otra manera. La forma de ver y pensar sobre las organizaciones se basa en patrones y regularidades en el diseño y comportamiento organizacional.

En un sentido real, la teoría de la organización puede hacer que un gerente sea más competente e influyente. Comprender cómo y por qué actúan las organizaciones permite que los gerentes aprendan a reaccionar. El estudio de las organizaciones permite que la gente vea y comprenda situaciones  que otra gente no puede ver ni comprender. El tema de la cultura organizacional ha sido cada vez más importante en años recientes, en la medida en que las organizaciones cambian hacia estructuras que recalcan el trabajo en equipo y la construcción de consensos. Compañías como Xerox están encontrando eso de emplear científicos sociales  para ayudarlos a entender su cultura a fin de mejorar la productividad y recortar costos.

Niveles de análisis en las organizaciones

Las organizaciones se caracterizan por cuatro niveles de análisis. El ser humano o individuo es el primer nivel, el grupo o departamento segundo nivel, la organización tercer nivel y las organizaciones en su conjunto (entorno) el cuarto nivel.

TEORIA DE LA ORGANIZACIÓN Y NIVELES DE ANÁLISIS


Puntos de vista de la teoría de la organización

1.- Punto de vista de la contingencia racional
Significa una orientación implícita de los gerentes hacia la eficiencia y el mantenimiento del statu quo organizacional. Esta perspectiva supone que los gerentes son racionales a propósito. Quizá los administradores no siempre tengan la respuesta correcta, pero tratan de hacer lo mejor para la organización  desde un punto de vista lógico. La racionalidad significa selección de metas, establecimiento de criterios de eficacia y que los gerentes adoptan estrategias para alcanzar resultados designados en la forma que sea mejor para la organización. Aún más, los administradores tratan de diseñar de manera lógica la estructura y los procesos para que se ajusten a las contingencias del ambiente, tecnología y otros factores en la situación de la organización.

2.- Punto de vista del marxismo radical
Los que adoptan este punto de vista están de acuerdo en que los gerentes son deliberadamente racionales, pero con un giro. Se cree que los administradores toman decisiones para mantenerse en la clase capitalista, reservándose el poder y los recursos. Los administradores toman decisiones no para alcanzar mayor eficiencia y productividad organizacionales, sino para conservar o mejorar su posición. Este punto de vista está impulsado por valores igualitarios y los sueldos de los directores generales. Un segundo aspecto de este punto de vista es la carencia en  cambiar el statu quo. La meta de la teoría organizacional debería ser liberar a los empleados de la alienación, explotación y represión.

3.- Punto de vista de la economía de transacción y costo
El foco de este punto de vista radica en el intercambio de bienes y servicios, más que en el de la producción, y asume un punto de vista económico algo limitado de los hechos de una organización. Sus partidarios están de acuerdo en que no pueden explicar todo el comportamiento en las organizaciones. La mayoría de la gente y de las organizaciones desea conducirse en forma que reduzcan sus costos al mínimo. Sin embargo, muchas de las actividades dentro de las organizaciones se basan en relaciones sociales y  de confianza, más que de supervisión de contratos y de relaciones económicas.

4.- Lo que la teoría de la organización puede hacer
En un sentido muy real, la teoría de la organización puede hacer que  un  gerente sea más competente  e influyente.  Comprender cómo y por qué actúan las organizaciones permite que los gerentes aprendan a reaccionar. El estudio de las organizaciones permite que la gente vea y comprenda situaciones que otra gente no puede ver ni comprender. El tema de la cultura organizacional ha sido cada vez más importante en años recientes, en la medida en que las organizaciones cambian hacia estructuras que recalcan el trabajo en equipo y la construcción de consensos.

Si buscas casos de estudio, artículos y herramientas para la gestión de empresas y alta dirección la respuesta la tienes en http://rafaeltrucios.blogspot.com/

Síguenos también en Facebook y Twitter

Importancia del diseño organizacional de una empresa - Elementos de un sistema empresarial

Los desafíos que enfrentan las organizaciones en el siglo XXI son muy diferentes de los retos de las décadas de los setenta y ochenta, por lo que el concepto de organizaciones y de la teoría de la organización se encuentra en evolución. Además, el mundo cambia más rápido que antes.

Algo de lo que podemos ser testigos en nuestro día a día es que el enfrentamiento del rápido cambio en las organizaciones resultó el problema más común que encaran los administradores en sus empresas.

Los gerentes de hoy pueden desafiar supuestos y prácticas pasadas de moda para crear organizaciones dispuestas al cambio. Algunos desafíos que enfrentan las organizaciones son la competencia global, la necesidad de una renovación organizacional, ubicar su ventaja estratégica, el manejo de relaciones nuevas con los empleados, el apoyo de la diversidad y el mantenimiento de altas normas de ética y responsabilidad social.

Pero, surge una pregunta fundamental en el afán por crear un sólido proceso administrativo de gestión empresarial: ¿Cuál es la importancia de las organizaciones?

Dentro de las principales características, las mas resaltantes son:


  • Reúne los recursos para alcanzar las metas y resultados.
  • Produce bienes y servicios con eficiencia.
  • Facilita la innovación.
  • Utiliza fabricación moderna y tecnología basada en computadora.
  • Se adapta e influye en un ambiente cambiante.
  • Crea valor para los propietarios, clientes y empleados.
  • Acomoda los desafíos constantes de diversidad, ética, patrones de desarrollo profesional y la motivación y coordinación de los empleados.


Las organizaciones como sistemas

¿Qué es un sistema?
Un sistema es un grupo de elementos que se integran con el propósito común de lograr un objetivo. Una organización, como una compañía o un área funcional, se ajusta a esta definición. La organización consiste en los recursos personal, material, máquinas (incluidas instalaciones y energía), dinero e  información (incluidos datos), los cuales colaboran hacia la consecución de objetivos específicos determinados por los dueños o por la gerencia.

Elementos de un sistema
Si los elementos del sistema representan una compañía manufacturera, los recursos de entrada son las materias primas, que se transforman en productos terminados o servicios por el proceso de manufactura. El mecanismo de control es la gerencia de la empresa, los objetivos son las metas que tiene la compañía y el ciclo de retroalimentación es el flujo de información hacia y desde la gerencia.

Sistema de ciclo abierto y ciclo cerrado
No todos los sistemas controlan sus propias operaciones. Un sistema que carece de los elementos de mecanismo de control, ciclo de retroalimentación y objetivos se denomina sistema abierto, por ejemplo un pequeño calefactor de espacios eléctrico que se enchufa y se enciende. El calefactor produce calor hasta que se le apaga. No hay manera de controlar sus salidas.

ENTRADAS - TRANSFORMACIONES - SALIDAS

Un sistema provisto de los tres elementos de control (objetivos, mecanismo de control y ciclo de retroalimentación) es un sistema cerrado.

OBJETIVO
MECANISMO DE CONTROL
ENTRADAS - TRANSFORMACIONES - SALIDAS

Sistemas abiertos y sistemas cerrados
Un sistema que se conecta a su entorno por medio de flujos de recursos se denomina sistema abierto. Un sistema de  calefacción, por ejemplo, obtiene sus entradas de una compañía de servicio y proporciona su calor al edificio o recinto que está calentando.
Por el mismo razonamiento, un sistema que no se conecta a su entorno es un sistema cerrado. Los sistemas cerrados solo existen en situaciones de laboratorio estrictamente controladas y no interesan aquí. Solo interesan los sistemas abiertos, pues son los que mejor describen la compañía y sus operaciones.

La importancia de una visión de sistema
Una visión de sistema considera las operaciones de negocio como sistemas incrustados en un marco ambiental mayor. Esta es una forma abstracta de pensar, pero puede ser valiosa para el gerente. La visión de sistemas permite lo siguiente:
Evita que el gerente se pierda en la complejidad de la estructura de la organización y los detalles del trabajo.
Reconoce la necesidad de tener buenos objetivos.
Destaca la importancia de que todas las partes de la organización colaboren.
Reconoce las interacciones de la organización con su entorno.
Asigna mucho valor a la información de retroalimentación que solo puede obtenerse con un sistema de ciclo cerrado.

Gracias a ello, podemos responder ¿Qué es un diseño organizacional?

El diseño organizacional es un proceso en el cual los gerentes toman decisiones para elegir la estructura organizacional adecuada para la estrategia de la organización y el entorno en el cual los miembros de la organización ponen en práctica dicha estrategia. Por lo tanto, el diseño organizacional hace que los gerentes dirijan la vista en dos sentidos al mismo tiempo: hacia el interior y el exterior de su organización.

Los conocimientos del diseño organizacional giraban entorno al funcionamiento interno de una organización. Poco a poco, la parte del "mundo exterior" de la ecuación del diseño organizacional ha ido captando más y más la atención de los gerentes. Se debe recordar dos aspectos: en primer término, debido a que las estrategias y los entornos cambian con el tiempo, el diseño de las organizaciones es un proceso permanente. En segundo término, los cambios de estructura suelen implicar un proceso de prueba y error.



Encuentra más casos de estudio de marketing, administración y empresas exitosas en http://www.facebook.com/EBlogDeRaffo
Recuerda que también puedes seguirnos en twitter como @rtrucios


Te invitamos a compartir nuestros contenidos con tus colegas y así hacer crecer nuestra comunidad

Un Comienzo con Microservicios: Un Tutorial de Dropwizard

Todos somos testigos de un aumento en la popularidad de las arquitecturas de microservicios. En una arquitectura de microservicios, Dropwizard ocupa un lugar muy importante. Es un marco para la creación de servicios web RESTful o, para ser más específicos, un conjunto de herramientas y frameworks para la creación de servicios web RESTful.
Permite a los desarrolladores un arranque más rápido del proyecto. Esto te ayuda a empaquetar tus aplicaciones, para que se puedan desplegar fácilmente en un entorno de producción como servicios independientes. Si alguna vez has estado en una situación en la que necesitas arrancar un proyecto en el framework Spring, por ejemplo, probablemente sabes lo doloroso que puede ser.
Ilustración: Ejemplo de Microservicios en el Tutorial de Dropwizard
Con Dropwizard, solo se trata de añadir una dependencia de Maven.
En este blog, te guiaré a través del proceso completo de escribir un simple servicio Dropwizard RESTful. Cuando terminemos, tendremos un servicio para operaciones básicas de CRUD en “partes”. Realmente no importa que es “parte”; puede ser cualquier cosa, pero fue lo primero que se me ocurrió.
Almacenaremos la data en una base de datos MySQL, usando JDBI para consultarla y usaremos los siguientes endpoints:
  • GET /parts -to retrieve all parts from DB
  • GET /part/{id} to get a particular part from DB
  • POST /parts -to create new part
  • PUT /parts/{id} -to edit an existing part
  • DELETE /parts/{id} -to delete the part from a DB
Usaremos OAuth para autenticar nuestro servicio y luego agregarle algunas pruebas de unidad

Bibliotecas Dropwizard Predeterminadas

En lugar de incluir todas las bibliotecas necesarias para crear un servicio REST por separado y configurar cada una de ellas, Dropwizard lo hace por nosotros. Aquí está la lista de bibliotecas que vienen predeterminadas con Dropwizard:
  • Jetty: Necesitarás HTTP para ejecutar una aplicación web. Dropwizard incorpora el contenedor servlet Jetty para ejecutar aplicaciones web. En lugar de implementar tus aplicaciones en un servidor de aplicaciones o servidor web, Dropwizard define un método principal que invoca al servidor Jetty como un proceso autónomo. A partir de ahora, Dropwizard recomienda sólo ejecutar la aplicación con Jetty; otros servicios web como Tomcat no son oficialmente compatibles.
  • Jersey: Jersey es una de las mejores implementaciones API de REST en el mercado. Además, sigue la especificación estándar de JAX-RS y es la implementación de referencia para la especificación JAX-RS. Dropwizard utiliza Jersey como el marco predeterminado para la creación de aplicaciones web RESTful.
  • Jackson: Jackson es el estándar de facto para el manejo del formato JSON. Es una de las mejores API de asignación de objetos para el formato JSON.
  • Métricas: Dropwizard tiene su propio módulo de métricas para exponer las métricas de la aplicación a través de los endpoints HTTP.
  • Guava: Además de estructuras de data inmutables y altamente optimizadas, Guava proporciona un número creciente de clases para acelerar el desarrollo en Java.
  • Logback y Slf4j: Estos dos se utilizan para mejorar los mecanismos de registro.
  • Freemarker y Mustache: La elección de motores de plantilla para su aplicación es una de las decisiones clave. El motor de plantilla elegido tiene que ser más flexible para escribir mejores secuencias de comandos. Dropwizard utiliza motores de plantilla Freemarker y Mustache, los cuales son bien conocidos y populares, para la construcción de las interfaces de usuario.
Aparte de la lista anterior, hay muchas otras bibliotecas como Joda Time, Liquibase, Apache HTTP Client y Hibernate Validator utilizadas por Dropwizard para la creación de servicios REST.

Configuración Maven

Dropwizard apoya, de manera oficial, a Maven. Incluso si puedes usar otras herramientas de compilación, la mayoría de las guías y documentación utilizan Maven, así que también lo usaremos aquí. Si no estás familiarizado con Maven, puedes consultar este tutorial Maven.
Este es el primer paso para crear tu aplicación Dropwizard. Agrega la siguiente entrada en el archivo pom.xml de Maven:
<dependencies>
 <dependency>
   <groupId>io.dropwizard</groupId>
   <artifactId>dropwizard-core</artifactId>
   <version>${dropwizard.version}</version>
 </dependency>
</dependencies>
Antes de añadir la entrada anterior, puedes añadir dropwizard.versión como se muestra a continuación:
<properties>
 <dropwizard.version>1.1.0</dropwizard.version>
</properties>
Eso es todo. Ya terminaste de escribir la configuración de Maven. Esto descargará todas las dependencias necesarias para tu proyecto. La versión actual de Dropwizard es 1.1.0, así que la estaremos usando en esta guía.
Ahora podemos pasar a escribir nuestra primera aplicación Dropwizard real.

Definir Clase de Configuración

Dropwizard almacena configuraciones en archivos YAML. Vas a necesitar el archivo configuration.yml en la carpeta raíz de la aplicación. Este archivo se deserializará a una instancia de la clase de configuración de tu aplicación y se validará. El archivo de configuración de tu aplicación es la subclase de la clase de configuración de Dropwizard (io.dropwizard.Configuration).
Vamos a crear una clase configuración simple:
import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import com.fasterxml.jackson.annotation.JsonProperty;

import io.dropwizard.Configuration;
import io.dropwizard.db.DataSourceFactory;

public class DropwizardBlogConfiguration extends Configuration {
 private static final String DATABASE = "database";

 @Valid
 @NotNull
 private DataSourceFactory dataSourceFactory = new DataSourceFactory();

 @JsonProperty(DATABASE)
 public DataSourceFactory getDataSourceFactory() {
   return dataSourceFactory;
 }

 @JsonProperty(DATABASE)
 public void setDataSourceFactory(final DataSourceFactory dataSourceFactory) {
   this.dataSourceFactory = dataSourceFactory;
 }
}
El archivo de configuración YAML se vería así:
database:
 driverClass: com.mysql.cj.jdbc.Driver
 url: jdbc:mysql://localhost/dropwizard_blog
 user: dropwizard_blog
 password: dropwizard_blog 
 maxWaitForConnection: 1s
 validationQuery: "SELECT 1"
 validationQueryTimeout: 3s
 minSize: 8
 maxSize: 32
 checkConnectionWhileIdle: false
 evictionInterval: 10s
 minIdleTime: 1 minute
 checkConnectionOnBorrow: true
La clase anterior se deserializará del archivo YAML y colocará los valores del archivo YAML en este objeto.

Definir una Clase de Aplicación

Ahora debemos ir y crear la clase de aplicación principal. Esta clase reunirá todos los paquetes, llevará la aplicación y la pondrá en funcionamiento para tu uso.
A continuación se muestra un ejemplo de una clase de aplicación en Dropwizard:
import io.dropwizard.Application;
import io.dropwizard.auth.AuthDynamicFeature;
import io.dropwizard.auth.oauth.OAuthCredentialAuthFilter;
import io.dropwizard.setup.Environment;

import javax.sql.DataSource;

import org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature;
import org.skife.jdbi.v2.DBI;

import com.toptal.blog.auth.DropwizardBlogAuthenticator;
import com.toptal.blog.auth.DropwizardBlogAuthorizer;
import com.toptal.blog.auth.User;
import com.toptal.blog.config.DropwizardBlogConfiguration;
import com.toptal.blog.health.DropwizardBlogApplicationHealthCheck;
import com.toptal.blog.resource.PartsResource;
import com.toptal.blog.service.PartsService;

public class DropwizardBlogApplication extends Application<DropwizardBlogConfiguration> {
 private static final String SQL = "sql";
 private static final String DROPWIZARD_BLOG_SERVICE = "Dropwizard blog service";
 private static final String BEARER = "Bearer";

 public static void main(String[] args) throws Exception {
   new DropwizardBlogApplication().run(args);
 }

 @Override
 public void run(DropwizardBlogConfiguration configuration, Environment environment) {
   // Datasource configuration
   final DataSource dataSource =
       configuration.getDataSourceFactory().build(environment.metrics(), SQL);
   DBI dbi = new DBI(dataSource);

   // Register Health Check
   DropwizardBlogApplicationHealthCheck healthCheck =
       new DropwizardBlogApplicationHealthCheck(dbi.onDemand(PartsService.class));
   environment.healthChecks().register(DROPWIZARD_BLOG_SERVICE, healthCheck);

   // Register OAuth authentication
   environment.jersey()
       .register(new AuthDynamicFeature(new OAuthCredentialAuthFilter.Builder<User>()
           .setAuthenticator(new DropwizardBlogAuthenticator())
           .setAuthorizer(new DropwizardBlogAuthorizer()).setPrefix(BEARER).buildAuthFilter()));
   environment.jersey().register(RolesAllowedDynamicFeature.class);

   // Register resources
   environment.jersey().register(new PartsResource(dbi.onDemand(PartsService.class)));
 }
}
Lo que hicimos anteriormente es anular el método de ejecución de Dropwizard. En este método, estamos instanciando una conexión de DB (Base de datos), registrando nuestro chequeo de salud personalizado (hablaremos de eso más adelante), inicializando la autenticación OAuth para nuestro servicio y finalmente, registrando un recurso Dropwizard.
Todo esto se explicará más adelante.

Define una Clase de Representación

Ahora tenemos que empezar a pensar en nuestra REST API y cuál será la representación de nuestro recurso. Tenemos que diseñar el formato JSON y la clase de representación correspondiente que se convierte al formato JSON deseado.
Veamos el formato JSON de muestra para este ejemplo de clase de representación simple:
{
 "code": 200,
 "data": {
   "id": 1,
   "name": "Part 1",
   "code": "PART_1_CODE"
 }
}
Para el formato JSON anterior, crearemos la clase de representación de la siguiente manera:
import org.hibernate.validator.constraints.Length;

import com.fasterxml.jackson.annotation.JsonProperty;

public class Representation<T> {
 private long code;

 @Length(max = 3)
 private T data;

 public Representation() {
   // Jackson deserialization
 }

 public Representation(long code, T data) {
   this.code = code;
   this.data = data;
 }

 @JsonProperty
 public long getCode() {
   return code;
 }

 @JsonProperty
 public T getData() {
   return data;
 }
}
Esto es POJO de una manera muy simple.

Definición de una Clase de Recursos

Un recurso es en lo que se basan los servicios REST. No es nada más que un URI de endpoint para acceder al recurso en el servidor. En este ejemplo, tendremos una clase de recurso con pocas anotaciones para el mapeo de URI de solicitud. Dado que Dropwizard utiliza la implementación JAX-RS, definiremos la ruta URI utilizando la anotación @Path.
Aquí te muestro una clase de recurso para nuestro ejemplo de Dropwizard:
import java.util.List;

import javax.annotation.security.RolesAllowed;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.eclipse.jetty.http.HttpStatus;

import com.codahale.metrics.annotation.Timed;
import com.toptal.blog.model.Part;
import com.toptal.blog.representation.Representation;
import com.toptal.blog.service.PartsService;

@Path("/parts")
@Produces(MediaType.APPLICATION_JSON)
@RolesAllowed("ADMIN")
public class PartsResource {
 private final PartsService partsService;;

 public PartsResource(PartsService partsService) {
   this.partsService = partsService;
 }

 @GET
 @Timed
 public Representation<List<Part>> getParts() {
   return new Representation<List<Part>>(HttpStatus.OK_200, partsService.getParts());
 }

 @GET
 @Timed
 @Path("{id}")
 public Representation<Part> getPart(@PathParam("id") final int id) {
   return new Representation<Part>(HttpStatus.OK_200, partsService.getPart(id));
 }

 @POST
 @Timed
 public Representation<Part> createPart(@NotNull @Valid final Part part) {
   return new Representation<Part>(HttpStatus.OK_200, partsService.createPart(part));
 }

 @PUT
 @Timed
 @Path("{id}")
 public Representation<Part> editPart(@NotNull @Valid final Part part,
     @PathParam("id") final int id) {
   part.setId(id);
   return new Representation<Part>(HttpStatus.OK_200, partsService.editPart(part));
 }

 @DELETE
 @Timed
 @Path("{id}")
 public Representation<String> deletePart(@PathParam("id") final int id) {
   return new Representation<String>(HttpStatus.OK_200, partsService.deletePart(id));
 }
}
Puedes ver como todos los endpoints realmente se definen en esta clase.

Registro de un Recurso

Volvería ahora a la clase de aplicación principal. Puedes ver al final de esa clase que hemos registrado nuestro recurso para ser inicializado con la ejecución del servicio. Tenemos que hacerlo con todos los recursos que podamos tener en nuestra aplicación. Éste es el fragmento de código responsable de eso:
// Register resources
   environment.jersey().register(new PartsResource(dbi.onDemand(PartsService.class)));

Capa de Servicio

Para un manejo de excepciones adecuado y la capacidad de ser independiente del motor de almacenamiento de data, introduciremos una clase de servicio de “capa-media”. Esta es la clase que llamaremos desde nuestra capa de recursos, sin importar lo que está subyacente. Es por eso que tenemos esta capa en particular entre capas de recursos y DAO. Ésta es nuestra clase de servicio:
import java.util.List;
import java.util.Objects;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response.Status;

import org.skife.jdbi.v2.exceptions.UnableToExecuteStatementException;
import org.skife.jdbi.v2.exceptions.UnableToObtainConnectionException;
import org.skife.jdbi.v2.sqlobject.CreateSqlObject;

import com.toptal.blog.dao.PartsDao;
import com.toptal.blog.model.Part;

public abstract class PartsService {
 private static final String PART_NOT_FOUND = "Part id %s not found.";
 private static final String DATABASE_REACH_ERROR =
     "Could not reach the MySQL database. The database may be down or there may be network connectivity issues. Details: ";
 private static final String DATABASE_CONNECTION_ERROR =
     "Could not create a connection to the MySQL database. The database configurations are likely incorrect. Details: ";
 private static final String DATABASE_UNEXPECTED_ERROR =
     "Unexpected error occurred while attempting to reach the database. Details: ";
 private static final String SUCCESS = "Success...";
 private static final String UNEXPECTED_ERROR = "An unexpected error occurred while deleting part.";

 @CreateSqlObject
 abstract PartsDao partsDao();

 public List<Part> getParts() {
   return partsDao().getParts();
 }

 public Part getPart(int id) {
   Part part = partsDao().getPart(id);
   if (Objects.isNull(part)) {
     throw new WebApplicationException(String.format(PART_NOT_FOUND, id), Status.NOT_FOUND);
   }
   return part;
 }

 public Part createPart(Part part) {
   partsDao().createPart(part);
   return partsDao().getPart(partsDao().lastInsertId());
 }

 public Part editPart(Part part) {
   if (Objects.isNull(partsDao().getPart(part.getId()))) {
     throw new WebApplicationException(String.format(PART_NOT_FOUND, part.getId()),
         Status.NOT_FOUND);
   }
   partsDao().editPart(part);
   return partsDao().getPart(part.getId());
 }

 public String deletePart(final int id) {
   int result = partsDao().deletePart(id);
   switch (result) {
     case 1:
       return SUCCESS;
     case 0:
       throw new WebApplicationException(String.format(PART_NOT_FOUND, id), Status.NOT_FOUND);
     default:
       throw new WebApplicationException(UNEXPECTED_ERROR, Status.INTERNAL_SERVER_ERROR);
   }
 }

 public String performHealthCheck() {
   try {
     partsDao().getParts();
   } catch (UnableToObtainConnectionException ex) {
     return checkUnableToObtainConnectionException(ex);
   } catch (UnableToExecuteStatementException ex) {
     return checkUnableToExecuteStatementException(ex);
   } catch (Exception ex) {
     return DATABASE_UNEXPECTED_ERROR + ex.getCause().getLocalizedMessage();
   }
   return null;
 }

 private String checkUnableToObtainConnectionException(UnableToObtainConnectionException ex) {
   if (ex.getCause() instanceof java.sql.SQLNonTransientConnectionException) {
     return DATABASE_REACH_ERROR + ex.getCause().getLocalizedMessage();
   } else if (ex.getCause() instanceof java.sql.SQLException) {
     return DATABASE_CONNECTION_ERROR + ex.getCause().getLocalizedMessage();
   } else {
     return DATABASE_UNEXPECTED_ERROR + ex.getCause().getLocalizedMessage();
   }
 }

 private String checkUnableToExecuteStatementException(UnableToExecuteStatementException ex) {
   if (ex.getCause() instanceof java.sql.SQLSyntaxErrorException) {
     return DATABASE_CONNECTION_ERROR + ex.getCause().getLocalizedMessage();
   } else {
     return DATABASE_UNEXPECTED_ERROR + ex.getCause().getLocalizedMessage();
   }
 }
}
La última parte de ésta es en realidad una implementación de control de salud, de la que hablaremos más adelante.

Capa DAO, JDBI y Mapper

Dropwizard es compatible con JDBI e Hibernate. Es un módulo Maven separado, por lo que primero vamos a agregarlo como una dependencia, así como el conector MySQL
<dependency>
 <groupId>io.dropwizard</groupId>
 <artifactId>dropwizard-jdbi</artifactId>
 <version>${dropwizard.version}</version>
</dependency>
<dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>${mysql.connector.version}</version>
</dependency>
Para un simple servicio CRUD, personalmente prefiero JDBI, ya que es más sencillo y mucho más rápido de implementar. He creado un esquema simple de MySQL con una tabla solamente para ser utilizada en nuestro ejemplo. Puedes encontrar el script init para el esquema dentro del origen. JDBI ofrece escritura simple de preguntas, usando anotaciones tales como @SqlQuery para la lectura y @SqlUpdate para escribir data. Aquí está nuestra interfaz DAO:
import java.util.List;

import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;

import com.toptal.blog.mapper.PartsMapper;
import com.toptal.blog.model.Part;

@RegisterMapper(PartsMapper.class)
public interface PartsDao {

 @SqlQuery("select * from parts;")
 public List<Part> getParts();

 @SqlQuery("select * from parts where id = :id")
 public Part getPart(@Bind("id") final int id);

 @SqlUpdate("insert into parts(name, code) values(:name, :code)")
 void createPart(@BindBean final Part part);

 @SqlUpdate("update parts set name = coalesce(:name, name), code = coalesce(:code, code) where id = :id")
 void editPart(@BindBean final Part part);

 @SqlUpdate("delete from parts where id = :id")
 int deletePart(@Bind("id") final int id);

 @SqlQuery("select last_insert_id();")
 public int lastInsertId();
}
Como puedes ver, es bastante simple. Sin embargo, necesitamos asignar nuestros conjuntos de resultados de SQL a un modelo, lo cual se hace mediante el registro de una clase mapper. Aquí está nuestra clase mapper:
import java.sql.ResultSet;
import java.sql.SQLException;

import org.skife.jdbi.v2.StatementContext;
import org.skife.jdbi.v2.tweak.ResultSetMapper;

import com.toptal.blog.model.Part;

public class PartsMapper implements ResultSetMapper<Part> {
 private static final String ID = "id";
 private static final String NAME = "name";
 private static final String CODE = "code";

 public Part map(int i, ResultSet resultSet, StatementContext statementContext)
     throws SQLException {
   return new Part(resultSet.getInt(ID), resultSet.getString(NAME), resultSet.getString(CODE));
 }
}
Y nuestro modelo:
import org.hibernate.validator.constraints.NotEmpty;

public class Part {
 private int id;
 @NotEmpty
 private String name;
 @NotEmpty
 private String code;

 public int getId() {
   return id;
 }

 public void setId(int id) {
   this.id = id;
 }

 public String getName() {
   return name;
 }

 public void setName(String name) {
   this.name = name;
 }

 public String getCode() {
   return code;
 }

 public void setCode(String code) {
   this.code = code;
 }

 public Part() {
   super();
 }

 public Part(int id, String name, String code) {
   super();
   this.id = id;
   this.name = name;
   this.code = code;
 }
}

Chequeo de Salud de Dropwizard

Dropwizard ofrece soporte nativo para la comprobación de la salud. En nuestro caso, probablemente vamos a comprobar si la base de datos está funcionando antes de decir que nuestro servicio es saludable. Lo que hacemos es realizar alguna acción sencilla de Base de Datos, como obtener partes de la Base de Datos y manejar los resultados potenciales (exitosos o excepciones).
Aquí está nuestra implementación de chequeo de salud en Dropwizard:
import com.codahale.metrics.health.HealthCheck;
import com.toptal.blog.service.PartsService;

public class DropwizardBlogApplicationHealthCheck extends HealthCheck {
 private static final String HEALTHY = "The Dropwizard blog Service is healthy for read and write";
 private static final String UNHEALTHY = "The Dropwizard blog Service is not healthy. ";
 private static final String MESSAGE_PLACEHOLDER = "{}";

 private final PartsService partsService;

 public DropwizardBlogApplicationHealthCheck(PartsService partsService) {
   this.partsService = partsService;
 }

 @Override
 public Result check() throws Exception {
   String mySqlHealthStatus = partsService.performHealthCheck();

   if (mySqlHealthStatus == null) {
     return Result.healthy(HEALTHY);
   } else {
     return Result.unhealthy(UNHEALTHY + MESSAGE_PLACEHOLDER, mySqlHealthStatus);
   }
 }
}

Adición de Autenticación

Dropwizard admite la autenticación básica y OAuth. Aquí, te mostraré cómo proteger tu servicio con OAuth. Sin embargo, debido a la complejidad, he omitido una estructura de Base de Datos subyacente y sólo mostraré cómo se desarrolla. Implementar a escala completa no debería ser un problema a partir de aquí. Dropwizard tiene dos interfaces importantes que necesitamos implementar.
El primero es Authenticator. Nuestra clase debe implementar el método authenticate, que debe comprobar si el identificador de acceso dado es válido. Así que yo llamaría esto como una primera puerta a la aplicación. Si se da con éxito, debería dar como resultado un principal. Este principal es nuestro usuario real con su rol. Éste es importante para otra interfaz de Dropwizard que necesitamos implementar. Éste es el Authorizer y es responsable de comprobar si el usuario tiene suficientes permisos para acceder a un determinado recurso. Por lo tanto, si regresas y revisas nuestra clase de recursos, verás que requiere el rol de administrador para acceder a sus endpoints. Estas anotaciones también pueden ser por método. El soporte de autorización Dropwizard es un módulo Maven separado, por lo que debemos agregarlo a dependencias:
<dependency>
 <groupId>io.dropwizard</groupId>
 <artifactId>dropwizard-auth</artifactId>
 <version>${dropwizard.version}</version>
</dependency>
Aquí están las clases de nuestro ejemplo que realmente no hacen nada inteligente pero es un esqueleto para una autorización de OAuth a gran escala:
import java.util.Optional;

import io.dropwizard.auth.AuthenticationException;
import io.dropwizard.auth.Authenticator;

public class DropwizardBlogAuthenticator implements Authenticator<String, User> {
 @Override
 public Optional<User> authenticate(String token) throws AuthenticationException {
   if ("test_token".equals(token)) {
     return Optional.of(new User());
   }
   return Optional.empty();
 }
}
import java.util.Objects;

import io.dropwizard.auth.Authorizer;

public class DropwizardBlogAuthorizer implements Authorizer<User> {
 @Override
 public boolean authorize(User principal, String role) {
   // Allow any logged in user.
   if (Objects.nonNull(principal)) {
     return true;
   }
   return false;
 }
}
import java.security.Principal;

public class User implements Principal {
 private int id;
 private String username;
 private String password;

 public int getId() {
   return id;
 }

 public void setId(int id) {
   this.id = id;
 }

 public String getUsername() {
   return username;
 }

 public void setUsername(String username) {
   this.username = username;
 }

 public String getPassword() {
   return password;
 }

 public void setPassword(String password) {
   this.password = password;
 }

 @Override
 public String getName() {
   return username;
 }
}
Pruebas de Unidad en DropWizard
Vamos a agregar algunas pruebas de unidad a nuestra aplicación. Me atengo a probar partes específicas del código de Dropwizard, en nuestro caso: Representación y Recurso. Necesitaremos agregar las siguientes dependencias a nuestro archivo Maven:
<dependency>
 <groupId>io.dropwizard</groupId>
 <artifactId>dropwizard-testing</artifactId>
 <version>${dropwizard.version}</version>
</dependency>
<dependency>
 <groupId>org.mockito</groupId>
 <artifactId>mockito-core</artifactId>
 <version>${mockito.version}</version>
 <scope>test</scope>
</dependency>
Para probar la representación, también necesitaremos un archivo JSON de ejemplo para probar contra éste. Así que vamos a crear fixtures/part.json bajo src/test/resources:
{
 "id": 1,
 "name": "testPartName",
 "code": "testPartCode"
}
Y aquí está la clase de prueba JUnit:
import static io.dropwizard.testing.FixtureHelpers.fixture;
import static org.assertj.core.api.Assertions.assertThat;

import org.junit.Test;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.toptal.blog.model.Part;

import io.dropwizard.jackson.Jackson;

public class RepresentationTest {
 private static final ObjectMapper MAPPER = Jackson.newObjectMapper();
 private static final String PART_JSON = "fixtures/part.json";
 private static final String TEST_PART_NAME = "testPartName";
 private static final String TEST_PART_CODE = "testPartCode";

 @Test
 public void serializesToJSON() throws Exception {
   final Part part = new Part(1, TEST_PART_NAME, TEST_PART_CODE);

   final String expected =
       MAPPER.writeValueAsString(MAPPER.readValue(fixture(PART_JSON), Part.class));

   assertThat(MAPPER.writeValueAsString(part)).isEqualTo(expected);
 }

 @Test
 public void deserializesFromJSON() throws Exception {
   final Part part = new Part(1, TEST_PART_NAME, TEST_PART_CODE);

   assertThat(MAPPER.readValue(fixture(PART_JSON), Part.class).getId()).isEqualTo(part.getId());
   assertThat(MAPPER.readValue(fixture(PART_JSON), Part.class).getName())
       .isEqualTo(part.getName());
   assertThat(MAPPER.readValue(fixture(PART_JSON), Part.class).getCode())
       .isEqualTo(part.getCode());
 }
}
Cuando se trata de probar los recursos, el punto principal de la prueba de Dropwizard es que realmente se está comportando como un cliente HTTP, enviando solicitudes HTTP contra los recursos. Por lo tanto, no estás probando métodos como lo harías normalmente en un caso común. Aquí está el ejemplo de nuestra clase PartsResource:
public class PartsResourceTest {
 private static final String SUCCESS = "Success...";
 private static final String TEST_PART_NAME = "testPartName";
 private static final String TEST_PART_CODE = "testPartCode";
 private static final String PARTS_ENDPOINT = "/parts";

 private static final PartsService partsService = mock(PartsService.class);

 @ClassRule
 public static final ResourceTestRule resources =
     ResourceTestRule.builder().addResource(new PartsResource(partsService)).build();

 private final Part part = new Part(1, TEST_PART_NAME, TEST_PART_CODE);

 @Before
 public void setup() {
   when(partsService.getPart(eq(1))).thenReturn(part);
   List<Part> parts = new ArrayList<>();
   parts.add(part);
   when(partsService.getParts()).thenReturn(parts);
   when(partsService.createPart(any(Part.class))).thenReturn(part);
   when(partsService.editPart(any(Part.class))).thenReturn(part);
   when(partsService.deletePart(eq(1))).thenReturn(SUCCESS);
 }

 @After
 public void tearDown() {
   reset(partsService);
 }

 @Test
 public void testGetPart() {
   Part partResponse = resources.target(PARTS_ENDPOINT + "/1").request()
       .get(TestPartRepresentation.class).getData();
   assertThat(partResponse.getId()).isEqualTo(part.getId());
   assertThat(partResponse.getName()).isEqualTo(part.getName());
   assertThat(partResponse.getCode()).isEqualTo(part.getCode());
   verify(partsService).getPart(1);
 }

 @Test
 public void testGetParts() {
   List<Part> parts =
       resources.target(PARTS_ENDPOINT).request().get(TestPartsRepresentation.class).getData();
   assertThat(parts.size()).isEqualTo(1);
   assertThat(parts.get(0).getId()).isEqualTo(part.getId());
   assertThat(parts.get(0).getName()).isEqualTo(part.getName());
   assertThat(parts.get(0).getCode()).isEqualTo(part.getCode());
   verify(partsService).getParts();
 }

 @Test
 public void testCreatePart() {
   Part newPart = resources.target(PARTS_ENDPOINT).request()
       .post(Entity.entity(part, MediaType.APPLICATION_JSON_TYPE), TestPartRepresentation.class)
       .getData();
   assertNotNull(newPart);
   assertThat(newPart.getId()).isEqualTo(part.getId());
   assertThat(newPart.getName()).isEqualTo(part.getName());
   assertThat(newPart.getCode()).isEqualTo(part.getCode());
   verify(partsService).createPart(any(Part.class));
 }

 @Test
 public void testEditPart() {
   Part editedPart = resources.target(PARTS_ENDPOINT + "/1").request()
       .put(Entity.entity(part, MediaType.APPLICATION_JSON_TYPE), TestPartRepresentation.class)
       .getData();
   assertNotNull(editedPart);
   assertThat(editedPart.getId()).isEqualTo(part.getId());
   assertThat(editedPart.getName()).isEqualTo(part.getName());
   assertThat(editedPart.getCode()).isEqualTo(part.getCode());
   verify(partsService).editPart(any(Part.class));
 }

 @Test
 public void testDeletePart() {
   assertThat(resources.target(PARTS_ENDPOINT + "/1").request()
       .delete(TestDeleteRepresentation.class).getData()).isEqualTo(SUCCESS);
   verify(partsService).deletePart(1);
 }

 private static class TestPartRepresentation extends Representation<Part> {

 }

 private static class TestPartsRepresentation extends Representation<List<Part>> {

 }

 private static class TestDeleteRepresentation extends Representation<String> {

 }
}

Construye tu Aplicación Dropwizard

La mejor práctica es crear el archivo único FAR JAR que contenga todos los archivos .class necesarios para ejecutar la aplicación. El mismo archivo JAR puede implementarse en un entorno diferente desde la prueba a la producción, sin ningún cambio en las bibliotecas de dependencias. Para comenzar a construir nuestra aplicación de ejemplo como un fat JAR, necesitamos configurar un complemento de Maven llamado maven-shade. Debes agregar las siguientes entradas en la sección de complementos de tu archivo pom.xml.
Aquí está la configuración Maven de ejemplo para construir el archivo JAR.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.endava</groupId>
 <artifactId>dropwizard-blog</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <name>Dropwizard Blog example</name>

 <properties>
   <dropwizard.version>1.1.0</dropwizard.version>
   <mockito.version>2.7.12</mockito.version>
   <mysql.connector.version>6.0.6</mysql.connector.version>
   <maven.compiler.source>1.8</maven.compiler.source>
   <maven.compiler.target>1.8</maven.compiler.target>
 </properties>

 <dependencies>
   <dependency>
     <groupId>io.dropwizard</groupId>
     <artifactId>dropwizard-core</artifactId>
     <version>${dropwizard.version}</version>
   </dependency>
   <dependency>
     <groupId>io.dropwizard</groupId>
     <artifactId>dropwizard-jdbi</artifactId>
     <version>${dropwizard.version}</version>
   </dependency>
   <dependency>
     <groupId>io.dropwizard</groupId>
     <artifactId>dropwizard-auth</artifactId>
     <version>${dropwizard.version}</version>
   </dependency>
   <dependency>
     <groupId>io.dropwizard</groupId>
     <artifactId>dropwizard-testing</artifactId>
     <version>${dropwizard.version}</version>
   </dependency>
   <dependency>
     <groupId>org.mockito</groupId>
     <artifactId>mockito-core</artifactId>
     <version>${mockito.version}</version>
     <scope>test</scope>
   </dependency>
   <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>${mysql.connector.version}</version>
   </dependency>
 </dependencies>

 <build>
   <plugins>
     <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-shade-plugin</artifactId>
       <version>2.3</version>
       <configuration>
         <createDependencyReducedPom>true</createDependencyReducedPom>
         <filters>
           <filter>
             <artifact>*:*</artifact>
             <excludes>
               <exclude>META-INF/*.SF</exclude>
               <exclude>META-INF/*.DSA</exclude>
               <exclude>META-INF/*.RSA</exclude>
             </excludes>
           </filter>
         </filters>
       </configuration>
       <executions>
         <execution>
           <phase>package</phase>
           <goals>
             <goal>shade</goal>
           </goals>
           <configuration>
             <transformers>
               <transformer
                 implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
               <transformer
                 implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                 <mainClass>com.endava.blog.DropwizardBlogApplication</mainClass>
               </transformer>
             </transformers>
           </configuration>
         </execution>
       </executions>
     </plugin>
   </plugins>
 </build>
</project>

Ejecución de la Aplicación

Ahora deberíamos poder ejecutar el servicio. Si construiste correctamente tu archivo JAR, lo que necesitas hacer es abrir el símbolo del sistema y ejecutar el siguiente comando para ejecutar tu archivo JAR:
java -jar target/dropwizard-blog-1.0.0.jar server configuration.yml
Si todo salió bien, deberías ver algo como esto:
INFO  [2017-04-23 22:51:14,471] org.eclipse.jetty.util.log: Logging initialized @962ms to org.eclipse.jetty.util.log.Slf4jLog
INFO  [2017-04-23 22:51:14,537] io.dropwizard.server.DefaultServerFactory: Registering jersey handler with root path prefix: /
INFO  [2017-04-23 22:51:14,538] io.dropwizard.server.DefaultServerFactory: Registering admin handler with root path prefix: /
INFO  [2017-04-23 22:51:14,681] io.dropwizard.server.DefaultServerFactory: Registering jersey handler with root path prefix: /
INFO  [2017-04-23 22:51:14,681] io.dropwizard.server.DefaultServerFactory: Registering admin handler with root path prefix: /
INFO  [2017-04-23 22:51:14,682] io.dropwizard.server.ServerFactory: Starting DropwizardBlogApplication
INFO  [2017-04-23 22:51:14,752] org.eclipse.jetty.setuid.SetUIDListener: Opened application@7d57dbb5{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
INFO  [2017-04-23 22:51:14,752] org.eclipse.jetty.setuid.SetUIDListener: Opened admin@630b6190{HTTP/1.1,[http/1.1]}{0.0.0.0:8081}
INFO  [2017-04-23 22:51:14,753] org.eclipse.jetty.server.Server: jetty-9.4.2.v20170220
INFO  [2017-04-23 22:51:15,153] io.dropwizard.jersey.DropwizardResourceConfig: The following paths were found for the configured resources:

   GET     /parts (com.toptal.blog.resource.PartsResource)
   POST    /parts (com.toptal.blog.resource.PartsResource)
   DELETE  /parts/{id} (com.toptal.blog.resource.PartsResource)
   GET     /parts/{id} (com.toptal.blog.resource.PartsResource)
   PUT     /parts/{id} (com.toptal.blog.resource.PartsResource)

INFO  [2017-04-23 22:51:15,154] org.eclipse.jetty.server.handler.ContextHandler: Started i.d.j.MutableServletContextHandler@58fa5769{/,null,AVAILABLE}
INFO  [2017-04-23 22:51:15,158] io.dropwizard.setup.AdminEnvironment: tasks = 

   POST    /tasks/log-level (io.dropwizard.servlets.tasks.LogConfigurationTask)
   POST    /tasks/gc (io.dropwizard.servlets.tasks.GarbageCollectionTask)

INFO  [2017-04-23 22:51:15,162] org.eclipse.jetty.server.handler.ContextHandler: Started i.d.j.MutableServletContextHandler@3fdcde7a{/,null,AVAILABLE}
INFO  [2017-04-23 22:51:15,176] org.eclipse.jetty.server.AbstractConnector: Started application@7d57dbb5{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
INFO  [2017-04-23 22:51:15,177] org.eclipse.jetty.server.AbstractConnector: Started admin@630b6190{HTTP/1.1,[http/1.1]}{0.0.0.0:8081}
INFO  [2017-04-23 22:51:15,177] org.eclipse.jetty.server.Server: Started @1670ms
Ahora tienes tu propia aplicación Dropwizard escuchando en puertos 8080 para solicitudes de aplicación y 8081 para solicitudes de administración.
Ten en cuenta que server configuration.yml se utiliza para iniciar el servidor HTTP y pasar la ubicación del archivo de configuración YAML al servidor.
¡Excelente! Finalmente hemos implementado un microservicio usando el framework Dropwizard. Ahora vamos a tomar un descanso y tomar una taza de té. Hiciste un buen trabajo.

Acceso a los Recursos

Puedes utilizar cualquier cliente HTTP como POSTMAN o cualquier otro. Deberías poder acceder a tu servidor presionando http://localhost:8080/parts. Debes recibir un mensaje indicando que las credenciales son necesarias para acceder al servicio. Para autenticar, agrega el encabezado Authorization con el valor support_test_token. Si se realiza correctamente, deberías ver algo como:
{
 "code": 200,
 "data": []
}
Lo que significa que tu base de datos está vacía. Crea tu primera parte cambiando el método HTTP de GET a POST y suministra esta carga útil:
{
 "name":"My first part",
 "code":"code_of_my_first_part"
}
Todos los demás endpoints funcionan de la misma manera, así que sigue jugando y disfruta.

Cómo Cambiar la Ruta del Contexto

La aplicación Dropwizard, de forma predeterminada, se iniciará y se ejecutará en /. Por ejemplo, si no menciona nada sobre la ruta de contexto de la aplicación de forma predeterminada, se puede acceder a la aplicación desde la URL http://localhost: 8080/. Si deseas configurar tu propia ruta de contexto para tu aplicación, añade las siguientes entradas a tu archivo YAML. ~~~ server: applicationContextPath: /application ~~~

Finiquitando Nuestro Tutorial Dropwizard

Ahora, cuando tengas instalado el servicio REST de Dropwizard, es momento de resumir algunas de las ventajas o desventajas clave de utilizar Dropwizard como framework REST. Es absolutamente obvio, por este post, que Dropwizard ofrece un bootstrap extremadamente rápido de tu proyecto. Y eso es probablemente la mayor ventaja de usar Dropwizard.
Además incluirá todas las bibliotecas/herramientas de vanguardia que necesitarás para desarrollar tu servicio. Así que definitivamente no necesitas preocuparte por eso. También te da una gestión de configuración muy agradable. Por supuesto, Dropwizard tiene algunas desventajas también. Usando Dropwizard estás restringido a usar lo que Dropwizard ofrece o apoya. Pierdes parte de la libertad a la que puedes estar acostumbrado cuando desarrollas. Pero aun así ni siquiera lo llamaría una desventaja ya que esto es exactamente lo que hace que Dropwizard sea lo que es—fácil de configurar, fácil de desarrollar, pero aún un marco REST muy robusto y de alto rendimiento.

BY DUSAN SIMONOVIC - FREELANCE SOFTWARE ENGINEER @ TOPTAL(TRANSLATED BY MARISELA ORDAZ)

Fuente:

Lo más leido esta semana

Nos leen

Blogger news

Mi Ping en TotalPing.com