tag:blogger.com,1999:blog-10121611324049058002024-02-20T12:02:54.843-08:00HAL 9KEste blog expresa mis vivencias y experiencias en el ámbito de mi cotidianidad como objetivista, libre pensador, tecnócrata, ingeniero y ser humano amante de la lectura, el baloncesto, deportes a motor y la buena cocina.
La premisa es simple: Ud afirma, Ud demuestra. Toda idea será debatida y sometida a juicio. Sólo respetamos personas, sus ideas serán cuestionadas. pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.comBlogger48125tag:blogger.com,1999:blog-1012161132404905800.post-15582210451844387422021-11-16T19:43:00.007-08:002021-11-16T19:45:36.032-08:00Problemas de sonido con Opensuse Tumbleweed<p>Hoy venimos rápido con una pequeña entrada que espero les sea de utilidad.</p><p>Un problema muy común cuando usamos la maravillosa distribución Rolling-Release de Opensuse, <a href="https://get.opensuse.org/tumbleweed/" target="_blank">Tumbleweed</a>, es el de perder la configuración de sonido después de instalar o realizar alguna actualización con el comando:</p><p><span style="font-family: monospace;"><span style="background-color: white; color: #18b218; font-decoration: underline;">sudo</span><span style="background-color: white;"> </span><span style="background-color: white; color: #18b218;">zypper</span><span style="background-color: white;"> dup</span><br /></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjrnqiYh-lZdRjHpOy8L9RDp8VOARFiXVtfxllwIktJhewYpysaWG_3qgsHaqwlxUaxMRciLeEDjm0mb6QxBjs71e6oZtSKVnYbpYpJAQVdnuaSnyC4dZMa-JTiiQYsEVjrUqLsrAHqd0/s1200/tumbleweed.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="801" data-original-width="1200" height="214" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjrnqiYh-lZdRjHpOy8L9RDp8VOARFiXVtfxllwIktJhewYpysaWG_3qgsHaqwlxUaxMRciLeEDjm0mb6QxBjs71e6oZtSKVnYbpYpJAQVdnuaSnyC4dZMa-JTiiQYsEVjrUqLsrAHqd0/s320/tumbleweed.png" width="320" /></a></div><p><br /></p><span><a name='more'></a></span><p> La primera opción que nos viene a la mente es intentar seguir <a href="https://en.opensuse.org/SDB:Audio_troubleshooting" target="_blank">la guía de solución de problemas de sonido con OpenSuse</a>.</p><p>No se Uds. pero en mi caso esa publicación suele ser frustrante y pocas veces me ha dado resultado.</p><p>En caso de que Ud. sea uno de los desafortunados, voy a dejar una serie de pequeños pasos que me funcionaron cuando ya estaba bastante desesperado por encontrar una solución.</p><h2 style="text-align: left;">Contexto</h2><p>El fallo que menciono suele suceder al actualizar kernels de reciente data, 5.13.x o superior.</p><p><span style="font-family: monospace;"><span style="background-color: white; color: #54ff54; font-weight: bold;">OS:</span><span style="background-color: white;"> openSUSE 20211111
</span><br /><span style="background-color: white; color: #54ff54; font-weight: bold;">Kernel:</span><span style="background-color: white;"> x86_64 Linux 5.14.14-2-default
</span><br /><span style="background-color: white; color: #54ff54; font-weight: bold;">Shell:</span><span style="background-color: white;"> zsh 5.8
</span><br /><span style="background-color: white; color: #54ff54; font-weight: bold;">DE:</span><span style="background-color: white;"> KDE 5.87.0 / Plasma 5.23.2
</span><br /><span style="background-color: white; color: #54ff54; font-weight: bold;">WM:</span><span style="background-color: white;"> KWin
</span><br /><span style="background-color: white; color: #54ff54; font-weight: bold;">Disk:</span><span style="background-color: white;"> 19G / 1,2T (2%)
</span><br /><span style="background-color: white; color: #54ff54; font-weight: bold;">CPU:</span><span style="background-color: white;"> 11th Gen Intel Core i7-11800H @ 16x 4.6GHz [55.0°C]
</span><br /><span style="background-color: white; color: #54ff54; font-weight: bold;">RAM:</span><span style="background-color: white;"> 3146MiB / 64002MiB</span><br />
<br /></span></p><p>Se puede hacer funcionar con éxito, digamos, unos audífonos Bluetooth pero los altoparlantes de tu laptop no funcionan para nada.</p><p>Ya ha intentado varios pasos, sino todos de la guía mencionada con anterioridad.</p><h2 style="text-align: left;">Alternativa</h2><p> Con la esperanza de arreglar este fallo, se propone hacer lo siguiente:</p><p></p><ul style="text-align: left;"><li>-Editar el archivo grub<br />Esto se puede hacer con el comando<br /><span style="background-color: white; color: #18b218; font-decoration: underline;">sudo</span><span style="background-color: white;"> </span><span style="background-color: white; color: #18b218;">nano</span><span style="background-color: white;"> </span><span style="background-color: white;">/etc/default/grub</span><br /></li><li><span style="background-color: white;">-Buscar la entrada que del atributo </span><span style="background-color: white;">GRUB_CMDLINE_LINUX_DEFAULT<br /></span>En mi caso tiene el valor...<br />GRUB_CMDLINE_LINUX_DEFAULT="quiet splash apparmor=0"</li><li>-Agregar en esa entrada el siguiente valor "<span style="font-family: monospace;"><span style="background-color: white;">snd_hda_intel.dmic_detect=0</span></span>"<br />Resultado...<br /><span style="background-color: white;">GRUB_CMDLINE_LINUX_DEFAULT="quiet splash apparmor=0 snd_hda_intel.dmic_detect=0"</span><br /></li><li><span style="background-color: white;">-Guardar el archivo, (ctrl-o), y salir (ctrl-x)</span></li><li><span style="background-color: white;">-Ejecutar el comando de configuración de grub<br /><span style="color: #18b218;">sudo</span> <span style="color: #ff5454; font-weight: bold;">grub2-mkconfig</span> -o /boot/grub2/grub.cfg<br /></span></li><li><span style="background-color: white;">-Hacer reboot</span></li></ul><div>Listo, al hacer login ya el sonido en los altoparlantes debe funcionar.</div><div>Espero tengan suerte solucionando sus problemas con Linux.</div><div><br /></div><div>Dejo enlace al post del que obtuve esta <a href="https://askubuntu.com/questions/1243369/sound-card-not-detected-ubuntu-20-04-sof-audio-pci" target="_blank">alternativa</a>.<br /><br /></div><p></p> <p></p>pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-1113040521357089752019-09-13T20:17:00.001-07:002019-09-13T20:17:28.607-07:00Architectural decisions on a recent project<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="reader-article-content" dir="ltr">
We can recall that the only real boss of the architect is <strong><em>requirements</em>.</strong> The architect may not listen to us, to developers, to customers, to anyone. But the requirements are the indisputable boss.<br />
So, there is not mystery neither magic over the decision making process, it must be ruled by the requirements.<br />
<br />
But, what was this project about? In fact, it was about consuming a <em>SOAP</em>
service provided by a third part, to allow our internal business side
to update the customer case-file or unique digital profile. As part of
this project, the number of request from our platform to the provider
side must be under certain control or below a number we can consider
acceptable for our consuming rate.<br />
Also, for both services, our own service and the one from the
provider, working with bio-metric data is a must, it involves
fingerprints and face recognition.<br />
So let’s start looking deeper into this project.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmWMCjZelldQlfIGmtACPxYKlIGcWOnwXgngjUPH_fVStLbBakY-QwPp72E838pr7TJXBcLNsnfOQp0AtEGSTdFFS0vfPUUuutNgeEtWsdExnoZrXiQwS-7HVi9FeHjX8p5Mi05LEcfRE/s1600/arch_dec.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="145" data-original-width="349" height="264" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmWMCjZelldQlfIGmtACPxYKlIGcWOnwXgngjUPH_fVStLbBakY-QwPp72E838pr7TJXBcLNsnfOQp0AtEGSTdFFS0vfPUUuutNgeEtWsdExnoZrXiQwS-7HVi9FeHjX8p5Mi05LEcfRE/s640/arch_dec.jpeg" width="640" /></a></div>
<br />
<br />
<a name='more'></a><br /><br />
<h4 style="text-align: left;">
<i>Q- Which kind of architectural approach are we going to use?</i></h4>
We can use a <em>Multi Layer</em> approach, a <em>Monolithic</em> one, <em>Micro-services</em>, etc.<br />
I realized that, because our expected demand on the service; it
means the load and the behavior; there will be a need for a kind of
horizontal scaling feature for this solution. The only actual thing <em>micro-services</em>
are good for is providing amazing horizontal scaling behavior, then
using a micro-service architecture sound pretty logical in this case.<br />
<br />
A- We are going to use a <em>micro-service</em> architecture.<br />
(This is eaten bread!!)<br />
<br />
<h4 style="text-align: left;">
Q- Where will do deploy our solution?</h4>
Are we going to use our own servers? Is there a chance for cloud computing?<br />
Browsing into the documents I found a request for preferring our <em>MS Azure</em> and <em>Pivotal Cloud Foundry</em>
platform over other deployment strategies for new solutions. It was
related to lower costs and shorter time to production parameters.<br />
<br />
A- <em>MS Azure</em> and <em>Pivotal Cloud Foundry</em> are selected as the deployment platform.<br />
(I got paid for doing this, it feels like stolen from the company!!)<br />
<br />
<h4 style="text-align: left;">
Q- Which environments are we going to use?</h4>
It sounds like an easy one because for all our cloud solutions we
have and accelerator assistant that provides us with a complete <em>Git</em> and source control platform, a documentation tool, a <em>JIRA</em> project, and the associated environments for <em>Devops</em> processes and pipelines. Those environments include the <em>Development</em> server, the <em>UAT</em> server and others.<br />
<br />
A- We are going to use our accelerator pipelines and platform.<br />
(Such easy)<br />
<br />
<h4 style="text-align: left;">
Q- How are we going to secure our solution?</h4>
The provider told us that it would be a service with a double
certificate based security from their side. Also, there was a
requirement for connecting different devices to our services, those
devices may include smart phones, tablets, ATMs, and the regular
applications from our platform.<br />
Our cloud platform already support <em>OAUTH</em> 2.0 authorization flows, including <em>JWT</em>
tokens and certificate secure access for our solutions. It makes easy
to relay on our platform to accomplish the security standards for our
solution approach.<br />
<br />
A- We will relay on our established <em>OAUTH</em> 2.0 flows for securing <em>REST</em> services over a <em>HTTPS</em> channel.<br />
<br />
<h4 style="text-align: left;">
Q- What kind of persistence strategy will be used for this project?</h4>
Once again, reading the requirements, there is a feature for
keeping the requested customer’s data for a previously defined period of
time, according to business needs. It implicates that as soon as our
services will be running into the cloud with a <em>micro-service</em>
architecture, our persistence mechanics have to be on the cloud, with
auto replication, balancing, and scaling features supported in such easy
way.<br />
Being <em>Pivotal Cloud Foundry</em> <em>(PCF)</em> our main platform for micro-services running over the <em>MS Azure</em> services, is natural to look at some <em>SQL Server DB services</em> that accomplish our goals. In fact, this kind of service are provided by default over this platform.<br />
So, <em>SQL Server DB service</em> will be our main choice for persisting the solution’s data.<br />
<br />
A- <em>SQL Server DB </em>service over PCF will be used for this solution.<br />
<br />
<h4 style="text-align: left;">
Q- What about the service orchestration?</h4>
It is a very interesting side for this project. There will be some
kind of long time transactions associated with keeping the customer’s
data into the “cache” and later request for updating this data
automatically.<br />
Some colleges said that running a batch file could be a choice for
accomplish this task. I didn’t agree. Those kind a files aren’t good
enough in a cloud platform. Also, we will need more control over the
decisions we have to take over the flow and the execution of the steps
of these processes.<br />
<br />
After thinking a while on this requirement, I realized that a very
light workflow engine embedded into the micro-service will perform those
task in a very fancy and powerful way.<br />
The previous description looks like an accurate case for the <em>Camunda BPM</em> engine.<br />
<br />
A- The <em>Camunda BPM</em> engine will be used for the services orchestration.<br />
<br />
<br />
In resume, we are going to implement a couple of <em>REST</em> services using <em>Spring-Boot</em> framework, <em>OAUTH</em> 2.0 facilities over an <em>HTTPS</em> secure point, <em>Java</em> will be our programming language, <em>certificates</em> are going to be used for communicating with the provider’s service. <em>Pivotal Cloud Foundry</em> and <em>MS Azure</em>
will be our main platform for cloud deployment, our accelerator
internal flow and app will be use for providing the pipeline and servers
for the solution, <em>Camunda BPM</em> will be used for services orchestration, <em>SQL server DB service</em> over azure will provide me Persistence layer. <em>Micro-services</em> architecture will be the model for constructing this solution.</div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-44878033208632111402019-08-19T19:22:00.002-07:002019-08-20T15:46:51.682-07:00¿Otro microservicio? NO, gracias<div dir="ltr" style="text-align: left;" trbidi="on">
Suele pasar en este mundo de la tecnología que, cada cierto tiempo, tenemos a todo el mundo hablando y usando determinada solución, producto o herramienta, sin ninguna otra razón de peso mas que la moda, o que el "main stream" de turno dice que es la forma correcta de hacer las cosas.<br />
<br />
Entre esas tecnologías o soluciones de moda nos encontramos con los ya harto renombrados, <i>microservicios</i>. Todo el mundo habla de ellos, todo el mundo migra hacia ellos, ... pero, y siempre hay un pero, ¿son en verdad tan beneficiosos los <i>microservicios</i>? ¿Cuanto hay de mito y cuanto de, ¿fea?, realidad?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLd1XqZ1oNPOEczTdQJfmyIxaW9iKl8tIupz7u4A6XHpNgdlst0iGdt7kTKsa59A2nPwFQmdYer-FuzNxIZI5bFtueAESWiR56wi8qE8tQJZRayw2QuEcydZy1Q233XMfYYQWXcCjkJDg/s1600/microservices_yump.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="501" data-original-width="1000" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLd1XqZ1oNPOEczTdQJfmyIxaW9iKl8tIupz7u4A6XHpNgdlst0iGdt7kTKsa59A2nPwFQmdYer-FuzNxIZI5bFtueAESWiR56wi8qE8tQJZRayw2QuEcydZy1Q233XMfYYQWXcCjkJDg/s400/microservices_yump.png" width="400" /></a></div>
<br />
<a name='more'></a><br />
<br />
Como ya es costumbre por estas lides, siempre empezamos con los conceptos, así que manos a las sobras!!!<br />
<br />
<h3 style="text-align: left;">
¿Qué son los <i>microservicios</i>? </h3>
Los <i>microservicios</i> son un patrón de componentes, en el que cada componente se construye, despliega y ejecuta como un servicio independiente, atómico en su funcionalidad; lógica y modelo de datos.<br />
Noten que dije que son un patrón de diseño, de construcción, de despliegue y de ejecución... pero No usé, ni pienso usar, el término "<i>Arquitectura</i>" para referirme a los <i>microservicios</i>, puesto que tal arquitectura simplemente NO EXISTE.<br />
<br />
<blockquote class="tr_bq">
Los <i>microservicios</i> son útiles únicamente cuando se necesita escalamiento horizontal masivo e independiente. Sí sus necesidades de escalamiento son ínfimas, entonces Ud. no necesita <i>microservicios</i>. Así de simple.</blockquote>
<h3 style="text-align: left;">
Beneficios <strike>mitos</strike> que ofrece este patrón</h3>
Vamos a revisar ahora los supuestos beneficios que normalmente se le atribuyen a este modelo de componentes.<br />
<h4 style="text-align: left;">
Código más <strike>complejo</strike> limpio</h4>
<blockquote class="tr_bq">
No se necesita introducir una capa extra de red en nuestra plataforma para tener código mas limpio y elegante.</blockquote>
La cruda verdad es que la limpieza, la elegancia y la calidad del código no tienen nada que ver con el modelo de solución o patrón de componentes que se esté usando. Todo lo antes expuesto depende en última instancia de la disciplina del equipo de desarrollo y las buenas prácticas férreas que se imponga el equipo.<br />
<h4 style="text-align: left;">
Son más fáciles <strike>complejos</strike> de implementar</h4>
<blockquote class="tr_bq">
Las transacciones distribuidas NUNCA son fáciles de implementar</blockquote>
Aunque la idea de que los <i>microservicios</i> modelan componentes aislados es atractiva, y sugiere que, al implementar cada componente por separado como un módulo independiente, deben ser estos últimos más fáciles de construir, desplegar y ejecutar. Pero la verdad es que todo lo antes expresado parte de un supuesto erróneo, y es el que asume que los dominios de negocio o los ámbitos de cada componente están bien definidos y separados. En el mundo real se necesita hacer un enorme trabajo de diseño y análisis y, apuesten que es así, mas de un pequeño "truco" para definir en forma separada los dominios de negocio y por ende de cada componente. Eso sin contar con que tarde o tempano vamos a necesitar lidiar con la tarea de orquestar varios <i>microservicos</i> con el propósito de completar transacciones distribuidas de mediana o larga duración.<br />
<br />
Es cuando se trata de orquestar transacciones distribuidas que la complejidad introducida por los <i>microservicios</i> se hace evidente y fracasa miserablemente en la mayoría de los casos.<br />
<br />
Nuevamente, cuando se lidia con transacciones distribuidas es cuando más disciplina se necesita, a todo nivel.<br />
<h4 style="text-align: left;">
Son más rápidos <strike>pesados</strike></h4>
<blockquote class="tr_bq">
Sí una <i>JVM</i> es lenta, varias <i>JVM</i> lo son aún mas</blockquote>
Cada componente por separado e independiente presenta una ventaja a la hora de necesitar y hacer uso del escalamiento horizontal, allí es donde los <i>microservicos</i> se lucen!!, pero ¿cuantos de nosotros tenemos necesidades de escalamiento masivo? al estilo de <i>Netflix</i>, ¿cuantos? levanten la mano, a ver, uno, dos, tres de entre 3 mil. Ahora imagine que cada componente de su patrón de solución necesita su propia <i>JVM</i>, cada <i>JVM</i> necesita ser iniciada antes de poder usarla, cada <i>JVM</i> consume sus propios recursos... como ven, todo esto aporta poco a la "rapidez"general de nuestra plataforma, salvo los contados casos de escalamiento brutal.<br />
<br />
Para variar, con un poco de disciplina y buenas prácticas de diseño se puede lograr un mejor desempeño sin necesidad de recurrir a los, de por sí complejos, <i>microservicios</i>. <br />
<h4 style="text-align: left;">
Mas simples para los ingenieros y desarrolladores</h4>
<blockquote class="tr_bq">
Sí sólo debo atender mis asuntos, lo que le pase a los demás no es de mi incumbencia</blockquote>
Cuando tienes un grupo de ingenieros y demás personas de <i>IT</i> atendiendo tan sólo lo que les compete, es muy frecuente que aparezca el síndrome de "No es asunto mio", en otras palabras, se dificulta en sobremanera la coordinación de los objetivos, reglas y demás buenas practicas entre los diferentes equipos.<br />
<br />
Un poco de disciplina ayuda mucho en la consecución de este beneficio en ambientes no basados en patrón de <i>microservicios</i>.<br />
<h4 style="text-align: left;">
Mejores para el escalamiento</h4>
<blockquote class="tr_bq">
Se pueden escalar <i>microservicios</i> tal como se puede escalar los módulos de un monolítico</blockquote>
Puede parecer contradictorio que critique al final el único beneficio real que ofrecen los <i>microservicios</i>, pero déjenme aclarar un poco la idea, la ventaja en escalamiento de los <i>microservicios</i> no viene tanto de su naturaleza como de las herramientas y tecnologías que los soportan. Sin <i>Docker</i> o <i>Kubernetes</i>, es poco lo que los <i>microservicios</i> hacen por el escalamiento, de hecho se pueden obtener beneficios similares usando las mismas tecnologías con módulos de un monolítico.<br />
<h3 style="text-align: left;">
Conclusión</h3>
Toda la complejidad y costos ocultos que aportan los <i>microservicios</i> sólo se justifican bajo circunstancias muy especiales, y la moda no es una de ellas. Todos los aparentes beneficios de ese patrón de componentes se pueden alcanzar con disciplina y buenas practicas en la mayoría de los casos.<br />
De hecho, todo ese "terror tecnológico" es sólo otro burdo intento de superar la disciplina con herramientas innovadoras de tecnología.<br />
<br />
Por último les dejo un par de enlaces para profundizar sobre el tema...<br />
<br />
<a href="https://www.campusmvp.es/recursos/post/la-muerte-de-la-locura-de-los-microservicios-en-2018.aspx" target="_blank">La muerte de la locura de los microservicios</a> y <a href="http://sivaprasadreddy.com/posts/2019/06/the-ugly-truth/" target="_blank">The ugly truth</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com2tag:blogger.com,1999:blog-1012161132404905800.post-76764765665268790702019-06-01T18:14:00.001-07:002019-06-01T18:15:19.672-07:00OAUTH 2.0, Conceptos y modo de funcionamiento<div dir="ltr" style="text-align: left;" trbidi="on">
Video donde revisamos algunos conceptos y modo de funcionamiento de OAUTH 2.0.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/pMLcAjE5Cso/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/pMLcAjE5Cso?feature=player_embedded" width="320"></iframe></div>
<br /></div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-45579885482926799952019-04-24T19:24:00.003-07:002019-05-22T19:15:30.443-07:00JWT explained!! Al fin!!!<div dir="ltr" style="text-align: left;" trbidi="on">
Siguiendo con la onda de seguridad, autenticación y autorización, hoy vamos a hablar de uno de los elementos que ya hemos mencionado como parte de estos mecanismos, los ya famosos <i>Json Web Token o JWT</i>, el cual es un <i>String</i> que cumple con el estándar <a href="https://tools.ietf.org/html/rfc7519">RFC 7519</a> para transmitir información con la identidad y <a href="https://en.wikipedia.org/wiki/Claims-based_identity">claims</a>
de un usuario de forma segura entre un cliente/servidor. Dicha
información puede ser verificada y confiable porque está firmada
digitalmente.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCMnKIDZJ3Jxpvx7lg0rOIg1064TrL8xltVrQNR1DBKSwMbjwbdoSrEWCCkjS3ihO-WF_Popdz_4YvKrirCqPSTLX0Ar2Q6orxN9mB6Y4leIqhCFx6kgxk9Nx4ZQH5GmIkNl7JwIZxGn0/s1600/jwt88.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="255" data-original-width="336" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCMnKIDZJ3Jxpvx7lg0rOIg1064TrL8xltVrQNR1DBKSwMbjwbdoSrEWCCkjS3ihO-WF_Popdz_4YvKrirCqPSTLX0Ar2Q6orxN9mB6Y4leIqhCFx6kgxk9Nx4ZQH5GmIkNl7JwIZxGn0/s320/jwt88.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<a name='more'></a>En otras palabras, <i>JWT</i> es un contenedor o cadena de caracteres codificados en <i>BASE64</i> y separados por un punto. Cada parte del <i>JWT</i> corresponde al <i>Header</i>, <i>Payload</i> y <i>Signature</i> respectivamente.<br />
<h3 style="clear: both; text-align: left;">
Estructura</h3>
Un JSON Web Token está dividido<strong> en tres partes</strong> .<br />
<ol>
<li>La primera es el <i><span style="color: red;">HEADER</span></i>, se denomina <i>JOSE</i> o <strong><i>JavaScript Object Signing and Encryption</i> </strong>y define cual es la tecnología criptográfica que se va a aplicar al token <strong>para securizar la información.</strong></li>
<li>La segunda parte es el <i style="background-color: white;"><span style="color: magenta;">PAYLOAD</span></i>, cuerpo o también conocido como <strong><i>JWT PayLoad o JWT Claims</i></strong> y almacena <strong>la información de negocio que necesitamos en el token.</strong> Esta parte se puede estructurar de muchas formas.</li>
<div class="google-auto-placed ap_container" style="clear: none; height: auto; text-align: center; width: 100%;">
<ins class="adsbygoogle adsbygoogle-noablate" data-ad-client="ca-pub-9246418527806139" data-ad-format="auto" data-adsbygoogle-status="done" style="display: block; margin: auto;"><ins id="aswift_1_expand" style="border: medium none; display: inline-table; height: 0px; margin: 0px; padding: 0px; position: relative; visibility: visible; width: 769px;"><ins id="aswift_1_anchor" style="border: medium none; display: block; height: 0px; margin: 0px; opacity: 0; overflow: hidden; padding: 0px; position: relative; visibility: visible; width: 769px;"><iframe allowfullscreen="true" allowtransparency="true" frameborder="0" height="193" hspace="0" id="aswift_1" marginheight="0" marginwidth="0" name="aswift_1" scrolling="no" style="border-style: initial; border-width: 0px; height: 193px; left: 0px; position: absolute; top: 0px; width: 769px;" vspace="0" width="769"></iframe></ins></ins></ins></div>
<li>La tercera parte es el <i><span style="color: #6fa8dc;">SIGNATURE</span></i>, o la firma <i>JWT</i> que se encarga de dar validez al token.</li>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxfvkJlKaumXCbBnD80Gj3P3keEj3BQijLfgNNbPdXlNYf693bhcWYxWNNAnBgAWJlKrVeZD2oOEFUxEHPOr20LlM5R5dRWN_mLqOdWfkUofDDJS7_vz-VnqNr5LM3gTIvWBFtkXTJPJQ/s1600/JsonWebToken-1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="285" data-original-width="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxfvkJlKaumXCbBnD80Gj3P3keEj3BQijLfgNNbPdXlNYf693bhcWYxWNNAnBgAWJlKrVeZD2oOEFUxEHPOr20LlM5R5dRWN_mLqOdWfkUofDDJS7_vz-VnqNr5LM3gTIvWBFtkXTJPJQ/s1600/JsonWebToken-1.jpg" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div style="text-align: center;">
</div>
<div style="text-align: center;">
<br /></div>
Es importante aclarar que la cadena/token esta <strong><em>codificado</em></strong> y lo <strong><em>crea nuestra aplicación</em></strong>, esto nos permite de manera muy fácil inspeccionar su contenido, por ejemplo con: <a href="https://jwt.io/">JWT Debugger</a>.<br />
<br />
Ejemplo de un <i>JWT</i>:<br />
<span style="color: red;">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9</span>.<span style="color: magenta;"><span style="background-color: white;">eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ</span>.</span><span style="color: #6fa8dc;">VuLOt6gBoBkdEcIIuZmQPrRachKywobaXML5Ttgf3G4</span><br />
<br />
<div style="text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUBpz5S1cIokzhlF_tpMbFgBN3tkiJ3kWbequsT0yo3TQkHARjPBwVvdmCD7kt3vSLQObQN2vM4CWDDjjUNSu4SCnLAGlSG0SsM-70knbrDd3QxPymXl8_ImVF3zTbuCcIyxAby7MXOZI/s1600/JSONWebTokenBase64.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="340" data-original-width="397" height="274" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUBpz5S1cIokzhlF_tpMbFgBN3tkiJ3kWbequsT0yo3TQkHARjPBwVvdmCD7kt3vSLQObQN2vM4CWDDjjUNSu4SCnLAGlSG0SsM-70knbrDd3QxPymXl8_ImVF3zTbuCcIyxAby7MXOZI/s320/JSONWebTokenBase64.jpg" width="320" /></a></div>
<br />
Al inspeccionar nuestro <i>JWT</i> de ejemplo en la dirección <a href="https://jwt.io/">https://jwt.io</a> podemos ver lo siguiente:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieU3pDr2jzsakilw_pWCtCLC1LtkVjdWYJZ4at7aKAbA7l6xJJRgPRf7NwaWkryosL00JARxGjbVGbz6keOfemvc7OFfhsWBnwuZCm_ZjAf8fnMBV6YTFJhQDE5ef-rxP6XvJKnsqZh0I/s1600/Screenshot_20190424_191034.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="563" data-original-width="811" height="443" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieU3pDr2jzsakilw_pWCtCLC1LtkVjdWYJZ4at7aKAbA7l6xJJRgPRf7NwaWkryosL00JARxGjbVGbz6keOfemvc7OFfhsWBnwuZCm_ZjAf8fnMBV6YTFJhQDE5ef-rxP6XvJKnsqZh0I/s640/Screenshot_20190424_191034.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
Pasemos ahora a estudiar cada parte por separado, así que manos a las sobras...<br />
<br />
<h3 style="text-align: left;">
Header</h3>
Como ya hemos especificado, el primer elemento es el <i><span style="color: red;">HEADER</span></i> o <i>JOSE</i>.<br />
<br />
Encoded:<br />
<span style="color: red;">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9</span><br />
<br />
Decoded:<br />
<div>
<pre class="brush: javascript">{
"alg": "HS256",
"typ": "JWT"
}
</pre>
</div>
<br />
Aquí vemos cómo definimos el tipo de token y el algoritmo criptográfico que vamos a utilizar<strong> (<i>HS256</i>)</strong>. <strong>¿Esto que quiere decir exactamente?</strong>
. En nuestro caso quiere decir que estamos usando un token <i>JWT</i> y un algoritmo de <i>HASH</i> muy concreto denominado <i>HMAC</i> que genera u<strong>n hash con <i>SHA256</i> utilizando una clave privada</strong>. Ya abordaremos estos conceptos en detalle más adelante.<br />
<br />
<h3 style="text-align: left;">
Payload</h3>
Este es el cuerpo del mensaje en el que podemos definir la información de negocio que consideremos adecuada.<br />
<br />
Encoded:<br />
<span style="background-color: white; color: magenta;">eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ</span><br />
<br />
Decoded:<br />
<div>
<pre class="brush: javascript">{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
</pre>
</div>
<br />
<h3 style="text-align: left;">
Signature</h3>
La tercera parte del token<br />
<br />
Encoded:<br />
<span style="color: #6fa8dc;">VuLOt6gBoBkdEcIIuZmQPrRachKywobaXML5Ttgf3G4</span><br />
<br />
Simplemente es un <i>hash</i> con la siguiente estructura:<br />
<br />
<div>
<pre class="brush: javascript">HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
CLAVE_PRIVADA)
</pre>
</div>
<br />
<div style="text-align: left;">
<i>CLAVE_PRIVADA</i> del ejemplo es "<b><i>secreta</i></b>".</div>
<h3 style="text-align: left;">
Criptografía y JSON Web Token</h3>
Para entender <i>JWT</i> necesitamos repasar algunos de conceptos criptográficos . Lo primero que tenemos que entender <strong>es el concepto de algoritmo de <i>HASH</i></strong>. Un algoritmo de <i>HASH</i> se encarga de generar un <i>HASH</i> (<strong>bloque de caracteres de longitud fija</strong>) a partir de una cadena arbitraria de texto.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCNOPqHAZ9ELJaHnwMeQxVJ-4IYuPrdIU8ka_3ExGxb0n-939Pm_Bx0LRNWb8N-lHtATHlm77aDJiBAmFB1kvC8unZbRhb3k5N-cCumf8YbpztnAoI5iPo7Y8EVqKD1f087zEMaSIGf8Y/s1600/JSONWebTokenCrearHASH.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="222" data-original-width="423" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCNOPqHAZ9ELJaHnwMeQxVJ-4IYuPrdIU8ka_3ExGxb0n-939Pm_Bx0LRNWb8N-lHtATHlm77aDJiBAmFB1kvC8unZbRhb3k5N-cCumf8YbpztnAoI5iPo7Y8EVqKD1f087zEMaSIGf8Y/s400/JSONWebTokenCrearHASH.jpg" width="400" /></a></div>
<br />
<br />
Los
algoritmos de <i>hash</i> sirven para comprobar que en ningún momento se ha
modificado el texto original ya que se aseguran de que ante dos textos
distintos siempre <strong>se genera un hash diferente</strong>. Por lo
tanto si alguien nos cambia el texto original y lo intenta dar por
válido podemos regenerar el hash y comprobar si cumple.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdWPmEzU3HLalZlzOUbjmlDQ_Pv84OnUeiCq_CNnNsVD60Tkluiyb0Ohk0VOxMLA_z5fAQqJrGCTwJGxDc-4noW1Wp8hswiMPBjcuZ68zl4V_8NzR8FB-DdnjNRvaCcvuuxwm8dj5H0g8/s1600/JSONWebTokenValidaHASH.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="252" data-original-width="362" height="277" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdWPmEzU3HLalZlzOUbjmlDQ_Pv84OnUeiCq_CNnNsVD60Tkluiyb0Ohk0VOxMLA_z5fAQqJrGCTwJGxDc-4noW1Wp8hswiMPBjcuZ68zl4V_8NzR8FB-DdnjNRvaCcvuuxwm8dj5H0g8/s400/JSONWebTokenValidaHASH.jpg" width="400" /></a></div>
<br />
<h3 style="text-align: left;">
JSON Web Token y HMAC</h3>
¿Qué es lo que tiene <strong>en especial usar un algoritmo <i>HMAC</i></strong> para generar el <i>hash</i>?. Lo que tiene de especial es que este algoritmo criptográfico se encarga de generar un hash <strong>para un texto utilizando una clave privada.</strong><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1NKC0LgIpeztT2bma-OrwDVYnSHYApiJIoKnFW6eeZJACvUNqu92BTrkPc09lcWm53wwrxSNLAHReHiIfbsYNYFs8Q60bC7YEOAFfv76kSiV7P_Cpy0ouTBr14_Ctlx6a3lXTdVI3N-Y/s1600/JSONWebTokenPrivateKey.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="371" data-original-width="476" height="311" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1NKC0LgIpeztT2bma-OrwDVYnSHYApiJIoKnFW6eeZJACvUNqu92BTrkPc09lcWm53wwrxSNLAHReHiIfbsYNYFs8Q60bC7YEOAFfv76kSiV7P_Cpy0ouTBr14_Ctlx6a3lXTdVI3N-Y/s400/JSONWebTokenPrivateKey.jpg" width="400" /></a></div>
<br />
<br />
Esto implica una diferencia importante ya que los <i>HASH</i> solo los pueden generar aquellas personas <strong>que conozcan la clave privada.</strong> Por lo tanto no solo sabemos ahora que el contenido no ha sido modificado sino también podemos <strong>saber quien es su creador. </strong>Vamos a profundizar un poco mas con este diagrama:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2nf6F1bLr7Kd4ROhcTP0uAJDajIHX7Shmh6180lfxf-8gPfbzI_nJgWKTQIlCeQKaFmQ-UVrOBCvZaF-eIMQg8h_Dg4jqfpN5p1nXkyVW-HODReNPrseDw5_9NAoNZa2d2HUyroc1Xmk/s1600/JSONWebTokenCompleto-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="520" data-original-width="432" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2nf6F1bLr7Kd4ROhcTP0uAJDajIHX7Shmh6180lfxf-8gPfbzI_nJgWKTQIlCeQKaFmQ-UVrOBCvZaF-eIMQg8h_Dg4jqfpN5p1nXkyVW-HODReNPrseDw5_9NAoNZa2d2HUyroc1Xmk/s400/JSONWebTokenCompleto-2.jpg" width="331" /></a></div>
<br />
El diagrama explica cómo se genera el <i>HASH</i><br />
<ol>
<li>En primer lugar generamos las estructuras de base64<strong> tanto de la parte <i>JOSE</i> como de los <i>Claims</i></strong></li>
<li>En segundo lugar usaremos el algoritmo <i>HMAC</i> con su clave privada <strong>para generar un <i>HASH</i></strong> basado en las estructuras de <i>Base64</i>.</li>
</ol>
Realizadas ambas operaciones el último paso es sumarlo todo y generar un token:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjBxcqYK-SRg4r2_IzLVEluK7nzD4IJNqLSjFaCPDjBb5YpxRf_4Ed9JUBy2fY02i-kC42gVBY9ylmnG9WX1A12rNo8Gam_C8SHRiSb4kzQuJCDMeoUmwAP5FWvAf4g5qTVev30LamslY/s1600/JSONWebTokenConJWT.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="139" data-original-width="476" height="116" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjBxcqYK-SRg4r2_IzLVEluK7nzD4IJNqLSjFaCPDjBb5YpxRf_4Ed9JUBy2fY02i-kC42gVBY9ylmnG9WX1A12rNo8Gam_C8SHRiSb4kzQuJCDMeoUmwAP5FWvAf4g5qTVev30LamslY/s400/JSONWebTokenConJWT.jpg" width="400" /></a></div>
<br />
<br />
Este token será el que enviemos al cliente y le permitirá autenticarse más adelante.<br />
<h3 style="text-align: left;">
JWT y Servidor</h3>
La forma de procesar los tokens <i>JWT</i> está ligada al servidor pero básicamente es algo del estilo:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2nf6F1bLr7Kd4ROhcTP0uAJDajIHX7Shmh6180lfxf-8gPfbzI_nJgWKTQIlCeQKaFmQ-UVrOBCvZaF-eIMQg8h_Dg4jqfpN5p1nXkyVW-HODReNPrseDw5_9NAoNZa2d2HUyroc1Xmk/s1600/JSONWebTokenCompleto-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="520" data-original-width="432" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2nf6F1bLr7Kd4ROhcTP0uAJDajIHX7Shmh6180lfxf-8gPfbzI_nJgWKTQIlCeQKaFmQ-UVrOBCvZaF-eIMQg8h_Dg4jqfpN5p1nXkyVW-HODReNPrseDw5_9NAoNZa2d2HUyroc1Xmk/s400/JSONWebTokenCompleto-2.jpg" width="331" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaJlCkxgNx7c6z9uULDae813L8JOHXExGYEzjN0gadgzXC54lFdaYOeZb1qKa13jiz0IR04cttZO2RB1Ocn5VdrqTxLKzBUcbUxrIzKHEBpp0Ok3VIb7z6-BHOVMq9JAI49VYbZGluD8o/s1600/JSONWebTokenServidor.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="375" data-original-width="353" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaJlCkxgNx7c6z9uULDae813L8JOHXExGYEzjN0gadgzXC54lFdaYOeZb1qKa13jiz0IR04cttZO2RB1Ocn5VdrqTxLKzBUcbUxrIzKHEBpp0Ok3VIb7z6-BHOVMq9JAI49VYbZGluD8o/s400/JSONWebTokenServidor.jpg" width="376" /></a></div>
<br />
<br />
<ol>
<li>El cliente se logea en el servidor y envía usuario y clave</li>
<li>El sistema le valida y genera un token usando el algoritmo <i>HMAC</i> y la clave privada</li>
<li>El cliente recibe el token</li>
<li>El cliente solicita unos datos y pasa como identificador el token</li>
<li>El servidor<strong> decodifica los bloques de base64 y usa su clave privada para comprobar el <i>HASH</i></strong>. Si todo es correcto, permite el acceso y envía la información solicitada al cliente.</li>
</ol>
<div>
Podemos observar hasta aquí, porque <i>JWT</i> es tan popular como mecanismo de autorización para <i>APIs</i>. </div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-50833669134615480892019-04-11T10:41:00.002-07:002019-04-11T11:47:19.774-07:00Usando proof-of-possession of key del lado del cliente<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
En nuestro <a href="http://pigbar-hal9k.blogspot.com/2019/03/usando-proof-of-possession-key.html">capítulo anterior</a> vimos cómo implementar <i>Proof Of Key</i> en el lado del servidor usando <i>OAUTH 2.0</i> con <i>SpringBoot</i>. Hoy corresponde enfocarnos en ese concepto del lado del cliente. En esta oportunidad vamos a desarrollar una aplicación que interactúe con el servidor o proveedor de <i>OAUTH</i> tras demostrar que está en posesión de la clave privada relacionada con la clave pública que se nos provee en el <i>JWT</i> correspondiente.<br />
Al igual que la anterior, esta publicación va a hacer uso de <i>Java 8</i>, <i>Maven</i>, <i>Spring Web</i>, <i>Spring Security</i> y <i>Nimbus JOSE + JWT</i>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDDb-aL3yCvh8Dvgm1-214Rdwrj6Xf1T9sAG5cKiQjDLRYJYhGwFU1mejbMr1G4E7_72DJ8L7psy5bPTvhe7_qRPIFB-QSwU8Oo-JUMBxLFgrCxvhAhh3MwkO0qtswgBMtYr4juzTEEQw/s1600/oauthkey.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="142" data-original-width="355" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDDb-aL3yCvh8Dvgm1-214Rdwrj6Xf1T9sAG5cKiQjDLRYJYhGwFU1mejbMr1G4E7_72DJ8L7psy5bPTvhe7_qRPIFB-QSwU8Oo-JUMBxLFgrCxvhAhh3MwkO0qtswgBMtYr4juzTEEQw/s400/oauthkey.jpeg" width="400" /></a></div>
<br />
<br />
<a name='more'></a>Así que sin mucho preámbulo vamos manos a las sobras!!<br />
<br />
<br />
<ol style="text-align: left;">
<li>Primero que todo, vamos a empezar por crear la aplicación <i><span style="font-family: "courier new" , "courier" , monospace;">pop-client</span></i> usando el inicializador de spring: <a href="https://start.spring.io/">Spring Initializr</a>.<br /><br />Escoja un Tipo de proyecto <i><span style="font-family: "courier new" , "courier" , monospace;">Maven</span></i>. <i><span style="font-family: "courier new" , "courier" , monospace;">Java</span></i> como lenguaje. <span style="font-family: "courier new" , "courier" , monospace;"><i>Sprig boot </i>2.1.3</span>.<br />Ingrese su <span style="font-family: "courier new" , "courier" , monospace;">Group</span> de preferencia como por ejemplo:<br /><br /><span style="font-family: "courier new" , "courier" , monospace;"><i>org.pigbar.hal9k.oauth2.pop</i></span>Ingrese el nombre del <span style="font-family: "courier new" , "courier" , monospace;">Artifact</span>:<br /><br /><i><span style="font-family: "courier new" , "courier" , monospace;">pop-client</span></i><span style="font-family: "courier new" , "courier" , monospace;"><i><br /></i></span>En las dependencias agregue:<br /><br /><span style="font-family: "courier new" , "courier" , monospace;"><i>Web, Security y Thymeleaf</i></span>Genere el proyecto, descárguelo y proceda a importarlo en su <i><span style="font-family: "courier new" , "courier" , monospace;">IDE</span></i> de preferencia como un proyecto <i><span style="font-family: "courier new" , "courier" , monospace;">Maven</span></i> existente.</li>
<li>En su proyecto <span style="font-family: "courier new" , "courier" , monospace;">Maven</span> verifique el contenido del archivo <span style="font-family: "courier new" , "courier" , monospace;">pom.xml</span>, debe ser como el siguiente:
<br /><div>
<pre class="brush: xml"><project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" 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>
<parent>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-parent</artifactid>
<version>2.1.3.RELEASE</version>
<relativepath>
</relativepath></parent>
<groupid>org.pigbar.hal9k.oauth2.pop</groupid>
<artifactid>pop-client</artifactid>
<version>0.0.1-SNAPSHOT</version>
<name>pop-client</name>
<description>Demo project for Spring Boot</description>
<properties>
<java .version="">1.8</java>
</properties>
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-security</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-thymeleaf</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-test</artifactid>
<scope>test</scope>
</dependency>
<dependency>
<groupid>org.springframework.security</groupid>
<artifactid>spring-security-test</artifactid>
<scope>test</scope>
</dependency>
<dependency>
<groupid>org.springframework.security.oauth</groupid>
<artifactid>spring-security-oauth2</artifactid>
<version>2.2.0.RELEASE</version>
</dependency>
<dependency>
<groupid>org.springframework.security</groupid>
<artifactid>spring-security-jwt</artifactid>
<version>1.0.10.RELEASE</version>
</dependency>
<dependency>
<groupid>com.nimbusds</groupid>
<artifactid>nimbus-jose-jwt</artifactid>
<version>4.23</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-maven-plugin</artifactid>
</plugin>
</plugins>
</build>
</project></pre>
</div>
</li>
<li>Dentro de la carpeta <span style="font-family: "courier new" , "courier" , monospace;"><i>src/maim/resources</i>,</span> en el archivo <i><span style="font-family: "courier new" , "courier" , monospace;">application.properties</span></i> ingrese los siguientes registros de <i>key = value</i>:<br /><br />
<div>
<pre class="brush: javascript">spring.security.user.name=pigbar
spring.security.user.password=1234
security.oauth2.resource.jwt.key-uri=http://localhost:8080/oauth/token_key
security.oauth2.client.client-id=clientapp
security.oauth2.client.client-secret=123456
server.port=9000
spring.http.converters.preferred-json-mapper=jackson
spring.thymeleaf.cache=false
</pre>
</div>
<br />
</li>
<li>En el <i>package</i> <i>org.pigbar.hal9k.oauth2.pop</i> cree los siguientes <i>sub-packages</i>:<br /><br /><i><span style="font-family: "courier new" , "courier" , monospace;">oauth<br />dashboard</span></i></li>
<li>En el sub-package <i>ouath</i> vamos a crear una clase denominada <i>JwkKeyPairManager</i>, que será la encargada de manejar el <i>keypair</i> para firmar el atributo <i>nonce</i> del <i>header </i>y demostrar que se posee la clave privada (<i>POP</i>).<br /><br />
<pre class="brush: java">package org.pigbar.hal9k.oauth2.pop.oauth;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.stereotype.Component;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.Payload;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.RSAKey;
@Component
public class JwkKeyPairManager {
private final JWK clientJwk;
public JwkKeyPairManager() {
KeyPair keyPair = createRSA256KeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RandomValueStringGenerator random = new RandomValueStringGenerator();
RSAKey.Builder builder = new RSAKey.Builder(publicKey);
builder.keyID(random.generate());
builder.privateKey(privateKey);
this.clientJwk = builder.build();
}
public JWK createJWK() {
return clientJwk.toPublicJWK();
}
public String getSignedContent(String content) {
Payload contentPayload = new Payload(content);
try {
RSASSASigner rsa = new RSASSASigner(((RSAKey) clientJwk).toPrivateKey());
JWSAlgorithm alg = JWSAlgorithm.RS256;
JWSHeader header = new JWSHeader.Builder(alg).keyID(clientJwk.getKeyID()).build();
JWSObject jws = new JWSObject(header, contentPayload);
jws.sign(rsa);
return jws.serialize();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private KeyPair createRSA256KeyPair() {
try {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
return generator.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}
</pre>
</li>
<li> Ahora, en el mismo paquete, vamos a crear un una clase denominada <i>PoPTokenRequestEnhancer</i> que se va a encargar de enviar la clave pública al servidor de autorización, <i>Authorization Server</i>, cuando se solicite un nuevo <i>Token</i> de acceso.<br /><br />
<pre class="brush: java">package org.pigbar.hal9k.oauth2.pop.oauth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
import org.springframework.security.oauth2.client.token.RequestEnhancer;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
@Component
public class PoPTokenRequestEnhancer implements RequestEnhancer {
@Autowired
private JwkKeyPairManager keyPairManager;
@Override
public void enhance(AccessTokenRequest request,
OAuth2ProtectedResourceDetails resource,
MultiValueMap<String, String> form,
HttpHeaders headers) {
form.add("public_key", keyPairManager.createJWK().toJSONString());
}
}
</pre>
</li>
<li> Como el cliente debe enviar el <i>nonce</i> firmado cada vez que interactúa con un recurso protegido, vamos a crear un <i>Interceptor</i>, <i>HttpRequestWithPoPSignatureInterceptor</i>, para agregar estos datos a cada <i>endpoint</i> externo con el que se trabaje. En el mismo paquete creamos lo siguiente:<br /><br />
<pre class="brush: java">package org.pigbar.hal9k.oauth2.pop.oauth;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.UUID;
@Component
public class HttpRequestWithPoPSignatureInterceptor
implements ClientHttpRequestInterceptor, ApplicationContextAware {
private ApplicationContext applicationContext;
@Autowired
private JwkKeyPairManager keyPairManager;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
OAuth2ClientContext clientContext = applicationContext.getBean(OAuth2ClientContext.class);
OAuth2AccessToken accessToken = clientContext.getAccessToken();
request.getHeaders().set("Authorization", "Bearer " + accessToken.getValue());
request.getHeaders().set("nonce", keyPairManager.getSignedContent(UUID.randomUUID().toString()));
return execution.execute(request, body);
}
}
</pre>
</li>
<li>Como es necesario mantener o guardar los tokens, vamos a crear un servicio que se encargue de administrar los tokens del cliente o usuario. En el mismo paquete creamos el siguiente servicio:<br /><br />
<pre class="brush: java">package org.pigbar.hal9k.oauth2.pop.oauth;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.ClientTokenServices;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Service;
@Service
public class OAuth2ClientTokenSevices implements ClientTokenServices {
private ConcurrentHashMap<String, ClientUser> users = new ConcurrentHashMap<>();
@Override
public OAuth2AccessToken getAccessToken(OAuth2ProtectedResourceDetails resource, Authentication authentication) {
ClientUser clientUser = getClientUser(authentication);
if (clientUser.accessToken == null) return null;
DefaultOAuth2AccessToken oAuth2AccessToken = new DefaultOAuth2AccessToken(clientUser.accessToken);
oAuth2AccessToken.setAdditionalInformation(clientUser.additionalInformation);
oAuth2AccessToken.setExpiration(new Date(clientUser.expirationTime));
return oAuth2AccessToken;
}
@Override
public void saveAccessToken(OAuth2ProtectedResourceDetails resource,
Authentication authentication, OAuth2AccessToken accessToken) {
ClientUser clientUser = getClientUser(authentication);
clientUser.accessToken = accessToken.getValue();
clientUser.expirationTime = accessToken.getExpiration().getTime();
clientUser.additionalInformation = accessToken.getAdditionalInformation();
users.put(clientUser.username, clientUser);
}
@Override
public void removeAccessToken(OAuth2ProtectedResourceDetails resource,
Authentication authentication) {
users.remove(getClientUser(authentication).username);
}
private ClientUser getClientUser(Authentication authentication) {
String username = ((User) authentication.getPrincipal()).getUsername();
ClientUser clientUser = users.get(username);
if (clientUser == null) {
clientUser = new ClientUser(username);
}
return clientUser;
}
private static class ClientUser {
private String username;
private String accessToken;
private Map<String, Object> additionalInformation;
private long expirationTime;
public ClientUser(String username) {
this.username = username;
}
}
}
</pre>
</li>
<li>Procedamos ahora a crear la clase que se encargará de la configuración del cliente. Por lo tanto, en el paquete de costumbre, procedemos a crear:<br /><br />
<pre class="brush: java">package org.pigbar.hal9k.oauth2.pop.oauth;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.AccessTokenProviderChain;
import org.springframework.security.oauth2.client.token.ClientTokenServices;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.oauth2.common.AuthenticationScheme;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
@Configuration
@EnableOAuth2Client
public class ClientConfiguration {
@Autowired
private ClientTokenServices clientTokenServices;
@Autowired
private OAuth2ClientContext oauth2ClientContext;
@Autowired
private HttpRequestWithPoPSignatureInterceptor interceptor;
@Autowired
private PoPTokenRequestEnhancer requestEnhancer;
@Bean
public AuthorizationCodeResourceDetails authorizationCode() {
AuthorizationCodeResourceDetails resourceDetails = new AuthorizationCodeResourceDetails();
resourceDetails.setId("oauth2server");
resourceDetails.setTokenName("oauth_token");
resourceDetails.setClientId("clientapp");
resourceDetails.setClientSecret("123456");
resourceDetails.setAccessTokenUri("http://localhost:8080/oauth/token");
resourceDetails.setUserAuthorizationUri("http://localhost:8080/oauth/authorize");
resourceDetails.setScope(Arrays.asList("read_profile"));
resourceDetails.setPreEstablishedRedirectUri(("http://localhost:9000/callback"));
resourceDetails.setUseCurrentUri(false);
resourceDetails.setClientAuthenticationScheme(AuthenticationScheme.header);
return resourceDetails;
}
@Bean
public OAuth2RestTemplate oauth2RestTemplate() {
OAuth2ProtectedResourceDetails resourceDetails = authorizationCode();
OAuth2RestTemplate template = new OAuth2RestTemplate(resourceDetails, oauth2ClientContext);
AuthorizationCodeAccessTokenProvider authorizationCode = new AuthorizationCodeAccessTokenProvider();
authorizationCode.setTokenRequestEnhancer(requestEnhancer);
AccessTokenProviderChain provider = new AccessTokenProviderChain(Arrays.asList(authorizationCode));
provider.setClientTokenServices(clientTokenServices);
template.setAccessTokenProvider(provider);
template.setInterceptors(Arrays.asList(interceptor));
return template;
}
}
</pre>
</li>
<li>Lista la configuración, procedemos entonces a definir los controles de acceso para este cliente. Nuevamente, en el mismo paquete, creamos lo siguiente:<br /><br />
<pre class="brush: java">package org.pigbar.hal9k.oauth2.pop.oauth;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().permitAll().and().authorizeRequests().antMatchers("/", "/index**", "/callback**", "/dashboard")
.authenticated().anyRequest().authenticated();
}
}
</pre>
</li>
<li> Como esta es una aplicación cliente, es lógico que creemos algunos recursos con los que el usuario pueda interactuar. Los siguientes elementos se usan para definir un Dashboard de cliente. En el paquete <i>dashboard</i> procedemos a crear:<br /><br />
Clase <i>Entry
</i><pre class="brush: java">package org.pigbar.hal9k.oauth2.pop.dashboard;
public class Entry {
private String value;
public Entry(String value) {
super();
this.value = value;
}
public String getValue() {
return value;
}
}
</pre>
Clase <i>UserProfile
</i><pre class="brush: java">package org.pigbar.hal9k.oauth2.pop.dashboard;
public class UserProfile {
private String name;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
</pre>
Clase <i>UserDashboard
</i><pre class="brush: java">package org.pigbar.hal9k.oauth2.pop.dashboard;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.servlet.ModelAndView;
import java.util.Arrays;
import java.util.List;
@Controller
public class UserDashboard {
@Autowired
private OAuth2RestTemplate restTemplate;
@GetMapping("/")
public String home() {
return "index";
}
@GetMapping("/callback")
public ModelAndView callback(String code, String state) {
return new ModelAndView("forward:/dashboard");
}
@GetMapping("/dashboard")
public ModelAndView dashboard() {
List<Entry> entries = Arrays.asList(
new Entry("entry 1"),
new Entry("entry 2"));
ModelAndView mv = new ModelAndView("dashboard");
mv.addObject("entries", entries);
tryToGetUserProfile(mv);
return mv;
}
private void tryToGetUserProfile(ModelAndView mv) {
String endpoint = "http://localhost:8080/api/profile";
try {
UserProfile userProfile = restTemplate.getForObject(endpoint, UserProfile.class);
mv.addObject("profile", userProfile);
} catch (HttpClientErrorException e) {
throw new RuntimeException("it was not possible to retrieve user profile");
}
}
}
</pre>
</li>
<li>Ahora, en la carpeta /<i>pop-client/src/main/resources/templates</i> creamos los siguientes archivos:<br /><br />
Archivo <i>index.html</i>:
<pre class="brush: xml"><html xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>client app</title>
</head>
<body>
<a href="/dashboard">Go to your dashboard</a>
</body>
</html>
</pre>
<br />
Archivo <i>dashboard.html</i>:<br />
<pre class="brush: xml"><!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>client app</title>
</head>
<body>
<h1>that's your dashboard</h1>
<table>
<tr>
<td><b>That's your entries</b></td>
</tr>
<tr th:each="entry : ${entries}">
<td th:text="${entry.value}">value</td>
</tr>
</table>
<h3>your profile from [Profile Application]</h3>
<table>
<tr>
<td><b>name</b></td>
<td th:text="${profile.name}">username</td>
</tr>
<tr>
<td><b>email</b></td>
<td th:text="${profile.email}">email</td>
</tr>
</table>
</body>
</html>
</pre>
</li>
<li>Finalmente, procedemos a crear nuestra clase de <i>Application</i> de <i>springboot</i>. Para ello nos dirigimos al paquete <i>org.pigbar.hal9k.oauth2.pop</i> y creamos la siguiente clase:<br /><br />
<pre class="brush: java">package org.pigbar.hal9k.oauth2.pop;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletContextInitializer;
@SpringBootApplication
public class PopClientApplication implements ServletContextInitializer {
public static void main(String[] args) {
SpringApplication.run(PopClientApplication.class, args);
}
@Override
public void onStartup(ServletContext servletContext)
throws ServletException {
servletContext.getSessionCookieConfig().setName("client-session");
}
}
</pre>
</li>
</ol>
<div>
Ya hemos creado nuestro cliente de <i>OAU</i>TH 2.0 con el mecanismo de <i>Proof Of Possession of Key</i>.<br />
Ejecute el servidor. Ejecute este cliente. Vaya en el navegador a la URL <i>http://localhost:9000</i> e introduzca sus credenciales, a saber <i>pigbar</i> y <i>1234</i> para el usuario y la clave respectivamente. Haga click en el enlace para el <i>Dashboard</i>...<br />
y veamos que sucede!!!<br />
<br />
<span style="background-color: #cc0000;"><span style="color: white;">P.D.: Va a notar que debe hacer Login dos veces, una vez en el cliente y otra en el servidor. Como evitar ese doble Login? <b>Esta es precisamente su tarea a resolver!!!</b> </span></span></div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-43776185910086575152019-03-23T19:20:00.001-07:002019-04-11T15:22:33.227-07:00Usando proof-of-possession key semantics con un Provider de OAuth 2.0<div dir="ltr" style="text-align: left;" trbidi="on">
Hace rato que <i><span style="font-family: "courier new" , "courier" , monospace;">OAUTH</span></i> 2.0 viene estando presente en el escenario de seguridad en <i><span style="font-family: "courier new" , "courier" , monospace;">IT</span></i>. El post que hoy nos ocupa tiene como propósito mostrar un ejemplo funcional del esquema Prueba de posesión de clave, del ingles<span style="font-family: "courier new" , "courier" , monospace;"><i> Proof Of Possession (POP)</i></span> of key usando <span style="font-family: "courier new" , "courier" , monospace;"><i>Spring Boot</i></span>.<br />
Este ejemplo usa como base el código presentado en el maravilloso libro, <i><span style="font-family: "courier new" , "courier" , monospace;">OAUTH</span></i> 2.0 Cookbook, la diferencia es que este SI FUNCIONA!!! ;)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX56a2DTqebsTmlvYzEfFaWACdfHG_mDXrKai7bLFYqrrRxdiKwx5E1aUG9otVc1UcrUKLDg_gOy6q8ZGODj71v6zID4kNa1WOWC777AXEf4GHB4f6g9zMWAbfsbb1vZh1TxtyNA_2nis/s1600/oauth44-641x372.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="372" data-original-width="641" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX56a2DTqebsTmlvYzEfFaWACdfHG_mDXrKai7bLFYqrrRxdiKwx5E1aUG9otVc1UcrUKLDg_gOy6q8ZGODj71v6zID4kNa1WOWC777AXEf4GHB4f6g9zMWAbfsbb1vZh1TxtyNA_2nis/s320/oauth44-641x372.png" width="320" /></a></div>
<a name='more'></a>Esta va a ser una publicación larga, digna del castigo que merecemos por el largo tiempo que llevamos de inactividad.<br />
<br />
Como siempre decimos, manos a las sobras!!!, pero primero algunos conceptos básicos.<br />
<br />
<h3 style="text-align: left;">
<b>OAUTH 2.0</b></h3>
Imagine por un momento que Ud. llega a un hotel, se registra, y le dan una llave digital para entrar a su fabulosa suite. Luego, Ud. usa la llave que le facilitaron para poder tener acceso a la respectiva suite o habitación de lujo, en donde pasa una estupenda velada... ok, ok, ya vamos a hablar de <i><span style="font-family: "courier new" , "courier" , monospace;">OAUTH</span></i>.<br />
La Suite de Lujo es el recurso al que Ud. quiere acceder (<span style="font-family: "courier new" , "courier" , monospace;">Resource</span>).<br />
El Hotel es El Propietario del Recurso (<span style="font-family: "courier new" , "courier" , monospace;">Resource Server</span>).<br />
La Administración del hotel es quien Autoriza el Acceso (<span style="font-family: "courier new" , "courier" , monospace;">Authorization Server</span>)<br />
La Llave Digital es el Token de acceso al recurso (<span style="font-family: "courier new" , "courier" , monospace;">Access Token</span>).<br />
Y Ud., obviamente, es el Cliente o Tercero que quiere acceder al recurso (<span style="font-family: "courier new" , "courier" , monospace;">Client</span>).<br />
<br />
Asi que, para poder acceder al recurso, Ud., el cliente, primero debe estar registrado, ser autorizado y tener un Token de acceso válido. Y es así como <i><span style="font-family: "courier new" , "courier" , monospace;">OAUTH</span></i> funciona.<br />
<br />
<b>Open Authorization (OAuth)</b> es un <a href="https://es.wikipedia.org/wiki/Est%C3%A1ndar_abierto" title="Estándar abierto">estándar abierto</a> que permite flujos simples de autorización para sitios web o aplicaciones informáticas. OAuth 2 es una estructura (framework) de autorización que le permite a
las aplicaciones obtener acceso limitado a cuentas de usuario en un
servicio <span style="font-family: "courier new" , "courier" , monospace;">HTTP</span>, como Facebook, GitHub y DigitalOcean. Delega la
autenticación del usuario al servicio que aloja la cuenta del mismo y
autoriza a las aplicaciones de terceros el acceso a dicha cuenta de
usuario. OAuth 2 proporciona flujos de autorización para aplicaciones
web y de escritorio; y dispositivos móviles.<br />
<br />
<h3 style="text-align: left;">
Proof Of Possession</h3>
Es un mecanismo e implementación de autorización en <span style="font-family: "courier new" , "courier" , monospace;">OAUTH</span> 2.0 en el que el cliente debe ser capaz de demostrar que posee una clave que valida el Token que dicho cliente pueda poseer. En otras palabras es un mecanismo para aumentar la seguridad de <span style="font-family: "courier new" , "courier" , monospace;">OAUTH</span> 2.0, garantizando que un Token proviene desde una fuente confiable.<br />
<br />
Para mayor información favor visitar el siguiente video: OAuth: <a href="https://www.youtube.com/watch?v=H6MxsFMAoP8">When Things Go Wrong</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/H6MxsFMAoP8/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/H6MxsFMAoP8?feature=player_embedded" width="320"></iframe></div>
<br />
<br />
Ahora si... comencemos.<br />
<br />
<h3 style="text-align: left;">
OAuth Provider - Servidores</h3>
Vamos a comenzar por construir una aplicación que funcione como un Proveedor de <span style="font-family: "courier new" , "courier" , monospace;">OAUTH</span> 2.0, la cual implementará en si misma los servidores de Autorización y de Recursos respectivamente. Esta será una aplicación de <i><span style="font-family: "courier new" , "courier" , monospace;">Spring Boot</span></i>, <span style="font-family: "courier new" , "courier" , monospace;"><i>Java</i> 8</span>, <span style="font-family: "courier new" , "courier" , monospace;">Maven</span>, <i><span style="font-family: "courier new" , "courier" , monospace;">Spring Web</span></i>, <i><span style="font-family: "courier new" , "courier" , monospace;">Spring Security</span></i>, y <i><span style="font-family: "courier new" , "courier" , monospace;">Nimbus JOSE + JWT</span> </i>(el cual proveerá <i><span style="font-family: "courier new" , "courier" , monospace;">JWE</span></i> y capacidades de encriptamiento). otras dependencias se verán en detalle al declararlas en el archivo .pom correspondiente.<br />
<br />
<br />
<ol style="text-align: left;">
<li>Primero que todo, vamos a empezar por crear la aplicación <i><span style="font-family: "courier new" , "courier" , monospace;">pop-server</span></i> usando el inicializador de spring: <a href="https://start.spring.io/">Spring Initializr</a>.<br />Escoja un Tipo de proyecto <i><span style="font-family: "courier new" , "courier" , monospace;">Maven</span></i>. <i><span style="font-family: "courier new" , "courier" , monospace;">Java</span></i> como lenguaje. <span style="font-family: "courier new" , "courier" , monospace;"><i>Sprig boot </i>2.1.3</span>.<br />Ingrese su <span style="font-family: "courier new" , "courier" , monospace;">Group</span> de preferencia como por ejemplo:<br /><br /><i><span style="font-family: "courier new" , "courier" , monospace;">org.pigbar.hal9k.oauth2.pop</span></i><br /><br />Ingrese el nombre del <span style="font-family: "courier new" , "courier" , monospace;">Artifact</span>:<br /><br /><span style="font-family: "courier new" , "courier" , monospace;"><i>pop-server</i></span><br /><br />En las dependencias agregue:<br /><br /><i><span style="font-family: "courier new" , "courier" , monospace;">Web, Security y Thymeleaf</span></i><br /><br />Genere el proyecto, descárguelo y proceda a importarlo en su <i><span style="font-family: "courier new" , "courier" , monospace;">IDE</span></i> de preferencia como un proyecto <i><span style="font-family: "courier new" , "courier" , monospace;">Maven</span></i> existente.</li>
<li>En su proyecto <span style="font-family: "courier new" , "courier" , monospace;">Maven</span> verifique el contenido del archivo <span style="font-family: "courier new" , "courier" , monospace;">pom.xml</span>, debe ser como el siguiente:
<br /><div>
<pre class="brush: xml"><project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" 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>
<parent>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-parent</artifactid>
<version>2.1.3.RELEASE</version>
<relativepath>
</relativepath></parent>
<groupid>org.pigbar.hal9k.oauth2.pop</groupid>
<artifactid>pop-server</artifactid>
<version>0.0.1-SNAPSHOT</version>
<name>pop-server</name>
<description>Demo project for Spring Boot</description>
<properties>
<java .version="">1.8</java>
</properties>
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-security</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-thymeleaf</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-test</artifactid>
<scope>test</scope>
</dependency>
<dependency>
<groupid>org.springframework.security</groupid>
<artifactid>spring-security-test</artifactid>
<scope>test</scope>
</dependency>
<dependency>
<groupid>org.springframework.security.oauth</groupid>
<artifactid>spring-security-oauth2</artifactid>
<version>2.2.0.RELEASE</version>
</dependency>
<dependency>
<groupid>org.springframework.security</groupid>
<artifactid>spring-security-jwt</artifactid>
<version>1.0.10.RELEASE</version>
</dependency>
<dependency>
<groupid>com.nimbusds</groupid>
<artifactid>nimbus-jose-jwt</artifactid>
<version>4.23</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-maven-plugin</artifactid>
</plugin>
</plugins>
</build>
</project></pre>
</div>
</li>
<li>Dentro de la carpeta <span style="font-family: "courier new" , "courier" , monospace;"><i>src/maim/resources</i>,</span> en el archivo <i><span style="font-family: "courier new" , "courier" , monospace;">application.properties</span></i> ingrese los siguientes registros de <i>key = value</i>:<br /><br />
<div>
<pre class="brush: javascript">spring.security.user.name=pigbar
spring.security.user.password=1234
spring.main.allow-bean-definition-overriding=true
security.oauth2.resource.jwt.key-value=non-prod
</pre>
</div>
<br />
</li>
<li>En el <i>package</i> <i>org.pigbar.hal9k.oauth2.pop</i> cree los siguientes <i>sub-packages</i>:<br /><br /><i><span style="font-family: "courier new" , "courier" , monospace;">api<br />oauth.authorizationserver<br />oauth.resourceserver</span></i></li>
<li>Como el <span style="font-family: "courier new" , "courier" , monospace;"><i>Authorization</i> Server</span> debe retornar un <i><span style="font-family: "courier new" , "courier" , monospace;">JWT Token</span></i> cuando reciba una Token Request y la aplicación debe soportar la semantica de <i>Proof Of Possession</i>, sera necesario escribir una clase que implemente la interface <i><span style="font-family: "courier new" , "courier" , monospace;">TokenEnhancer</span></i>. Esta clase sera la responsable de extraer la la clave pública, <i><span style="font-family: "courier new" , "courier" , monospace;">Public Key</span></i>, enviada por el cliente en la fase de token request o solicitud de token. Esta clave pública sera usada como información adicional del <i><span style="font-family: "courier new" , "courier" , monospace;">JWT Token</span></i>.<br />Vamos a crear la clase <i><span style="font-family: "courier new" , "courier" , monospace;">PoPTokenEnhancer</span></i> como una implementación de la interface <i><span style="font-family: "courier new" , "courier" , monospace;">TokenEnhancer</span></i>, dentro del package <i><span style="font-family: "courier new" , "courier" , monospace;">oauth.authorizationserver</span></i>:<br /><br />
<div>
<pre class="brush: java">import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import java.util.HashMap;
import java.util.Map;
/**
* This class propagates the public_key sent by the PoP client request.
*/
class PoPTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(
OAuth2AccessToken accessToken,
OAuth2Authentication authentication) {
Map<String Object=""> additional = new HashMap<>();
String publicKey = authentication.getOAuth2Request().getRequestParameters().get("public_key");
additional.put("public_key", publicKey);
DefaultOAuth2AccessToken defaultAccessToken = (DefaultOAuth2AccessToken) accessToken;
defaultAccessToken.setAdditionalInformation(additional);
return accessToken;
}
}
</pre>
</div>
</li>
<li> Para evitar la duplicación de datos, creamos una clase que se encargue de remover el atributo sobrante <i><span style="font-family: "courier new" , "courier" , monospace;">public_key</span></i> del tohen de respuesta en una solicitud de token. En el mismo paquete anterior creamos la siguiente clase:<br /><br />
<div>
<pre class="brush: java">import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
public class CleanTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
accessToken.getAdditionalInformation().remove("public_key");
return accessToken;
}
}
</pre>
</div>
</li>
<li> Es hora de crear la clase encargada de configurar el <i><span style="font-family: "courier new" , "courier" , monospace;">Authorization Server</span></i>. En el mismo package creamos la siguiente clase:<br /><br />
<div>
<pre class="brush: java">import java.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("non-prod");
return converter;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain chain = new TokenEnhancerChain();
chain.setTokenEnhancers(
Arrays.asList(new PoPTokenEnhancer(), accessTokenConverter(), new CleanTokenEnhancer()));
endpoints.tokenEnhancer(chain);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("clientapp").secret("{noop}123456").scopes("read_profile")
.authorizedGrantTypes("authorization_code");
}
}
</pre>
</div>
<br /><br />Preste atención al detalle del código:<br /><br />
<div>
<pre class="brush: java">clients.inMemory().withClient("clientapp").secret("{noop}123456").scopes("read_profile")
</pre>
</div>
<br />Donde el fragmento "<i><span style="font-family: "courier new" , "courier" , monospace;">{noop}</span></i>" se agrega para especificar el password encoder, o su ausencia, para compatibilidad en spring security y evitar el conocido "<i><span style="font-family: "courier new" , "courier" , monospace;">Spring Boot PasswordEncoder Error</span></i>"</li>
<li>Listo, ya tenemos un <i><span style="font-family: "courier new" , "courier" , monospace;">Authorization Server </span></i>listo para proveer un <i><span style="font-family: "courier new" , "courier" , monospace;">JWT Token </span></i>con la <i><span style="font-family: "courier new" , "courier" , monospace;">public_key</span></i> requerida para que el cliente la pueda enviar al <i><span style="font-family: "courier new" , "courier" , monospace;">Resource Server</span></i> y este último pueda validar la <i><span style="font-family: "courier new" , "courier" , monospace;">POP</span></i>.</li>
<li>Dicho esto es momento de empezar a codificar nuestro <i><span style="font-family: "courier new" , "courier" , monospace;">Resource Server</span></i>. Primero vamos a crear una implementación de la interface <i><span style="font-family: "courier new" , "courier" , monospace;">Authentication</span></i>, la cual sera, de hecho, un decorador de una implementación existente. Esta implementación tiene por objeto manejar el atributo <i><span style="font-family: "courier new" , "courier" , monospace;">nonce</span></i>, el cual es usado como el valor generado que debe ser firmado por el servidor y el cliente. En el package <i><span style="font-family: "courier new" , "courier" , monospace;">oauth.resourceserver</span></i>, vamos a crear la siguiente clase:<br /><br />
<div>
<pre class="brush: java">import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
public class PoPAuthenticationToken implements Authentication {
private Authentication authentication;
private String nonce;
public PoPAuthenticationToken(Authentication authentication) {
this.authentication = authentication;
}
public void setNonce(String nonce) {
this.nonce = nonce;
}
public String getNonce() {
return nonce;
}
@Override
public Collection getAuthorities() {
return authentication.getAuthorities();
}
@Override
public Object getCredentials() {
return authentication.getCredentials();
}
@Override
public Object getDetails() {
return authentication.getDetails();
}
@Override
public Object getPrincipal() {
return authentication.getPrincipal();
}
@Override
public boolean isAuthenticated() {
return authentication.isAuthenticated();
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
authentication.setAuthenticated(isAuthenticated);
}
@Override
public String getName() {
return authentication.getName();
}
}
</pre>
</div>
</li>
<li> Es momento de escribir la clase <i><span style="font-family: "courier new" , "courier" , monospace;">PoPTokenExtractor</span></i>, la cual se va a encargar de crear una instancia de <i><span style="font-family: "courier new" , "courier" , monospace;">PoPAuthenticationToken</span></i> y le establece en el <i><span style="font-family: "courier new" , "courier" , monospace;">Header</span></i> el valor adecuado del atributo <i><span style="font-family: "courier new" , "courier" , monospace;">nonce</span></i>.<br /><br />
<div>
<pre class="brush: java">import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.authentication.TokenExtractor;
import javax.servlet.http.HttpServletRequest;
public class PoPTokenExtractor implements TokenExtractor {
private TokenExtractor delegate;
public PoPTokenExtractor(TokenExtractor delegate) {
this.delegate = delegate;
}
@Override
public Authentication extract(HttpServletRequest request) {
Authentication authentication = delegate.extract(request);
if (authentication != null) {
PoPAuthenticationToken popAuthenticationToken = new PoPAuthenticationToken(authentication);
popAuthenticationToken.setNonce(request.getHeader("nonce"));
return popAuthenticationToken;
}
return authentication;
}
}
</pre>
</div>
<br /> </li>
<li>Como estamos usando atributos particulares propios, es necesario entonces que el proceso de Autorización sea personalizado. Es por ello que en el mismo package anterior vamos a crear la clase siguiente:<br /><br />
<div>
<pre class="brush: java">import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTParser;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
public class PoPAuthenticationManager implements AuthenticationManager {
private AuthenticationManager authenticationManager;
public PoPAuthenticationManager(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
Authentication authenticationResult = authenticationManager
.authenticate(authentication);
if (authenticationResult.isAuthenticated()) {
// validates nonce because JWT is already valid
if (authentication instanceof PoPAuthenticationToken) {
PoPAuthenticationToken popAuthentication = (PoPAuthenticationToken) authentication;
// starts validating nonce here
String nonce = popAuthentication.getNonce();
if (nonce == null) {
throw new UnapprovedClientAuthenticationException(
"This request does not have a valid signed nonce");
}
String token = (String) popAuthentication.getPrincipal();
System.out.println("access token:" + token);
try {
JWT jwt = JWTParser.parse(token);
String publicKey = jwt.getJWTClaimsSet().getClaim("public_key").toString();
JWK jwk = JWK.parse(publicKey);
JWSObject jwsNonce = JWSObject.parse(nonce);
JWSVerifier verifier = new RSASSAVerifier((RSAKey) jwk);
if (!jwsNonce.verify(verifier)) {
throw new InvalidTokenException("Client hasn't possession of given token");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
return authenticationResult;
}
}
</pre>
</div>
</li>
<li>Ahora si, vamos a crear la clase <i><span style="font-family: "courier new" , "courier" , monospace;">OAuth2ResourceServer</span></i>, la cual estará a cargo de la configuración del <i><span style="font-family: "courier new" , "courier" , monospace;">Resource Server</span></i>:<br /><br />
<div>
<pre class="brush: java">import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.jwt.crypto.sign.MacSigner;
import org.springframework.security.jwt.crypto.sign.SignatureVerifier;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
@Configuration
@EnableResourceServer
public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter {
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore());
return tokenServices;
}
@Bean
public TokenStore tokenStore() {
JwtTokenStore tokenStore = new JwtTokenStore(accessTokenConverter());
return tokenStore;
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setVerifier(verifier());
converter.setSigningKey("non-prod");
return converter;
}
@Bean
public SignatureVerifier verifier() {
return new MacSigner("non-prod");
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenExtractor(new PoPTokenExtractor(new BearerTokenExtractor()));
OAuth2AuthenticationManager oauth = new OAuth2AuthenticationManager();
oauth.setTokenServices(tokenServices());
resources.authenticationManager(new PoPAuthenticationManager(oauth));
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().requestMatchers().antMatchers("/api/**");
}
}
</pre>
</div>
</li>
<li>Como nuestro <i><span style="font-family: "courier new" , "courier" , monospace;">OAuth Provider</span></i> es también nuestro<i><span style="font-family: "courier new" , "courier" , monospace;"> Authorization Server</span></i> y nuestro <i><span style="font-family: "courier new" , "courier" , monospace;">Resource Server</span></i>, ahora crearemos una <i><span style="font-family: "courier new" , "courier" , monospace;">API REST </span></i>para que sea consumida desde un Cliente <i><span style="font-family: "courier new" , "courier" , monospace;">OAUTH 2.0</span></i>. Así que vayamos al package <i><span style="font-family: "courier new" , "courier" , monospace;">api</span></i> y creemos la siguiente clase:<br /><br />
<div>
<pre class="brush: java">import org.springframework.http.ResponseEntity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {
@RequestMapping("/api/profile")
public ResponseEntity<UserProfile< myProfile() {
String username = (String) SecurgtyContextHolder.getContext()
.getAuthentication().getPrincipal();
String email = username + "@mailinator.com";
UserProfile profile = new UserProfile(username, email);
return ResponseEntity.ok(profile);
}
public static class UserProfile {
private String name;
private String email;
public UserProfile(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
}
}
</pre>
</div>
</li>
<li>Para finalizar, debemos crear una clase encargada de establecer la configuración de acceso al servidor y sus recursos. En el mismo package, <i><span style="font-family: "courier new" , "courier" , monospace;">api</span></i>, creemos la proxima clase:<br /><br />
<div>
<pre class="brush: java">import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().permitAll().and().authorizeRequests().antMatchers("/", "/oauth/**").authenticated()
.anyRequest().authenticated();
}
}</pre>
</div>
</li>
</ol>
<br />
Para poder probar nuestro <i>Provider</i>, debemos ejecutar nuestra aplicación de <i>Spring Boot </i>y usar un cliente adecuado.
Nuestra siguiente publicación cubrirá la creación de ese cliente de <i>OAUTH 2.0</i>.
<br />
<br /></div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-80752371463029960242017-07-11T23:17:00.000-07:002017-07-12T20:52:18.570-07:00Abandone toda esperanza quien entre aquí<div dir="ltr" style="text-align: left;" trbidi="on">
Ese era el "slogan" o frase motivacional de nuestra gerencia de desarrollo en INSISTO.<br />
<br />
Como podrán apreciar, mi gerencia tenía fama de ser áspera, directa, dura, elitista y dictatorial. No apta para pusilánimes. La gerencia "Hitler" le decían. De hecho, cuando alguien se quejaba de sus condiciones de trabajo o de sus tareas, era enviado a pasar unos meses bajo mi tutela en la gerencia de desarrollos, para que la <strike>víctima</strike> persona supiera cuan feliz y fácil era su vida y no lo sabía.<br />
<br />
Eran tiempos mas honestos.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0g8TBbumiW8ESiIJ2sUai2v-v8rFtmLHsGQKPBuOGWuIW8993sqZ7doe_o5t5Dj31bkiThu9JBNN99Fp1JpJY0CC9KV-x78uY09eRtrO0c7uEQkiJ6p55UjgLN5DskV2dLdcUxqriDQc/s1600/abandone_esperanza.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="360" data-original-width="480" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0g8TBbumiW8ESiIJ2sUai2v-v8rFtmLHsGQKPBuOGWuIW8993sqZ7doe_o5t5Dj31bkiThu9JBNN99Fp1JpJY0CC9KV-x78uY09eRtrO0c7uEQkiJ6p55UjgLN5DskV2dLdcUxqriDQc/s320/abandone_esperanza.jpg" width="320" /></a></div>
<a name='more'></a><br />
Nos decíamos las cosas con claridad y directamente. Sin pelos en la lengua, sin adornos. En fin, sin mucho cuidado de los modos y con énfasis en el fondo, en el qué y en el porqué de las cosas. Como adultos, como hombres y seres humanos inteligentes.<br />
<br />
No era preocupación ni prioridad la felicidad, la paz y el amor. La productividad, el ingenio, la inteligencia, la eficacia y la eficiencia eran nuestras prioridades. Todo se cuestionaba hasta que se llegaba a una decisión final, esta última a cargo de un responsable establecido. Las reglas eran claras.<br />
<br />
Cada uno tenía uno o mas roles claros. Cada uno era responsable de su trabajo.<br />
<br />
No creía, y aun no creo, en programadores felices. Si alguien esta muy, pero muy feliz y relax es porque no esta haciendo su trabajo. Sencillamente no puede ser que TOOODOOO le este saliendo bien. Programar es resolver problemas, y para resolver problemas se pasa mas de una rabieta, lo que amerita un regular gesto o frase de sano desagrado e incomodidad, para que luego venga el merecido eureka de la victoria.<br />
<br />
A mi como gerente, y nosotros como empresa, nos valía un cuerno quien era Ud. Nos importaba que, más que Ud mismo, fuera quien necesitábamos que fuera y como necesitábamos que fuera. Así de simple. No era requerido ser "humilde" ni modesto. Requeríamos en cambio que fuera jodidamente bueno en su trabajo. Competente e inteligente. Ni siquiera nos teníamos que agradar. Bastaba con que pudiéramos trabajar bien y realizar una sana competencia y aprendizaje.<br />
<br />
Tiempos mas civilizados.<br />
<br />
Ahora.... ahora somos vistos como unos monstruos. Unos tiranos. Unos psicópatas que traumaban a sus desarrolladores y empleados.<br />
<br />
En el nuevo management se espera brindar felicidad, paz y armonía. Igualdad a toda costa, incluso forzada y por encima de la justicia.<br />
<br />
Mucho cuidado con ofender a alguien. Nadie puede sentirse ofendido, molesto o incomodo por motivo alguno. No existen minorías ni diferencias.<br />
<br />
Todos tienen que estar de acuerdo. Hay que ser open-mind, light, tolerante y permisivo, y sentirse orgulloso de serlo. En este nuevo management entender es aceptar. Mucho cuidado con disentir o no estar de acuerdo.<br />
<br />
Se debe abundar en eufemismos, nada de verdades directas y crudas. Nada de cagadas, fallas y errores, nada de eso. Lo de moda son puntos de mejora, motivos de superación, sugerencias a tener en cuenta, y otra sarta de frases melosas por el estilo.<br />
<br />
El "respeto" a las opiniones,<strike> que no a las personas</strike>, es la norma. Nada de reglas lógicas y duras. Todo debe ser suave, ligero, plumoso y dulce. Todo es aceptable. Nada es cuestionable. Recuérdelo.<br />
<br />
Nada de conflictos. Nada de discusiones honestas. Nada de argumentos inteligentes y con fundamento. No. Todo debe ser un montón de puntos comunes, una suerte de naderías acordadas, todo políticamente correcto y bendecido.<br />
<br />
Ni piense en poner objetivos demandantes, presionar y exigir al equipo. No señor. Todo debe ser un por favor, un querer, un nacer, una voluntad, un sueño en proceso, un camino de rosas, el paraíso pues.<br />
<br />
Nada de darle zapatazos a la gente. Que eso es de trogloditas y brutos. Conduzca a sus <strike>hijos</strike> <strike>esclavos</strike> desarrolladores por un camino de armonía, de paz interior, de superación rosa, que sean fuentes de luz, siempre protegidos, resguardados y bien cuidados. Hábleles bonito, suavecito, despacito como dice la <strike>maldita</strike> canción, resalte puras bondades, algo menos que genial es inaceptable, todos son grandiosos y merecedores de halagos, pompas y platillos. Todos líderes y emprendedores, visionarios y maravillosos.<br />
<br />
No es bien visto el buscar culpables y señalar responsables cuando las cosas vayan mal. Ahora es un todo, un equipo, un trabajo en conjunto, una fuerza unida, una familia bella y grande donde todos, <strike>y por lo tanto nadie</strike>, somos responsables y felices. ¿Poner el dedo en la llaga? ni sueñe. Todo debe ser bypass, tangencial, rebuscado, refinado, pre-digerido y auto-censurado.<br />
<br />
Olvídese de pretender despedir a alguien por incompetencia. Nada más inapropiado. Invierta miles de horas hombres y recursos y búsquele al <strike>inepto</strike> empleado un lugar donde destacar y auméntele el salario, que bien se lo merece por el esfuerzo. Que lindo.<br />
<br />
Ya habrá entendido que se debe premiar el esfuerzo. Nada de resultados y objetivos. El esfuerzo y la intensión es lo que vale.<br />
<br />
Abunde en retiros espirituales, celebraciones sociales, festejos, adornos, reuniones y demás florituras de carácter netamente social. No amargue a sus <strike>esclavos</strike> empleados con asuntos laborales ni con planes de proyectos que nadie quiere seguir. La felicidad del equipo es lo primero.<br />
<br />
Haga eco de cuanta frase de moda encuentre. Hable de personalidades, mencione al famoso Steve Jobs mínimo tres veces por charla. No olvide a Bill Gates, a Cohelo, Beyonce, la foto del gatito de moda en internet y a cuanto guru temporal se aparezca.<br />
<br />
Evangelice con los términos de moda. El "Agile" es lo máximo, ni hablar del Blockchain, IOT y cuanta verborrea contemporánea y que sea tendencia y esté calentita en el mercado exista. Un punto mas si es new-age, mágica y misteriosa. Olvídese de esos viejos métodos recontra probados y austeros. Use lo fashion. Esté en onda. Sea buena vibra. Relax.<br />
<br />
Siga todas esas normas y entenderá como se pasa de ser un equipo reconocido como "<i><b>Los Nucleares</b></i>" por su excelente desempeño, a ser conocido como "<i><b>Los Mulas de Siempre</b></i>" por tener cagada tras cagada. Perdón. Es la costumbre. Quise decir: Por tener los maravillosos miembros del equipo algunos puntos de mejora que fortalecer para alcanzar sus logros y los de esta gran familia que representamos.<br />
<br />
TARADOS!!!<br />
<br />
<br />
<br />
<br />
<br />
<br /></div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-76109981356278987722017-05-20T14:27:00.001-07:002017-11-19T10:01:38.608-08:00Getters y Setters grandes enemigos de la OOP<div dir="ltr" style="text-align: left;" trbidi="on">
Es mucho el artículo, publicación y blogs de , ¿supuestos?, entendidos en el tema que hablan sobre, o exponen el problema con, el uso o más bien ABUSO de los <i>Getters</i> y <i>Setters</i> en la programación orientada a objetos <i>(OOP).</i><br />
<br />
Es este un tema recurrente y para nada nuevo, no señor, de hecho viene dando vueltas en el entorno de desarrollos <i>OOP</i> desde hace un buen rato. Pero....<br />
<br />
<h4 style="text-align: left;">
¿Cuál es el gran problema con usar getters y setters?</h4>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWTE41vWLAPqEOZu3bhYZQEN5gyxO39EPZPO0IXId22yGzwhp1IwxAvKJvJpdF53_232OdVwEty8RwW5fND1Je1TlkM0GOzkhgnMGf-Q0Z1thoyqPbJ7C3ozDVkAhjHmeCyQf27l1yJ3I/s1600/800px-Frog_vivisection.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWTE41vWLAPqEOZu3bhYZQEN5gyxO39EPZPO0IXId22yGzwhp1IwxAvKJvJpdF53_232OdVwEty8RwW5fND1Je1TlkM0GOzkhgnMGf-Q0Z1thoyqPbJ7C3ozDVkAhjHmeCyQf27l1yJ3I/s320/800px-Frog_vivisection.jpg" width="286" /></a></div>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<a name='more'></a>Interesante pregunta...<br />
<br />
En principio no parece haber nada malo con ellos, los <i>getters</i> y <i>setters,</i> y muchas herramientas y <i>frameworks</i> promueven su uso, es más, existen cientos y miles de programas construidos con estos elementos y funcionan bastante bien.<br />
<br />
Sí funcionan ¿porqué cambiarlos?<br />
<br />
¿Que hace que cada cierto tiempo salga algún papanatas con ínfulas de sabio, como el autor, diciendo que el uso de estos recursos de programación debe ser evitado, abolido e incluso castigado!!!?<br />
<br />
Algo debe estar sucediendo para que se pretenda imponer <a href="http://pigbar-hal9k.blogspot.cl/p/los-principios-pigbar-para-la.html">reglas que eliminan de facto a estas formas de construcción</a>.<br />
<br />
Intentaré responder a estas cuestiones de la mejor manera.<br />
<br />
<h4 style="text-align: left;">
Vamos con un ejemplo...</h4>
Me gusta ver televisión a un volumen que se podría considerar alto, al menos para mi señora lo es, por lo cual frecuentemente me encuentro con la tarea de tener que ajustar el nivel del audio al volumen deseado. Esto último lo realizo o bien pulsando un botón o moviendo una perilla hasta que consigo el resultado esperado.<br />
<br />
Así de simple. Pulso un botón dispuesto para tal fin, o muevo un control con igual propósito. Recibo por lo general un <i>feedback</i> del nivel de volumen alcanzado tanto en forma numérica como el que llega a mis oídos. Y ya.<br />
<br />
No soy técnico en electrónica, ni tengo que serlo para operar un control remoto de un televisor u otro aparato cualquiera.<br />
<br />
Se imagina que para lograr usar el control remoto y subir o bajar el volumen de la Tv tuviera que hacer algo como lo siguiente:<br />
<br />
<ul style="text-align: left;">
<li>Obtener tarjeta de circuito electrónico.</li>
<li>Buscar chip de volumen.</li>
<li>Buscar condensador de potencia.</li>
<li>Almacenar carga.</li>
<li>Poner carga en circuito... </li>
</ul>
<br />
y listo... volumen modificado!!!<br />
<br />
¿Capta la diferencia?<br />
<br />
En el primer caso usamos el control remoto mediante el <i>"Contrato"</i> o <i>"Interface"</i> que el mismo nos expone para poder operar sobre el. Sin preocuparnos de cómo está construido ni cual es su estructura interna.<br />
<br />
En el segundo caso debemos ser consientes de cómo demonios está construido el control remoto, es más, debemos saber como funciona internamente, para poder lograr modificar el volumen del Tv.<br />
<br />
Ambos logran el mismo objetivo. Intrínsecamente y técnicamente hablando ninguna forma es incorrecta. El problema es que una de esas formas es totalmente insegura e inmantenible mientras que la otra es sencilla y protegida. Ud decide cual es cual.<br />
<br />
Y es esta última forma de trabajo la que promueven y permiten los <i>getters</i> y <i>setters.</i> Por eso son tan dañinos. Así de simple. Permiten hacer una <i><b>Vivisección</b></i> del objeto al que pertenecen, descubriendo sus componentes y estructuras internas y facilitando su modificación, alteración y reemplazo, lo cual no siempre resulta deseable, de hecho pocas veces lo es, y en general termina siendo una practica contraproducente.<br />
<br />
En vez de programar para una Abstracción, Contrato o Interface, los programadores actuales terminan PIDIENDO un montón de datos o estructuras a los objetos para ellos, los programadores, hacer el trabajo y modificar o actualizar el estado interno del objeto. Trabajan exactamente como se describe en el segundo ejemplo.<br />
<br />
Uno de estos supuestos desarrolladores orientados a objetos hacen un diseño o construcción como la siguiente:<br />
<br />
<div>
<pre class="brush: java"> public classs ControlRemoto{
private Integer volumen;
public Integer getVolumen(){
return volumen;
}
public void setVolumen(Integer volumenNuevo){
volumen= volumenNuevo;
}
}
public class VolumenUtil{
public static void subirVolumen(ControlRemoto control){
control.setVolumen(control.getVolumen() + 1);
}
public static void bajarVolumen(ControlRemoto control){
control.setVolumen(control.getVolumen() - 1);
}
}
public class Tester{
public static void main(String[] args){
ControlRemoto myControl = new ControlRemoto();
myControl.setVolumen(40);
System.out.println("Volumen actual : " + myControl.getVolumen());
VolumenUtil.subirVolumen(myControl);
VolumenUtil.subirVolumen(myControl);
VolumenUtil.bajarVolumen(myControl);
System.out.println("Volumen final : " + myControl.getVolumen());
}
}
</pre>
</div>
<br />
Admítalo, Ud ha visto, y seguramente hasta ha escrito, código como ese. Usando clases <i>"utilitarias"</i> y pidiéndole datos al objeto para Ud hacer el trabajo. Para Ud estar bajo control.<br />
<br />
¿Ve como se expone la construcción interna del objeto?<br />
¿Ve como desde afuera se puede cambiar el estado del objeto <i>ControlRemoto</i> desde cualquier parte del sistema?<br />
<br />
Esto implica que, en un ambiente <i>multihilos</i> y distribuido, nunca podríamos confiar en los objetos ControlRemoto, por que cualquiera, desde cualquier parte del programa, podría cambiar su estado en forma arbitraria, sin que los objetos <i>ControlRemoto</i> tengan control ni conocimiento sobre ello, y eso es <b>FATAL.</b> Es <b>BASURA.</b> Eso es peor que la programación procedimental.<br />
<br />
Digamos ahora que Ud Cree haber entendido el problema y propone, inocentemente, el código siguiente como alternativa o mejor solución al anterior:<br />
<br />
<br />
<br />
<div>
<pre class="brush: java"> public classs ControlRemoto{
private Integer volumen;
public ControlRemoto(Integer volumen){
this.volumen = volumen;
}
public Integer subirVolumen(){
return ++volumen;
}
public Integer bajarVolumen(){
return --volumen;
}
public Integer getVolumen(){
return volumen;
}
}
public class Tester{
public static void main(String[] args){
ControlRemoto myControl = new ControlRemoto(40);
System.out.println("Volumen actual : " + myControl.getVolumen());
myControl.subirVolumen();
myControl.subirVolumen();
myControl.bajarVolumen();
System.out.println("Volumen final : " + myControl.getVolumen());
}
}
</pre>
</div>
<br />
Y esta ya es una gran mejora en verdad sobre la propuesta anterior. No obstante, imaginemos que pasaría si en la clase <i>Tester</i> hiciéramos algo como lo siguiente:<br />
<br />
<div>
<pre class="brush: java"> Integer vol = myControl.getVolumen();</pre>
<pre class="brush: java"> vol += 40; </pre>
<pre class="brush: java"> System.out.println("Volumen actual : " + myControl.getVolumen());
</pre>
</div>
<br />
¿Cuál sería el resultado impreso? ¿Se alteró el valor de la propiedad <i>"volumen"</i>?<br />
De ser así, ¿Cómo evitamos este efecto no deseado?<br />
<br />
Es por ello que los objetos deben ser lo mayormente inmutables que sea posible.<br />
Internamente necesito que la propiedad volumen pueda ser modificada. Pero es mi deber garantizar que desde afuera de la clase no puedan cambiarla o alterarla.<br />
<br />
Propongamos entonces una nueva versión de la clase <i>CotrolRemoto</i>:<br />
<br />
<div>
<pre class="brush: java"> public classs ControlRemoto{
private Integer volumen;
public ControlRemoto(Integer volumen){
this.volumen = volumen;
}
public Integer subirVolumen(){
return ++volumen.clone();
}
public Integer bajarVolumen(){
return --volumen.clone();
}
public Integer getVolumen(){
return volumen.clone();
}
}
public class Tester{
public static void main(String[] args){
ControlRemoto myControl = new ControlRemoto(40);
System.out.println("Volumen actual : " + myControl.getVolumen());
myControl.subirVolumen();
myControl.subirVolumen();
myControl.bajarVolumen();</pre>
<pre class="brush: java"> Integer vol= myControl.getVolumen();</pre>
<pre class="brush: java"> vol+= 50;</pre>
<pre class="brush: java"> System.out.println("Volumen final : " + myControl.getVolumen());
}
}
</pre>
</div>
<br />
Las pruebas se las dejo en manos de Uds.<br />
<br />
Los <i>getter</i> y <i>setter, </i>su uso y abuso, son los que han provocado comentarios como el de quien dijo que:<br />
<br />
<blockquote class="tr_bq">
"Con la programación orientada a objetos se ha conseguido es un desastre, queríamos una <i>Banana,</i> pero lo que obtuvimos fue un <i><b>Gorila</b></i> sosteniendo una <b><i>Banana</i></b> y la <i><b>Jungla ENTERA</b></i>!!!".</blockquote>
<br />
Recuerde, dígale al objeto QUE hacer y dele los elementos para hacerlo. NO le pida datos al objeto para Ud hacer el trabajo. Sea flojo, mandon e inteligente al mismo tiempo. Deje que los objetos trabajen para Ud.<br />
<br />
Espero sus comentarios y opiniones.</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com1tag:blogger.com,1999:blog-1012161132404905800.post-25418234951512752312017-05-14T12:48:00.000-07:002017-05-14T12:48:19.371-07:00Métodos Comunistas y Propiedades Capitalistas<div dir="ltr" style="text-align: left;" trbidi="on">
No, este no es un artículo sobre política, sigue siendo sobre programación orientada a objectos <i>(OOP), </i>específicamente sobre <i>métodos públicos</i> y <i>propiedades privadas</i>, de allí el título. <br />
<br />
Todo surge por un comentario que me hizo un querido amigo al leer mi publicación sobre l<a href="http://pigbar-hal9k.blogspot.cl/p/los-principios-pigbar-para-la.html">as reglas pigbar de programación</a>. El me comentó:<br />
<br />
"Mr. Bladi, entiendo sus reglas acerca de que las <i>propiedades</i> deban ser privadas por aquello del <i>encapsulamiento,</i> ¿pero que todos los <i>métodos</i> deban ser públicos? eso me cuesta entenderlo, eso implica que no existen <i>métodos</i> privados, y yo debo saber lo que un objeto hace sin preocuparme del cómo, por lo que esos <i>métodos</i> privados pueden ser útiles."<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg190EA48mguxJaxTa2m2IdFvy2w-tprsbW83ykTHuGNH_kwmWzKnpWFe2-IZPM0R6gx2uppGIrwoFYIY1JlYPXYkTmA4-5Cu5fOmZgFXq11DVoR-dbHjZeuB8qYR6NWQq-5Jj_I8eiA5E/s1600/rocky-iv-.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="176" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg190EA48mguxJaxTa2m2IdFvy2w-tprsbW83ykTHuGNH_kwmWzKnpWFe2-IZPM0R6gx2uppGIrwoFYIY1JlYPXYkTmA4-5Cu5fOmZgFXq11DVoR-dbHjZeuB8qYR6NWQq-5Jj_I8eiA5E/s320/rocky-iv-.jpg" width="320" /></a></div>
<br />
<a name='more'></a>... largo es el camino del aprendizaje ... pensé ... jajaja<br /><br />
y procedí a explicarle.<br />
<br />
Le dije:<br />
Tienes razón y estás equivocado. Todo al mismo tiempo como el gato de schrödinger.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmldaZpxSu2knx2jhvI3P3hCtRa9K_-sX1DEIfEMDuYXJjSaUY3rYZGc6-lHJxC5uNC4k_G-AcekwkF6vofDmh-koD7XJC0NLkTsWdWza8gCL8RhDd88vj3ZeFxfw6a6zun-EESdUqOAs/s1600/schr%25C3%25B6dinger_cat.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmldaZpxSu2knx2jhvI3P3hCtRa9K_-sX1DEIfEMDuYXJjSaUY3rYZGc6-lHJxC5uNC4k_G-AcekwkF6vofDmh-koD7XJC0NLkTsWdWza8gCL8RhDd88vj3ZeFxfw6a6zun-EESdUqOAs/s320/schr%25C3%25B6dinger_cat.gif" width="320" /></a></div>
<br />
Tienes razón porque el concepto de encapsulamiento implica que se guarda o encapsulan tanto las propiedades como los métodos en una clase, escondiendo los detalles de la implementación, y eso está súper bien.<br />
<br />
Pero, y siempre hay un pero, estás equivocado por que el problema con los <i>métodos</i> privados es que esa funcionalidad que escondes dentro de las entrañas inescrutables de un <i>método</i> privado, no puede ser compartida por otras clases o partes del programa. En otras palabras, sí necesitas o llegas a necesitar que ese comportamiento se realice en otra parte del sistema, vas a tener que recurrir a algunos recursos poco recomendados como son el tristemente celebre <i>Copy & Paste</i> o recurrir a librerías con <i>clases utilitarias</i>, las cuales también son poco recomendadas y <a href="http://pigbar-hal9k.blogspot.cl/2017/05/historia-de-una-conversa-sobre-oop.html">las considero ofensivas en la <i>OOP</i></a>.<br />
<br />
¿Me explico?<br />
<br />
Por otra parte ese comportamiento, funcionalidad o utilidad del <i>método</i> escrito en forma privada, no forma parte de ningún contrato por el que deba trabajar la clase, no forma parte de ninguna <i>interface</i>, por lo que no podemos trabajarlo usando ese valioso y sagrado mecanismo de programar para una abstracción, para una interface o para un contrato.<br />
<br />
La única forma de acceder esa funcionalidad es dentro de la clase misma donde nunca podrá ser compartida y, en mi experiencia, en la programación de sistemas no conozco aún una funcionalidad tan peculiar, tan única en si misma, que no merezca ni pueda ser compartida o generalizada dentro de una abstracción.<br />
<br />
De acá se desprende el axioma: Todo método privado, TODOS; son candidatos a una abstracción, a una nueva clase, y deben ser migrados a esa abstracción. <br />
<br />
Es por ello que impongo férreamente , con disciplina dura, el uso de los antes mencionados principios en lo referente a la visibilidad de <i>propiedades</i> y <i>métodos</i>. <br />
<br />
Por su parte, las propiedades deber ser privadas y en lo posible nunca expuestas al mundo exterior. Ellas forman parte del estado del objeto y son sus elementos mas sagrados. Con ello quiero reflejar que <a href="http://www.yegor256.com/2014/06/09/objects-should-be-immutable.html">todos los objetos deberían ser inmutables</a> para proteger al sistema de las consecuencias nefastas que derivan del control o gestión sobre los cambios de estados en las clases.<br />
<br />
Es por ello que manifiesto que no deben existir <i>setters</i>, que las propiedades deben ser <i>final</i> y que los <i>getters</i> no son recomendados. Todo sea por preservar la inmutabilidad de la clase, favorecer el <i>encapsulamiento</i> y el <i>ocultamiento</i> de la implementación y, por qué no, de la estructura interna del objeto.<br />
<br />
<br />
<br /></div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com2tag:blogger.com,1999:blog-1012161132404905800.post-11023983943866316952017-05-13T21:16:00.002-07:002017-05-13T22:33:32.905-07:00NULL debe morir<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="MsoNormal">
Uno de los grandes errores de la programación orientada a
objetos (<i>OOP</i>) con <i>Java </i>ha sido la
existencia de las referencias a <i>NULL</i>.<br />
Esta es la causa del popular y formidable error “<b><i><span style="background: white; color: #41423d; font-family: "tahoma" , "sans-serif"; font-size: 8.0pt; line-height: 115%;">java.lang</span></i></b><b><i><span style="background: white; color: #41423d; font-family: "tahoma" , "sans-serif"; font-size: 9.0pt; line-height: 115%;">.NullpointerException</span></i></b>”.
Toda una embrarrada.<br />
La existencia de este tipo de referencia es la causa de
muchos dolores de cabeza, de muchísimo código innecesario y defensivo, de
muchas malas prácticas y de una pésima filosofía de desarrollo.<o:p></o:p></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNGsCDHBZFj9xG68qtzLQAzzJyURvfVtVEt9kGedEq2QdQdadWoIwfXSsWJoAQZfb2f_cQ18LA_4sxTK6LFIjllLWa6sI4v_wsGpZx2KGOS_Pvk3P5Gj9BWhxGKj_VcJ7-IFfWhZAK_w4/s320/tdd-una-gua-de-supervivencia-22-728.jpg" width="320" /></div>
<div>
<br /></div>
<a name='more'></a><br />
<div class="MsoNormal">
<br /></div>
<div>
<span style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;">Las
referencias a <i>NULL</i> nunca debieron
existir, porque su abuso provoca código como el siguiente:</span><br />
<span style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;"><br /></span></div>
<div>
<pre class="brush: java">ProductHE product = deal.getProductHM();
PriceHEValue priceHE = null;
If (product ¡= null && product.getMortageRate() ¡= null && product.getMortageRate().getTaxRange() != null && product.getMortageRate().getTaxRange().getListPrices() != null && !product.getMortageRate().getTaxRange().getListPrices().isEmpty() && product.getMortageRate().getTaxRange().getListPrices().get(0) != null){
priceHE = product.getMortageRate().getTaxRange().getListPrices().get(0);
}
deal.getContratHE().setPrimaryProductPrice(priceHE);
</pre>
</div>
<div>
<br />
No sé por dónde empezar a decir <b>TODO </b>lo que está mal, que digo mal <b>PÉSIMO</b>, en este código.<br />
Y lo más triste, este código está basado en hechos reales, código real, algunos nombres fueron cambiados para proteger la identidad de los involucrados!! ;)<br />
<br />
¿Pueden creer que alguien se sintió inteligente al escribir esa basura?<br />
Aquí no estamos para ser políticamente correctos. Eso es basura duélale a quien le duela.<br />
<br />
<h4 style="text-align: left;">
Como dijo Hannibal Letcter, vamos por partes:
</h4>
<br />
<pre class="brush: java">ProductHE product = deal.getProductHM();
</pre>
<br />
¿Por qué demonios <i>getProductHM()</i> puede retornar un <i>NULL</i>?<br />
<br />
Desde allí empiezan nuestros problemas. Eso implica que no podemos confiar en el método. Que no podemos confiar en el objeto, que no podemos confiar en sus propiedades….<br />
Debemos ser defensivos al extremo, cuidadosos al trabajar con esos objetos miserables y estúpidos.<br />
<br />
¿No me cree? ¿Le parece que exagero? Mire lo que viene a continuación entonces:
<br />
<br />
<pre class="brush: java">If (product ¡= null && product.getMortageRate() ¡= null && product.getMortageRate().getTaxRange() != null && product.getMortageRate().getTaxRange().getListPrices() != null && !product.getMortageRate().getTaxRange().getListPrices().isEmpty() && product.getMortageRate().getTaxRange().getListPrices().get(0) != null)
</pre>
<br />
TODO ese código tiene el único propósito de evitar una <i><b>NullpointerException</b></i>; así de simple.<br />
No tiene otra sentido ni fundamento.<br />
Imagine un sistema enorme, en el que los módulos estén plagados de código por ese estilo. Esto ocurre porque no podemos confiar en nuestros objetos. Y eso es triste y terrible.<br />
<br />
Pero las cosas no terminan allí, no señor.<br />
Luego de todo ese dolor del orto, digo de cabeza, para evitar una <i><b>NullpointerException </b></i>resulta que procedemos a continuar con el programa asignando posibles referencias a <i>NULL</i>. Es decir, no aprendimos la lección.
<br />
<br />
<pre class="brush: java">deal.getContratHE().setPrimaryProductPrice(priceHE);
</pre>
<br />
A estas alturas <i>priceHE </i>aún puede ser <i>NULL </i>y la asignamos y usamos así felizmente ignorantes.<br />
Este código es tan malo, que ni siquiera tienen la decencia de trabajar los <i>NULL </i>con elegancia.<br />
<br />
Voy a poner un ejemplo en el que, aunque se usa <i>NULL </i>y eso sigue siendo un error, al menos lo hacen de un modo que no perjudica la legibilidad del código.
Imagine que dentro de la clase <i>ProductHE</i>, escribimos el siguiente método:
<br />
<br />
<pre class="brush: java">public final class ProductHE implements HEableProduct{
public PriceHEValue getPrimaryPrice(){
if (product.getMortageRate() == null) return null;
if (product.getMortageRate().getTaxRange() == null) return null;
if (product.getMortageRate().getTaxRange().getListPrices() == null) return null;
return product.getMortageRate().getTaxRange().getListPrices().get(0);
}
}
</pre>
<br />
El horroroso código anterior quedaría de la siguiente forma:<br />
<br />
<pre class="brush: java">ProductHE product = deal.getProductHM();
deal.getContratHE().setPrimaryProductPrice(product == null? null: product. getPrimaryPrice());
</pre>
<br />
¡Elegante! ¿No les parece?<br />
<br />
Vamos, admítalo. Esta última versión, aunque usa <i>NULL</i>, es mucho más fácil de leer, mantener e incluso usar.<br />
<br />
Todo el problema del código anterior, además de usar <i>NULL</i>, deriva de la desconfianza y del ego. Así es.<br />
<br />
Desconfianza en el objeto idiota que nos puede lanzar una horrible e indeseable <i><b>NullpointerException</b></i>, y con razón. Ego porque al considerar al objeto anémico y estúpido, en vez de dejar que el objeto, <i>product </i>en este caso, trabaje para nosotros y haga el esfuerzo y tareas para las que debería haber sido diseñado, nosotros en nuestra “<i>grandeza</i>” optamos por pedirle un montón de datos al objeto para hacer todo el trabajo, cálculos y validaciones por nuestra cuenta, lo cual es una muy mala práctica en la <i>OOP </i>en general.<br />
Esto rompe <a href="http://pigbar-hal9k.blogspot.com/p/los-principios-pigbar-para-la.html">las reglas pigbar de programación</a>.<br />
<br />
Volviendo al tema central de esta publicación, sí no debemos usar <i>NULL </i>en todo nuestro código<br />
<br />
<h4 style="text-align: left;">
¿Qué opciones tenemos?</h4>
<br />
-- 100 dólares y se los digo. Ok, Ok, sigamos sin cobrar…<br />
<br />
Como siempre, tenemos un grupo de opciones que podemos usar.<br />
En este caso vamos a ver dos de ellas. Una es el principio de <i>Fail Fast – Fail a Lot</i>, lo cual quiere decir que lancemos excepciones tan pronto y tan frecuentemente como lo necesitemos.<br />
<br />
La otra es usar los <i>NULL-Objects</i>, que no es más que una implementación de los objetos diseñada para fallar cuando se intenten hacer cosas para las que no tiene permiso o simplemente no puede hacerlas, representa un objeto no válido del todo.<br />
<br />
Nuestro ejemplo anterior podría ahora lucir de esta forma:
<br />
<br />
<pre class="brush: java">public final class ProductHE implements HEableProduct{
public PriceHEValue getPrimaryPrice(){
try{
return product.getMortageRate().getTaxRange().getListPrices().get(0);
} catch(NoValidObjectException e){
return new NullPriceHEValue();
}
}
}
// lo usamos…
deal.getContratHE().setPrimaryProductPrice(deal.getProductHM(). getPrimaryPrice());
</pre>
<br />
Donde <i>NullPriceHEValue </i>es la implementación <i>NULL </i>de la interface de <i>PriceHEValue </i>y <i>NoValidObjectException </i> no es más que una excepción personalizada lanzada por alguna de las implementaciones nulas del código, por los <i>NULL-Objects</i>.<br />
<br />
Vea que los métodos lanzan excepciones y retornan implementaciones para <i>NULL-Object</i> según nos convenga.
Recuerde, o lanzamos una excepción temprana o retornamos un <i>NULL-Object</i>.<br />
<br />
Veamos otro ejemplo un poquito más largo, favor seguir con atención las declaraciones e implementaciones. Algunos comentarios están en ingles en favor de la internacionalización del código:
<br />
<br />
<div>
<pre class="brush: java">
//interfaces
public interface Product{
public String name();
public HEPrice priceHE();
}
public interface Products{
public Product findById(int id);
public Product add(Product product);
public Iterator<Product> products();
}
public interface HEprice{
public String type();
public BigDecimal rate();
}
// pigbar rules implementations!! YEAH!!
//product states
public final class ProductNormalState implements Product{
private final String name;
private final HEPrice priceHE;
public ProductNormalState(String name, HEPrice priceHE){
this.name = name;
this.priceHE = priceHE;
}
public String name(){
return name;
}
public HEPrice priceHE(){
return priceHE;
}
}
//product null state
public final class ProductNullState implements Product{
// just for discipline
public ProductNullState (){
}
// in the case our logic permit an invalid name else throw a NullProductException
public String name(){
return “Invalid Product”;
}
// depending on the logic can throw an exception or return a HEPriceNullState object
public HEPrice priceHE(){
throw new NullProductException(“Null Product, cannot have a priceHE”);
}
}
// products
// product not validation
Public final class ProductsNoValidation implements Products{
private final ArrayList<Product> products;
public ProductsNoValidation(){
this(new ArrayList());
}
public ProductsNoValidation(ArrayList<Product> products){
this.products = products;
}
public Product findById(int id){
if (id <= 0) return new ProductNullState();
return new ProductNormalState(“Product-” + System.currentTimeMillis(),
new HEPriceNormalState(“Type-” + + System.currentTimeMillis(),
new BigDecimal(System.currentTimeMillis())));
}
public Product add(Product product){
this.products.add(product);
return product;
}
public Iterator<Product> products(){
return products.iterator();
}
}
// products with validation, a Decorator for Products, nice!! This allow to decorate with many validatios
Public final class ProductsWithValidation implements Products{
private final Products products;
public ProductsWithValidation(){
this(new ProductsNoValidation ());
}
public ProductsWithValidation(Products products){
this.products = products;
}
public Product findById(int id){
// just a validation for some id’s values
if (id >= 10) throw new InvalidParameterException(“Invalid Id for fin a Product, value : ” + id);
return products.findById(id);
}
public Product add(Product product){
if (product.name().equalsIgnoreCase(“INVALID PRODUCT”))
throw new InvalidParameterException(“Are you serious? Adding an Invalid Product!!”);
return products.add(product);
}
public Iterator<Product> products(){
return products.products();
}
}
// HEPrice implementations, the normal state
public class HEPriceNormalState implements HEPrice{
private final String type;
private final BigDecimal rate;
public HEPriceNormalState(String type, BigDecimal rate){
this.type = type;
this.rate = rate;
}
public String type(){
return type;
}
public BigDecimal rate(){
return rate;
}
}
// HEPrice null state, not used but nice to see the implementation
public class HEPriceNullState implements HEPrice{
public HEPriceNullState(){
}
public String type(){
throw new HEPriceNullException(“Null HEPrice cannot have a valid type”);
}
public BigDecimal rate(){
throw new HEPriceNullException(“Null HEPrice cannot have a valid rate”);
}
}
// now the tester…
public final class Tester{
public static void main(String[] args){
new Tester().doTest();
}
public void doTest(){
final Products products = new ProductsWithValidation(new ProductsNoValidation());
Product productTmp;
for (int id= -1; id <= 11; id++){
try{
productTmp = products.findById(id);
showProduct(productTmp);
products.add(product);
} catch(Exception e){
Logger.getLogger(“Tester.doTest”).severe(“Error testing produc when Id : “ + id + ”, with message : ” + e.getMessage());
}
}
showProductsRate(products);
}
public void showProduct(Product productTmp){
try{
System.out.println(“Product name : ” + productTmp.name());
System.out.println(“Product price type : ” + productTmp.priceHE ().type());
} catch(Exception e){
Logger.getLogger(“Tester. showProduct”).severe(“Error showin produc with message : ” + e.getMessage());
}
}
public void showProductsRate(Products products){
while(products.products().hasNext()) {
Product product = products.products().next();
System.out.println(“Product name : ” + productTmp.name());
System.out.println(“Product price rate : ” + productTmp.priceHE ().rate());
}
}
}</pre>
</div>
<br />
Uff…. Código largo pero interesante.<br />
Obviamente ese fue un ejemplo incompleto, pues faltan algunas <i>Excepciones </i>por declarar y algunos <i>thows </i>en los métodos. Lo dejo así para limpieza del ejemplo.<br />
<br />
Pero ya puede ver la idea del manejo de <i>NULL </i>en ese código.<br />
Simplemente: <b><i>NO USE NULL</i></b>. <i>Period</i>.<br />
<br />
Con estos principios ya no tenemos que desvelarnos pensando en cómo evitar las terribles <i><b>NullpointerException </b></i>y hacemos nuestro código más robusto y elegante.
<br />
<br /></div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-63044895704258560242017-05-09T20:48:00.000-07:002017-05-13T15:48:32.797-07:00Historia de una conversa sobre OOP<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Y luego de un largo rato volvemos por acá con una historia basada en hechos reales, sobre una conversación muy didáctica que tuve con un amigo:<br />
<br />
<div class="MsoNormal">
-Mr. Bladi, he escuchado que Ud. se opone, es más desprecia,
al uso de las clases Utilitarias y los métodos estáticos en la programación
orientada a objetos (OOP).<o:p></o:p></div>
<div class="MsoNormal">
-Ciertamente. No aconsejo su uso y lo considero una mala
práctica, algo ofensivo en la OOP.<o:p></o:p></div>
<div class="MsoNormal">
-Pero si no podemos usar clases utilitarias y métodos
estáticos, ¿Cuáles opciones Tenemos?<o:p></o:p></div>
<div class="MsoNormal">
-Tenemos unas cuantas opciones. Pero antes un poco de contexto.
Las clases utilitarias, esas que están repletas de métodos estáticos, no son
objetos reales, son un recurso totalmente procedimental y rompen el principio
de encapsulamiento en la OOP.<br />
Peor aún, las clases utilitarias con su torrente de métodos estáticos, son muy difíciles de testear en las pruebas automáticas. <br />
<o:p></o:p></div>
<br />
<div class="MsoNormal">
TODO MÉTODO ESTÁTICO, E INCLUSO LOS PRIVADOS, SON CANDIDATOS
PARA UNA NUEVA CLASE, es decir son elegibles para una nueva abstracción.<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwjmyGskD6ze3uCNpxlx0oE2G4afUvMwxuCCUabCEqV7jJb0AmePSm_LO9h1FrpuIgb3OoRKyj2vNh6xdaoTo44Bs1zWGD12phnce7maLKRKUHPoifd8g18t9aXdEvrZA2SXRGZxRSByk/s1600/peque%25C3%25B1osaltamontes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwjmyGskD6ze3uCNpxlx0oE2G4afUvMwxuCCUabCEqV7jJb0AmePSm_LO9h1FrpuIgb3OoRKyj2vNh6xdaoTo44Bs1zWGD12phnce7maLKRKUHPoifd8g18t9aXdEvrZA2SXRGZxRSByk/s320/peque%25C3%25B1osaltamontes.png" width="320" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<a name='more'></a><br />
<div class="MsoNormal">
Veamos un ejemplo…. Y como siempre nuestro grito de guerra:
Manos a las sobras!!!<o:p></o:p></div>
<div class="MsoNormal">
<span style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;">Supongamos que tenemos la usual clase:</span></div>
<div class="MsoNormal">
<span style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;"><br /></span></div>
</div>
<pre class="brush: java">public class MyMath {
public static double sumar(double a, double b) {
return a + b;
}
public static double restar(double a, double b) {
return a - b;
}
public static double multiplicar(double a, double b) {
return a * b;
}
public static double dividir(double a, double b) {
return a / b;
}
}
</pre>
<div class="MsoNormal">
<br />
La cual podemos y solemos utilizar del siguiente modo:<o:p></o:p><br />
<br /></div>
</div>
<pre class="brush: java">double result = MyMath.sumar(2.0, 3.0);
System.out.println(“result = “ + result);
System.out.println(“result * 3 + 2 = ” + (MyMath.sumar(MyMath.multiplicar(result, 3.0),2.0)));
</pre>
<br />
<div class="MsoNormal">
<h4 style="text-align: left;">
Primera implementación:</h4>
</div>
<span style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;">Haciendo un análisis podemos observar que tenemos una operación entre dos operadores numéricos, lo que se puede representar en una interface tal como:</span></div>
<pre class="brush: java">public interface Operacion{
public double ejecutar(double ope1, double ope2);
}
</pre>
<br />
Escribimos clases para cada implementación de Operacion que deseemos:
<br />
<br /></div>
<pre class="brush: java">public final class Sumar implements Operacion {
public double ejecutar(double ope1, double ope2){
return ope1 + ope2;
}
}
public final class Multiplicar implements Operacion {
public double ejecutar(double ope1, double ope2){
return ope1 * ope2;
}
}
</pre>
<br />
Y la podemos usar de la siguiente forma:
<br />
<br />
<pre class="brush: java">Operacion sumar = new Sumar();
Operacion multiplicar = new Multiplicar();
double result = sumar.ejecutar(2.0, 3.0);
System.out.println(“result = “ + result);
System.out.println(“result * 3 + 2 = ” + (sumar.ejecutar(multiplicar.ejecutar(result, 3.0),2.0)));
</pre>
<br /></div>
Como ven, nada de métodos estáticos y dejamos que los objetos trabajen para nosotros. Pero.... siempre hay un pero, esta implementación tampoco es del todo correcta. Según los <a href="http://pigbar-hal9k.blogspot.com/p/los-principios-pigbar-para-la.html" target="_blank">principios pigbar</a>, no deben existir clases con sólo métodos, así como no deben existir clases con sólo propiedades. Ambos casos son síntomas de un mal diseño.<br />
<br />
Así que mejoremos este enfoque.<br />
<br />
<h4 style="text-align: left;">
Segunda implementación: </h4>
Ahora la interface Operacion queda de la siguiente forma:<br />
<br />
<pre class="brush: java">public interface Operacion{
public double ejecutar();
}
</pre>
</div>
<br />
Mucho mas sencilla. Y ahora sus implementaciones:<br />
<br />
<pre class="brush: java">public final class Sumar implements Operacion {
private double ope1, ope2;
public Sumar(double ope1, double ope2){
this.ope1= ope1;
this.ope2= ope2;
}
public double ejecutar(){
return ope1 + ope2;
}
}
public final class Multiplicar implements Operacion {
private double ope1, ope2;
public Multiplicar(double ope1, double ope2){
this.ope1= ope1;
this.ope2= ope2;
}
public double ejecutar(){
return ope1 * ope2;
}
}
</pre>
<br />
Como ven, muy parecidas pero con grandes diferencias. Estos si son verdaderos objetos encapsulando comportamiento y datos.
Ahora los podemos usar de la siguiente forma:<br />
<br />
<pre class="brush: java">Operacion sumar = new Sumar(2.0, 3.0);
double result = sumar.ejecutar();
System.out.println(“result = “ + result);
System.out.println(“result * 3 + 2 = ” + (new Sumar(new Multiplicar(result, 3.0).ejecutar(),2.0).ejecutar()));
</pre>
<br />
Hemos dado un paso al frente en nuestra visión de la programación orientada a objetos. Pero aún lo podemos hacer de forma distinta...<br />
<br />
<h4 style="text-align: left;">
Tercera implementación:</h4>
<br />
Y… ¿Qué tal si hacemos esto más al estilo “Fluent”?
Pues veamos….
Vamos a crear una Interface Operable:
<br />
<br />
<pre class="brush: java">public interface Operable{
public double valor();
public Operable sumar(double operando);
public Operable multiplicar(double operando);
}
</pre>
<br />
E implementamos la Interface:
<br />
<br />
<pre class="brush: java">public final class Operando implements Operable{
private double valor;
public Operando(){
this(0.0);
}
public Operando(double number){
valor= number;
}
public double valor(){
return valor;
}
public Operable sumar(double operando){
return new Operando(this.valor + operando);
}
public Operable multiplicar(double operando) ){
return new Operando(this.valor * operando);
}
@overwrite
public String toString(){
return “” + valor;
}
}
</pre>
<br />
Ahora lo podemos usar escribiendo código como el siguiente:
<br />
<br />
<pre class="brush: java">Operando result = new Operando(2.0).sumar(3.0);
System.out.println(“result = “ + result);
System.out.println(“result * 3 + 2 = ” + result.multiplicar(3.0).sumar(2.0));
</pre>
<br />
Elegante, ¿no les parece?
Así que nada de excusas para clases utilitarias y métodos estáticos.<br />
<br />
-Mr. Bladi, cuando crezca quiero ser como Ud.<br />
-Lo serás mi pequeño saltamontes. Lo serás...
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com2tag:blogger.com,1999:blog-1012161132404905800.post-67325367326460672022016-12-07T13:59:00.004-08:002016-12-07T13:59:57.129-08:00Webinar sobre la notación BPMN 2.0 con Camunda Modeler<div dir="ltr" style="text-align: left;" trbidi="on">
<h1 style="color: #202020; display: block; font-family: Helvetica; font-size: 26px; font-style: normal; font-weight: bold; letter-spacing: normal; line-height: 125%; margin: 0; padding: 0; text-align: left;">
BPMN 2.0</h1>
Es el estándar para la representación de procesos de <em>BPM.</em> La implementación de<a href="https://camunda.org/" style="-ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; color: #2baadf; font-weight: normal; mso-line-height-rule: exactly; text-decoration: underline;" target="_blank"> Camunda BPM</a> es muy completa y nos presenta un editor o <em>"modeler"</em> muy poderoso y simple de usar.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrAdhTwHjOQVUDCwRErFqq4YzzKNA_WwExtFCAIWSTR0SWB6VZ9UPaP5vGDDVOxEtxsY4s1DCE1lXEyIs2FbilMVBNRSCddCHnqnTRVw-MLdsDqLkRUjQNd1LJRINdWK-Q_MPQJfdFr1M/s1600/camunda_modeler_bpmn.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrAdhTwHjOQVUDCwRErFqq4YzzKNA_WwExtFCAIWSTR0SWB6VZ9UPaP5vGDDVOxEtxsY4s1DCE1lXEyIs2FbilMVBNRSCddCHnqnTRVw-MLdsDqLkRUjQNd1LJRINdWK-Q_MPQJfdFr1M/s320/camunda_modeler_bpmn.png" width="320" /></a></div>
<br />
<br />
En este Webinar haremos una introducción a la notación <em>BPMN 2.0</em>, sus elementos más relevantes y su uso en un proceso de <em>BPM,</em> junto a algunas buenas prácticas de modelado de procesos.<br />
<br />
El Webinar se realizará el día Viernes 16 de Diciembre a partir de las 15:00 horas, en horario de Santiago de Chile.<br />
<br />
Haremos uso de la plataforma de transmisión en línea por <a href="http://www.youtube.com/" style="-ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; color: #2baadf; font-weight: normal; mso-line-height-rule: exactly; text-decoration: underline;" target="_blank">Youtube,</a> por lo que sólo debe acceder a la <a href="https://www.youtube.com/watch?v=MasRtcI7uA8" style="-ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; color: #2baadf; font-weight: normal; mso-line-height-rule: exactly; text-decoration: underline;" target="_blank">URL suministrada</a> para acceder al evento en la fecha y hora acordada.<br />
<br />
Url del evento: https://www.youtube.com/watch?v=MasRtcI7uA8<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/MasRtcI7uA8/default_live.jpg" src="https://www.youtube.com/embed/MasRtcI7uA8?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br />
<br />
Para mayor información sobre los primeros pasos con la plataforma de Camunda BPM los invito a visitar las publicaciones sobre los <a href="http://pigbar-hal9k.blogspot.cl/2016/11/primeros-pasos-con-camunda-bpm.html" target="_blank">Primeros pasos con <i>Camunda</i> <i>BPM</i></a> en este Blog.<br />
<br />
<br />
Hasta pronto </div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-1649112776744873422016-12-03T15:13:00.000-08:002016-12-03T15:13:29.311-08:00Integración de Liferay, BOS y Openxava en un Proceso BPMN de Compras<div dir="ltr" style="text-align: left;" trbidi="on">
Hoy hagamos la corta, como dicen en mi bello Santiago de Chile.<br />
Les dejo un video demostrativo de la integración de las siguientes herramientas:<br />
<br />
<i>Bonita Open Solution 5.5 (BOS)</i><br />
<i>Liferay CE 5.5</i><br />
<i>OpenXava 4.3</i><br />
<i>Alfresco CE 3.3</i><br />
<br />
Es una aplicación de proceso de compras públicas, donde podemos observar la lista de tareas, formularios de aplicación avanzados, integración con <i>Alfresco,</i> carga y visualización de documentos, cambio de roles en el proceso, entre muchas otras cosas.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /><iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/BT9SygHOhO4/0.jpg" src="https://www.youtube.com/embed/BT9SygHOhO4?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br />
<br />
<a name='more'></a><br /><br />
Los formularios, <i>portlets</i> fueron desarrollados íntegramente con <i>Openxava,</i> y se construyó un tema personalizado de <i>Liferay</i> para dar imagen corporativa a la aplicación.<br />
<br />
<i>Liferay</i> es el encargado de la gestión de usuarios y roles. Es la plataforma que brinda el marco para la capa de presentación de la aplicación.<br />
<br />
La comunicación con el motor de <i>BPM</i> se hace por medio de la<i> API REST</i> de <i>BOS,</i> actualmente conocido como<i> BonitaBPM</i>.<br />
<br />
<br />
Saludos cordiales</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com1tag:blogger.com,1999:blog-1012161132404905800.post-86163897289112198592016-12-02T10:58:00.001-08:002016-12-02T11:29:48.508-08:00Primeros pasos con Camunda BPM – Invocar una Clase Java desde una Tarea de Servicios en un proceso BPMN 2.0<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; color: rgb(0, 0, 10); line-height: 120%; text-align: left; }p.western { font-family: "Liberation Serif",serif; font-size: 12pt; }p.cjk { font-family: "Tahoma"; font-size: 12pt; }p.ctl { font-family: "FreeSans"; font-size: 12pt; }a:link { }</style>
<br />
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Ya
en nuestra <span style="color: navy;"><span lang="zxx"><u><a href="http://pigbar-hal9k.blogspot.cl/2016/11/primeros-pasos-con-camunda-bpm-agregar_27.html">publicación
anterior</a></u></span></span> aprendimos cómo agregar Formularios
de <i>HTML</i> a nuestras <i>Tareas Humanas</i> o con Actor para
nuestro proceso de <i>BPMN 2.0</i>.</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
En
esta oportunidad, siendo esta nuestra última publicación de la
serie Primeros pasos con <i>Camunda</i> <i>BPM</i>, vamos a aprender
a configurar e invocar a clases de <i>Java</i> para que se ejecuten
desde nuestras <i>actividades o tareas de servicio</i>. </div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Esto es una funcionalidad muy importante puesto que nos permite desde nuestro
proceso de <i>BPM</i> invocar <i>servicios</i> o consumirlos tal cual lo solemos
hacer desde nuestras aplicaciones <i>Java</i> normales. Salvo algunas
excepciones, casi todo lo que se puede hacer desde <i>Java</i> es posible
hacerlo desde nuestras clases para automatización de <i>servicios.</i></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZr60FS9SzyhtotHfBVgodXIDQeLcYZ6vKv9KGLMFF0LAdaiwwwueTXtD1LUoNikAsE-o7Uzi-0VIESacYRAV_L5uDiyOvk_43jrHU9ec_9LtTVX-Bh0s-IPRtNdJQhtCeLl7o9RyeA_I/s1600/bpm_java_00.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZr60FS9SzyhtotHfBVgodXIDQeLcYZ6vKv9KGLMFF0LAdaiwwwueTXtD1LUoNikAsE-o7Uzi-0VIESacYRAV_L5uDiyOvk_43jrHU9ec_9LtTVX-Bh0s-IPRtNdJQhtCeLl7o9RyeA_I/s320/bpm_java_00.png" width="320" /></a></div>
<a name='more'></a><div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<i>
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; color: rgb(0, 0, 10); line-height: 120%; text-align: left; }p.western { font-family: "Liberation Serif",serif; font-size: 12pt; }p.cjk { font-family: "Tahoma"; font-size: 12pt; }p.ctl { font-family: "FreeSans"; font-size: 12pt; }a:link { }</style>
</i></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Así
que síganme los buenos y manos a las sobras…</div>
<i>
</i>
<br />
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<i><br /></i></div>
<i>
</i>
<br />
<h2>
<i><div class="western" style="line-height: 100%; margin-bottom: 0cm; text-align: left;">
<a href="https://draft.blogger.com/null" name="add-a-javadelegate-implementation"></a>Agregar una implementación de JavaDelegate</div>
</i></h2>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<i>
</i></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<i><br />
</i></div>
<i>
</i>
<br />
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Como
las tareas de <i>servicio</i> deben ser asociadas a una clase <i>java</i> que
podamos ejecutar, esto lo hacemos construyendo clases que implementen
la <i>interface</i> <i> JavaDelegate,</i> lo que garantiza que nuestras
implementaciones tengan un método con la siguiente firma:</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<br /></div>
<pre class="brush:java">public void execute(DelegateExecution execution) throws Exception
</pre>
<br />
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; color: rgb(0, 0, 10); line-height: 120%; text-align: left; }p.western { font-family: "Liberation Serif",serif; font-size: 12pt; }p.cjk { font-family: "Tahoma"; font-size: 12pt; }p.ctl { font-family: "FreeSans"; font-size: 12pt; }a:link { }</style>
<br />
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
El
cual recibirá un parámetro <i>DelegateExecution</i>, que representa
nuestro contexto de ejecucuión del proceso y es la puerta de entrada
para la <i>API</i> del motor de procesos de <i>Camunda</i>.</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Vayamos
a nuestra <i>IDE</i>, <i>eclipse</i>, y abramos nuestro proyecto de
<i>BPM</i>, <i>bpm_demo</i>, y en el paquete:</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<i>/src/main/java/pigbar/bpm/apps/bpm_demo</i></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Agreguemos
una clase, <i>ServiceTaskDelegator</i>, que implemente la Interface
antes identificada,</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhWhzvSu-3EdBGZ4x61jZZvqRqwDQ8QBWUjJNAio9BJTztOMhsKWEwUdjt6MHrhQHSOzdDF3v_tPLfDX6_KxjDbnhO3SN8A8V1oC3b-hCORFymhNki9bfVmXtKTU_r4BS067y0qsjsK_Q/s1600/bpm_java_01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhWhzvSu-3EdBGZ4x61jZZvqRqwDQ8QBWUjJNAio9BJTztOMhsKWEwUdjt6MHrhQHSOzdDF3v_tPLfDX6_KxjDbnhO3SN8A8V1oC3b-hCORFymhNki9bfVmXtKTU_r4BS067y0qsjsK_Q/s400/bpm_java_01.png" width="386" /></a></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
quedando
como se muestra a continuación:</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
</div>
<pre class="brush:java">
package pigbar.bpm.apps.bpm_demo;
import java.util.logging.Logger;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
public class ServiceTaskDelegator implements JavaDelegate {
private final static Logger LOGGER = Logger.getLogger("SOLICITUD-PRESTAMO");
public void execute(DelegateExecution execution) throws Exception {
LOGGER.info("Solicitud de Prestamo realizado por: '" + execution.getVariable("customerId") + "'...");
LOGGER.info("Por un monto total de: '" + execution.getVariable("amount") + "'.");
}
}
</pre>
<br/>
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; color: rgb(0, 0, 10); line-height: 120%; text-align: left; }p.western { font-family: "Liberation Serif",serif; font-size: 12pt; }p.cjk { font-family: "Tahoma"; font-size: 12pt; }p.ctl { font-family: "FreeSans"; font-size: 12pt; }a:link { }</style>
<br />
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Note
como accedemos a la variables del proceso mediante la variable
<i>execution</i> del tipo <span style="color: black;"><span style="font-family: monospace;"><span style="font-size: small;">DelegateExecution.</span></span></span></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYpOaOU8j8M52lkJ5U5T9q1CU33p9ACy9HZ7JixoA-mIJIEyoyswsiqYnSkpa25n8WUBnH5eAFE_KP37wgUEEFkXc2iodzV3pvgHWUls7VFjPVZIw57Cdi0Z-plGXwfczPplxrqzqtUFA/s1600/bpm_java_02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYpOaOU8j8M52lkJ5U5T9q1CU33p9ACy9HZ7JixoA-mIJIEyoyswsiqYnSkpa25n8WUBnH5eAFE_KP37wgUEEFkXc2iodzV3pvgHWUls7VFjPVZIw57Cdi0Z-plGXwfczPplxrqzqtUFA/s320/bpm_java_02.png" width="320" /></a></div>
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; color: rgb(0, 0, 10); line-height: 120%; text-align: left; }p.western { font-family: "Liberation Serif",serif; font-size: 12pt; }p.cjk { font-family: "Tahoma"; font-size: 12pt; }p.ctl { font-family: "FreeSans"; font-size: 12pt; }a:link { }</style>
<br />
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Excelente!!!</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhusI-eeO_P9KPZF8Ip4TVGkqdqI0fwkDOsyRoTUUXWSqSIOFca9Z_RMe3PafqYZxAfStK0lO9dnJ1k3VzTMPvrGwkkvGcSbT3LuYe91VLI-i9uhEtCZdxenru63zyhyphenhyphenrETMuROXLrlvyY/s1600/bpm_java_03.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="187" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhusI-eeO_P9KPZF8Ip4TVGkqdqI0fwkDOsyRoTUUXWSqSIOFca9Z_RMe3PafqYZxAfStK0lO9dnJ1k3VzTMPvrGwkkvGcSbT3LuYe91VLI-i9uhEtCZdxenru63zyhyphenhyphenrETMuROXLrlvyY/s320/bpm_java_03.gif" width="320" /></a></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<h2 style="text-align: left;">
Agregar
una <i>Tarea</i> o <i>Actividad de Servicio </i>al Proceso </h2>
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; color: rgb(0, 0, 10); line-height: 120%; text-align: left; }p.western { font-family: "Liberation Serif",serif; font-size: 12pt; }p.cjk { font-family: "Tahoma"; font-size: 12pt; }p.ctl { font-family: "FreeSans"; font-size: 12pt; }a:link { }</style>
<br />
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Como
ya hemos implementado nuestras clases <i>Java</i> que se harán cargo
ejecutar nuestra lógica de servicio, es hora de ir al editor o
modelador de <i>Camunda BPM</i> para agregar una nueva <i>Tarea</i> o
<i>Actividad</i> de Servicio a nuestro proceso <i>BPMN </i><span style="font-style: normal;">y
configurarla adecuadamente para asociarla con nuestras clases de
implementación de la interface </span><i>JavaDelegate</i><span style="font-style: normal;">.</span></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Abramos
nuestro procesos en el <i>Modeler</i>, seleccione y arrastre el
evento de finalización hacia la derecha para hacer espacio para la
nueva <i>Tarea de Servicio</i>. </div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Desde la barra de herramientas
seleccione la figura correspondiente a <i>Actividades</i> y arrástrela
hasta la posición correspondiente entre la T<i>area Humana</i> y el
<i>Evento de Finalización</i>. El editor automáticamente enlazará
los <i>flujos</i> adecuados. Con la Tarea de Servicios seleccionada,
ubique la opción de Configuración y seleccione “<i>Servicce Task</i>”.</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin4YjEKayV84q6UROCBOumUmOblXPdxL2_QzAHluh-2VFp8J2is1tu1AMPH1dASurB7PZrSMQd3Iz-MzGl7FBqq98kNsgOBTCsjozv_8RxSU9xJ8jpqK2_jacnL4DEWRV56JhhFyy8-O0/s1600/bpm_java_04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="283" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin4YjEKayV84q6UROCBOumUmOblXPdxL2_QzAHluh-2VFp8J2is1tu1AMPH1dASurB7PZrSMQd3Iz-MzGl7FBqq98kNsgOBTCsjozv_8RxSU9xJ8jpqK2_jacnL4DEWRV56JhhFyy8-O0/s400/bpm_java_04.png" width="400" /></a></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Proceda
a nombrar la nueva <i>Tarea de Servicio</i> como “<i>Mi Servicio</i>”,
que creativo ¿no les parece?, y nos debe quedar un flujo como el
siguiente:</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVAgC_1CHkioQBXNfU4jvvExcmH9qploUp3z44pmWgo26Y_di8uVcI5cyOObjemQxzTN32UHmK2BVgPDbKwIRSEgUdWujgA_3yyaZeVMjQo5rFWgoSs_uqWvrv5UL1wSR40uz5ipORS-U/s1600/bpm_java_05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="110" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVAgC_1CHkioQBXNfU4jvvExcmH9qploUp3z44pmWgo26Y_di8uVcI5cyOObjemQxzTN32UHmK2BVgPDbKwIRSEgUdWujgA_3yyaZeVMjQo5rFWgoSs_uqWvrv5UL1wSR40uz5ipORS-U/s400/bpm_java_05.png" width="400" /></a></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Seleccione
la Tarea de Servicio, en la barra de propiedades ubique la sección
de “<i>Details</i>”, despliegue el comboBox denominado
“<i>Implementation</i>” y seleccione el valor “<i>Java Class</i>”.
Seguidamente asigne el valor adecuado correspondiente al nombre
calificado de la clase de implementación</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<i>pigbar.bpm.apps.bpm_demo.ServiceTaskDelegator</i></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnl4yfyJU7OEIdxpVdrNPNBcJAJIkw15le4H6286_4hYn7Ie3uPTtpMOlhfIB0vFAhdL4aof8n__RdjVKYtX37eRasCq6gzzKNR8ONfTukmM218filP1GfYimj4gneSfxfyQy3h7qKhMQ/s1600/bpm_java_06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="115" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnl4yfyJU7OEIdxpVdrNPNBcJAJIkw15le4H6286_4hYn7Ie3uPTtpMOlhfIB0vFAhdL4aof8n__RdjVKYtX37eRasCq6gzzKNR8ONfTukmM218filP1GfYimj4gneSfxfyQy3h7qKhMQ/s320/bpm_java_06.png" width="320" /></a></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Guarde
los cambios realizados al proceso <i>BPMN</i> y desde el eclipse
construya, empaquete, despliegue y ejecute nuevamente nuestro
proyecto <i>Maven Java</i>.</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Levante
una instancia del Proceso con los siguientes valores:</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<i>Customer
Id = Yo el Supremo</i></div>
<i>
</i>
<br />
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<i>Ammount
= 125000</i></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Complete
la <i>Tarea Humana</i> asignada al usuario <i>John</i> y en el <i>Log</i> del servidor
deberíamos poder observar una salida similar a la siguiente:</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
</div>
<pre class="brush:xml">02-Dec-2016 12:02:38.479 INFO [http-nio-8080-exec-17] pigbar.bpm.apps.bpm_demo.ServiceTaskDelegator.execute Solicitud de Prestamo realizado por: 'Yo El Supremo'...
02-Dec-2016 12:02:38.479 INFO [http-nio-8080-exec-17] pigbar.bpm.apps.bpm_demo.ServiceTaskDelegator.execute Por un monto total de: '125000.0'.
</pre>
<br />
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; color: rgb(0, 0, 10); line-height: 120%; text-align: left; }p.western { font-family: "Liberation Serif",serif; font-size: 12pt; }p.cjk { font-family: "Tahoma"; font-size: 12pt; }p.ctl { font-family: "FreeSans"; font-size: 12pt; }a:link { }</style>
<br />
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Lo
que demuestra que nuestra <i>Tarea de Servicio</i> se ejecutó a la
perfeccción.</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Genial!!!.</div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Hasta
aquí nuestra serie de publicaciones sobre los primeros pasos con
Camunda BPM. </div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Nos quedan pendientes los temas específicos de la
notación <i>BPMN,</i> la <i>API REST</i> de la plataforma y como desarrollar
aplicaciones para este poderoso y versátil motor de <i>BPM.</i></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Pronto
les estaré invitando al Webinar sobre la notación <i>BPMN</i> que
estaremos realizando con la plataforma de <i>Camunda BPM.</i></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Atentos
a este medio y al <i>twitter!!!</i></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="western" style="line-height: 100%; margin-bottom: 0cm;">
Hasta
la próxima</div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com5tag:blogger.com,1999:blog-1012161132404905800.post-41916048305170034442016-11-27T08:51:00.001-08:002016-11-27T08:53:55.825-08:00Primeros pasos con Camunda BPM – Agregar Formularios HTML al Proceso BPMN<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<style type="text/css">p { margin-bottom: 0.25cm; line-height: 120%; }a:link { }</style>
<br />
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Es
común cuando se trabaja con procesos en <i>BPM</i> bajo la notación
<i>BPMN</i> el considerar formularios de entrada tanto para el inicio
del proceso como para sus Tareas Humanas, sobre todo cuando se desea
aprovechar las bondades que ofrece el motor de <i>BPM</i>, en este
caso la plataforma <i>BPM</i> de <i>Camunda</i>.</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
En
esta publicación vamos a tratar el tema de cómo agregar formularios
de <i>HTML</i> personalizados para nuestras actividades de Inicio de
Proceso y Tareas Humanas en el proceso <i>BPMN</i> que desplegamos en
nuestra <a href="http://pigbar-hal9k.blogspot.cl/2016/11/primeros-pasos-con-camunda-bpm_21.html">publicación
anterior</a>.</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Así
que síganme los buenos y manos a las sobras…</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjNO5qDiL_F44jT9fMj1TEfEr700mEtyDviI63BAQgtASi7VtfZVZfhyDzjOBbLRUc6DPp-d5G2ypAOy12kvMj0vjKIFQAyvhTG5nxn5Utk-wAnqF3OKkLKPcCr6t_rVnvDhKBYnPlvjM/s1600/bpm_forms_00.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="181" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjNO5qDiL_F44jT9fMj1TEfEr700mEtyDviI63BAQgtASi7VtfZVZfhyDzjOBbLRUc6DPp-d5G2ypAOy12kvMj0vjKIFQAyvhTG5nxn5Utk-wAnqF3OKkLKPcCr6t_rVnvDhKBYnPlvjM/s400/bpm_forms_00.png" width="400" /></a></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
</div>
<a name='more'></a><br />
<br />
<h2 align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Crear
carpeta <i>FORMS</i> en Eclipse</h2>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Vayamos
a nuestro <a href="http://pigbar-hal9k.blogspot.cl/2016/11/primeros-pasos-con-camunda-bpm_16.html">proyecto
Maven-Java en eclipse</a>, que ya hemos configurado en publicaciones
anteriores, y ubiquemos la ruta:</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<i>bpm_demo/src/main/webapp</i></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Allí agregamos la carpeta de nombre: <i>forms</i></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJ3sV9vYCB2mIH0OkkuEYwxyyVod2zUVLBQsqdcgkdM5qwnssXdUMRZ_ZCZE3CIltT3sq98hyXJzRWEiBiUf_g9WYoHs-FLnM033f5sxEFezet6F3fqtB83VHlx0C3Pdwz0BdMUZWVWqo/s1600/bpmn_form_01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJ3sV9vYCB2mIH0OkkuEYwxyyVod2zUVLBQsqdcgkdM5qwnssXdUMRZ_ZCZE3CIltT3sq98hyXJzRWEiBiUf_g9WYoHs-FLnM033f5sxEFezet6F3fqtB83VHlx0C3Pdwz0BdMUZWVWqo/s320/bpmn_form_01.png" width="301" /></a></div>
<br />
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<h2 align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Agregar
archivos <i>HTML</i></h2>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Dentro
de la carpeta <i>forms</i> recién creada, creemos un archivo
denominado:</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<i>init_proc_prestamo.html</i></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
con
el siguiente contenido:</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
</div>
<pre class="brush:html"><form name="requestPrestamo">
<div class="form-group">
<label for="customerId">Customer ID</label>
<input class="form-control"
cam-variable-type="String"
cam-variable-name="customerId"
name="customerId" />
</div>
<div class="form-group">
<label for="amount">Amount</label>
<input class="form-control"
cam-variable-type="Double"
cam-variable-name="amount"
name="amount" />
</div>
</form>
</pre>
<br />
<style type="text/css">p { margin-bottom: 0.25cm; line-height: 120%; }a:link { }</style>
<br />
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Note
que declaramos dos campos de entrada correspondientes a las variables
<i><b>customerId</b></i> y <i><b>amount</b></i>.</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
En
ese mismo directorio creemos el archivo denominado:</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<i>check_prestamo.html</i></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
con
el siguiente contenido:</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
</div>
<pre class="brush:html"><form name="checkPrestamo">
<div class="form-group">
<label for="customerId">Customer ID</label>
<input class="form-control"
cam-variable-type="String"
cam-variable-name="customerId"
name="customerId"
readonly="true" />
</div>
<div class="form-group">
<label for="amount">Amount</label>
<input class="form-control"
cam-variable-type="Double"
cam-variable-name="amount"
name ="amount" />
</div>
</form>
</pre>
<br />
<style type="text/css">p { margin-bottom: 0.25cm; line-height: 120%; }code.cjk { font-family: "Courier New",monospace; }a:link { }</style>
<br />
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Con
esto ya tenemos listos los archivos .<i>html</i> que debemos asociar
con nuestras actividades del proceso <i>BPMN</i>, lo cual
realizaremos sin demora en el próximo paso.</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKSixHkR5c8fw8JV9E1mTY4IdVPLv5RJdYjJYmZbq02LC_UTR9lcf-jTtFR7qwKS9ATbhM4WNv3JakCCFyt1l271i4nbiFbQEf7W0RsdLQuxklisx6fXCt5kS4ZNdWhbK-KYgpgssDWG4/s1600/bpm_forms_02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="132" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKSixHkR5c8fw8JV9E1mTY4IdVPLv5RJdYjJYmZbq02LC_UTR9lcf-jTtFR7qwKS9ATbhM4WNv3JakCCFyt1l271i4nbiFbQEf7W0RsdLQuxklisx6fXCt5kS4ZNdWhbK-KYgpgssDWG4/s320/bpm_forms_02.png" width="320" /></a></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<h2 align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Agregar
<i>Formularios</i> al proceso <i>BPMN</i></h2>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Vayamos
a nuestro fabuloso editor, modeler, de Camunda BPM y abramos nuestro
proceso denominado:</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<i>bpm_demo/src/main/resources/diagrama_sol_pretamo_1.bpmn</i></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Seguidamente,
ubiquemos el elemento “<i>evento de inicio</i>”, selecciónelo
pinchando o haciendo <i>click</i> sobre él. En la barra de
propiedades, seleccione la pestaña o sección “<i>Forms</i>” y
agregue a la propiedad “<i>Form Key</i>” el siguiente valor:</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<code class="western"><i>embedded:app:forms/</i></code><code class="western"><i>init_proc_prestamo.html</i></code></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijrvMazGt6D8hUVoAwDKtwUeeSkclu2ZaBcUOaJ4yvGSv2PET-wj7gtICZfxcpHtxdhc7K9GA6bkXThTh2KiDUq3gR2rSHsjzNnyXmKZq8zZ_yU3qh_dwmfx7WnWgyRC30piKxMqVRW5E/s1600/bpm_forms_03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="130" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijrvMazGt6D8hUVoAwDKtwUeeSkclu2ZaBcUOaJ4yvGSv2PET-wj7gtICZfxcpHtxdhc7K9GA6bkXThTh2KiDUq3gR2rSHsjzNnyXmKZq8zZ_yU3qh_dwmfx7WnWgyRC30piKxMqVRW5E/s400/bpm_forms_03.png" width="400" /></a></div>
<br />
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Esto
significa que vamos a usar un formulario incrustado en la ventana de
inicio y que se encuentra dentro de los recursos de la aplicación.</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
De
igual forma vamos a asociar nuestra tarea humana “<span style="font-variant: normal;"><span style="color: #444444;"><span style="font-family: "helvetica neue" , "helvetica" , "arial" , sans-serif;"><span style="font-size: x-small;"><span style="letter-spacing: normal;"><span style="font-style: normal;"><span style="font-weight: normal;">Solicitar
Préstamo</span></span></span></span></span></span></span>” con el
formulario “<i>check_prestamo.html</i>”. Pare ello seleccionemos
la actividad humana en cuestión, vayamos a la barra de propiedades,
sección de formularios y establecemos la propiedad “<i>Form Key</i>”
con el siguiente valor:
</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<code class="western"><i>e</i></code><code class="western"><i>mbedded:app:forms/</i></code><code class="western"><i>check_prestamo.html</i></code></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihRPXe6DUxPJxxlGOCnx6cwEd7OXl26fc1Jmkj7B6GA9WBdxijgWQVCP5jvO9YxqKJY9ixIIeAO8dBQcqMQzZn1xuhgvZSTnyT37dpDmbW5vC5j-jqZAAdsyA-z2a3JF8HZFl_MOAHs-0/s1600/bpm_forms_04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihRPXe6DUxPJxxlGOCnx6cwEd7OXl26fc1Jmkj7B6GA9WBdxijgWQVCP5jvO9YxqKJY9ixIIeAO8dBQcqMQzZn1xuhgvZSTnyT37dpDmbW5vC5j-jqZAAdsyA-z2a3JF8HZFl_MOAHs-0/s400/bpm_forms_04.png" width="400" /></a></div>
<br />
<br />
Guarde los cambios, vaya al eclipse y reconstruya y re despliegue el proceso. <br />
<br />
<h2 style="text-align: left;">
Iniciar una Instancia de Proceso </h2>
Iniciemos el servidor de <i>BPM</i> de <i>Camunda,</i> vayamos al "<i>TaskList"</i> con el usuario Demo y busquemos la opción "<i>Start Process"</i>, seleccionamos el proceso<i> "Solicitar Préstamo</i>" y podemos ver lo siguiente:<br />
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUgld12ERRfhUJx7RMCb_7xxnIbSHMj30wWfchzpS8YrCPGlq0FmT38_8sLP2gNqUqaZxkWAfbY9EUKCRrq5CsIURwmt-KaG67LgP2-ttjeFY2nZFfBz9pTjE55uofTOU9yAXbcPI_ffA/s1600/bpm_forms_05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="147" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUgld12ERRfhUJx7RMCb_7xxnIbSHMj30wWfchzpS8YrCPGlq0FmT38_8sLP2gNqUqaZxkWAfbY9EUKCRrq5CsIURwmt-KaG67LgP2-ttjeFY2nZFfBz9pTjE55uofTOU9yAXbcPI_ffA/s400/bpm_forms_05.png" width="400" /></a></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Cerremos
la sesión, e iniciemos con el usuario John.</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Vemos
que tiene asignada la tarea “<i>Solicitar Préstamo</i>”, hacemos
<i>click</i> en la tarea y podemos observar lo siguiente:</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNot6IdF-1gRCbIz52G90SiYc_RFYk8hOGD4-lBPUW2-2uJLLYQAUgt9SgB00wMa7Ee0J5aPqUuozgSBiSAq-VsV49z1REfQpSQd_OGhGxr8mvuFbW6dR30AC8BltVPGvn2GT1An_Qnas/s1600/bpm_forms_06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNot6IdF-1gRCbIz52G90SiYc_RFYk8hOGD4-lBPUW2-2uJLLYQAUgt9SgB00wMa7Ee0J5aPqUuozgSBiSAq-VsV49z1REfQpSQd_OGhGxr8mvuFbW6dR30AC8BltVPGvn2GT1An_Qnas/s400/bpm_forms_06.png" width="400" /></a></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Que
es justamente lo que queríamos demostrar.</div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div align="justify" style="line-height: 100%; margin-bottom: 0cm;">
Saludos
y hasta una próxima entrega.</div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com6tag:blogger.com,1999:blog-1012161132404905800.post-44653517716202663692016-11-21T17:13:00.000-08:002016-11-21T17:13:37.724-08:00Primeros pasos con Camunda BPM – Desplegar y Probar el Proceso BPMN 2.0<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Como decíamos ayer… bueno, no ayer exactamente,
pero en nuestra </span><a href="http://pigbar-hal9k.blogspot.cl/2016/11/primeros-pasos-con-camunda-bpm_19.html"><span lang="ES-CL" style="mso-ansi-language: ES-CL;">publicación anterior</span></a><span lang="ES-CL" style="mso-ansi-language: ES-CL;"> ya vimos cómo elaborar nuestro
primer proceso de <i style="mso-bidi-font-style: normal;">BPMN 2.0</i> y guardar
los cambios de la configuración respectiva. Vamos ahora a revisar los pasos
necesarios para desplegar y probar dicho proceso en la </span><a href="https://camunda.org/"><span lang="ES-CL" style="mso-ansi-language: ES-CL;">plataforma
<i style="mso-bidi-font-style: normal;">BPM</i> de <i style="mso-bidi-font-style: normal;">Camunda</i></span></a><span lang="ES-CL" style="mso-ansi-language: ES-CL;">.
</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Así mismo revisaremos los detalles necesarios
para configurar los permisos de usuarios y la funcionalidad que pueden ejecutar
sobre el proceso desplegado, todo esto haciendo uso de la plataforma de
administración de <i style="mso-bidi-font-style: normal;">Camunda</i>. Tampoco
podemos olvidar que daremos una mirada a las instancias en ejecución de nuestro
proceso mediante la herramienta Cockpit.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Entonces, sin más preámbulos, manos a las
sobras…</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3RXxAF0jzeWd6oGTZiA-pcgk7ZJcVGZq4phQDIsMhfSAeg9zjlLp2rAJOHBko8PHduhvOhOljokGibwdd0T-uxwligxlNvTa3JmxP28_TrvZqPjRL9AQoCYpyOi7BFehC2eR1OBlcres/s1600/deploy_bpm_00.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3RXxAF0jzeWd6oGTZiA-pcgk7ZJcVGZq4phQDIsMhfSAeg9zjlLp2rAJOHBko8PHduhvOhOljokGibwdd0T-uxwligxlNvTa3JmxP28_TrvZqPjRL9AQoCYpyOi7BFehC2eR1OBlcres/s400/deploy_bpm_00.png" width="400" /></a></div>
<br />
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"></span></div>
<a name='more'></a><br />
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<h2 class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Construir la aplicación <i style="mso-bidi-font-style: normal;">Web</i> con <i style="mso-bidi-font-style: normal;">Maven</i></span></h2>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Para ello debemos tener cargado muestro
proyecto <i style="mso-bidi-font-style: normal;">Java</i> Maven en la <i style="mso-bidi-font-style: normal;">IDE</i> de eclipse.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Vaya al explorador, ubique el archivo <i style="mso-bidi-font-style: normal;">pom.xml</i>, haga click con el botón derecho
del ratón sobre ese archivo, en el menú contextual seleccione la opción <i style="mso-bidi-font-style: normal;">Run As / Maven Install</i>.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Al finalizar esta tarea se debe generar un
archivo .<i style="mso-bidi-font-style: normal;">war</i> de la aplicación, <i style="mso-bidi-font-style: normal;">bpm_demo-0.1.war</i>, en el directorio <i style="mso-bidi-font-style: normal;">target</i> del proyecto. Pulse <i style="mso-bidi-font-style: normal;">f5</i> para recargar o refrescar el entorno.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxxmz1Td7VJG6kqkIaQx6datWEB_kSNg37gPTg0jGAAk4DtScRX-HRYhlzSPwg7V561Wck8WdkFo38yUaBNSQyWrGTeRAZZ2-q6x0gKgSrlzyObD3lPGiKhpGHYJje8WXwto6dsDruzpM/s1600/deploy_bpm_01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxxmz1Td7VJG6kqkIaQx6datWEB_kSNg37gPTg0jGAAk4DtScRX-HRYhlzSPwg7V561Wck8WdkFo38yUaBNSQyWrGTeRAZZ2-q6x0gKgSrlzyObD3lPGiKhpGHYJje8WXwto6dsDruzpM/s1600/deploy_bpm_01.png" /></a></div>
<h2 class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"></span></h2>
<h2 class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Desplegar en Apache Tomcat</span></h2>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Sí aún no tiene el <i style="mso-bidi-font-style: normal;">Tomcat</i> ejecutándose, la plataforma de <i style="mso-bidi-font-style: normal;">Camunda BPM</i>, vaya al directorio de instalación, CAMUNDA_HOME, del
servidor, y ejecute el archivo start-camunda.sh o start-camunda.bat según
corresponda a su ambiente operativo.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<span lang="ES-CL" style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;">Seguidamente copie el archivo <i style="mso-bidi-font-style: normal;">bpm_demo-0.1.war,</i> generado en el paso
anterior, y<span style="mso-spacerun: yes;"> </span>péguelo en el
directorio<span style="mso-spacerun: yes;"> </span><i style="mso-bidi-font-style: normal;">CAMUNDA_HOME/server/apache-tomcat-8.0.24/ webapps/</i>, de modo que se
inicie el auto-despliegue en el servidor Tomcat.</span><br />
<br />
<span lang="ES-CL" style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;">Esto debe generar la carpeta descomprimida del
recurso, .war, en el directorio webapps y en el log del servidor debe generar
un mensaje indicando que el despliegue fue exitoso.</span><br />
<br />
<span lang="ES-CL" style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;"></span> <br />
<span lang="ES-CL" style="font-family: "calibri" , "sans-serif"; font-size: 11.0pt; line-height: 115%;"></span> </div>
<pre class="brush:xml">21-Nov-2016 16:18:43.218 INFO [localhost-startStop-2] org.apache.catalina.startup.HostConfig.deployWAR Despliegue del archivo /home/pigbar/Developer/Servers/camunda-bpm-tomcat-7.5.0/server/apache-tomcat-8.0.24/webapps/bpm_demo-0.1.war de la aplicación web
21-Nov-2016 16:18:43.858 INFO [localhost-startStop-2] org.apache.jasper.servlet.TldScanner.scanJars Al menos un JAR, que se ha explorado buscando TLDs, aún no contenía TLDs. Activar historial de depuración para este historiador para una completa lista de los JARs que fueron explorados y de los que nos se halló TLDs. Saltarse JARs no necesarios durante la exploración puede dar lugar a una mejora de tiempo significativa en el arranque y compilación de JSP .
21-Nov-2016 16:18:43.858 INFO [localhost-startStop-2] org.camunda.commons.logging.BaseLogger.logInfo ENGINE-07015 Detected @ProcessApplication class 'pigbar.bpm.apps.bpm_demo.BPMDemoApp'
21-Nov-2016 16:18:43.859 INFO [localhost-startStop-2] org.camunda.commons.logging.BaseLogger.logInfo ENGINE-08026 No processes.xml file found in process application 'BPM Demo'
21-Nov-2016 16:18:43.860 INFO [localhost-startStop-2] org.camunda.commons.logging.BaseLogger.logInfo SPIN-01010 Discovered Spin data format provider: org.camunda.spin.impl.json.jackson.format.JacksonJsonDataFormatProvider[name = application/json]
21-Nov-2016 16:18:43.860 INFO [localhost-startStop-2] org.camunda.commons.logging.BaseLogger.logInfo SPIN-01010 Discovered Spin data format provider: org.camunda.spin.impl.xml.dom.format.DomXmlDataFormatProvider[name = application/xml]
21-Nov-2016 16:18:43.860 INFO [localhost-startStop-2] org.camunda.commons.logging.BaseLogger.logInfo SPIN-01009 Discovered Spin data format: org.camunda.spin.impl.xml.dom.format.DomXmlDataFormat[name = application/xml]
21-Nov-2016 16:18:43.860 INFO [localhost-startStop-2] org.camunda.commons.logging.BaseLogger.logInfo SPIN-01009 Discovered Spin data format: org.camunda.spin.impl.json.jackson.format.JacksonJsonDataFormat[name = application/json]
21-Nov-2016 16:18:43.861 INFO [localhost-startStop-2] org.camunda.commons.logging.BaseLogger.logInfo ENGINE-08050 Process application BPM Demo successfully deployed
</pre>
<br />
<h2 style="text-align: left;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Verificar el despliegue con la herramienta <i style="mso-bidi-font-style: normal;">Cockpit</i></span>
</h2>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Vayamos a nuestro explorador y abramos la
aplicación Cockpit, podemos hacerlo mediante la url:</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<a href="http://localhost:8080/camunda/app/cockpit"><i style="mso-bidi-font-style: normal;"><span lang="ES-CL" style="background: white; color: #0b2d5f; font-family: "Helvetica","sans-serif"; mso-ansi-language: ES-CL; text-decoration: none; text-underline: none;">http://localhost:8080/camunda/app/cockpit</span></i></a><i style="mso-bidi-font-style: normal;"><span lang="ES-CL" style="mso-ansi-language: ES-CL;"></span></i></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Ingresamos las credenciales adecuadas cuando se
nos solicite:</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<i style="mso-bidi-font-style: normal;"><span lang="ES-CL" style="mso-ansi-language: ES-CL;">Usuario: demo</span></i></div>
<div class="MsoNormal" style="text-align: justify;">
<i style="mso-bidi-font-style: normal;"><span lang="ES-CL" style="mso-ansi-language: ES-CL;">Clave: demo</span></i></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">El tablero o <i style="mso-bidi-font-style: normal;">Dashboard</i> nos debe indicar que se ha añadido una nueva definición
de proceso, <i style="mso-bidi-font-style: normal;">process definition</i>, y
podemos observarla haciendo click en el menú <i style="mso-bidi-font-style: normal;">processes</i> de la herramienta.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgopTiiSQ_nPH7Nc4mFz6N7rYo0JMIcU6A9M7UHLYNh3Pnk4S2DtPWboz_IlnMExLZT9XQX_MHFGXtf71TL8-ikYPGSbhhgOkst-KRv8KFmvJujByCBjY7PMF47ruxL_a42_qBP8FI88wo/s1600/deploy_bpm_02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="97" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgopTiiSQ_nPH7Nc4mFz6N7rYo0JMIcU6A9M7UHLYNh3Pnk4S2DtPWboz_IlnMExLZT9XQX_MHFGXtf71TL8-ikYPGSbhhgOkst-KRv8KFmvJujByCBjY7PMF47ruxL_a42_qBP8FI88wo/s400/deploy_bpm_02.png" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Genial!! En caso de problemas deberíamos
iniciar por revisar los mensajes del log.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<h2 class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Iniciar una Instancia de Proceso</span></h2>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Cierre la sesión en el <i style="mso-bidi-font-style: normal;">Cockpit</i>. Vayamos a la aplicación TaskList de Camunda BPM, </span><a href="http://localhost:8080/camunda/app/tasklist"><span lang="ES-CL" style="background: white; color: #0b2d5f; font-family: "Helvetica","sans-serif"; mso-ansi-language: ES-CL; text-decoration: none; text-underline: none;">http://localhost:8080/camunda/app/tasklist</span></a><span lang="ES-CL" style="mso-ansi-language: ES-CL;">, Ingresamos las credenciales
adecuadas cuando se nos solicite:</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<i style="mso-bidi-font-style: normal;"><span lang="ES-CL" style="mso-ansi-language: ES-CL;">Usuario: demo</span></i></div>
<div class="MsoNormal" style="text-align: justify;">
<i style="mso-bidi-font-style: normal;"><span lang="ES-CL" style="mso-ansi-language: ES-CL;">Clave: demo</span></i></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Y hacemos click en la opción <i style="mso-bidi-font-style: normal;">Start process</i>.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcLCjd82JUwbL6sPz7QHUewlEIRns7Ehu2HCB3NL4fUMPnUt0YIGQCuI2hRXBW8Pux7JW9qfeDtn7KU3ZFNUSIlUNc7CWuM0mGxEUZX3Evnh-SnuIcmPSD0DFisgLwlBChtt5FZRiAxgs/s1600/deploy_bpm_03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcLCjd82JUwbL6sPz7QHUewlEIRns7Ehu2HCB3NL4fUMPnUt0YIGQCuI2hRXBW8Pux7JW9qfeDtn7KU3ZFNUSIlUNc7CWuM0mGxEUZX3Evnh-SnuIcmPSD0DFisgLwlBChtt5FZRiAxgs/s400/deploy_bpm_03.png" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Donde podemos seleccionar nuestro proceso
Solicitud de Préstamo, y definir o establecer las variables que consideremos
pertinentes para el inicio del proceso, ya sea mediante un formulario
personalizado o mediante la pantalla de inicio por omisión.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtCoxrqyLyzSoTPxEu5iemGZnbubgyQLZW150W-TR0zR2NANeQ0dKZ3igs3YPbOkO-9JWYDMKrKoSIYyt_n8LxXe0hxJBW7baZZzHulDN3cVYl28_aWTMKNqnutv9zS1MyOKfojJinBLM/s1600/deploy_bpm_04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtCoxrqyLyzSoTPxEu5iemGZnbubgyQLZW150W-TR0zR2NANeQ0dKZ3igs3YPbOkO-9JWYDMKrKoSIYyt_n8LxXe0hxJBW7baZZzHulDN3cVYl28_aWTMKNqnutv9zS1MyOKfojJinBLM/s400/deploy_bpm_04.png" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">En nuestro ejemplo no se especificó ninguna
variable para el proceso simple, ni se declaró ninguna pantalla de inicio de
proceso, por lo que podemos dar inicio a la instancia haciendo click en el
botón <i style="mso-bidi-font-style: normal;">start</i>.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">La aplicación <i style="mso-bidi-font-style: normal;">TaskList</i> nos debería informar que el proceso fue iniciado con
éxito.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Cierre la sesión en el <i style="mso-bidi-font-style: normal;">TaskList</i>. Sí volvemos a la herramienta <i style="mso-bidi-font-style: normal;">Cockpit</i>, esta nos debe indicar ahora que hay una nueva instancia de
proceso para “<i style="mso-bidi-font-style: normal;">Solicitud de Préstamo</i>”
en ejecución.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxWbm2kkICoC1N3XO4tQA92Ee6CwW3OAMSP2Bc7hCs-IJkiLZSG5gLyyq7PkEvTQqccZh1HlXGltCHsHA1KrSzC_Nn44l2D2DB_um1xaEJkSvdo_ES-J_NYAmRgQJdB0XejGcIqlBYRVk/s1600/deploy_bpm_05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="52" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxWbm2kkICoC1N3XO4tQA92Ee6CwW3OAMSP2Bc7hCs-IJkiLZSG5gLyyq7PkEvTQqccZh1HlXGltCHsHA1KrSzC_Nn44l2D2DB_um1xaEJkSvdo_ES-J_NYAmRgQJdB0XejGcIqlBYRVk/s400/deploy_bpm_05.png" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<h2 class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Configurar las Autorizaciones de Inicio de
Proceso</span></h2>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Debe recordar que en nuestra definición de
proceso inicial habíamos dicho que la <i style="mso-bidi-font-style: normal;">Tarea
Humana</i> “<i style="mso-bidi-font-style: normal;">Solicitar Préstamo</i>”
estuviese asignada al usuario John. Por lo que es necesario autorizar a este
usuario a que pueda realizar tareas sobre el proceso.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Cierre la sesión en el <i style="mso-bidi-font-style: normal;">Cockpit</i>. Vayamos a la herramienta <i style="mso-bidi-font-style: normal;">Camunda Admin</i>, </span><a href="http://localhost:8080/camunda/app/admin/default/#/login"><span lang="ES-CL" style="mso-ansi-language: ES-CL;">http://localhost:8080/camunda/app/admin/default/#/login</span></a><span lang="ES-CL" style="mso-ansi-language: ES-CL;">, Ingresamos las credenciales
adecuadas cuando se nos solicite:</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<i style="mso-bidi-font-style: normal;"><span lang="ES-CL" style="mso-ansi-language: ES-CL;">Usuario: demo</span></i></div>
<div class="MsoNormal" style="text-align: justify;">
<i style="mso-bidi-font-style: normal;"><span lang="ES-CL" style="mso-ansi-language: ES-CL;">Clave: demo</span></i></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Y hacemos click el menú <i style="mso-bidi-font-style: normal;">Authorizations</i>, donde debemos seleccionar la opción <i style="mso-bidi-font-style: normal;">Process Definition</i> y pulsar el botón o
enlace <i style="mso-bidi-font-style: normal;">créate new authorization</i>.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVwtS9hiF9IFIrmQUz74NM8f7FxbJ0F-nqzurzDQKttz62f25pymnUQ_S2fsCZA0fd0-G64tFdbUyY6L5jVslxzwfbS-qUj7X4dUCf6rv3U7IEv1zK15ZaBGHcjMai7Vv6WcJBq5IXP6I/s1600/deploy_bpm_06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVwtS9hiF9IFIrmQUz74NM8f7FxbJ0F-nqzurzDQKttz62f25pymnUQ_S2fsCZA0fd0-G64tFdbUyY6L5jVslxzwfbS-qUj7X4dUCf6rv3U7IEv1zK15ZaBGHcjMai7Vv6WcJBq5IXP6I/s400/deploy_bpm_06.png" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Indique que el usuario es “john”, con los
permisos igual a “ALL”, y sobre el Resource ID indique el valor “Process_Solicitud_Prestamo”.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Cuando esté listo guarde los cambios.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Agregue una nueva autorización en la opción <i style="mso-bidi-font-style: normal;">Process Instance</i>.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTorjoD5hQMDCweUW7utqJ7h_R9JLwKX-6VA2rMuzZqoyDIzfmiAn6rBXhctwCGN2Mu7ZSASSTWHedtsoaTBBOrztRhVdxmmF_ModvfwEjuJ4bhvq9p6RR18B1T5tMo1-3vDjdTpRCFBU/s1600/deploy_bpm_07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="155" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTorjoD5hQMDCweUW7utqJ7h_R9JLwKX-6VA2rMuzZqoyDIzfmiAn6rBXhctwCGN2Mu7ZSASSTWHedtsoaTBBOrztRhVdxmmF_ModvfwEjuJ4bhvq9p6RR18B1T5tMo1-3vDjdTpRCFBU/s400/deploy_bpm_07.png" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Indique que el usuario es “john”, con los permisos
igual a “CREATE”, y sobre el Resource ID indique el valor “*”.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<h2 class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Trabajar en la Tarea </span></h2>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Cierre la sesión en el <i style="mso-bidi-font-style: normal;">Admin</i>. Vayamos al <i style="mso-bidi-font-style: normal;">TaskList</i>
e inicie sesión con las credenciales <i style="mso-bidi-font-style: normal;">john/john.</i>
Deberíamos ser capaces de poder ver las tareas asignadas a John. Seleccione la
Tarea disponible y luego haga click en la pestaña diagrama, <i style="mso-bidi-font-style: normal;">Diagram</i>. Esto muestra el diagrama del
proceso con la tarea resaltada lista para trabajar en ella.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Podemos reclamar o tomar una tarea, completarla
estableciendo sus variables, etc.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikDOS0kpPBWpZuRuNYaVVyUbv6H6hvb_loKfwNyl9ywc31Y88FN-m_OMv9fNnjxgiVCD_q5c8rwtKGiWHX8cqR0HipsCpv-_VNtrRAwZMBlQYOnwiouf-UgCYiO7ap3ynOreQSd621XRY/s1600/deploy_bpm_08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="170" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikDOS0kpPBWpZuRuNYaVVyUbv6H6hvb_loKfwNyl9ywc31Y88FN-m_OMv9fNnjxgiVCD_q5c8rwtKGiWHX8cqR0HipsCpv-_VNtrRAwZMBlQYOnwiouf-UgCYiO7ap3ynOreQSd621XRY/s400/deploy_bpm_08.png" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"></span><span lang="ES-CL" style="mso-ansi-language: ES-CL;"> </span>
</div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"> </span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Para completar una tarea, vaya a la pestaña
Formulario, <i style="mso-bidi-font-style: normal;">Form</i>, la cual nos
mostrará el formulario que hayamos definido para esta tarea o, como es nuestro
caso, nos mostrará un formulario por omisión que nos permitirá manipular
variables y pulsar el botón <i style="mso-bidi-font-style: normal;">Complete</i>
para culminar la tarea.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6fAMUW1FrkJMffp245scKvn1KPWoZD95D_Yo1wKKFISZrzUuVmtRyXvqW8X-HbMpDGRzXK52_b0blHFIaF3kBgbAw14Z6i5bTdsxl4iIQIjvV1coWbIBwJpK8x43tGFTRCuAeWnvox0I/s1600/deploy_bpm_09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6fAMUW1FrkJMffp245scKvn1KPWoZD95D_Yo1wKKFISZrzUuVmtRyXvqW8X-HbMpDGRzXK52_b0blHFIaF3kBgbAw14Z6i5bTdsxl4iIQIjvV1coWbIBwJpK8x43tGFTRCuAeWnvox0I/s400/deploy_bpm_09.png" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Como hemos podido apreciar, las herramientas
<i>TaskList,</i> <i>Cockpit</i> y <i>Admin,</i> son recursos muy valiosos a la hora de trabajar con
las definiciones de procesos, iniciar instancias, administrar permisos y
ejecutar tareas.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Hasta una próxima publicación.</span></div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-76952614575484720752016-11-19T11:39:00.000-08:002016-11-19T11:41:17.196-08:00Primeros pasos con Camunda BPM – Modelando un Proceso BPMN 2.0<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Tenemos entre manos la tercera publicación de
nuestra serie sobre la </span><a href="https://camunda.org/"><span lang="ES-CL" style="mso-ansi-language: ES-CL;">Plataforma de BPM de Camunda</span></a><span lang="ES-CL" style="mso-ansi-language: ES-CL;">. </span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">El día de hoy vamos, por fin, a
empezar a modelar o construir nuestro primer proceso sencillo en notación <i style="mso-bidi-font-style: normal;">BPMN</i> 2.0. Para ello vamos a usar el
modelador o editor que ya hemos instalado en nuestra </span><a href="http://pigbar-hal9k.blogspot.cl/2016/11/primeros-pasos-con-camunda-bpm.html"><span lang="ES-CL" style="mso-ansi-language: ES-CL;">primera publicación</span></a><span lang="ES-CL" style="mso-ansi-language: ES-CL;">, y vamos a guardarlo en la sección
de recursos del proyecto Maven Java que configuramos en la </span><a href="http://pigbar-hal9k.blogspot.cl/2016/11/primeros-pasos-con-camunda-bpm_16.html"><span lang="ES-CL" style="mso-ansi-language: ES-CL;">segunda publicación</span></a><span lang="ES-CL" style="mso-ansi-language: ES-CL;">.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Así que, como ya es costumbre, manos a las sobras…</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl0SVZumoM_Aaioxu98Ks56-7p6JGYLEXFt8o_QCc3Rv-5gHWnx6hpdIPtbn1ODBvw2Tghyl4CwO0Hq5VBMbQ3SmeZkAQ0E0KKdCS9gcn4aXJ0tXl_UbVr0UtOkJXfRNMcWBS34CFXn-U/s1600/bpm01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="182" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl0SVZumoM_Aaioxu98Ks56-7p6JGYLEXFt8o_QCc3Rv-5gHWnx6hpdIPtbn1ODBvw2Tghyl4CwO0Hq5VBMbQ3SmeZkAQ0E0KKdCS9gcn4aXJ0tXl_UbVr0UtOkJXfRNMcWBS34CFXn-U/s320/bpm01.png" width="320" /></a></div>
<a name='more'></a><br />
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"></span></div>
<h2 class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Crear un nuevo diagrama <i>BPMN</i></span></h2>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Para ello lo primero que vamos a hacer es
levantar o ejecutar nuestro modeler, así que vaya al directorio donde tenga
instalado el modelador y ejecute el archivo <span style="mso-spacerun: yes;"> </span><i style="mso-bidi-font-style: normal;">camunda-modeler</i>,
y haga click o pinche en el botón identificado como <i style="mso-bidi-font-style: normal;">BPMN diagram</i> o yendo al menú <i style="mso-bidi-font-style: normal;">File
/ New / BPMN diagram</i>.</span><br />
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim8OwI7SMsHvcappnnE58bLHx5RVwjdWnG-d_Juk1UQ0QNfKHu6jIqpMchKareXYiM7xoZVpeIx1a22HtOnAR6qdJdWZCAfqagxoQTpuJK3vZDC5IOXVBDLrKkYbes4Ml3mUDSElAc-BU/s1600/bpmn_02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim8OwI7SMsHvcappnnE58bLHx5RVwjdWnG-d_Juk1UQ0QNfKHu6jIqpMchKareXYiM7xoZVpeIx1a22HtOnAR6qdJdWZCAfqagxoQTpuJK3vZDC5IOXVBDLrKkYbes4Ml3mUDSElAc-BU/s400/bpmn_02.png" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Donde se nos presenta la ventana de edición de
procesos con un <i style="mso-bidi-font-style: normal;">componente de Evento de
Inicio</i> colocado en ella. Podemos hacer doble-click en ese elemento y
podemos editar la etiqueta o nombre que queremos asignarle a ese componente.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Si seleccionamos ese elemento, haciendo click
sobre el mismo, el editor nos presenta una serie de elementos de ayuda de
construcción rápida, o <i style="mso-bidi-font-style: normal;">menú contextual</i>,
mediante los cuales podemos proceder a modelar con rapidez y flexibilidad
nuestro proceso.</span><br />
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNwVKOUeI8ARjNFAvuQ7HJaC7bbB_I9GqWJSpmmnK2Yl8EMvYYY-n8IcVe8C8h68Xs3xiX-C8o52cLAQ1uX9mWPNHsxj6ZC1HtP1Ga93NUWRd3vvFBx60-5qD5acwhtpy2ZNw5vPY-IVU/s1600/bpmn_03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNwVKOUeI8ARjNFAvuQ7HJaC7bbB_I9GqWJSpmmnK2Yl8EMvYYY-n8IcVe8C8h68Xs3xiX-C8o52cLAQ1uX9mWPNHsxj6ZC1HtP1Ga93NUWRd3vvFBx60-5qD5acwhtpy2ZNw5vPY-IVU/s320/bpmn_03.png" width="320" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">En el lado izquierdo de la ventana del editor
encontramos la paleta de herramientas o de componente de la notación <i style="mso-bidi-font-style: normal;">BPMN 2.0</i>, desde la cual podemos
seleccionar estos componentes y ubicarlos dentro del área de construcción del
diagrama.</span><br />
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilQj3eR-3uciNoEJfvXpuDcbcMEN4Ixn9SDITS9U8nkZTRE-h6rTwwzZ5rGeyLK-Fa_qTfuvzgnbpVOSe37aqE0h8iNwLXB0Ts-69JAIFeeyAaOCBUAvF0-cwKoAnEYEOEzWragR44Npw/s1600/bpmn_04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilQj3eR-3uciNoEJfvXpuDcbcMEN4Ixn9SDITS9U8nkZTRE-h6rTwwzZ5rGeyLK-Fa_qTfuvzgnbpVOSe37aqE0h8iNwLXB0Ts-69JAIFeeyAaOCBUAvF0-cwKoAnEYEOEzWragR44Npw/s320/bpmn_04.png" width="107" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">En el lado derecho encontramos la barra de
propiedades para cada componente seleccionado. En la que podemos ajustar los
valores para los distintos elementos de cada componente.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsly-olRw5IRFK98FMTngMyla2se_H9IfZptmFotmDAsDiZA7-PT03wGsutGCoCV_ASuC3Lj2G-8b2N6EvSmDFWI-fXHrHtqpJd7fBY3PHfmM_S7BuW4RXc-bNKlDmcveOUlVUYalkhmg/s1600/bpmn_05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsly-olRw5IRFK98FMTngMyla2se_H9IfZptmFotmDAsDiZA7-PT03wGsutGCoCV_ASuC3Lj2G-8b2N6EvSmDFWI-fXHrHtqpJd7fBY3PHfmM_S7BuW4RXc-bNKlDmcveOUlVUYalkhmg/s320/bpmn_05.png" width="211" /></a></div>
<br />
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">En la parte superior se encuentran el menú y la
barra de herramienta u opciones de acceso rápido.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJdOPAnSPjCNeTDk5gO7VPjzqKgrg8dwpJ0TDXB0rnAc1nMNv8LhwcnA9QdGqyr3LozzSD9ATvrClIn1PbwE5XFuQoeLoAx1QX0VAl_2AmCBjfgMCiqKptsUaFW1HGfc3wbZqUiAeZ32E/s1600/bpmn_06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="38" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJdOPAnSPjCNeTDk5gO7VPjzqKgrg8dwpJ0TDXB0rnAc1nMNv8LhwcnA9QdGqyr3LozzSD9ATvrClIn1PbwE5XFuQoeLoAx1QX0VAl_2AmCBjfgMCiqKptsUaFW1HGfc3wbZqUiAeZ32E/s320/bpmn_06.png" width="320" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Y en la parte inferior podemos seleccionar en
unas pestañas la vista de diagrama o la vista de <i style="mso-bidi-font-style: normal;">XML</i> de del proceso.</span><br />
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_Z_Hn_wfhPpDHqI1G3nkMIicgkzKpxvOkD9KAFiphd845H10DJAxr4260nljEl8ER3pC3-8Y9lu5nJAm4erbPOXXcPwlkmxVuvWRR8JOY92DWulFG1usmW-QN0tC-spNjtkLoDGexbHE/s1600/bpmn_07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_Z_Hn_wfhPpDHqI1G3nkMIicgkzKpxvOkD9KAFiphd845H10DJAxr4260nljEl8ER3pC3-8Y9lu5nJAm4erbPOXXcPwlkmxVuvWRR8JOY92DWulFG1usmW-QN0tC-spNjtkLoDGexbHE/s1600/bpmn_07.png" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<h2 class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Modelar un Proceso simple</span></h2>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Haga click sobre el <i style="mso-bidi-font-style: normal;">evento de inicio</i>, en el <i style="mso-bidi-font-style: normal;">menú
contextual</i> seleccione la figura del <i style="mso-bidi-font-style: normal;">componente
de actividad </i>(rectángulo) y arrástrelo hasta una posición adecuada en el
diagrama. Recuerde siempre ponerse en sintonía con su “lado femenino” en esta
etapa, ya que un diagrama ordenado, espaciado y bien distribuido es mucho más
fácil de leer y de mantener. </span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Seleccione el <i style="mso-bidi-font-style: normal;">componente de actividad</i> y, en el <i style="mso-bidi-font-style: normal;">menú contextual</i>, seleccione la <i style="mso-bidi-font-style: normal;">figura
de herramienta</i> para poder cambiar o establecer el tipo de actividad como <i style="mso-bidi-font-style: normal;">Tarea Humana</i>.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipEvrMV0p0O9aomguybhK7erjttOl-HziYJZLMtbXVhyphenhyphenwvWYJT22nEKIdlMij5hQkfzlD8g6rVYu5aBiGMuYS6BeiDhyLCWCUrIknSYMUvnECiQgLCZiuD-e9Z0ekMar8KUfYcfYnJTvI/s1600/bpmn_08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="291" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipEvrMV0p0O9aomguybhK7erjttOl-HziYJZLMtbXVhyphenhyphenwvWYJT22nEKIdlMij5hQkfzlD8g6rVYu5aBiGMuYS6BeiDhyLCWCUrIknSYMUvnECiQgLCZiuD-e9Z0ekMar8KUfYcfYnJTvI/s320/bpmn_08.png" width="320" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Seleccione la <i style="mso-bidi-font-style: normal;">Tarea Humana</i> y asígnele el nombre se “Solicitar Préstamo”. Siempre
es una buena práctica, colocar a los componentes un nombre e identificador
adecuado a su propósito. Por ejemplo, los componentes de actividades conllevan
la ejecución de una acción, por lo que nombre se debe asociar a una frase con
ese sentido, tales como “Aprobar Solicitud”, “Revisar reclamo”, “Obtener
informe”, etc.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsSC7_MGpHD4TcMkCpS5L9DqJPtZRtktSY4lNKtvPKvIo09ikemQZl_6SZvhLxV0clxyvAP5BEEqIMprTqr3G4DhtHEg9rYM41LqGzSa0AfCZFWKSUqwYIY14DsvF9QHEOiEBv8Clq3RU/s1600/bpmn_09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="137" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsSC7_MGpHD4TcMkCpS5L9DqJPtZRtktSY4lNKtvPKvIo09ikemQZl_6SZvhLxV0clxyvAP5BEEqIMprTqr3G4DhtHEg9rYM41LqGzSa0AfCZFWKSUqwYIY14DsvF9QHEOiEBv8Clq3RU/s320/bpmn_09.png" width="320" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Seleccione <i style="mso-bidi-font-style: normal;">la
Tarea Humana</i> y agregue un evento de finalización desde el menú contextual.
El evento de finalización es el que tiene el borde en “negrita” o borde relleno
y grueso. </span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhH52137AdyP8u8FTD9oHEI0fcnXSKr02LdffVcHESnVHPllmkZX6XRhrcamX5eaXh2AJBdHQDEzcoY08uEemxj9LjSujqEsEW4M0UdUZ6FTM1sPszcrLv5xUxMucZSo8oQQaD7YfqSfuQ/s1600/bpmn_10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhH52137AdyP8u8FTD9oHEI0fcnXSKr02LdffVcHESnVHPllmkZX6XRhrcamX5eaXh2AJBdHQDEzcoY08uEemxj9LjSujqEsEW4M0UdUZ6FTM1sPszcrLv5xUxMucZSo8oQQaD7YfqSfuQ/s320/bpmn_10.png" width="320" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<h2 class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Configurar la Tarea Humana</span></h2>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Seguidamente seleccione la <i style="mso-bidi-font-style: normal;">Tarea Humana</i>, vaya ahora a la ventana de propiedades y cambie el <i style="mso-bidi-font-style: normal;">ID</i> de la tarea a “Task_Solicitar_Prestamo”,
actualice la propiedad <i style="mso-bidi-font-style: normal;">Assignee</i> a “john”.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4bv1MCn_uAEL-I58fycZGOfwYKOpkdBs4q4ID5HpYMtNyHS-hUuBGsGnAaHAKATqiEvTu6vHbaORdFEd5tVOd81KHZzRSg1xskW3-fdgCJNKIeOHOkLCeoLdVvh0aWv1v-hYL8C89UKw/s1600/bpm11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4bv1MCn_uAEL-I58fycZGOfwYKOpkdBs4q4ID5HpYMtNyHS-hUuBGsGnAaHAKATqiEvTu6vHbaORdFEd5tVOd81KHZzRSg1xskW3-fdgCJNKIeOHOkLCeoLdVvh0aWv1v-hYL8C89UKw/s320/bpm11.png" width="320" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<h2 class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Configurar el Proceso para su ejecución</span></h2>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Haga click en alguna región en blanco dentro
del diagrama BPM, paso seguido establezca el ID del proceso a un valor
adecuado, en este caso usaremos “Process_Solicitud_Prestamo”. Este valor es muy
importante, pues es una de las opciones principales que usaremos para iniciar
nuestros procesos por medio de la API más adelante en estas publicaciones. </span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Por otra parte, es necesario asignarle al proceso
un nombre adecuado y, opcionalmente, un número de versión.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Así mismo debemos establecer la propiedad <i style="mso-bidi-font-style: normal;">Executable</i> a true, marcando la casilla o
caja de chequeo adecuada. Sí no establecemos esta propiedad el proceso será
ignorado por el motor de procesos de <i style="mso-bidi-font-style: normal;">Camunda</i>.</span><br />
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy2CFWnLKdFI1YnsjILnY8NR6oel3Oz5QNAp5Tkh-qidWn4euwDl9m0SNhCIsgIPSyURRKsYKMLEadMEvsHNCebpx1N_EY0p2ASwtlodJC9GCuZbrTcoOyIg25VkF9E4sPqDQcRp2i958/s1600/bpm12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy2CFWnLKdFI1YnsjILnY8NR6oel3Oz5QNAp5Tkh-qidWn4euwDl9m0SNhCIsgIPSyURRKsYKMLEadMEvsHNCebpx1N_EY0p2ASwtlodJC9GCuZbrTcoOyIg25VkF9E4sPqDQcRp2i958/s320/bpm12.png" width="292" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<h2 class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Guardar los cambios</span></h2>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Una vez que hemos cumplido con estas, a todas
luces elementales, configuraciones, llega la hora de guardar nuestro proceso de
manera que quede disponible y visible para el proyecto <i style="mso-bidi-font-style: normal;">Maven</i> <i style="mso-bidi-font-style: normal;">Java</i> que habíamos
configurado previamente. </span><br />
</div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Vaya al menú <i style="mso-bidi-font-style: normal;">File</i> del editor, seleccione la opción <i style="mso-bidi-font-style: normal;">Save as</i>…, en la ventana de dialogo desplegada seleccione la ruta
del <i style="mso-bidi-font-style: normal;">workspace</i> donde se creó el
proyecto Maven Java anterior, y busque la carpeta<span style="mso-spacerun: yes;"> </span><i style="mso-bidi-font-style: normal;">src/main/resources</i>,
dele un nombre adecuado al archivo como <i style="mso-bidi-font-style: normal;">diagrama_sol_prestamo_1.bpmn.</i>
Sí tiene el eclipse abierto pulse la tecla F5 y el recurso estará disponible
dentro del proyecto.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDspHUmNfY6bpOBdfG2xsh5OpROGJAxaFc0wuJHsnZ8c4ZDZ0KxcJMRJTFBvVXoXJA6HVdmSYZdhyphenhyphenkhpbnJi9w46goE2cHgVELImkeo4PCXq6tRCRXd1MY6mEv9B3kiLz30YUpKpvrtmc/s1600/bpm13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="93" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDspHUmNfY6bpOBdfG2xsh5OpROGJAxaFc0wuJHsnZ8c4ZDZ0KxcJMRJTFBvVXoXJA6HVdmSYZdhyphenhyphenkhpbnJi9w46goE2cHgVELImkeo4PCXq6tRCRXd1MY6mEv9B3kiLz30YUpKpvrtmc/s320/bpm13.png" width="320" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Ya tenemos un proyecto configurado y un proceso
adecuado listo para ser desplegado y puesto a prueba en el motor de <i style="mso-bidi-font-style: normal;">BPM</i> de <i style="mso-bidi-font-style: normal;">Camunda</i>, lo cual es el tema de nuestra próxima publicación.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL" style="mso-ansi-language: ES-CL;">Hasta pronto.</span></div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-89363386082281460382016-11-16T13:56:00.002-08:002016-11-16T13:56:45.509-08:00Primeros pasos con Camunda BPM – Configurar Proyecto JAVA<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; line-height: 120%; text-align: left; }a:link { color: rgb(0, 0, 255); }</style>
<br />
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">En
nuestro <a href="http://pigbar-hal9k.blogspot.cl/2016/11/primeros-pasos-con-camunda-bpm.html">artículo
anterior</a> dimos inicio a la instalación de la plataforma de
</span><span lang="es-CL"><i>Camunda</i></span><span lang="es-CL">
</span><span lang="es-CL"><i>BPM</i></span><span lang="es-CL"> y del
modelador o editor.</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">En
esta oportunidad vamos a tratar el tema de cómo configurar nuestro
ambiente de desarrollo para poder modelar procesos, crear clases
asociadas a estos procesos y desplegar nuestros procesos en la
plataforma de </span><span lang="es-CL"><i>BPM</i></span><span lang="es-CL">.</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Usaremos
</span><span lang="es-CL"><i>Eclipse</i></span><span lang="es-CL">
como </span><span lang="es-CL"><i>IDE</i></span><span lang="es-CL">
para el desarrollo y </span><span lang="es-CL"><i>Maven</i></span><span lang="es-CL">
como herramienta de construcción del proyecto. </span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwQYijh4E7aA2L2T2FV07npJXR0o2xBaVjZfgf3tJebLUG3vP5eMttYhlAryw05ldDtGhZ8KYGInzf8eKe6cMskTytLeMeGnqJdeA-jfKYsOYw0fGhF0ed-8HOvqmw8bFuD0sOK851cRs/s1600/camunda_paltform_java.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="176" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwQYijh4E7aA2L2T2FV07npJXR0o2xBaVjZfgf3tJebLUG3vP5eMttYhlAryw05ldDtGhZ8KYGInzf8eKe6cMskTytLeMeGnqJdeA-jfKYsOYw0fGhF0ed-8HOvqmw8bFuD0sOK851cRs/s320/camunda_paltform_java.png" width="320" /></a></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<a name='more'></a>
<br />
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">¿Se
pueden modelar y desplegar procesos sin usar </span><span lang="es-CL"><i>Eclipse</i></span><span lang="es-CL">
ni </span><span lang="es-CL"><i>Maven</i></span><span lang="es-CL">? </span>
</div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">La
respuesta es SI. </span>
</div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Sí
Ud. sabe lo que hace puede generar su propio proyecto .</span><span lang="es-CL"><i>war</i></span><span lang="es-CL">
de java que contenga todos los archivos necesarios con la estructura
requerida. Obvio que con </span><span lang="es-CL"><i>Maven</i></span><span lang="es-CL">
sobre </span><span lang="es-CL"><i>Eclipse</i></span><span lang="es-CL">
todo este proceso resulta mucho más fácil de gestionar y de
ejecutar.</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Es
más, hasta podemos modelar nuestros procesos </span><span lang="es-CL"><i>BPMN</i></span><span lang="es-CL">
sin hacer uso del </span><span lang="es-CL"><i>Modeler</i></span><span lang="es-CL">
o editor de </span><span lang="es-CL"><i>Camunda</i></span><span lang="es-CL">.
Al ser el editor de </span><span lang="es-CL"><i>Camunda</i></span><span lang="es-CL">
compatible con el estándar </span><span lang="es-CL"><i>BPMN 2.0</i></span><span lang="es-CL">,
cualquier editor o software de edición de procesos compatible con
dicho estándar, sin aportar etiquetas propias del fabricante, se
podrá usar como fuente para los diagramas de proceso que usaremos en
nuestro proyecto de </span><span lang="es-CL"><i>BPM</i></span><span lang="es-CL">.</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Obviamente,
en estos artículos usaremos las bondades suministradas por el
</span><span lang="es-CL"><i>Modeler</i></span><span lang="es-CL"> de
</span><span lang="es-CL"><i>Camunda</i></span><span lang="es-CL">.</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Así
que sin mayores preámbulos…. Manos a las sobras…</span></div>
<ol>
</ol>
<h2 style="text-align: left;">
<span lang="es-CL">1.- Crear
un nuevo proyecto Maven en </span><span lang="es-CL"><i>Eclipse</i></span>
</h2>
<ol>
</ol>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Vaya
a su editor </span><span lang="es-CL"><i>eclipse</i></span><span lang="es-CL">,
opción “</span><span lang="es-CL"><i>File</i></span><span lang="es-CL">”,
opción “</span><span lang="es-CL"><i>New</i></span><span lang="es-CL">”
y escoja la opción “</span><span lang="es-CL"><i>Maven Project</i></span><span lang="es-CL">”,
o la opción “</span><span lang="es-CL"><i>Other</i></span><span lang="es-CL">”
en caso de que no tenga desplegada la opción de proyectos </span><span lang="es-CL"><i>Maven</i></span><span lang="es-CL">
en el menú principal.</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">En
esta ventana seleccionamos nuestros </span><span lang="es-CL"><i>Workspace</i></span><span lang="es-CL">
o dejamos el que ya está definido por omisión, y seleccionamos la
opción de “</span><span lang="es-CL"><i>Create a simple Project
(skip archetype selection)</i></span><span lang="es-CL">”</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGTXYSNhu8r_3yF8YDD8k3At-6-YRa4I0FNb_IIlwEFHXX0mlLObl3pMqp6Myp1qPRnhoV0fNm0MTUMRFKZxoFNjyernKJOvzCc4UCK3CyejHv76KO7PeTuhVJy41qT5cMj67NDfa0fpY/s1600/maven_proyect_01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGTXYSNhu8r_3yF8YDD8k3At-6-YRa4I0FNb_IIlwEFHXX0mlLObl3pMqp6Myp1qPRnhoV0fNm0MTUMRFKZxoFNjyernKJOvzCc4UCK3CyejHv76KO7PeTuhVJy41qT5cMj67NDfa0fpY/s400/maven_proyect_01.png" width="400" /></a></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL"><br /></span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Hacemos
</span><span lang="es-CL"><i>click</i></span><span lang="es-CL">,
pinchar, en el botón “</span><span lang="es-CL"><i>next</i></span><span lang="es-CL">”
para que lleguemos a la pestaña donde debemos configurar nuestros
artefactos del proyecto.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhewpz34L-yRAwNnu3aw8UsUWofWULncb2NPLp56bGJgjvXPjgaW_NHEx-3k_GJobSp1W8tZfnL6ozAxUAvLRNtGVvez5R5K8gOdiA9-gXR2_PtkwbKY9MQeK1K3nmXtuZ0mBAgBhGFRUQ/s1600/maven_proyect_02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhewpz34L-yRAwNnu3aw8UsUWofWULncb2NPLp56bGJgjvXPjgaW_NHEx-3k_GJobSp1W8tZfnL6ozAxUAvLRNtGVvez5R5K8gOdiA9-gXR2_PtkwbKY9MQeK1K3nmXtuZ0mBAgBhGFRUQ/s400/maven_proyect_02.png" width="400" /></a></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL"><br /></span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Acá
establecemos los siguientes elementos:</span></div>
<br />
<pre class="brush:xml"> Group ID = org.pigbar.bpm (o el ID de Grupo de su preferencia)
Artifact ID = bpm_demo (Su nombre de proyecto BPM o artefacto)
Version = 0.1 (o su esquema de versión favorito)
Packaging= war (el empaquetado del proyecto BPM es un .war estándar)
</pre>
<br />
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; line-height: 120%; text-align: left; }a:link { color: rgb(0, 0, 255); }</style>
<br />
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Cuando
tenga todo listo pulse el botón “</span><span lang="es-CL"><i>Finish</i></span><span lang="es-CL">”.
Eclipse procederá a configurar para nosotros un proyecto </span><span lang="es-CL"><i>Java</i></span><span lang="es-CL">
con la distribución de un proyecto </span><span lang="es-CL"><i>Maven</i></span><span lang="es-CL">
cualquiera y los mostrará en el explorador, </span><span lang="es-CL"><i>explorer</i></span><span lang="es-CL">,
de proyectos de la herramienta.</span></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNW1oEZS17phJCArxg_X4gnULrvaMXEyVdtZQ-0bAVouLP2cPtt5HjW4lryTEvrQ3E6mfUn7pOSbFAd5Y1Pn37WfHCF7xMadX-6uXoToRv-eY0UBQZhVDDk00cfGGpLJuL7-x-ePmksKE/s1600/maven_proyect_03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNW1oEZS17phJCArxg_X4gnULrvaMXEyVdtZQ-0bAVouLP2cPtt5HjW4lryTEvrQ3E6mfUn7pOSbFAd5Y1Pn37WfHCF7xMadX-6uXoToRv-eY0UBQZhVDDk00cfGGpLJuL7-x-ePmksKE/s1600/maven_proyect_03.png" /></a></div>
<h2 lang="es-CL" style="line-height: 115%; margin-bottom: 0.35cm; text-align: left;">
<span lang="es-CL">2.- Agregar
las dependencias </span><span lang="es-CL"><i>Maven</i></span><span lang="es-CL">
de </span><span lang="es-CL"><i>Camunda</i></span>
</h2>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Una
vez creado nuestro proyecto </span><span lang="es-CL"><i>Maven</i></span><span lang="es-CL">,
es hora de agregar las dependencias correspondientes en el archivo
</span><span lang="es-CL"><i>pom.xml</i></span><span lang="es-CL">
del proyecto.</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Abra
el archivo </span><span lang="es-CL"><i>pom.xml</i></span><span lang="es-CL">,
el cual se encuentra en el directorio raíz de las carpetas del
proyecto, y agreguemos las siguientes definiciones o dependencias:</span></div>
<br /></div>
<pre class="brush:xml"><project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" 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>org.pigbar.bpm</groupid>
<artifactid>bpm_demo</artifactid>
<version>0.1</version>
<packaging>war</packaging>
<dependencymanagement>
<dependencies>
<dependency>
<groupid>org.camunda.bpm</groupid>
<artifactid>camunda-bom</artifactid>
<version>7.5.0</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencymanagement>
<dependencies>
<dependency>
<groupid>org.camunda.bpm</groupid>
<artifactid>camunda-engine</artifactid>
<scope>provided</scope>
</dependency>
<dependency>
<groupid>javax.servlet</groupid>
<artifactid>javax.servlet-api</artifactid>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-war-plugin</artifactid>
<version>2.3</version>
<configuration>
<failonmissingwebxml>false</failonmissingwebxml>
</configuration>
</plugin>
</plugins>
</build>
</project>
</pre>
<br />
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; line-height: 120%; text-align: left; }a:link { color: rgb(0, 0, 255); }</style>
<br />
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Guarde
los cambios y listo, ya podemos hacer nuestro primer “</span><span lang="es-CL"><i>build</i></span><span lang="es-CL">”
del Proyecto.</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Ubique
el archivo </span><span lang="es-CL"><i>pom.xml</i></span><span lang="es-CL">
en el explorador de proyectos o de paquetes, haga clik derecho sobre
el archivo y seleccione la opción “</span><span lang="es-CL"><i>Run
as</i></span><span lang="es-CL">” y luego “</span><span lang="es-CL"><i>Maven
install</i></span><span lang="es-CL">”. Esto hará que el Maven
descargue las dependencias incorporados en el archivo </span><span lang="es-CL"><i>pom.xml</i></span><span lang="es-CL">
de nuestro proyecto.</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Al
final debe darnos un mensaje del tipo:</span></div>
<br /></div>
<pre class="brush:xml">[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
</pre>
<br />
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; line-height: 120%; text-align: left; }a:link { color: rgb(0, 0, 255); }</style>
<br />
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Vayamos
al siguiente paso…</span></div>
</div>
<h2 style="text-align: left;">
<span lang="es-CL">3.- Agregar
una Clase de Aplicación de Proceso (Process Application)</span></h2>
<span lang="es-CL"> </span>
<br />
<div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">La
clase Aplicación de Proceso constituye la interface entre nuestro
proceso y el motor de </span><span lang="es-CL"><i>BPM</i></span><span lang="es-CL">
de la plataforma de </span><span lang="es-CL"><i>Camunda</i></span><span lang="es-CL">.</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Vayamos
al explorador de proyectos, ubique la carpeta </span><span lang="es-CL"><i>src/main/java</i></span><span lang="es-CL">
y cree allí un paquete con un nombre adecuado a sus estándares y
preferencias, por ejemplo:</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<i><span lang="es-CL">pigbar.bpm.apps.bpm_demo</span></i></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Dentro
de ese paquete cree una nueva clase Java con el nombre:</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<i><span lang="es-CL">BPMDemoApp</span></i></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Y
que extienda de la clase:</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<i>org.camunda.bpm.application.impl.ServletProcessApplication</i></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzzlPTCsJ_v8xiUxWe5pf7ZVsmtAwGz0ZiZRdVGmysl31NUmtT4d7E3YUE9kagPwhq2L_tcS6ktDEjiBCvM4vzLZMZN_jV7mxpnjuAR9Mtx11XMDUFofu9WhUdEEXfcLij5AGiHff7eEQ/s1600/bpmdemoapp01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="396" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzzlPTCsJ_v8xiUxWe5pf7ZVsmtAwGz0ZiZRdVGmysl31NUmtT4d7E3YUE9kagPwhq2L_tcS6ktDEjiBCvM4vzLZMZN_jV7mxpnjuAR9Mtx11XMDUFofu9WhUdEEXfcLij5AGiHff7eEQ/s400/bpmdemoapp01.png" width="400" /></a></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<br />
<br /></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Agregue
la anotación </span><span lang="es-CL"><i>@ProcessApplication("BPM
Demo")</i></span><span lang="es-CL"> a la clase, la cual nos
debe quedar de la siguiente forma:</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
</div>
</div>
<pre class="brush:java">package pigbar.bpm.apps.bpm_demo;
import org.camunda.bpm.application.ProcessApplication;
import org.camunda.bpm.application.impl.ServletProcessApplication;
@ProcessApplication("BPM Demo")
public class BPMDemoApp extends ServletProcessApplication {
// sin implementar cuerpo de la clase
}
</pre>
<br />
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; line-height: 120%; text-align: left; }a:link { color: rgb(0, 0, 255); }</style>
<br />
<h2 style="text-align: left;">
<span lang="es-CL">4.- Agregar
archivo descriptor de despliegue </span><span lang="es-CL"><i>processes.xml</i></span>
</h2>
<div>
<div lang="es-CL" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">El
archivo </span><span lang="es-CL"><i>processes.xml</i></span><span lang="es-CL">
se utiliza para indicarle valores de configuración a la plataforma
de BPM de Camunda donde nuestro proceso va a ser desplegado y
ejecutado.</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Este
archivo debe ser creado en el directorio
“</span><span lang="es-CL"><i>src/main/resources/META-INF</i></span><span lang="es-CL">”,
así que vayamos a la carpeta “</span><span lang="es-CL"><i>src/main/resources</i></span><span lang="es-CL">”
y en ella creamos la carpeta “</span><span lang="es-CL"><i>META-INF</i></span><span lang="es-CL">”
en caso de no existir. Ya dentro de este directorio procedemos a
crear el archivo </span><span lang="es-CL"><i>processes.xml</i></span><span lang="es-CL">
con el siguiente contenido:</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
</div>
</div>
<pre class="brush:xml"><process-application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.camunda.org/schema/1.0/ProcessApplication">
<process-archive name="bpm-demo">
<process-engine>default</process-engine>
<properties>
<property name="isDeleteUponUndeploy">false</property>
<property name="isScanForProcessDefinitions">true</property>
</properties>
</process-archive>
</process-application>
</pre>
<br />
<style type="text/css">p { margin-bottom: 0.25cm; direction: ltr; line-height: 120%; text-align: left; }a:link { color: rgb(0, 0, 255); }</style>
<br />
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">El
archivo processes.xml se puede dejar vacío, en ese caso se usa la
<a href="https://docs.camunda.org/manual/latest/user-guide/process-applications/the-processes-xml-deployment-descriptor/#empty-processes-xml">configuración
por omisión</a> de la plataforma.</span></div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Ya
estamos listos para modelar nuestros procesos, pero eso es tema de
nuestra próxima publicación.</span></div>
<div lang="es-CL" style="line-height: 115%; margin-bottom: 0.35cm;">
<br />
<br />
</div>
<div style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Hasta
pronto.</span></div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-64865762515276983532016-11-15T16:44:00.000-08:002016-11-15T16:44:19.532-08:00Primeros pasos con Camunda BPM...<div dir="ltr" style="text-align: left;" trbidi="on">
<h2>
<style type="text/css">h2 { margin-bottom: 0cm; direction: ltr; color: rgb(79, 129, 189); line-height: 115%; text-align: left; page-break-inside: avoid; }h2.western { font-family: "Cambria",serif; font-size: 13pt; }h2.cjk { font-size: 13pt; }h2.ctl { font-size: 13pt; }h1 { margin-top: 0.85cm; margin-bottom: 0cm; direction: ltr; color: rgb(54, 95, 145); line-height: 115%; text-align: left; page-break-inside: avoid; }h1.western { font-family: "Cambria",serif; font-size: 14pt; }h1.cjk { font-size: 14pt; }h1.ctl { font-size: 14pt; }p { margin-bottom: 0.25cm; direction: ltr; line-height: 120%; text-align: left; }a:link { color: rgb(0, 0, 255); }</style>
</h2>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">... e impresiones.</span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">En
el competido mercado de las <a href="https://soaagenda.com/2007/08/09/que-es-bpm-que-es-bpms/" target="_blank">Soluciones de Business Process Management(BPMS)</a> se encuentran diversos fabricantes con productos u opciones de
diversa calidad. Por mi foco de carrera o área de trabajo me ha
tocado prácticamente trabajar con la gran e inmensa mayoría de
todas estas soluciones de software, desde las más sencillas y
económicas, las más populares y conocidas, las comerciales, las de
código abierto, y hasta las más costosas, “worldclass”, de
estas soluciones de <i>BPM. </i></span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL"><i><br /></i></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQEDhrhzTAvXh0H5V0L5k3a1Kq-0Te4Tq5o19FwI9qLB0YY3Rw4wGlaHbQepWuSlJ36hXb-hSCCLcCbs9CD5Dld3RRYvTao1ouipCfLw8uFk75tjgVFILQ4UJVIDMgRMZhDd82RkEp7Ec/s1600/camunda_logo_largo.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="75" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQEDhrhzTAvXh0H5V0L5k3a1Kq-0Te4Tq5o19FwI9qLB0YY3Rw4wGlaHbQepWuSlJ36hXb-hSCCLcCbs9CD5Dld3RRYvTao1ouipCfLw8uFk75tjgVFILQ4UJVIDMgRMZhDd82RkEp7Ec/s320/camunda_logo_largo.jpeg" width="320" /></a></div>
<a name='more'></a><br /><div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Dentro
de este ecosistema variopinto, nos encontramos con una solución de
<i>BPM</i> de código abierto, <a href="https://camunda.org/" target="_blank"><b><i>Camunda,</i></b></a> que viene con un completo editor o
modelador de <i>BPMN,</i> un poderoso y flexible motor de <i>BPM</i> y una suite de
gestión de procesos y tareas plena de funcionalidades. Pero aún hay
más, esta herramienta incluye capacidad para el modelado y ejecución
de reglas de negocio <i>(DMN</i> 1.1) mediante matrices de decisión, así
como el modelado y ejecución de casos de negocio <i>(CMMN</i> 1.1). Estoy
hablando de un fabricante poco conocido por acá en la América
completa, pero que, gracias a su gran calidad y particular enfoque,
viene ganando terreno y muy buena fama dentro del mercado mundial de
las herramientas de automatización de procesos de negocio. Su
solución de <i>BPM</i> viene en dos “sabores” fundamentales; la versión
de la comunidad y la versión Empresarial o Licenciada.</span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Hace
rato que escribí un artículo sobre mi visión personal del enfoque
en <i>BPM,</i> ese artículo se titulaba “<a href="http://pigbar-hal9k.blogspot.cl/2016/01/not-zero-code-nor-complex-process.html" target="_blank">Not Zero Code Nor ComplexProcess</a>”, ni cero código ni procesos complejos, en el cual
manifiesto mi preferencia por las herramientas que resultan
“<i>developer friendly</i>” y por el modelado efectivo para la
automatización eficiente. Imaginen mi expresión de agrado cuando me
acerqué a <i>Camunda</i> <i>BPM</i> y descubrí que esa es precisamente su muy
particular visión, filosofía y enfoque en cuanto a las soluciones
de <i>BPM</i> basadas en la notación <i>BPMN</i> 2.0. </span>
</div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Especial
mención merece el hecho de que cuando descargué el producto por
primera vez en su versión 7.5, y me disponía a iniciar mi prueba o
evaluación de esta solución de <i>BPM,</i> me encontraba con varias
inquietudes, por lo que me descargué uno de los <i>whitepapers</i> que me
parecieron interesantes en la página del fabricante. Para mi
sorpresa, al poco rato de haber descargado el documento en cuestión
recibí un e-mail de un miembro del equipo de <i>Camunda</i> <i>BPM</i> quien me
agradecía por mi interés en la herramienta y su documentación, y
se puso a la orden ante cualquier inquietud que pudiese tener. Todo
en perfecto español, lo cual es un detalle que algunos pueden
encontrar muy agradable, incluso yo.</span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Claro
que aproveché la oportunidad y le planteé de inmediato algunas
dudas que tenía, sobre todo en lo referente a la comparación de
<i>Camunda</i> con otras soluciones de <i>BPM</i> existente en el mercado. Al cabo
de no más de un día recibí una más que amplia y adecuada
respuesta a todas mis preguntas, bien sustentada técnicamente y con
referencias de sobra a mayor documentación y casos de éxito. </span>
</div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Ya
se habrán dado cuenta a estas alturas que mi impresión con el
producto, y tanto la comunidad y empresa que lo soportan, ha sido
excelente.</span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Doy
con esto inicio a una serie de publicaciones en las que aprovechare
las bondades de <i>Camunda</i> <i>BPM</i> para hablar y dar a conocer un poco sobre
esta fabulosa herramienta y su implementación de la notación <i>BPMN.</i>
Usaré como base la información disponible en el sitio de
documentación de Camunda <i>BPM</i> y los resultados de mis propias pruebas
sobre la versión de la comunidad del producto.</span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Así
que, como ya es costumbre, iniciamos con nuestro grito de batalla:
Manos a las sobras!!!</span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<h3 class="western" style="text-align: left;">
<span lang="es-CL">Descarga e Instalación</span></h3>
<div align="justify" lang="es-CL" style="line-height: 115%; margin-bottom: 0.35cm;">
</div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Para
trabajar con <i>Camunda</i> <i>BPM</i> lo primero que necesita es instalar la
plataforma <i>BPM</i> de <i>Camunda</i> (motor de <i>BPM</i> y herramientas adicionales) y
el modelador <i>BPMN</i> 2.0. Vamos a necesitar tener instalado y
configurado nuestro ambiente con la <i>JDK</i> 1.7 o superior.</span></div>
<h4 align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL"> </span><span lang="es-CL">Pre-requisitos</span></h4>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Asegúrese
de tener instalado o disponibles los siguientes productos de
software:</span></div>
<ul style="text-align: left;">
<li>Java
Development Kit <i>(JDK)</i> 1.7 +</li>
<li><span lang="es-CL"><i>Apache</i>
<i>Maven</i></span></li>
<li><span lang="es-CL">Un
<i>navegador</i> <i>web</i> de última generación </span>
</li>
</ul>
<h4 class="western" style="text-align: left;">
<span lang="es-CL">Plataforma BPM de Camunda</span></h4>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Vaya
al <a href="https://camunda.org/download/" target="_blank">sitio del fabricante</a> y descargue la distribución de su
preferencia. En este ejemplo vamos a usar la versión que viene pre
configurada con <i>Apache Tomcat</i>, pero igual la podemos descargar con
<i>JBoss AS 7</i> e incluso con <i>Wildfly</i> 10. Genial.</span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZvpyOZBJU4k3YfkL4poh8tuqHBafnSYGT6oE3AXMtb5SfoRf-mc_nLuECzCJgZQRpuiuDspuHdqGKzeqMpx2jHQpMX_nJ7uNqv9Wyt3DwyQj3nkloCPmHwSnCVI7uC8m9Er77NUQ01MA/s1600/camunda_download.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="197" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZvpyOZBJU4k3YfkL4poh8tuqHBafnSYGT6oE3AXMtb5SfoRf-mc_nLuECzCJgZQRpuiuDspuHdqGKzeqMpx2jHQpMX_nJ7uNqv9Wyt3DwyQj3nkloCPmHwSnCVI7uC8m9Er77NUQ01MA/s400/camunda_download.png" width="400" /></a></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Una
vez que tengamos descargada nuestra distribución, descomprímala o
desempaquétela en el directorio de su preferencia,
<i>“/developer/tools/camunda-bpm-tomcat-7.5.0</i>” por ejemplo. De ahora
en adelante llamaremos a ese directorio <i>CAMUNDA_HOME.</i></span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Luego
de haber descomprimido la plataforma de <i>Camunda</i> <i>BPM,</i> diríjase al
directorio <i>CAMUNDA_HOME</i> y ejecute el script denominado
<i>start-camunda.sh,</i> para los usuarios de Unix-Linux, o el
<i>start-camunda.bat</i> para la plataforma Windows.</span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Este
script en cuestión, levanta el servidor con el motor de <i>Camunda</i> <i>BPM</i>
y las herramientas de gestión asociadas. Usualmente abre una ventana
de navegador web con la pantalla de bienvenida de la plataforma. Sí
no se abre automáticamente sólo tenemos que visitar la <i>URL</i>
</span><span style="color: #555555;"><span style="font-family: Helvetica, serif;"><span lang="es-CL"><span style="background: #ffffff;"> </span></span></span></span><a href="http://localhost:8080/camunda-welcome/index.html"><span style="color: #155cb5;"><span style="font-family: Helvetica, serif;"><span lang="es-CL"><span style="background: #ffffff;">http://localhost:8080/camunda-welcome/index.html</span></span></span></span></a></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWTjCKE-9PLTC0VvhwsHu5iEg_McNgs0ky_M4om-xj2bt6H4NOPEBW9CagbOfrnvOucBE6Q2dzzPE73cDuWxol05SLjjFKsk-E2LqCs2Wo0zya38RyXMHEL6p8y1_EDTrE4S8p8DQF-tM/s1600/camunda_welcome.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWTjCKE-9PLTC0VvhwsHu5iEg_McNgs0ky_M4om-xj2bt6H4NOPEBW9CagbOfrnvOucBE6Q2dzzPE73cDuWxol05SLjjFKsk-E2LqCs2Wo0zya38RyXMHEL6p8y1_EDTrE4S8p8DQF-tM/s400/camunda_welcome.png" width="400" /></a></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">En
esa pantalla vamos a encontrar enlaces para <i>Camunda Tasklist</i>, <i>Camunda
Cockpit </i>y <i>Camunda Admin.</i></span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL"><i>Camunda
Tasklist, </i>es la excelente plataforma para la gestión de procesos,
instancias y tareas de Camunda BPM. Permite iniciar procesos, ver las
tareas asignadas, ejecutar las tareas, entre muchas otras opciones.</span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_T66pUmn3UQ511rVUucxQ2DhMYlg69WRAwQQIX3ZpbBzUUKiqmk2G5-zZvVpGaWUhWBjrPewzCgvqncTRJUX6hh6rnJBzMjXCESJzmB7heuuiTByNcJi3zGj-r_pcBD75yVI1JtvSULY/s1600/camunda_task.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="197" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_T66pUmn3UQ511rVUucxQ2DhMYlg69WRAwQQIX3ZpbBzUUKiqmk2G5-zZvVpGaWUhWBjrPewzCgvqncTRJUX6hh6rnJBzMjXCESJzmB7heuuiTByNcJi3zGj-r_pcBD75yVI1JtvSULY/s400/camunda_task.png" width="400" /></a></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL"><i>Camunda
Cockpit</i>, es la herramienta de gestión de instancias de <i>Camunda</i> <i>BPM.</i>
Una invaluable inclusión en la plataforma. Permite ver las variables
de un proceso y modificarlas, revisar en cual etapa de ejecución se
encuentra una instancia, y, por si fuera poco, permite mover la
ejecución a una tarea cualquiera, iniciar una instancia en una tarea
específica e incluso migrar las instancias actuales hacia una
versión más actualizada del mismo proceso.</span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw1EiOQJWY2gbmVePCiSk6zy0NNPUmXWQYloMafEpw5r_kpuaq8t29Cqb_1Bd5KgSY3iaMpssOSJx4WtlbhLRSycNY2ZFvLDF0d9SY4tx-TznTNOGLx-sXeWS-kaB3HGa15dGy-01mpcY/s1600/camunda_cockpit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="197" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw1EiOQJWY2gbmVePCiSk6zy0NNPUmXWQYloMafEpw5r_kpuaq8t29Cqb_1Bd5KgSY3iaMpssOSJx4WtlbhLRSycNY2ZFvLDF0d9SY4tx-TznTNOGLx-sXeWS-kaB3HGa15dGy-01mpcY/s400/camunda_cockpit.png" width="400" /></a></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL"><i>Camunda
Admin</i>, es la herramienta de gestión de usuarios y roles de<i> Camunda
BPM</i>.</span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivVQEloU9NJDC1wquY_OGgTrYis6DREUB7Gn3QR8rZ-AkD_vvuCAEoYdjEv2K7qSaQcXjH8QnqDZGUsZlCXONnMLF-GOjE-kavGCZfSnPbr9CcWEWT6KGKADJv-YJJL17m20VNxAMiG34/s1600/camunda_admin.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="197" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivVQEloU9NJDC1wquY_OGgTrYis6DREUB7Gn3QR8rZ-AkD_vvuCAEoYdjEv2K7qSaQcXjH8QnqDZGUsZlCXONnMLF-GOjE-kavGCZfSnPbr9CcWEWT6KGKADJv-YJJL17m20VNxAMiG34/s400/camunda_admin.png" width="400" /></a></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL"> </span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Recuerde,
en caso de dudas siempre puede acudir al fórum de la comunidad.</span></div>
<div align="justify" lang="es-CL" style="line-height: 115%; margin-bottom: 0.35cm;">
<br />
</div>
<h4 class="western" style="text-align: left;">
<span lang="es-CL">Modelador de Camunda</span></h4>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Para
instalar el modelador de <i>BPMN</i> 2.0 de <i>Camunda,</i> debe dirigirse a la
<a href="https://camunda.org/download/modeler/" target="_blank">página de descargas</a> y bajar la versión que convenga a su
plataforma.</span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimhgpf5nK_SQIaRxfpHA1ZkRKTs-67cyDamloAGfKd9x9FLz8MAkdJlZwjO0Y-7V8CeQqXX05XGxm-tvMuBComojpRA7P-18Z16pGcyj1KZTZMQUy4ebr8LT8FsSw0xB6IkI-oMzLMmX0/s1600/camunda_download_modeler.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="196" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimhgpf5nK_SQIaRxfpHA1ZkRKTs-67cyDamloAGfKd9x9FLz8MAkdJlZwjO0Y-7V8CeQqXX05XGxm-tvMuBComojpRA7P-18Z16pGcyj1KZTZMQUy4ebr8LT8FsSw0xB6IkI-oMzLMmX0/s400/camunda_download_modeler.png" width="400" /></a></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Descomprima
el archivo descargado en el directorio de su agrado, y seguidamente
ejecute el archivo denominado <i>camunda-modeler.</i></span></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAaGVPq-r2WsEFtyu13m_IoxI4xFDxHSWbkudPLinDv6-gK1bzZjJ5E2xJL_iux8Ljpoc4xa768BRZZBPO6aRE5rV0B5qz0EGYx_UMIEmXPBjAJXeo5GfnBL2RlLbfrJ_fDsOQkVJLgwM/s1600/camunda_modeler.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="317" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAaGVPq-r2WsEFtyu13m_IoxI4xFDxHSWbkudPLinDv6-gK1bzZjJ5E2xJL_iux8Ljpoc4xa768BRZZBPO6aRE5rV0B5qz0EGYx_UMIEmXPBjAJXeo5GfnBL2RlLbfrJ_fDsOQkVJLgwM/s400/camunda_modeler.png" width="400" /></a></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<span lang="es-CL">Esto
abre la pantalla principal del editor o modelador el cual nos permite
desarrollar diagramas de<i> BPMN, DMN y CMMN.</i></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSQRvfNTZrjEiBRH-rWyaotMV9EXJ0niHdVgbumHA3O4ig9koZI63z5SInEQ7yk8_O8UFfsQD2yo0wK8D-2qyG7dnlhe4agMMbsAk0J_l72XGnOyD3MeZUQS1Sq4tnCKfTaf50Xyhne5I/s1600/camunda_modeler_bpmn.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSQRvfNTZrjEiBRH-rWyaotMV9EXJ0niHdVgbumHA3O4ig9koZI63z5SInEQ7yk8_O8UFfsQD2yo0wK8D-2qyG7dnlhe4agMMbsAk0J_l72XGnOyD3MeZUQS1Sq4tnCKfTaf50Xyhne5I/s320/camunda_modeler_bpmn.png" width="320" /></a></div>
<br />
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<br />
<br />
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
Como vemos es muy sencillo dar los primeros pasos con esta fabulosa plataforma de <i>BPM</i> que nos traen los amigos de <i>Camunda.</i></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
<br /></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
Hasta <i> una próxima entrega.</i></div>
<div align="justify" style="line-height: 115%; margin-bottom: 0.35cm;">
</div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com4tag:blogger.com,1999:blog-1012161132404905800.post-33948647209625035112016-11-09T10:32:00.002-08:002016-11-09T10:32:41.029-08:00Cero o Uno, that is the question<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Recuerde las máquinas o computadoras solo
entienden Ceros y Unos (0,1) encendido o apagado para ser más exactos. Cuando
tengamos computadores quánticos capaces de procesar tres estados o más esta
idea tendrá que cambiar. Pero mientras es sólo eso, ceros y unos.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ3Jl1dFC9irqCyk3LgT_JvIXdvfY7vSzXYmNQZjNRgEN9E63oDMPuBNnwjtPlYRKKPCOa3MoeDpfRLczpu97jfHhDoCvuxw66rt0iqz9Dqcct8aDWr4R88pDwrjan5r38HuBG3zpSIX0/s1600/binario.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ3Jl1dFC9irqCyk3LgT_JvIXdvfY7vSzXYmNQZjNRgEN9E63oDMPuBNnwjtPlYRKKPCOa3MoeDpfRLczpu97jfHhDoCvuxw66rt0iqz9Dqcct8aDWr4R88pDwrjan5r38HuBG3zpSIX0/s400/binario.jpg" width="368" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"></span></div>
<a name='more'></a><br /><br />
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Esa fabulosa canción que tanto le gusta y que
desea guardar en su computador, se almacena en algún formato que a la larga
será interpretado en ceros y unos. No se almacena sonido. No se almacenan
acordes. Son ceros y unos en diversas secuencias que son interpretados como
música.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Lo mismo ocurre sí se almacenan imágenes, hojas
de cálculo y cualquier otro medio o recurso.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Esa fabulosa página web, tal cual Ud la ve en
su navegador, es sólo la representación de un recurso, recurso que a su vez es
tan sólo ceros y unos. No se almacena caracteres ni etiquetas, son solo
secuencias numéricas que se
interpretaran como tales. Se obtiene una representación de ese recurso.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">TODO lo que Ud ve en la pantalla de su
ordenador, computador e incluso móvil, es tan sólo la representación de
diversos recursos; ceros y unos representados en algún modo o formato que los
humanos podamos entender.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Esto tiene, entre otras, dos consecuencias bien
importantes.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">La primera es que es IMPOSIBLE hacer nada útil,
como humanos, con esos recursos si no tenemos el programa que interprete el
formato que requerimos o los medios físicos para leer las fuentes de
almacenamiento.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Segunda, la representación para humanos es
incidental y no necesariamente requerida en lo que respecta a la comunicación
entre las partes del ordenador y entre ordenadores entre si.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">La primera de ellas, a su vez, acarrea una
consecuencia aterradora al largo plazo, la denominada era del <b>oscurantismo digital</b>.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Hagamos un ejercicio para exponer mejor lo que
intento explicar.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Voy a buscar entre mis viejos cajones de la
universidad, en los tempranos 90’s, cuando el diskette de 3,5 era el medio de
almacenamiento más popular.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Listo!! Eureka!! Tengo un Diskette disponible,
en buen estado y con archivos guardados.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Primer reto:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">¿Dónde DIABLOS leo ese Diskette?, ¿Con cuál
hardware?<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Ese medio de almacenamiento es un fósil de los
90’s y ya casi nadie del vulgo, del común, usa las unidades de disco necesarias
para leer estos dispositivos, y yo no soy la excepción. No tengo una unidad de diskettes.
Ninguno de mis amigos cercanos posee una.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Puntaje: Diskette 1, Humano 0.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Segundo reto:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Imaginemos que logro leer el, ya odioso,
diskette del primer reto. Supongamos que está en buen estado y que no tiene
sectores dañados. Sus datos no se han degradado.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Revisando los archivos me encuentro con que
son, en su mayoría, archivos con la extensión .wq1.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">¿Qué demonios es un archivo .wq1?<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Después de acudir por ayuda al grandioso San
Google, jajaja, caí en cuenta que se trataba de archivos de la, en su tiempo,
popular hoja de cálculo Quattro Pro de la extinta Borland para el sistema
operativo DOS. </span>De esa misma búsqueda, averigüé que podía abrir o leer esos
archivos usando la suite de ofimática “Corel WordPerfect Office X7”.</div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">No conseguí descargar Corel WordPerfect Office
X7, pero digamos que, al menos, ya sé cómo leer esos archivos, declaremos ½
punto a mi favor.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Puntaje: Diskette 1.5, Humano 0.5<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">¿Ya ven por donde va la idea? <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Imaginen dentro de 50 años. Va a ser titánico
intentar leer un archivo de los años 90. Ni hablar de épocas anteriores.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Con el devenir del tiempo, todos esos archivos
respaldados, serán inútiles sino tenemos el programa que permita interpretar
ese formato.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Si por alguna razón perdemos esos programas, o
la información de cómo se asocian con sus datos, nos encontraremos ante el
oscurantismo digital. Porque no sabremos, ni tendremos como saber, de que iba
toda esa “información” guardada en esos medios, si es que acaso aun disponemos
de los elementos o equipos necesarios para procesar a su vez los diversos
medios de almacenamiento de que dispongamos.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Respecto a la segunda gran consecuencia debo
agregar que esta acarrea la noción de que la representación de recursos para
los humanos es prioritaria, dejando de lado la disponibilidad de esos recursos
para la comunicación inter-máquinas.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">La gran mayoría de los esfuerzos que se han
llevado a cabo en áreas de desarrollo de software están vinculados a las
interfaces, capa de presentación, para humanos. Que sí los sistemas iOS,
Android, etc. Que sí frameworks en JQuery, Angular, NodeJS, etc. Todos
orientados a como brindar al usuario una “experiencia” superior. Y eso está muy
bien.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">El problema es que en ese esfuerzo hemos dejado
de lado el problema de fondo que buscamos resolver, el cual no es más que la
comunicación entre máquinas. REST no es más que un intento de facilitar esa
comunicación, y uno muy bueno. Pero hemos dado una vuelta de tuerca, un giro
completo, para volver a encontrarnos con problemas que ya habíamos resuelto de
manera efectiva, y ahora queremos dejar de lado esas soluciones envalentonados
por la supuesta novedad de nuestras plataformas tecnológicas.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Los sistemas IBM VM/CMS, MVS y UNIX son
ejemplos poderosos de grandes soluciones a grandes problemas, y por soluciones
grandes me refiero a soluciones innovadoras, eficientes y eficaces, sencillas y
geniales. Con muchos puntos de mejora obviamente. Pero grandes en su aporte e
impacto. No es de extrañar que estos ejemplos sean precisamente de sistemas
operativos usualmente asociados a grandes máquinas o mainframes.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">La naturaleza de los problemas que se
resolvieron con estos sistemas no ha cambiado en core. Muchas de las soluciones
ofrecidas en estas plataformas son fundamentales aún hoy día. Obvio, en esos
sistemas la experiencia del usuario no era la que dominaba o dirigía el diseño.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Necesitamos conocer y comprender ese pasado que
debemos sostener y repetir en cuanto a su genialidad y aporte, para que, con
fundamento, podamos ser dignos de ofrecer nuestras propias grandes soluciones a
los nuevos problemas, sin tener que reinventar la rueda ni el creer que
descubrimos el café con leche.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">La virtualización, la “nube”, los sistemas para
dispositivos móviles, la transformación digital, las metodologías ágiles, las
bases de datos no relacionales, el procesamiento distribuido y, apuesto mi credibilidad
en esto, la computación quántica (en sus fundamentos) son todos asuntos que ya
hemos resuelto, y que a cada vuelta de tuerca retornan revestidos de novedad,
como la panacea de moda. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Baladí, todo eso es baladí. Ceros y Unos son
los que mandan.<o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Como decía el gran Dennis Ritchie, UNIX es muy simple,
sólo que hay que ser un genio para comprender su simplicidad. <o:p></o:p></span></div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-81036565277720055882016-11-05T05:01:00.000-07:002016-11-05T05:06:26.660-07:00Homus Arquitectus<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Una breve reseña sobre la evolución en la arquitectura de software.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8a63m8eHkUqv5ZNGKiJOMyrYN8j12oaF5pElLDcZcpKuLdWBysX6MRcOSt4_wZt5aLQyCGnWCNy0J7KEqEn5RpCxK4QmaPAdEcahi9f5cR16mmzOXiHMiYmP20vkwo0FjS2oV-_QAZ4Q/s1600/evolucion_computacion.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8a63m8eHkUqv5ZNGKiJOMyrYN8j12oaF5pElLDcZcpKuLdWBysX6MRcOSt4_wZt5aLQyCGnWCNy0J7KEqEn5RpCxK4QmaPAdEcahi9f5cR16mmzOXiHMiYmP20vkwo0FjS2oV-_QAZ4Q/s400/evolucion_computacion.jpg" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Al principio fue el Mainframe, ohhh todo
poderoso, con un sin número de clientes tontos, denominados así por su casi
nula capacidad de computo. Todo residía en el Mainframe. ¿La Persistencia? En
el Mainframe. ¿La lógica de negocios? En el Mainframe. ¿Las aplicaciones como
tal? Adivine… En el Mainframe. ¿La capa de presentación? Allí mismo pues, en el
sagrado Mainframe.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<a name='more'></a><br />
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEBmM7N_d6aLUWLFg_JCIRB9viu40J5TXY8W1EQR1-8PAxlrD6hY6CnrrgqzDfdNQg0Mthaon4uhaCVQfwNN3BijmLOkA_9Pou9zQ1D_RDYGuCbHJtkkFG2UGbqu2ziAQsZuXs0HOkrTA/s1600/mainframe_01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEBmM7N_d6aLUWLFg_JCIRB9viu40J5TXY8W1EQR1-8PAxlrD6hY6CnrrgqzDfdNQg0Mthaon4uhaCVQfwNN3BijmLOkA_9Pou9zQ1D_RDYGuCbHJtkkFG2UGbqu2ziAQsZuXs0HOkrTA/s400/mainframe_01.png" width="400" /></a></div>
<br />
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">El esquema de arquitectura basado en Mainframes
y clientes tontos tenía algunas ventajas como lo son:<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpFirst" style="mso-list: l0 level1 lfo1; text-align: justify; text-indent: -18.0pt;">
</div>
<ul>
<li>·<span style="font-size: 7pt; font-stretch: normal; font-variant-numeric: normal; line-height: normal;">
</span><span lang="ES-CL" style="text-indent: -18pt;">Sencillez
de arquitectura</span></li>
<li>·<span style="font-size: 7pt; font-stretch: normal; font-variant-numeric: normal; line-height: normal;">
</span><span lang="ES-CL" style="text-indent: -18pt;">Facilidad
de Monitoreo</span></li>
<li>·<span style="font-size: 7pt; font-stretch: normal; font-variant-numeric: normal; line-height: normal;">
</span><span lang="ES-CL" style="text-indent: -18pt;">Control
simplificado de despliegues</span></li>
</ul>
<!--[if !supportLists]--><br />
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Pero a su vez tenía una principal desventaja,
condición tal en la que centraremos las ideas de esta publicación; me refiero a
la enorme incapacidad para el crecimiento o escalabilidad!!<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Para resolver este problema se estableció
entonces un modelo al que llamamos Cliente servidor. En el cual los Mainframes
son básicamente servidores de Base de Datos, mientras que los clientes, ahora
denominados clientes gordos, con muchos recursos asignados, eran los encargados
de ejecutar las aplicaciones, lo que incluye la capa de presentación e incluso
una buena dosis de Inteligencia de Negocio.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3Mkr91i-4qECDQf_rqjSVBKmhnKtWTryg8y9DOjc53n6G70LgvTseOQjjttADsxLMfv6_PHR8ZKbYb1-Rl41701uux_Wxt4sxldGR4Bc6EICyA_YcaOqu1zDFpkfKdlUUzv_WyLLh568/s1600/mainframe_02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="168" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3Mkr91i-4qECDQf_rqjSVBKmhnKtWTryg8y9DOjc53n6G70LgvTseOQjjttADsxLMfv6_PHR8ZKbYb1-Rl41701uux_Wxt4sxldGR4Bc6EICyA_YcaOqu1zDFpkfKdlUUzv_WyLLh568/s400/mainframe_02.png" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Este modelo resolvía gran parte del problema de
escalabilidad del modelo anterior, pero trae consigo el problema conocido como
la “Pesadilla del Mantenimiento”. En otras palabras, al residir los aplicativos
en las máquinas clientes, cuando se precisa de una actualización es necesario
idear mecanismos que permitan propagar ese cambio o actualización en todos los
clientes conectados. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">En ese contexto surge el modelo de 3 capas como
propuesta para solventar la problemática anterior. Recuerde, aquí somos como
los políticos la culpa siempre es del gobierno anterior jajaja. Volvamos al
tema que nos atañe, el modelo de 3 capas, pueden ser más capas pero en esencia
son 3, proponía tener una capa de
servicios, con su hardware y software
dedicados, que se encargara de atender la capa de Persistencia (bases de
datos), la capa de Lógica de Negocio y la capa de Presentación. Las primeras
dos estarían en servidores dedicados, mientras que la capa de presentación
estaría a cargo de las máquinas clientes, siendo el navegador o browser el aplicativo
o medio adoptado de preferencia para estas lides.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLh0hL1kjA3xrRvuq90H99oUAiIgQhShQbfEcEkViUQX5rWQpx6ThyphenhyphenXzTo3ibda5n27gbF-1iWx17srlvEZHdcck0j5PG684yfHsAR_JII-XHEmrWvSsrDXBxHk-p1mMCspAUHNXDAqV0/s1600/mainframe_03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLh0hL1kjA3xrRvuq90H99oUAiIgQhShQbfEcEkViUQX5rWQpx6ThyphenhyphenXzTo3ibda5n27gbF-1iWx17srlvEZHdcck0j5PG684yfHsAR_JII-XHEmrWvSsrDXBxHk-p1mMCspAUHNXDAqV0/s400/mainframe_03.png" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">En este modelo la persistencia queda a cargo de
los servidores (¿mainframes?) de base de datos.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">La lógica de negocio, servicios y aplicaciones
queda a cargo de los servidores de aplicaciones.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Mientras que la presentación, y su
correspondiente lógica y servicios asociados, era manejada en las máquinas
clientes a cargo del navegador u otra aplicación conveniente.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Con ello resolvíamos la escalabilidad de cara a
las máquinas clientes, la escalabilidad en las máquinas de persistencia y
lógica de negocio, resolvíamos además el problema de la “Pesadilla del Mantenimiento”,
era suficiente con actualizar las aplicativos en los servidores de aplicaciones
para que los clientes al conectarse ya tuviesen disponible la última versión
disponible del software demandado; un paraíso pues… pero no tanto. Aún quedaban
cosas por resolver.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Sí bien el modelo anterior hace mucho por
resolver los asuntos hasta ahora mencionados, hace poco o nada por resolver
otro problema de la capa de negocio, el de la redundancia de tareas o
repetición de funciones, formalmente conocido como repetición de servicios.
Esto se refiere al problema originado por estar los sistemas concebidos como
islas funcionales, usualmente reflejando las necesidades de algún ente jerárquico
de la organización, departamento, unidad, división, etc. Muchas de estas “islas”
tienen que resolver problemas, o usar recursos, comunes a toda la organización
y cada una de ellas, las islas, tiene su propia versión o procedimiento de cómo
lidiar con el asunto y, por supuesto, cada uno cree que el suyo es el procedimiento
único, válido y verdadero.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Imagine a cada isla que tenga que lidiar con la
tarea de validar tarjetas de crédito. Cada una escribirá su programa, función o
servicio, en su propio lenguaje de programación, con sus propias reglas y
lógica de negocio y desplegándolas en sus propias plataformas particulares. Con
el pasar del tiempo vamos a terminar con un montón de servicios, en esencia
código y recursos, destinados a repetir una misma tarea, lo cual es a todas
luces poco eficiente, difícil de gobernar, complicado de mantener e innecesario
para la organización.<o:p></o:p></span><br />
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">¿Cómo se soluciona esto? Mediante <a href="http://pigbar-hal9k.blogspot.cl/2016/01/bueno-malo-mejor-peor.html" target="_blank">asesinos conocidos</a>. Mediante estándares. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Es allí cuando surge el estándar propuesto como
Arquitectura Orientada a Servicios, SOA de sus siglas en ingles.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Este propone una manera común, estándar, para
comunicarnos con funciones o servicios. Establece de forma clara como se deben
pasar los mensajes y parámetros, como se retornan los resultados y como se
establece la comunicación. No importa si la implementación final de un servicio
está realizada en C# o Java, mientras se ajuste al estándar podremos consumir
ese servicio con éxito y usarlo en nuestros sistemas, pudiendo además unificar la
administración y monitoreo de tales servicios.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjslzuBSGp0d-cuJqy5HaEX7SigveKgbRP6ncyNbwOKx1KHvEtHtU3XcQlaDX7cCaTf_15xfvHv1NQXCx8Po6ezPELG2KaxdJaDu-dvgdVfIg49p4wWVxEJPfRD3vXABYmK_04qWSwod5M/s1600/fn_soa-fn1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="307" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjslzuBSGp0d-cuJqy5HaEX7SigveKgbRP6ncyNbwOKx1KHvEtHtU3XcQlaDX7cCaTf_15xfvHv1NQXCx8Po6ezPELG2KaxdJaDu-dvgdVfIg49p4wWVxEJPfRD3vXABYmK_04qWSwod5M/s400/fn_soa-fn1.jpg" width="400" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Bajo este esquema de solución ya no existirán N
versiones del servicio requerido para validar tarjetas de crédito, sino que por
el contrario, se habrá establecido un servicio único que puede ser consumido o
usado desde los diferentes sistemas de la organización. En este contexto, es
válido pensar en servicios que se pueden exponer a entidades fueras de la organización,
lo que abre un mundo de posibilidades en las relaciones inter-organizativas (b2b)
y crea nuevas preocupaciones respecto a la seguridad, entre otros asuntos.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Si miráis con atención mis queridos lectores, estas
propuestas de arquitectura, y su consecuente evolución, buscan resolver un
problema subyacente, común a todas, el cual consiste en ¿Cómo hacemos que las
máquinas se comuniquen eficientemente entre sí?<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Puede parecer que no es ese el meollo del
asunto, pero a la larga, entre todas las capas y estándares que establecemos,
lo que se persigue es eso, Comunicar Máquinas con eficiencia (o partes de
ellas).<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL"><br /></span></div>
<br />
<div class="MsoNormal" style="text-align: justify;">
<span lang="ES-CL">Pero este es tema ya para otra publicación.<o:p></o:p></span></div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com0tag:blogger.com,1999:blog-1012161132404905800.post-33239710535126759182016-10-27T08:40:00.001-07:002016-10-27T08:40:22.529-07:00Uso de la actividad de envío de emails y notificaciones de tareas por email en jBPM 6.x<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div style="line-height: 100%; margin-bottom: 0cm;">
Continuando con los
artículos sobre <i>jBPM 6.x</i>, en esta oportunidad les traigo un
tema relacionado con el envió de <i>emails</i> y notificaciones por <i>email.</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTVzPUCO2TTIhXzFbaf3U941h0BQLUtUpti3oT5pWRfGds5cqoufWuE-rfq7qAzhwPAvmbOPCFWe5L0qIvQmjDCs3EFeZ50zdsVBTHRee-keC17X0XY96vT9oPEfGpHcd91sdp4IHFdLE/s1600/email.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTVzPUCO2TTIhXzFbaf3U941h0BQLUtUpti3oT5pWRfGds5cqoufWuE-rfq7qAzhwPAvmbOPCFWe5L0qIvQmjDCs3EFeZ50zdsVBTHRee-keC17X0XY96vT9oPEfGpHcd91sdp4IHFdLE/s320/email.jpg" width="320" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Estas actividades
son muy frecuentes en los procesos de negocios, donde nos podemos
encontrar con la necesidad de enviar un <i>email</i> como parte de un
proceso, en una tarea específica. En este caso hacemos uso de la
tarea de servicio <i>email.</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<a name='more'></a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8wUHeWog7q19h3wE4aX2Y1RWIEIoM7UX6mzvBhcyEEinf5xJ3ttgC7iXalkr_uWMOMmtRuL1p7g5lqtuwnWrt0iS8nhpP3qPr09SQD6K0l4lZixwetvxgd9Lv4ocxmUVjpuqkzucUW8Y/s1600/tareas_servicios_email.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8wUHeWog7q19h3wE4aX2Y1RWIEIoM7UX6mzvBhcyEEinf5xJ3ttgC7iXalkr_uWMOMmtRuL1p7g5lqtuwnWrt0iS8nhpP3qPr09SQD6K0l4lZixwetvxgd9Lv4ocxmUVjpuqkzucUW8Y/s1600/tareas_servicios_email.png" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Y en otras
ocasiones, podemos requerir el envío de <i>emails</i> cuando una tarea no
se ha iniciado por ejemplo, esto se logra mediante la configuración
de notificaciones en las tareas humanas.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
En este ejemplo seguiremos usando las definiciones realizadas en nuestra <a href="http://pigbar-hal9k.blogspot.cl/2016/10/configurar-jbpm-para-obtener-grupos-y.html" target="_blank">publicación anterior.</a><br />
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Vayamos con el
primer caso, <b>el uso de la tarea de servicio de enviar correos o
</b><i><b>emails</b>.</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
1.- Seleccione la
Tarea de servicio de <i>Emails</i> y agregarla al flujo.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
2.- Configurar los
parámetros de envío de correo.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Para ello
seleccionamos en el flujo la tarea de <i>emails</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIUTAuIgWm4gKSihCAz3p8dXE29vNG4qlhQWRpBRRjeb2Caci8hpvrVygGAOiTqc6e3ZV1GvJ_0k0Xr8rUguNgsX3jphBRy-RQWKpdZmF-xs-1JnremrAy13mxJIJecZsN_hoTLDacofs/s1600/email_activiti.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIUTAuIgWm4gKSihCAz3p8dXE29vNG4qlhQWRpBRRjeb2Caci8hpvrVygGAOiTqc6e3ZV1GvJ_0k0Xr8rUguNgsX3jphBRy-RQWKpdZmF-xs-1JnremrAy13mxJIJecZsN_hoTLDacofs/s1600/email_activiti.png" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Y en las propiedades
de la tarea vamos a la sección de <i>“tareas”,</i> donde se nos abre
una ventana en la que encontramos los parámetros siguientes:
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxJOW3V2Iw4w8pzcWxJRvIxBf48Wm1OmrDv1lEeAlknjp19sz_bbLaO4HwIB6CWz7EiOFpQVKw9WSZkCjLM0o_FCJI7qAT1Ld_35olltlzIr5gMWB0FtZLyWTvRwITooMnwBMtsSw6PhM/s1600/email_data_IO.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="231" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxJOW3V2Iw4w8pzcWxJRvIxBf48Wm1OmrDv1lEeAlknjp19sz_bbLaO4HwIB6CWz7EiOFpQVKw9WSZkCjLM0o_FCJI7qAT1Ld_35olltlzIr5gMWB0FtZLyWTvRwITooMnwBMtsSw6PhM/s400/email_data_IO.png" width="400" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
donde:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<ul>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<b>To</b>, o
Para, donde especificamos la variable que contiene el valor adecuado
para el destinatario del <i>email.</i></div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<b>From</b>,
o Desde, el cual permite establecer la variable que contiene el
valor adecuado para el usuario u origen del <i>email.</i>
</div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<b>Subject</b>,
o Asunto, donde especificamos la variable que contiene el valor
adecuado para el asunto, tema o motivo del <i>email.</i></div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
<b>Body</b>,
o cuerpo, el cual permite establecer la variable que contiene el
valor adecuado para el contenido o cuerpo del <i>email.</i>
</div>
</li>
</ul>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Hasta aquí todo
normal y sencillo.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Pero queda un paso
que usualmente se suele olvidar y cuya omisión es fuente de
problemas frecuentes en la configuración y uso de la actividad de
servicio de envío de <i>emails.</i> El paso a continuación.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<style type="text/css">p { margin-bottom: 0.25cm; line-height: 120%; }a:link { }</style>
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
3.- Configurar
manejador de item de trabajo.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<ul>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
Abrir el
editor de proyecto y buscar la sección correspondiente al
descriptor de despliegue o<i> Deployment Descriptor.</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo7A13U6vpK5RtRzkRQfUylYAlYB2xf9JcEMjHw8jWO5239AOm0zTnIj1Q3l1Xa_784wCkXn8-WEruNonFKP79DWI42r4Tq_mXDGWPG2tJpbE5SfH66cUQz3AbwrKdG_rm1-U-PLdu8Nw/s1600/open_project_editor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo7A13U6vpK5RtRzkRQfUylYAlYB2xf9JcEMjHw8jWO5239AOm0zTnIj1Q3l1Xa_784wCkXn8-WEruNonFKP79DWI42r4Tq_mXDGWPG2tJpbE5SfH66cUQz3AbwrKdG_rm1-U-PLdu8Nw/s1600/open_project_editor.png" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9ixgf0xMtWJ5GzjhJqRfrLc7vdgUhpwdXN6bE6s-ylY7LYTRqNzjkudOS3QntPf7Ykv5m0gEqWPnChdyavnu1qNov8BhYkr7qMRB_PjV48dqiPISvFKkVzsOPWSqg6EyUUASD99ux_kE/s1600/Captura+de+pantalla+de+2016-10-25+15-27-06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9ixgf0xMtWJ5GzjhJqRfrLc7vdgUhpwdXN6bE6s-ylY7LYTRqNzjkudOS3QntPf7Ykv5m0gEqWPnChdyavnu1qNov8BhYkr7qMRB_PjV48dqiPISvFKkVzsOPWSqg6EyUUASD99ux_kE/s320/Captura+de+pantalla+de+2016-10-25+15-27-06.png" width="232" /></a></div>
</li>
</ul>
<br />
<ul>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
Buscar la
sección correspondiente al <i>Work Item handlers</i>, y pulsar el
botón <b><i>add</i></b> o agregar.</div>
</li>
</ul>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUbmQr71opWFvxKtY8EcZv6cyiYC4BTzw44Reyo0vDp6uZyo2iB8x7OeUDEPS1H1HKtRmmyUbrMAz9n9hV3AIZTJ30S2BZfFEZsbtEMvOJTE3PNOOyWIDT99YNUMp7GL-pCXWyVBYE8nI/s1600/deployment_descriptor_email.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUbmQr71opWFvxKtY8EcZv6cyiYC4BTzw44Reyo0vDp6uZyo2iB8x7OeUDEPS1H1HKtRmmyUbrMAz9n9hV3AIZTJ30S2BZfFEZsbtEMvOJTE3PNOOyWIDT99YNUMp7GL-pCXWyVBYE8nI/s640/deployment_descriptor_email.png" width="640" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
En esta sección
agregamos un item al que denominaremos <i>Email,</i><span style="font-style: normal;">
</span><span style="font-style: normal;">del tipo </span><i>mvel</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Con el siguiente
contenido:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
</div>
<pre class="brush:java"> new org.jbpm.process.workitem.email.EmailWorkItemHandler("smtp.gmail.com", "587", "tucorreo@gmail.com", "tu_password", "true")
</pre>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
<br />
<div style="line-height: 100%; margin-bottom: 0cm;">
<style type="text/css">p { margin-bottom: 0.25cm; line-height: 120%; }a:link {</style>El cual especifica
el servidor de <i>smtp</i>, el puerto a usar, la cuenta de correo de
envío, el password de la cuenta y el uso del modo seguro.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Guardamos y
desplegamos nuestro proceso.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Con eso ya
deberíamos poder hacer las pruebas correspondientes.</div>
<div style="border-bottom: 1px solid #000000; border-left: none; border-right: none; border-top: none; line-height: 100%; margin-bottom: 0cm; padding-bottom: 0.07cm; padding-left: 0cm; padding-right: 0cm; padding-top: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<b>Configuración de
notificaciones en tareas humanas.</b></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Esta configuración
se realiza en el marco de dos grandes frentes. El primero es el
servidor de aplicaciones, Wildfly en nuestro ejemplo, y el segundo es
la configuración de las tareas humanas en si mismas.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<ul>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
Configurar el
Servidor</div>
</li>
</ul>
<div style="line-height: 100%; margin-bottom: 0cm;">
Detener el servidor
Wildfly.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Ubicar los archivos
:</div>
<ul style="text-align: left;"><ul><ul>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
standalone.xml</div>
</li>
<li>
<div style="line-height: 100%; margin-bottom: 0cm;">
standalone-full.xml</div>
</li>
</ul>
</ul>
</ul>
<div style="line-height: 100%; margin-bottom: 0cm;">
En ambos archivos
agregar lo siguiente:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
</div>
<style type="text/css">p { margin-bottom: 0.25cm; line-height: 120%; }a:link { }</style>
<br />
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
</div>
<pre class="brush:xml">Propiedades.
<system-properties>
<property name="org.kie.mail.session" value="java:jboss/mail/Default">
</property></system-properties>
Subsystem.
<subsystem xmlns="urn:jboss:domain:mail:2.0">
<mail-session debug="true" from="tu_correo@gmail.com" jndi-name="java:jboss/mail/Default" name="default">
<smtp-server outbound-socket-binding-ref="mail-smtp" password="tu_password" ssl="true" username="tu_correo@gmail.com">
</smtp-server></mail-session>
</subsystem>
Socket-binding-group.
<outbound-socket-binding name="mail-smtp">
<remote-destination host="smtp.gmail.com" port="465">
</remote-destination></outbound-socket-binding>
</pre>
<style type="text/css">p { margin-bottom: 0.25cm; line-height: 120%; }a:link { }</style>
<br />
<div style="line-height: 100%; margin-bottom: 0cm;">
Guardar los
archivos.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Ubicar el archivo<i>
jbpm-console.war</i> en el directorio deployments del <i>standalone</i>
de <i>Wildfly.</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Abrir el archivo con
algún editor adecuado para poder modificar y actualizar el .war</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Ubicar el directorio<i>
\jbpm-console.war\WEB-INF\classes\</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Abrir el archivo
<i>userinfo.properties </i>y agregar el contenido siguiente:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<pre class="brush:xml">admin=intellegoqa@gmail.com:en-UK:admin
Administrator=intellegoqa@gmail.com:en-UK:Administrator
Administrators=intellegoqa@gmail.com:en-UK:Administrators:[Administrator]
</pre>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
</div>
<br />
<style type="text/css">p { margin-bottom: 0.25cm; line-height: 120%; }a:link { }</style>
<br />
<div style="line-height: 100%; margin-bottom: 0cm;">
Guardar los cambios
y actualizar el .war.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Reiniciar el
servidor.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Abrir la aplicación
jbpm-console e ingresar las credenciales de administrador.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Abrir el proceso BPM
deseado.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Ubicar la tarea
humana a la que se le desea añadir Notificaciones.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCOhaRdCpC-PdeR2fO7HLRpdJ0zAkgnkd1a1dLODDiW1mwkijlOEkoYeUWEnDSSImCcpS5Hg-d_O1frXwlPcvtzG4agEqn1IYTR6mEIG3xRr8W_eTQHGt95BLvWJL0Lv7_6icQ2dAy1QU/s1600/human_task_notifications.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="112" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCOhaRdCpC-PdeR2fO7HLRpdJ0zAkgnkd1a1dLODDiW1mwkijlOEkoYeUWEnDSSImCcpS5Hg-d_O1frXwlPcvtzG4agEqn1IYTR6mEIG3xRr8W_eTQHGt95BLvWJL0Lv7_6icQ2dAy1QU/s400/human_task_notifications.png" width="400" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
En la ventana de
propiedades ubicar la propiedad Notificaciones (Notificatios) y abrir
la ventana desplegable.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Pulsar agregar
notificación</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtA7TCaGYU4p6Z_1F4q1eOf60m-loQTsGPCciT90dcY58BRsak18AGewvb3Z6t2lspUV28qCKO6tLXZReGG2656x_VbvyiPfplWvWbHpn90Ak4atWlcM92NphokV6mPUto2YfpeKMTpvI/s1600/notifications_emails.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="157" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtA7TCaGYU4p6Z_1F4q1eOf60m-loQTsGPCciT90dcY58BRsak18AGewvb3Z6t2lspUV28qCKO6tLXZReGG2656x_VbvyiPfplWvWbHpn90Ak4atWlcM92NphokV6mPUto2YfpeKMTpvI/s400/notifications_emails.png" width="400" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Seleccionar el tipo
de notificación para las tareas, iniciadas o No-iniciadas.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Establecer cuando
expira la tarea (1d = Un día, 1m = Un minuto, etc).</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Indicar nombre de
usuario que se usará para enviar el <i>email,</i> no se deben colocar
cuentas de correos.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Indicar si es para
usuarios colocando los nombres de usuarios separados por coma que
recibiran el <i>email.</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Indicar si es para
un grupo, se colocan los nombres de grupo separados por coma.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Se indica el nombre
de usuario al que hay que responder.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Se especifica un
asunto del <i>email.</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Se especifica un
cuerpo del <i>email.</i>
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Los valores
anteriores puede usar variables del proceso o de la tarea, referirse
a la documentación del producto para detalles.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Guardar el proceso y
desplegarlo.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Listo, ya deberíamos
poder tener notificaciones de correo en nuestras tareas. Enjoy it!!!</div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com3tag:blogger.com,1999:blog-1012161132404905800.post-24311139125585217752016-10-20T11:08:00.000-07:002016-10-20T11:08:49.418-07:00Configurar jBPM para obtener Grupos y Usuarios desde nuestra Base de Datos<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>jBPM</i> en su serie 6.x
viene configurado para usar su propio esquema de Roles (Grupos) y
Usuarios, pero un requerimiento muy frecuente es permitir que el <i>jBPM</i>
busque u obtenga los Grupos y Usuarios desde nuestros medios
personalizados, usualmente una Base de Datos.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Escribo este
artículo debido a que recientemente me encontraba trabajando en un
par de proyectos de <i>BPM</i> con <i>jBPM</i> 6.3, y era requisito obtener los
Usuarios y Grupos desde una fuente relacional, razón por la cual me
toco apoyar al arquitecto de turno en cómo realizar esa tarea.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Ya en un <a href="http://pigbar-hal9k.blogspot.cl/2016/10/como-configurar-jbpm-para-usar-nuestra_16.html" target="_blank">artículo anterior</a> aprendimos a configurar el <i>jBPM</i> para que haga uso de nuestra
propia Base de Datos favorita, <i>Postgresql</i>, para la persistencia de
sus datos. Hoy vamos a seguir con ese ejemplo como base para
aprovechar el ambiente que se definió en esa oportunidad.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Así que sin mas
preámbulos manos a las sobras…</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiECrwpeu81nJkgWZvTKuJ_sI-TA7B4Cbowy_lNCuwQ-7y_Eh_fNflQjSx_mdy9dfxQdYiGtVBDuAHB19na9_9zVdp9a3MbrM5ZHIGXj_qX48xLYm6iBNiwP1U1qkJTB2iQSZPdQ30oz_k/s1600/group_user_actions.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiECrwpeu81nJkgWZvTKuJ_sI-TA7B4Cbowy_lNCuwQ-7y_Eh_fNflQjSx_mdy9dfxQdYiGtVBDuAHB19na9_9zVdp9a3MbrM5ZHIGXj_qX48xLYm6iBNiwP1U1qkJTB2iQSZPdQ30oz_k/s400/group_user_actions.jpg" width="400" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<a name='more'></a><br /><br />
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
1.- Crear nuestra
estructura de tablas.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
O usar la que ya
tenemos. En todo caso en este ejemplo usaremos la base de datos
denominada <b><i>usersrolesbd</i></b> con la siguiente definición de tablas:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<table cellpadding="4" cellspacing="0" style="width: 100%px;">
<colgroup><col width="85*"></col>
<col width="85*"></col>
<col width="85*"></col>
</colgroup><tbody>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="33%">
<div align="right">
<span style="background: transparent;"><b><span style="color: #073763;">Tabla</span></b></span></div>
</td>
<td colspan="2" style="border: 1px solid #000000; padding: 0.1cm;" width="67%">
<div align="center">
<b><span style="color: #073763;">users</span></b></div>
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<span style="background: transparent;"><b>Columna</b></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<b>Tipo</b><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<b>Valor por omisión</b><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>login_name * PK</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>Character(20)</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i><br />
</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>user_fullname *</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>Character(80)</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i><br />
</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>user_lang</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>Character(5)</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i>en-UK</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>user_email</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>Character(120)</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i><br />
</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>user_isgroup</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>boolean</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i>false</i><br />
</td>
</tr>
</tbody></table>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Tabla de Usuarios (y
Grupo o Rol)</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<table cellpadding="4" cellspacing="0" style="width: 100%px;">
<colgroup><col width="85*"></col>
<col width="85*"></col>
<col width="85*"></col>
</colgroup><tbody>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="33%">
<div align="right">
<span style="background: transparent;"><b><span style="color: #073763;">Tabla</span></b></span></div>
</td>
<td colspan="2" style="border: 1px solid #000000; padding: 0.1cm;" width="67%">
<div align="center">
<b><span style="color: #073763;">usersbyrol</span></b></div>
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<span style="background: transparent;"><b>Columna</b></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<b>Tipo</b><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<b>Valor por omisión</b><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<span style="background: transparent;"><i>Id * PK</i></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>Autogenerada</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i><br />
</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<span style="background: transparent;"><i>rol_name * FK (users)</i></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>Character(20)</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i><br />
</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<span style="background: transparent;"><i>user_name * FK (users)</i></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>Character(20)</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<br />
<br />
</td>
</tr>
</tbody></table>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Tabla de Usuarios
por Rol</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
2.- Generar <i>scripts</i>
de Consultas y cargar datos base de Administrador.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
2.1.- Haremos uso de
las siguientes consultas de <i>SQL</i> :</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<table cellpadding="4" cellspacing="0" style="width: 100%px;">
<colgroup><col width="85*"></col>
<col width="85*"></col>
<col width="85*"></col>
</colgroup><tbody>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="33%">
<b>Propiedad</b><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="33%">
<b>SQL</b><br />
</td>
<td style="border: 1px solid #000000; padding: 0.1cm;" width="33%">
<b>Descripción</b><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>db.user.query</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>SELECT login_name FROM users WHERE login_name = ?</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i>Consulta sí existe un usuario dado su nombre de usuario o
login</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>db.roles.query</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>SELECT login_name FROM users WHERE login_name = ? AND
user_isgroup = ‘true’</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i>Consulta sí existe el Grupo o Rol dado su nombre de grupo</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>db.user.roles.query</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>SELECT <span style="background: transparent;">rol_name </span>
FROM usersbyrol WHERE <span style="background: transparent;">user_name</span>
= ?</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i>Consulta los Roles para un nombre de usuario dado</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>db.name.query</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>SELECT user_fullname FROM users WHERE login_name = ?</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i>Consulta el nombre de un usuario dado su login
</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>db.email.query</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>SELECT user_email FROM users WHERE login_name = ?</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i>Consulta el email de un usuario o grupo dado su login o nombre
de usuario</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>db.lang.query</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>SELECT user_lang FROM users WHERE login_name = ?</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i>Consulta el Lenguaje para un usuario dado su login</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>db.has.email.query</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>SELECT user_email FROM users WHERE login_name = ?</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i>Consulta sí el Grupo tiene email</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>db.group.mem.query</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="33%">
<i>SELECT <span style="background: transparent;">user_name </span>
FROM usersbyrol WHERE <span style="background: transparent;">rol_name
</span> = ?</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0.1cm; padding-top: 0cm;" width="33%">
<i>Consulta los usuarios para un Grupo o Rol dado</i><br />
</td>
</tr>
</tbody></table>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
2.2.- Crear datos bases.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
En la tabla <i><b>users</b></i>
agregar los siguientes registros:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<table cellpadding="4" cellspacing="0" style="width: 100%px;">
<colgroup><col width="128*"></col>
<col width="128*"></col>
</colgroup><tbody>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="50%">
<span style="background: transparent;"><b>Columna</b></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="50%">
<b>Valor</b><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>login_name * PK</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>admin</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>user_fullname *</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>Administrador Admin</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>user_lang</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>en-UK</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>user_email</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>maildeladmin@correo.com</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>user_isgroup</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>false</i><br />
</td>
</tr>
</tbody></table>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<table cellpadding="4" cellspacing="0" style="width: 100%px;">
<colgroup><col width="128*"></col>
<col width="128*"></col>
</colgroup><tbody>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="50%">
<span style="background: transparent;"><b>Columna</b></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="50%">
<b>Valor</b><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>login_name * PK</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>Administrator</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>user_fullname *</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>Administrador Administrator</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>user_lang</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>en-UK</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>user_email</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>maildeladministrator@correo.com</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>user_isgroup</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>false</i><br />
</td>
</tr>
</tbody></table>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<table cellpadding="4" cellspacing="0" style="width: 100%px;">
<colgroup><col width="128*"></col>
<col width="128*"></col>
</colgroup><tbody>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="50%">
<span style="background: transparent;"><b>Columna</b></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="50%">
<b>Valor</b><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>login_name * PK</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>Administrators</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>user_fullname *</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>Grupo Administrador</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>user_lang</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>en-UK</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>user_email</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i><br />
</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>user_isgroup</i><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>true</i><br />
</td>
</tr>
</tbody></table>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Puede crear otros
usuarios y grupos de su elección. Pero no debe olvidar los antes
indicados.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
En la tabla
<i><b>usersbyrol</b></i> agregar los siguientes registros:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<table cellpadding="4" cellspacing="0" style="width: 100%px;">
<colgroup><col width="128*"></col>
<col width="128*"></col>
</colgroup><tbody>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="50%">
<span style="background: transparent;"><b>Columna</b></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="50%">
<b>Valor</b><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<span style="background: transparent;"><i>rol_name * FK (users)</i></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>Administrators</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<span style="background: transparent;"><i>user_name * FK (users)</i></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>admin</i><br />
</td>
</tr>
</tbody></table>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i><br />
</i></div>
<table cellpadding="4" cellspacing="0" style="width: 100%px;">
<colgroup><col width="128*"></col>
<col width="128*"></col>
</colgroup><tbody>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="50%">
<span style="background: transparent;"><i>Columna</i></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: 1px solid #000000; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0.1cm;" width="50%">
<i>Valor</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<span style="background: transparent;"><i>rol_name * FK (users)</i></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>Administrators</i><br />
</td>
</tr>
<tr valign="top">
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<span style="background: transparent;"><i>user_name * FK (users)</i></span><br />
</td>
<td style="border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: none; border-top: none; padding-bottom: 0.1cm; padding-left: 0.1cm; padding-right: 0cm; padding-top: 0cm;" width="50%">
<i>Administrator</i><br />
</td>
</tr>
</tbody></table>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Puede relacionar
otros usuarios y grupos. Pero no debe olvidar loa antes indicados.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
3.- Crear <i>DataSource</i>
de acceso en servidor <i>Wildfly</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Una vez que tenemos
definida nuestra base de datos, su estructura y los <i>scripts</i> de <i>sql</i>
respectivos, procedemos a crear el <i>DataSource</i> correspondiente para
poder acceder a nuestra base de datos mediante su <i>JNDI</i> pertinente.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Para ello haremos lo
siguiente:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
3.1.- Abrir la
consola de administración del servidor.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Accedemos a la ruta
en la que se encuentre nuestro servidor de <i>jBPM</i>, por ejemplo</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<pre class="brush:html"></pre>
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<a href="http://localhost:9080/console">http://localhost:9080/console</a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
3.2.- Ingresar las
credenciales del usuario administrador en caso de que sean
solicitadas.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Si aun no tiene un
usuario administrador creado, al abrir la <i>url</i> antes mencionada, será redireccionado a una página donde se le señala esta circunstancia,
y se le invita a ejecutar un comando adecuado “<b><i>add-user.bat / add-user.sh</i></b>” para
incorporar el usuario de <i>management</i> adecuado.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibYvn1sZeZES2DKBh1N_0vQPVQJi7Eb9IDO4-5thoTH4ARxQTHrBsTO0Xu8ywXCkv0rNPZNv3olr-h0KujBYuwNAyh8Zj8dT9vPnd8JLkz2kttywDJ4FhTtk8n1YqgbDTtTrzNugmaNaU/s1600/login_adm_console.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="110" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibYvn1sZeZES2DKBh1N_0vQPVQJi7Eb9IDO4-5thoTH4ARxQTHrBsTO0Xu8ywXCkv0rNPZNv3olr-h0KujBYuwNAyh8Zj8dT9vPnd8JLkz2kttywDJ4FhTtk8n1YqgbDTtTrzNugmaNaU/s400/login_adm_console.png" width="400" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
3.3.- Ir a la
sección <i>Create datasource</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Hacemos click o
pinchamos en el enlace para crear <i>datasources</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBOFTo8s4G04oFng4jVu4Dejiz26ejQ4vEDDve8QeyBOETkr5LE2vuzKTPBqwVhDioJIHO63YkZW0agLPOJSoiAigaxIqPfboUMxWVlBe0ZYA2sHVuzxiYunCkRABCWP5Rc3xAFm-fOgc/s1600/create_datasources.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBOFTo8s4G04oFng4jVu4Dejiz26ejQ4vEDDve8QeyBOETkr5LE2vuzKTPBqwVhDioJIHO63YkZW0agLPOJSoiAigaxIqPfboUMxWVlBe0ZYA2sHVuzxiYunCkRABCWP5Rc3xAFm-fOgc/s320/create_datasources.png" width="320" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
3.4.- Hacer click o
pinchar en el botón “add”.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Esto nos lleva a la
ventana donde debemos ingresar los datos para nuestro <i>datasource</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
3.5.- Ingresar datos
de identificación del <i>datasource</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Hay que poner
especial atención a ingresar la <i>JNDI</i> en el formato adecuado.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Se acostumbra que
sea <i>java:jboss/datasources/DATASOURCE_NAME</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqqw6lgUbIZZkLUF_UOqpcP8u-iwamIJq1NLpMSosINA46-IG1R7NmA1dlyTpq_GQnrbjpuad3BYP9GkO2VN1z9slxyo-FfZBg4TFfk0TMWkgFqxgLnuUefmbSmjSFamxsL-fghwpmY7A/s1600/creating_ds_01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="245" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqqw6lgUbIZZkLUF_UOqpcP8u-iwamIJq1NLpMSosINA46-IG1R7NmA1dlyTpq_GQnrbjpuad3BYP9GkO2VN1z9slxyo-FfZBg4TFfk0TMWkgFqxgLnuUefmbSmjSFamxsL-fghwpmY7A/s400/creating_ds_01.png" width="400" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Datos:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<pre class="brush:xml"></pre>
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>Name = users_rolesDS</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>JNDI =
java:jboss/datasources/users_rolesDS</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Ingresar datos y
pulsar “<i>next</i>” o siguiente.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
3.6.- Seleccionamos
el <i>Driver</i> adecuado.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Se nos presenta la
lista de <i>drivers</i> declarados, de no existir aún el nuestro lo
definimos o bien detectándolo o especificando el <i>driver</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifvwPbigSNB7SDDqSgbr9AL-Xa8sXZMoFJlI__-bzNsQiBcmm2NTt1yIOKMw9mk1JQLXSKuJWkU-UcQTEsD4-kg7UEjVtKfJJN6cVxo-at9ma1DD0TtF1ARpXWarA9hKc7jhGr3tc5TCk/s1600/creating_ds_02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="281" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifvwPbigSNB7SDDqSgbr9AL-Xa8sXZMoFJlI__-bzNsQiBcmm2NTt1yIOKMw9mk1JQLXSKuJWkU-UcQTEsD4-kg7UEjVtKfJJN6cVxo-at9ma1DD0TtF1ARpXWarA9hKc7jhGr3tc5TCk/s400/creating_ds_02.png" width="400" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
En nuestro ejemplo
usamos el <i>driver</i> existente para nuestra conexión a <i>Postgresql</i> del
ejemplo anterior.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Seleccionar el
<i>driver</i> adecuado y pulsar “<i>next</i>” o siguiente.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
3.7.- Ingresar datos
para la conexión <i>jdbc</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
En esta sección se
solicitan los datos adecuados para realizar el acceso a la base de
datos y probar la conexión respectiva.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_oYQN_TGsaBfGuZAJYt8Hq5qtwmz_ApmY48A8B87i01dX5h8Z_kNorlt5aJXi5dJgXO_zLck7HklEZsldLKMPMEATlp1nGtASbwDc2BChjL7-eX2R7mU0b5WiO0LNlaRtBbde04GWF_8/s1600/creating_ds_03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_oYQN_TGsaBfGuZAJYt8Hq5qtwmz_ApmY48A8B87i01dX5h8Z_kNorlt5aJXi5dJgXO_zLck7HklEZsldLKMPMEATlp1nGtASbwDc2BChjL7-eX2R7mU0b5WiO0LNlaRtBbde04GWF_8/s400/creating_ds_03.png" width="400" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Datos:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<pre class="brush:xml"></pre>
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>Connection URL =
jdbc:postgresql://localhost:5432/usersrolesdb</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>Username = jbpmuser</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>Password = ********
(el que corresponda)</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Hacer click o
pinchar en “<i>Test connection</i>”. En caso de error revisar nuestros
datos de acceso y <i>url</i> de conexión.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Cuando todo este
correcto pulsar “<i>Done</i>”.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
3.8.- Activar
nuestro <i>datasource</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Pare ellos sólo
debemos seleccionar nuestro <i>datasource</i> recien creado en la lista de
<i>datasources</i> disponibles, y hacer click o pinchar en el botón
“<i>enable</i>”.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
4.- Preparar
archivos de configuración.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
En un editor de
texto de su preferencia cree y edite los siguientes archivos con el
contenido indicado.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
4.1.- Archivo<i>
jbpm.usergroup.callback.properties</i>:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<pre class="brush:xml"></pre>
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
db.ds.jndi.name=java:jboss/datasources/users_rolesDS</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
db.user.query=SELECT
login_name FROM users WHERE login_name = ?</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
db.roles.query=SELECT
login_name FROM users WHERE login_name = ? AND user_isgroup = ‘true’</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
db.user.roles.query=SELECT
rol_name FROM usersbyrol WHERE user_name = ?</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
# Note que las
propiedades y los valores de las <i>Query</i> son las que ya habíamos
definido con anterioridad.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
# Este archivo se
usa para definir como obtener los roles para un usuario dado</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
4.2.- Archivo<i>
jbpm.user.info.properties</i>:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<pre class="brush:xml"></pre>
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
db.ds.jndi.name=ava:jboss/datasources/users_rolesDS</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
db.name.query=SELECT
user_fullname FROM users WHERE login_name = ?</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
db.email.query=SELECT
user_email FROM users WHERE login_name = ?</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
db.lang.query=SELECT
user_lang FROM users WHERE login_name = ?</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
db.has.email.query=SELECT
user_email FROM users WHERE login_name = ?</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
db.group.mem.query=SELECT
user_name FROM usersbyrol WHERE rol_name = ?</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
# Note que las
propiedades y los valores de las <i>Query</i> son las que ya habíamos
definido con anterioridad.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
# Este archivo se
usa para definir como obtener la información extra para un usuario
dado.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
5.- Configurar
archivo .<i>war</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
El siguiente paso
consiste en modificar nuestro archivo .war correspondiente al
<i>jbpm_console</i> para que admita la configuración de usuarios y roles
desde nuestra base de datos.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Para ello tenemos
que ir al directorio de instalación del jBPM instaler,
<i>JBPM_INSTALLER_HOME, </i><span style="font-style: normal;">e ir al
direcorio </span><i>/lib</i><span style="font-style: normal;">. </span><span style="font-style: normal;">Allí
</span><span style="font-style: normal;">encontraremos el archivo el
archivo .</span><i>war</i><span style="font-style: normal;"> correspondiente al jbpm-console adecuado a nuestra
versión. En este ejemplo usamos la versión 6.3, por lo que el .</span><i>war</i><span style="font-style: normal;">
que debemos usar es el
</span><i><b>jbpm-console-6.3.0.Final-wildfly-8.1.0.Final.war</b></i><span style="font-style: normal;">.</span></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-style: normal;">Una
vez ubicado ese .</span><i>war</i><span style="font-style: normal;">, lo abrimos con alguna herramienta adecuada para
manipular archivos .zip (winzip. 7Zip, winrar, gestor de archivadores, etc).</span></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="font-style: normal; line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
5.1.- Configurar el
archivo <b><i>beans.xml</i></b>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Dentro del .war ir
al directorio<i> /WEB-INF/</i> y abrir el archivo <i>beans.xml.</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Ubicar la linea que
dice:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<pre class="brush:xml"></pre>
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<class></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
org.jbpm.services.cdi.producer.JAASUserGroupInfoProducer</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</class></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Nota: Esto indica
que se usa la implementación de <i>JAAS</i> por omisión.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Y reemplazarla por:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<pre class="brush:xml"></pre>
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<class></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
org.jbpm.services.cdi.producer.DBUserGroupInfoProducer</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</class></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Lo que indica al
<i>jBPM</i> que queremos usar la implementación para Grupos y Usuarios por
Base de Datos que viene con la herramienta.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Recuerde guardar los
cambios realizados al archivo.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
5.2.- Configurar
archivos .<i>properties</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Dentro del .war ir
al directorio /WEB-INF/classes/. Seguidamente ubicamos nuestros
archivos:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<pre class="brush:xml"></pre>
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
jbpm.user.info.properties</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
jbpm.usergroup.callback.properties</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
userinfo.properties</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Los cuales ya
teníamos listos desde los pasos anteriores. Seleccionamos esos
archivos y los arrastramos y soltamos en el directorio
<i>/WEB-INF/classes</i>/ del .<i>war</i> del jbpm-console. Sí nos pregunta sí
deseamos reemplazar algún archivo existente respondemos que si a
todo.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
5.3.- Actualizar el
.<i>war</i> de jbpm-console.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Cerramos el editor
del .<i>war</i>. Si nos pregunta sí deseamos guardar los cambios y
actualizar el archivo respondemos que SI, obviamente.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Paso seguido, nos
dirigimos al directorio del instaler de jBPM, <i>JBPM_INSTALLER_HOME,</i><span style="font-style: normal;">
y por la consola ejecutamos el comando:</span></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-style: normal;">ant
install.demo.noeclipse</span></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-style: normal;">Mediante
el cual se generara la nueva instalación con las configuraciones
realizadas.</span></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-style: normal;"><br /></span></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<span style="font-style: normal;">LISTO!!!
Ya debe tener </span><i>jBPM</i><span style="font-style: normal;"> configurado para usar su Base de Datos
personalizada para Grupos y Usuarios.</span></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<br />
<div style="line-height: 100%; margin-bottom: 0cm;">
Éxito
y hasta una próxima entrega.</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com1tag:blogger.com,1999:blog-1012161132404905800.post-76816470304103571852016-10-16T12:51:00.003-07:002016-10-16T14:16:15.527-07:00Como configurar jBPM para usar nuestra propia Base de Datos en un sólo paso<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div dir="ltr" style="text-align: left;" trbidi="on">
<style type="text/css">p { margin-bottom: 0.25cm; line-height: 120%; }</style>
<br />
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Llevo un buen rato
trabajando con <i>jBPM</i> en su serie 6.x, y mi opinión sobre este
producto en la versión mecionada no ha mejorado para nada.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Es una herramienta
plena de funciones y caracteristicas avanzadas, pero tambien está
llena de Bugs y es realmente inestable, sobre todo en el ambiente de
modelamiento. </div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Así mismo, debo
decir que tiene una muy aceptable <i>API REST</i> y que el motor de procesos
y la consecuente ejecución de los procesos es estable y bastante
rápida.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
En esta publicación daré inicio a una serie de artículos que hablan sobre ciertas
configuraciones comunes e importantes que se hacen con <i>jBPM.</i></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Hoy iniciamos con la
configuración de <i>jBPM</i> para que use nuestra base de datos favorita.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Esto tiene sentido
porque el producto viene con la base de datos <i>H2</i> por omisión, la
cual es excelente para pruebas y evaluaciones rápidas de la
herramienta, pero es completamente inaceptable en un ambiente de
desarrollo, <i>QA</i> o producción cualquiera.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Así que manos a las
sobras, que digo, manos a las obras!!! jajajaja</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPNCoIaI3JtsC-nRH0OA3jsKiU6BcnO8N1bP9D0DHo5X9rs3sCyESepWwM6i5zp6q4wZ4yy6SfpXrLJiiexm6BfnSfg0-1pRqnEZtS9xj_fp4ufb0Er-pPeN8G5br3xCfvVUVaztGQt30/s1600/workflow_design.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPNCoIaI3JtsC-nRH0OA3jsKiU6BcnO8N1bP9D0DHo5X9rs3sCyESepWwM6i5zp6q4wZ4yy6SfpXrLJiiexm6BfnSfg0-1pRqnEZtS9xj_fp4ufb0Er-pPeN8G5br3xCfvVUVaztGQt30/s400/workflow_design.png" width="400" /></a></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<a name='more'></a><br />
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Prerequisitos.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<ul style="text-align: justify;">
<li>Tener instalada y
configurada la <a href="http://www.oracle.com/technetwork/es/java/javase/downloads/index.html" target="_blank"><i>Oracle</i> Java </a><i><a href="http://www.oracle.com/technetwork/es/java/javase/downloads/index.html" target="_blank">JDK 7+</a>.</i></li>
</ul>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
- Recuerde, como
recomendación general para cualquier plataforma operativa (mac,
linux guindows), nunca instale la <i>JDK</i> es una ruta o path que posee
nombres de directorio con espacios en blanco.</div>
<ul style="text-align: justify;">
<li>Instalar y
configurar <a href="http://ant.apache.org/" target="_blank"><i>Apache ANT.</i></a></li>
</ul>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
- Recuerde
configurar la variable de ambiente <i>ANT_HOME</i> con el path o ruta hacia
la carpeta o directorio de instalación raíz del <i>ANT.</i></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<ul style="text-align: justify;">
<li>Descargar el
instalador de <i><a href="https://www.jbpm.org/download/download.html" target="_blank">jBPM 6.x</a> </i>y descomprimirlo en un directorio adecuado, al
cual llamaremos desde ahora J<i>BPM_INSTALLER_HOME</i>.</li>
</ul>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<ul style="text-align: justify;">
<li>Tener instalada
nuestra base de datos favorita y compatible con <i>jBPM.</i></li>
</ul>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
- Acá la lista de base de datos soportadas: </div>
<ul style="text-align: justify;">
<li><i>db2</i></li>
<li><i>derby</i></li>
<li><i>h2</i></li>
<li><i>hsqldb</i></li>
<li><i>mysql5</i></li>
<li><i>mysqlinnodb</i></li>
<li><i>oracle</i></li>
<li><i>postgresql</i></li>
<li><i>sqlserver</i></li>
<li><i>sqlserver2008</i></li>
</ul>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
-Debe tener creado
un Esquema o BD con un nombre apropiado para su instancia de <i>jBPM,</i> en
este caso lo llamaremos <i>jbpmdb</i> (que creativo estoy) y usaremos
<i><a href="https://www.postgresql.org/download/" target="_blank">Postgresql 9.x</a> </i>como motor de Base de Datos.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<ul style="text-align: left;">
<li>Tener una herramienta para la gestión de la base de datos a usar, que permita ejecutar <i>scripts</i> de <i>sql.</i> En este caso puede ser el <a href="https://www.pgadmin.org/" target="_blank"><i>PgAdmin,</i></a> o la aplicación de consola del <i>postgresql.</i><br />
</li>
</ul>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Iniciamos</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<b>1.- Configurar el acceso a datos.</b></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
1.1.- Modificar o actualizar los archivos <i>standalone-xxxxx.xml.</i></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Vaya al directorio de instalación J<i>BPM_INSTALLER_HOME</i>, allí debe encontrar los archivos:</div>
<ul style="text-align: left;">
<li><i>standalone-full-wildfly-8.1.0.Final.xml</i>
</li>
<li><i>standalone-wildfly-8.1.0.Final.xml</i>
</li>
</ul>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Para poder modificar con éxito estos archivos debe tener en claro los siguientes datos:</div>
<ul style="text-align: left;">
<li>URL de conexión a la base de datos deseada. Verifique el nombre o IP del servidor, así como el nombre de la base de datos o esquema a utilizar.</li>
<li>Credenciales del usuario para acceder al servidor de base de datos. Debe usar el usuario adecuado con los permisos completos para el acceso a la BD.</li>
<li>Establecer el nombre del <i>Driver</i> que se configurará mas adelante.</li>
</ul>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
En cada uno de ellos ubicar la sección "<i>datasources</i>" que contiene:</div>
<pre class="brush:xml"><datasource jta="true" jndi-name="java:jboss/datasources/jbpmDS" pool-name="H2DS" enabled="true" use-java-context="true" use-ccm="true">
<connection-url>jdbc:h2:tcp://localhost/~/jbpm-db;MVCC=TRUE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
</security>
</datasource>
</pre>
<br />
Y modificarla de acuerdo a los valores deseados, tal como se muestra a continuación:<br />
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<pre class="brush:xml"><datasource jta="true" jndi-name="java:jboss/datasources/jbpmDS" pool-name="PostgreSQLDS" enabled="true" use-java-context="true" use-ccm="true">
<connection-url>jdbc:postgresql://localhost:5432/jbpm</connection-url>
<driver>postgresql</driver>
<security>
<user-name>jbpm</user-name>
<password>jbpm</password>
</security>
</datasource>
</pre>
<br />
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Recuerde que debe declarar o crear el datasource <i>"PostgreSQLDS"</i> en la consola de administración del servidor <i>WildFly</i> en la sección de DataSources.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
1.2.- En los mismos archivos anteriores declarar el módulo de <i>Driver</i> a utilizar.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Esto consiste en adicionar información sobre el driver a usar, el cual ya se declaro en el paso anterior <i><driver><b>postgresql</b></driver></i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Así mismo debe declarar un nombre único para el Módulo del Dirver. Este nombre usa el formato separado por puntos, tal cual los nombres de paquetes en <i>Java</i>. Este nombre de módulo debe corresponder al valor de la propiedad <i>db.driver.module.prefix</i> que modificaremos en el archivo <i>build.properties</i> mas adelante en este tutorial.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
En la sección <i><datasources></datasources></i> ubicar la sección <i>"drivers"</i> : </div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<pre class="brush:xml"><drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</pre>
<br />
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Y agregar la definición de Módulo de Driver que deseamos:</div>
<pre class="brush:xml"><drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
<driver name="postgresql" module="org.postgresql">
<xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
</driver>
</drivers>
</pre>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Note el nombre del módulo <i>module="<b>org.postgresql</b>"</i>, el cual se hará corresponder con el valor de la propiedad <i>db.driver.module.prefix = "<b>org/postgresql</b>"</i> en el archivo <i>build.properties</i> antes mencionado, y con la propiedad <i>name</i> del archivo de módulo del paso siguiente.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
1.3.- Crear el archivo para el Módulo de Driver.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
En el siguiente directorio:</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
J<i>BPM_INSTALLER_HOME/db</i></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Crear el archivo <b><i>postgresql_module.xml</i></b> con el siguiente contenido:</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<pre class="brush:xml"><module xmlns="urn:jboss:module:1.0" name="org.postgresql">
<resources>
<resource-root path="postgresql-9.1-902.jdbc4.jar"/>
</resources>
</module>
</pre>
<br />
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
El nombre <i>postgresql</i> del arrchivo <i>module.xml</i> debe corresponder o corresponderá al valor de la propiedad <i>db.name</i> del archivo <i>build.properties</i>, según este criterio <i>db.name</i><i>_module.xml</i>. </div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
1.4.- Modificar el archivo <i>build.properties</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
En el directorio J<i>BPM_INSTALLER_HOME</i> ubicar el archivo <i>build.properties</i> y ubicar y comentar la sección correspondiente a la configuración para el <i>H2</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<pre class="brush:xml"># default is H2
# H2.version=1.3.168
# db.name=h2
# db.driver.jar.name=h2-${H2.version}.jar
# db.driver.download.url=http://repo1.maven.org/maven2/com/h2database/h2/${H2.version}/h2-${H2.version}.jar</pre>
</div>
<br />
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
Y descomentar o agregar la configuración correspondiente a la base de datos <i>Postgresql</i> o la de su elección:</div>
<div style="line-height: 100%; margin-bottom: 0cm; text-align: justify;">
<br /></div>
<pre class="brush:xml">#postgresql
db.name=<b>postgresql</b>
db.driver.module.prefix=<b>org/postgresql</b>
db.driver.jar.name=postgresql-9.1-902.jdbc4.jar
db.driver.download.url=https://repository.jboss.org/nexus/content/repositories/thirdparty-uploads/postgresql/postgresql/9.1-902.jdbc4/postgresql-9.1-902.jdbc4.jar
</pre>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Note que se declara una URL desde la cual descargar el <i>driver</i> correspondiente a nuestra BD de elección. Existe la posibilidad de descargar el <i>driver</i> (.jar) adecuado en forma manual, y dejarlo en el siguiente directorio:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
J<i>BPM_INSTALLER_HOME/db/driver</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
De modo que el servidor pueda reconocerlo y usarlo en correspondencia. En esta opción es conveniente dejar comentada la propiedad <i>db.driver.download.url</i>.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
1.5.- Cambiar el dialecto de la base de datos para <i>hibernate</i>. </div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
En el siguiente directorio:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>JBPM_INSTALLER_HOME/db</i> </div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Ubicar el archivo jbpm-persistence-JPA2.xml, y modificar la declaración del dialecto de la base de datos del valor para H2 por el dialecto de nuestra BD favorita, Postgresql en este caso.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Original:</div>
<pre class="brush:xml"><property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
</pre>
<br />
<div style="line-height: 100%; margin-bottom: 0cm;">
Cambiar por:</div>
<pre class="brush:xml"><property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
</pre>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
Ahora viene un paso importante a tener en cuenta.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
1.6.- Modificar archivo <i>.war</i> de la aplicación <i>console</i> de <i>jBPM.</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Ir al directorio siguiente:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>JBPM_INSTALLER_HOME/lib</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Ubicar el archivo .war correspondiente al console de jBPM, en la versión 6.3 es el siguiente:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>jbpm-console-6.3.0.Final-wildfly-8.1.0.Final.war </i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Abrir con una herramienta adecuada para archivos comprimidos, <i>winzip,</i> <i>7zip,</i> o la herramienta correcta para su plataforma que le permita modificar el <i>.war</i> en cuestión.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Dentro del <i>.war</i> ubicar el directorio <i>/WEB-INF/classes/META-INF</i> y abrir el archivo <i>persistence.xml</i> para su modificación. Allí modificar la propiedad:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<pre class="brush:xml"><property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
</pre>
<br />
<div style="line-height: 100%; margin-bottom: 0cm;">
Y cambiar por el nuevo valor:</div>
<pre class="brush:xml"><property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
</pre>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br />
Como ve son los mismos valores y propiedad que en el paso anterior. Luego se debe proceder a guardar los cambios y cerrar el editor del comprimido <i>.war.</i> Si la aplicación le pregunta por sí desea guardar los cambios responder que si.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
1.7.- Ejecutar los <i>scripts</i> de <i>sql</i> para construir las estructuras de datos en la base de datos. <b><br /></b></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Vaya al directorio siguiente:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>JBPM_INSTALLER_HOME/db/ddl-scripts/</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Ubique el directorio de los <i>scripts</i> de <i>sql</i> que corresponda a su BD deseada, en este caso usaremos el directorio <i>postgresql,</i> allí ubicamos dos archivos:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<ol style="text-align: left;">
<li><i>postgresql-jbpm-schema.sql</i></li>
<li><i>quartz_tables_postgres.sql </i></li>
</ol>
<div style="line-height: 100%; margin-bottom: 0cm;">
Debe ir a la aplicación de gestión de su base de datos y ejecutar esos scripts en el orden dado con anterioridad.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
1.8.- Instalar y ejecutar el servidor.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Por la consola de comandos de su sistema, vaya al directorio:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>JBPM_INSTALLER_HOME</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Y ejecute los comando adecuados para instalar el ambiente y ejecutarlo. </div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Para instalar ejecute el comando:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>ant install.demo.noeclipse</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Para ejecutar el servidor ejecute:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>ant start.demo.noeclipse</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Para detener el servidor ejecute:</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<i>ant stop.demo</i></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Listo. Ya deberíamos tener un ambiente de <i>jBPM</i> configurado para usar nuestra propia base de datos, <i>Postgresql</i> en nuestro ejemplo.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
<div style="line-height: 100%; margin-bottom: 0cm;">
Vieron que era <b>UN SÓLO PASO</b>!!! claro.... dividido en 8!!! jajajajajaa detalles, detalles.</div>
<div style="line-height: 100%; margin-bottom: 0cm;">
<br /></div>
</div>
</div>
pigbarhttp://www.blogger.com/profile/03565753688943109547noreply@blogger.com4