<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3243236739421377577</id><updated>2025-01-24T05:17:55.776-05:00</updated><category term="java"/><category term="swing"/><category term="webservices"/><category term="sql"/><category term="aplicaciones web"/><category term="redes"/><category term="ciencia de la computación"/><category term="programación"/><category term="ccna"/><category term="cisco"/><category term="entretenimiento"/><category term="C"/><category term="j2ee"/><category term="mysql"/><category term="geometría computacional"/><category term="procesamiento multimedia"/><category term="rest"/><category term="spring"/><category term="compiladores"/><category term="jdbc"/><category term="opiniones"/><category term="php"/><category term="seguridad"/><category term="video"/><category term="debian"/><category term="electrónica"/><category term="flex"/><category term="glassfish"/><category term="javascript"/><category term="jquery"/><category term="json"/><category term="linux"/><category term="matlab"/><category term="noticias"/><category term="oracle"/><category term="pensamientos"/><category term="postgresql"/><category term="primefaces"/><category term="simulación"/><category term="sistemas operativos"/><category term="utilitarios"/><category term="xml"/><category term="diseño web"/><category term="docker"/><category term="eventos"/><category term="html"/><category term="inteligencia artificial"/><category term="maven"/><category term="programación lógica"/><category term="robotica"/><category term="sql server"/><category term="struts"/><category term="wireless"/><category term="abap"/><category term="autómatas"/><category term="camunda"/><category term="certificación"/><category term="css"/><category term="devops"/><category term="facturacion electronica"/><category term="forms"/><category term="gadgets"/><category term="git"/><category term="gps"/><category term="gráficos por computador"/><category term="hibernate"/><category term="jax-ws"/><category term="jdeveloper"/><category term="juegos"/><category term="lambda"/><category term="latex"/><category term="mvc"/><category term="mybatis"/><category term="ocpjp"/><category term="películas"/><category term="programación funcional"/><category term="sap"/><category term="scheme"/><category term="sistemas expertos"/><category term="wallpapers"/><category term="websphere"/><category term="xslt"/><title type='text'>.:: RolandoPalermo ::.</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>133</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-7103602652546467987</id><published>2020-02-14T16:07:00.004-05:00</published><updated>2020-02-14T16:13:21.954-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="camunda"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><title type='text'>Getting Cannot create a session after the response has been committed in Camunda</title><content type='html'>Solution for Camunda error &lt;b&gt;Cannot create a session after the response has been committed&lt;/b&gt;.
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/rolandopalermo/e964119bc448be494ab2dc8be3ba1c5b.js&quot;&gt;&lt;/script&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/7103602652546467987/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2020/02/cannot-create-session-after-response.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/7103602652546467987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/7103602652546467987'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2020/02/cannot-create-session-after-response.html' title='Getting Cannot create a session after the response has been committed in Camunda'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-8973275541089143678</id><published>2019-06-06T14:50:00.000-05:00</published><updated>2019-06-06T15:03:07.394-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="docker"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><title type='text'>Ejecutar script SQL con Postgres &amp; Docker</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
Muchas veces, al ejecutar un contenedor Docker para Postgres, deseamos inicializar el servidor o la base de datos creada con ciertos scripts previamente creados. En este artículo les mostraré cómo ejecutar un contenedor para Postgres agregando las dos siguientes actividades:
&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;1. Ejecutar un script para inicializar las tablas maestras&lt;/b&gt;&lt;br /&gt;
Esto normalmente se realiza con la instrucción:
&lt;br /&gt;
&lt;pre class=&quot;brush:sql&quot;&gt;psql -U postgres veronica &amp;lt; veronica.sql
&lt;/pre&gt;
Pero en el caso de Docker, podemos agregar el script al directorio /docker-entrypoint-initdb.d/ y Docker ejecutará automáticamente dicho script luego de iniciar el servicio de base de datos.
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;2. Agregar una llave para encriptación que será utilizada por la extensión pgcrypto.&lt;/b&gt;&lt;br /&gt;
Si no utilizamos docker, bastaría con realizar lo siguiente&lt;br /&gt;
&lt;pre class=&quot;brush:sql&quot;&gt;postgres -c encrypt.key=a_secret_key
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Ahora, ambas configuraciones se pueden hacer también directamente con Docker tal como se muestra en el siguiente Dockerfile:
&lt;/div&gt;
&lt;pre class=&quot;brush:bash&quot;&gt;FROM postgres:11.3

# About the author
MAINTAINER Rolando Rodríguez &amp;lt;rolando.roc@gmail.com&amp;gt;

# Environment variables

# Set Postgres environment variables
ENV POSTGRES_PASSWORD=123456 
    POSTGRES_USER=postgres 
    POSTGRES_DB=sample

# Get a sql script and move it to initialization scripts folder
ADD https://raw.githubusercontent.com/rolandopalermo/veronica/master/veronica-app/src/main/postgres/veronica.sql /docker-entrypoint-initdb.d/

# Make sql script executable
RUN chmod 744 /docker-entrypoint-initdb.d/veronica.sql

# Expose the PostgreSQL port
EXPOSE 5432

# Run a command, for example: $ postgres -c encrypt.key=8qxBjzCdQkwdpu
CMD [&quot;postgres&quot;, &quot;-c&quot;, &quot;encrypt.key=8qxBjzCdQkwdpu&quot;]
&lt;/pre&gt;
Para más información, puedes revisar el siguiente repositorio: &lt;a href=&quot;https://github.com/rolandopalermo/dockerfiles/tree/master/postgres-run-sql-command&quot;&gt;https://github.com/rolandopalermo/dockerfiles/tree/master/postgres-run-sql-command&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/8973275541089143678/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2019/06/how-to-run-sql-script-docker-postgres.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/8973275541089143678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/8973275541089143678'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2019/06/how-to-run-sql-script-docker-postgres.html' title='Ejecutar script SQL con Postgres &amp; Docker'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-3427920796739837579</id><published>2019-05-22T19:26:00.001-05:00</published><updated>2019-05-25T22:28:25.173-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><category scheme="http://www.blogger.com/atom/ns#" term="docker"/><title type='text'>Clean out your Docker images, containers and volumes</title><content type='html'>&lt;b&gt;Cleaning up containers&lt;/b&gt;&lt;br /&gt;
Kill all running containers

&lt;pre class=&quot;brush:cpp&quot;&gt;&amp;gt; docker kill $(docker ps -q)&lt;/pre&gt;

Delete all stopped containers
&lt;pre class=&quot;brush:cpp&quot;&gt;&amp;gt; docker rm $(docker ps -a -q)&lt;/pre&gt;

&lt;b&gt;Cleaning up images&lt;/b&gt;&lt;br /&gt;
Delete an image
&lt;pre class=&quot;brush:cpp&quot;&gt;&amp;gt; docker rmi &amp;lt;image name&amp;gt;&lt;/pre&gt;

Delete all &#39;untagged/dangling&#39; images
&lt;pre class=&quot;brush:cpp&quot;&gt;&amp;gt; docker rmi $(docker images -q -f dangling=true)&lt;/pre&gt;

Delete all images
&lt;pre class=&quot;brush:cpp&quot;&gt;&amp;gt; docker rmi $(docker images -q)&lt;/pre&gt;

&lt;b&gt;Cleaning up volumnes&lt;/b&gt;&lt;br /&gt;
Once a volume is not longer associated with a container, it is considered &#39;dangling&#39;
&lt;br /&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;&amp;gt; docker volume rm $(docker volume ls -f dangling=true -q)
&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/3427920796739837579/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2019/05/clean-out-your-docker-images-containers.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/3427920796739837579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/3427920796739837579'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2019/05/clean-out-your-docker-images-containers.html' title='Clean out your Docker images, containers and volumes'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-996993881801722375</id><published>2019-05-16T22:20:00.000-05:00</published><updated>2019-05-16T22:25:43.249-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="xml"/><category scheme="http://www.blogger.com/atom/ns#" term="xslt"/><title type='text'>How to remove namespaces from XML using XSLT</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
Sometimes, XML documents you receive could contain unneeded or incorrect namespace information. You can use XSLT stylesheets to remove the namespace information in these documents.
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
XML Input
&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&amp;gt;
&amp;lt;ns1:reportRequest xmlns:ns1=&quot;http://v1.dto.reports.rolandopalermo.com&quot;&amp;gt;
    &amp;lt;ns1:metadata&amp;gt;
        &amp;lt;ns1:account&amp;gt;12345678&amp;lt;/ns1:account&amp;gt;
        &amp;lt;ns1:reportName&amp;gt;Current_Payment&amp;lt;/ns1:reportName&amp;gt;
    &amp;lt;/ns1:metadata&amp;gt;
    &amp;lt;ns1:report&amp;gt;
        &amp;lt;ns1:reportId&amp;gt;1&amp;lt;/ns1:reportId&amp;gt;
        &amp;lt;ns1:header&amp;gt;
            &amp;lt;ns1:id&amp;gt;999999999&amp;lt;/ns1:id&amp;gt;
            &amp;lt;ns1:name&amp;gt;John Smith&amp;lt;/ns1:name&amp;gt;
        &amp;lt;/ns1:header&amp;gt;
        &amp;lt;ns1:invoices&amp;gt;
            &amp;lt;ns1:invoice&amp;gt;
                &amp;lt;ns1:invoiceNumber&amp;gt;0000000000&amp;lt;/ns1:invoiceNumber&amp;gt;
                &amp;lt;ns1:dueDate&amp;gt;07/01/18&amp;lt;/ns1:dueDate&amp;gt;
                &amp;lt;ns1:invoiceAmount&amp;gt;14.00&amp;lt;/ns1:invoiceAmount&amp;gt;
                &amp;lt;ns1:amountPaid&amp;gt;14.00&amp;lt;/ns1:amountPaid&amp;gt;
            &amp;lt;/ns1:invoice&amp;gt;
        &amp;lt;/ns1:invoices&amp;gt;
        &amp;lt;ns1:paymentMethodInformation&amp;gt;
            &amp;lt;ns1:cardType&amp;gt;VISA&amp;lt;/ns1:cardType&amp;gt;
            &amp;lt;ns1:cardName&amp;gt;************1111&amp;lt;/ns1:cardName&amp;gt;
            &amp;lt;ns1:cardHolder&amp;gt;Juan Pérez&amp;lt;/ns1:cardHolder&amp;gt;
            &amp;lt;ns1:authorizationCode&amp;gt;dd92c0f864ea9ff1016501e880d03451&amp;lt;/ns1:authorizationCode&amp;gt;
        &amp;lt;/ns1:paymentMethodInformation&amp;gt;
    &amp;lt;/ns1:report&amp;gt;
&amp;lt;/ns1:reportRequest&amp;gt;
&lt;/pre&gt;
XSLT
&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;xsl:stylesheet
    xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; version=&quot;1.0&quot;
    xmlns:ns1=&quot;http://v1.dto.reports.rolandopalermo.com&quot;&amp;gt;
    &amp;lt;xsl:template match=&quot;/&quot;&amp;gt;
        &amp;lt;xsl:apply-templates
            select=&quot;ns1:reportRequest/ns1:report&quot; /&amp;gt;
    &amp;lt;/xsl:template&amp;gt;
    &amp;lt;xsl:template match=&quot;*&quot;&amp;gt;
        &amp;lt;xsl:element name=&quot;{local-name(.)}&quot;&amp;gt;
            &amp;lt;xsl:apply-templates /&amp;gt;
        &amp;lt;/xsl:element&amp;gt;
    &amp;lt;/xsl:template&amp;gt;
    &amp;lt;xsl:template match=&quot;@*&quot;&amp;gt;
        &amp;lt;xsl:copy /&amp;gt;
    &amp;lt;/xsl:template&amp;gt;
&amp;lt;/xsl:stylesheet&amp;gt;
&lt;/pre&gt;
XML Output
&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;report&amp;gt;
    &amp;lt;reportId&amp;gt;1&amp;lt;/reportId&amp;gt;
    &amp;lt;header&amp;gt;
        &amp;lt;id&amp;gt;999999999&amp;lt;/id&amp;gt;
        &amp;lt;name&amp;gt;John Smith&amp;lt;/name&amp;gt;
    &amp;lt;/header&amp;gt;
    &amp;lt;invoices&amp;gt;
        &amp;lt;invoice&amp;gt;
            &amp;lt;invoiceNumber&amp;gt;0000000000&amp;lt;/invoiceNumber&amp;gt;
            &amp;lt;dueDate&amp;gt;07/01/18&amp;lt;/dueDate&amp;gt;
            &amp;lt;invoiceAmount&amp;gt;14.00&amp;lt;/invoiceAmount&amp;gt;
            &amp;lt;amountPaid&amp;gt;14.00&amp;lt;/amountPaid&amp;gt;
        &amp;lt;/invoice&amp;gt;
    &amp;lt;/invoices&amp;gt;
    &amp;lt;paymentMethodInformation&amp;gt;
        &amp;lt;cardType&amp;gt;VISA&amp;lt;/cardType&amp;gt;
        &amp;lt;cardName&amp;gt;************1111&amp;lt;/cardName&amp;gt;
        &amp;lt;cardHolder&amp;gt;Juan Pérez&amp;lt;/cardHolder&amp;gt;
        &amp;lt;authorizationCode&amp;gt;dd92c0f864ea9ff1016501e880d03451&amp;lt;/authorizationCode&amp;gt;
    &amp;lt;/paymentMethodInformation&amp;gt;
&amp;lt;/report&amp;gt;
&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/996993881801722375/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2019/05/xslt-remove-namespaces.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/996993881801722375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/996993881801722375'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2019/05/xslt-remove-namespaces.html' title='How to remove namespaces from XML using XSLT'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-8179298009123804964</id><published>2018-10-25T11:46:00.002-05:00</published><updated>2019-05-15T13:28:40.015-05:00</updated><title type='text'>How to reset a remote git repository to remove all commits</title><content type='html'>Delete the .git directory locally and recreate the git repostory:
&lt;img border=&quot;0&quot; data-original-height=&quot;511&quot; data-original-width=&quot;694&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7EUPBhIpbgu7HYoMgipmKwUTemei26UJVjcd3Of9ZHcqlj4xRRJ99dHz7RXzqcchID-vHMLAqMCcNh2pd7Ngo5xS1LE-BnW41kk3_yOTezIHP0SbBYQU4YoRyERKW200wS0-zegsio4o/s1600/github.jpg&quot; style=&quot;display: none;&quot; /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:css&quot;&gt;$ cd (project-directory)
$ git init
$ (add some files)
$ git add .
$ git commit -m &#39;Initial commit&#39;
&lt;/pre&gt;
Push to remote server, overwriting.
&lt;b&gt;&lt;span style=&quot;color: red;&quot;&gt;Remember you&#39;re going to mess everyone else up doing this so you better be the only client.
&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:css&quot;&gt;
$ git remote add origin &amp;lt;url&amp;gt;
$ git push --force --set-upstream origin master
&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/8179298009123804964/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2018/10/how-to-reset-remote-git-repository-to.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/8179298009123804964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/8179298009123804964'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2018/10/how-to-reset-remote-git-repository-to.html' title='How to reset a remote git repository to remove all commits'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7EUPBhIpbgu7HYoMgipmKwUTemei26UJVjcd3Of9ZHcqlj4xRRJ99dHz7RXzqcchID-vHMLAqMCcNh2pd7Ngo5xS1LE-BnW41kk3_yOTezIHP0SbBYQU4YoRyERKW200wS0-zegsio4o/s72-c/github.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-479178426805233770</id><published>2018-10-21T01:08:00.000-05:00</published><updated>2019-05-15T13:30:22.286-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="maven"/><title type='text'>How to Create an Executable JAR with Maven</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
In this quick article we will focus on packaging a Maven project into an executable Jar file. In order to create an executable jar, we don’t need any additional dependencies. We just need to create Maven Java project, and have at least one class with the main(…) method.&lt;/div&gt;&lt;br /&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSE4xLcH1_D6F_M_7DVQdTGAm-dqeBumnMrdlZrSMEOfikPmDBl-8019JG7TNURfHyaMtXmdZXJNARfQ1KL1lTlBxZg66tRRvddntEgB8yVmHEq3cEkso0HhyH_Bpm6x1UKYL3jZySMxk/s1600/mvn.png&quot; data-original-width=&quot;310&quot; data-original-height=&quot;290&quot; style=&#39;display:none;&#39;/&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
We also need to make sure that our pom.xml contains the the following elements:
&lt;/div&gt;
&lt;pre class=&#39;brush:xml&#39;&gt;
&amp;lt;build&amp;gt;
    &amp;lt;finalName&amp;gt;anjus-invoicing-${project.version}&amp;lt;/finalName&amp;gt;
    &amp;lt;plugins&amp;gt;
        &amp;lt;plugin&amp;gt;
            &amp;lt;artifactId&amp;gt;maven-assembly-plugin&amp;lt;/artifactId&amp;gt;
            &amp;lt;configuration&amp;gt;
                &amp;lt;descriptorRefs&amp;gt;
                    &amp;lt;descriptorRef&amp;gt;jar-with-dependencies&amp;lt;/descriptorRef&amp;gt;
                &amp;lt;/descriptorRefs&amp;gt;
                &amp;lt;appendAssemblyId&amp;gt;false&amp;lt;/appendAssemblyId&amp;gt;
                &amp;lt;archive&amp;gt;
                    &amp;lt;manifest&amp;gt;
                        &amp;lt;mainClass&amp;gt;com.rolandopalermo.example.Main&amp;lt;/mainClass&amp;gt;
                    &amp;lt;/manifest&amp;gt;
                &amp;lt;/archive&amp;gt;
            &amp;lt;/configuration&amp;gt;
            &amp;lt;executions&amp;gt;
                &amp;lt;execution&amp;gt;
                    &amp;lt;id&amp;gt;make-assembly&amp;lt;/id&amp;gt;
                    &amp;lt;phase&amp;gt;package&amp;lt;/phase&amp;gt;
                    &amp;lt;goals&amp;gt;
                        &amp;lt;goal&amp;gt;assembly&amp;lt;/goal&amp;gt;
                    &amp;lt;/goals&amp;gt;
                &amp;lt;/execution&amp;gt;
            &amp;lt;/executions&amp;gt;
        &amp;lt;/plugin&amp;gt;
    &amp;lt;/plugins&amp;gt;
&amp;lt;/build&amp;gt;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/479178426805233770/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2018/10/executable-jar-with-maven.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/479178426805233770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/479178426805233770'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2018/10/executable-jar-with-maven.html' title='How to Create an Executable JAR with Maven'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSE4xLcH1_D6F_M_7DVQdTGAm-dqeBumnMrdlZrSMEOfikPmDBl-8019JG7TNURfHyaMtXmdZXJNARfQ1KL1lTlBxZg66tRRvddntEgB8yVmHEq3cEkso0HhyH_Bpm6x1UKYL3jZySMxk/s72-c/mvn.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-4080971100951438866</id><published>2018-03-20T23:59:00.002-05:00</published><updated>2018-03-21T00:20:12.647-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="json"/><category scheme="http://www.blogger.com/atom/ns#" term="rest"/><category scheme="http://www.blogger.com/atom/ns#" term="webservices"/><title type='text'>Deserialización JSON de tipos genéricos usando Jackson</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
Como parte de las buenas prácticas en la reutilización de clases, es común encontrar el uso de tipos genéricos en Java. Sin embargo, cuando estas forman parte de una respuesta JSON, pueden ser un dolor de cabeza. Imaginemos que tenemos como respuestas de un API Rest los dos siguientes escenarios:&lt;/div&gt;
&lt;br /&gt;
&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGBYRF9bxbEnz0F2KIzBJRgKBlx_9fLrskEol64EAAhyum3oVQZroCtTxssNx6dn1V-eTyhZcpR5R72FnBRtZAuFpzKHQED3RIQs3mYyrd1tGP0STc3PhR_etcGJ6p-h1pNWvwCPGBgYQ/s1600/JSON-Logo.png&quot; style=&quot;display: none;&quot; /&gt;
&lt;b&gt;PersonaResponse
&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:js&quot;&gt;{
   &quot;codigo&quot;:1,
   &quot;mensaje&quot;:&quot;ok&quot;,
   &quot;data&quot;:{
      &quot;nombres&quot;:&quot;Rolando Palermo&quot;,
      &quot;edad&quot;:29
   }
}
&lt;/pre&gt;
&lt;b&gt;ProductoResponse&lt;/b&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:js&quot;&gt;{
   &quot;codigo&quot;:1,
   &quot;mensaje&quot;:&quot;ok&quot;,
   &quot;data&quot;:{
      &quot;codigo&quot;:&quot;FX-536&quot;,
      &quot;precio&quot;:56.98,
      &quot;moneda&quot;:&quot;PEN&quot;,
   }
}
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Ambos Json tienen propiedades  comunes, sin embargo sólo el objeto &lt;b&gt;data&lt;/b&gt; es diferente. Para deserializar estos jsons sin tipos genéricos, tendríamos que crear 2 envoltorios con 2 clases de datos diferentes. Pero con los tipos genéricos solo necesitamos crear una clase genérica para las propiedades de la raíz y una clase específica para cada objeto en la clave de &lt;b&gt;data&lt;/b&gt;.
&lt;/div&gt;&lt;br&gt;
&lt;b&gt;GenericResponse.java&lt;/b&gt;
&lt;pre class=&quot;brush:java&quot;&gt;
public class GenericResponse&amp;lt;T&amp;gt; {

    private String codigo;
    private String mensaje;
    T data;

    public String getCodigo() {
        return codigo;
    }

    public void setCodigo(String codigo) {
        this.codigo = codigo;
    }

    public String getMensaje() {
        return mensaje;
    }

    public void setMensaje(String mensaje) {
        this.mensaje = mensaje;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
    
}
&lt;/pre&gt;
&lt;b&gt;PersonaResponse&lt;/b&gt;
&lt;pre class=&quot;brush:java&quot;&gt;
public class PersonaResponse {

    private String nombres;
    private int edad;

    public String getNombres() {
        return nombres;
    }

    public void setNombres(String nombres) {
        this.nombres = nombres;
    }

    public int getEdad() {
        return edad;
    }

    public void setEdad(int edad) {
        this.edad = edad;
    }
}
&lt;/pre&gt;

&lt;b&gt;ProductoResponse&lt;/b&gt;
&lt;pre class=&quot;brush:java&quot;&gt;
public class ProductoResponse {

    private String codigo;
    private double precio;
    private String moneda;

    public String getCodigo() {
        return codigo;
    }

    public void setCodigo(String codigo) {
        this.codigo = codigo;
    }

    public double getPrecio() {
        return precio;
    }

    public void setPrecio(double precio) {
        this.precio = precio;
    }

    public String getMoneda() {
        return moneda;
    }

    public void setMoneda(String moneda) {
        this.moneda = moneda;
    }

}
&lt;/pre&gt;
Ahora, la deserialización JSON nos quedaría de la siguiente manera:
&lt;pre class=&quot;brush:java&quot;&gt;
ObjectMapper mapper = new ObjectMapper();
//Para persona
GenericResponse&amp;lt;PersonaResponse&amp;gt; response1 = mapper.readValue(jsonString, new TypeReference&amp;lt;GenericResponse&amp;lt;PersonaResponse&amp;gt;&amp;gt;() {});
//Para producto
GenericResponse&amp;lt;ProductoResponse&amp;gt; response2 = mapper.readValue(jsonString, new TypeReference&amp;lt;GenericResponse&amp;lt;ProductoResponse&amp;gt;&amp;gt;() {});
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/4080971100951438866/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2018/03/json-deserialize-generic-types-using.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/4080971100951438866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/4080971100951438866'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2018/03/json-deserialize-generic-types-using.html' title='Deserialización JSON de tipos genéricos usando Jackson'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGBYRF9bxbEnz0F2KIzBJRgKBlx_9fLrskEol64EAAhyum3oVQZroCtTxssNx6dn1V-eTyhZcpR5R72FnBRtZAuFpzKHQED3RIQs3mYyrd1tGP0STc3PhR_etcGJ6p-h1pNWvwCPGBgYQ/s72-c/JSON-Logo.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-2302598287879822479</id><published>2018-02-24T12:56:00.001-05:00</published><updated>2019-05-15T14:00:55.673-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="sql"/><category scheme="http://www.blogger.com/atom/ns#" term="sql server"/><title type='text'>Bloqueo de recursos en SQL Server</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
En los últimos años hemos sido testigos de un crecimiento exponencial de aplicaciones distribuidas, con infinidad de componentes concurrentes de propósito específico interactuando unos con otros en tiempo real y a grandes velocidades. Estos nuevos enfoques de arquitecturas asíncronas han traído consigo antiguos problemas que nosotros, los desarrolladores, debemos resolver en nuestro día a día; uno de ellos, el mítico &lt;a href=&quot;https://es.wikipedia.org/wiki/Bloqueo_mutuo&quot;&gt;bloqueo mutuo&lt;/a&gt;.
&lt;img border=&quot;0&quot; data-original-height=&quot;360&quot; data-original-width=&quot;597&quot; height=&quot;192&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS2y631vyMEUMkhTcqfOqZDyJyPrO-0ipJMqKHWhNdA-9TO9WZmoha_qOxs26gH5I8dXF7F3LXvLRrKstg5nfutukUClckX5IaaCmX_h9gRXEOxjt-eiJe9zvJYyxDjqvoutNOOgvHhNs/s320/sqlserver2017_2.png&quot; style=&quot;display: none;&quot; width=&quot;320&quot; /&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Escenarios tales como accesos a interfaces de hardware, aplicaciones IOT o hasta la simple generación de números de secuencia de tickets son casos donde el interbloqueo o bloqueo mutuo es un problema que de no ser resuelto, podría comprometer el éxito de un proyecto de software. Si bien es cierto, existen soluciones que van desde complejas arquitecturas distribuidas hasta increíbles artimañanas inventadas por algún programador adicto al café, en este artículo nos centraremos en una propuesta que manejará el interbloqueo desde base de datos haciendo uso de un procedimiento almacenado de sistema, el &lt;a href=&quot;https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-getapplock-transact-sql&quot;&gt;sp-getapplock&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
El problema se planteará de la siguiente manera: &lt;i&gt;&quot;Debemos desarrollar un procedimiento almacenado que garantice la inserción de registros en una tabla determinada, cada uno de los cuales estará identificado por un id que deberá generarse de manera secuencial sin dejar ningún vacío, esto quiere decir que de presentarse algún error, se deberá ejecutar una instrucción de rollback y la siguiente inserción deberá hacer uso de esta secuencia&quot;&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
El primer paso será crear nuestra tabla, para lo cual haremos ejecutaremos la siguiente consulta en SQL Server.&lt;/div&gt;
&lt;pre class=&quot;brush:sql&quot;&gt;CREATE TABLE dbo.Registros  
   (Registro_Seq_ID int PRIMARY KEY NOT NULL,  
    Registro_Descripcion varchar(25) NOT NULL)  
GO 
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
El siguiente paso será crear un procedimiento almacenado que se encargue de la inserción, esto con el fin de tener un punto de entrada dónde poder aplicar nuestro control contra los interbloqueos.
&lt;/div&gt;
&lt;pre class=&quot;brush:sql&quot;&gt;SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE spInsertarRegistro
 @Descripcion VARCHAR(25),
 @RegistroSeq INT OUT
AS
BEGIN
 SET NOCOUNT ON;
 SELECT @RegistroSeq = ISNULL(MAX(Registro_Seq_ID), 0) + 1  from Registros;
 INSERT INTO Registros(Registro_Seq_ID, Registro_Descripcion) VALUES (@RegistroSeq, @Descripcion);
END
GO
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Y ahora utilizaremos Java para probar nuestro procedimiento almacenado.
&lt;/div&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.sql;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class App {
    
 public String driver = &quot;com.microsoft.sqlserver.jdbc.SQLServerDriver&quot;;
 public void insertRegistro(String descripcion) throws SQLException,
 ClassNotFoundException {
  String connectionUrl = &quot;jdbc:sqlserver://localhost:55418;databaseName=BD_TEST;user=user_test_app;password=12345678&quot;;
  try (
  Connection connection = DriverManager.getConnection(connectionUrl);
  CallableStatement cstmt = connection.prepareCall(&quot;{call spInsertarRegistro(?,?)}&quot;)) {
   Class.forName(driver);
   cstmt.setString(1, descripcion);
   cstmt.registerOutParameter(2, java.sql.Types.INTEGER);
   cstmt.execute();
   System.out.println(&quot;Se creó el registro [&quot; + cstmt.getInt(2) + &quot;]&quot;);
  }
 }
 
 public static void main(String[] args) throws Exception {
  App app = new App();
  app.insertRegistro(&quot;Registro sin interbloqueo&quot;);
 }
 
}
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Al ejecutar dicha clase, veremos que nuestro registro se insertó correctamente, sin embargo ahora realizaremos una pequeña mofidicación al método main para que inserte registros de manera continua, estableciendo una pausa de 200 milisegundos entre cada inserción. Al ejecutar un sólo proceso, el resultado será el siguiente:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;612&quot; data-original-width=&quot;968&quot; height=&quot;404&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGlB0r56Nes2M5YK9hROyklCJsee3SgQhT8DOHfcXME4_Lce8i7Kz7I75V2FooedYkfZn0PxgRmVNRmL8CrBlCCOrYL1Ahyy5eL8O9LoGJhF3JF2zv2oEoidmUKXKtdQryUYSAw467bl8/s640/sp-getapplock_un_proceso.jpg&quot; width=&quot;640&quot; /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sin embargo, al ejecutar tres procesos, la historia cambia:&lt;br /&gt;
&lt;br /&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;715&quot; data-original-width=&quot;1100&quot; height=&quot;416&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmwN7sOCUe4es6QvVP6jznDB5A4aMGsE4LWxUYyrxucl6h4e1U2R6vXPC4SYsGm-NdUqoGBZkFBk2X5mszy3Yz2kTxUj7tgUGOCxF9mJPiwffD0nqFyz32JLtHzbNTCRVTasxMBw_lFTU/s640/sp-getapplock_tres_procesos.jpg&quot; width=&quot;640&quot; /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;
Es aquí donde sp-getapplock viene a salvarnos el día. Nuestro procedimiento sufrirá una ligera modifación, la cual evitará que más de una petición intente ejecutarlo de manera concurrente. El recurso de bloqueo creado por sp_getapplock se crea en la base de datos actual para la sesión.&lt;/div&gt;
&lt;pre class=&quot;brush:sql&quot;&gt;SET ANSI_NULLS ON  
 GO  
 SET QUOTED_IDENTIFIER ON  
 GO  
 ALTER PROCEDURE spInsertarRegistro2  
      @Descripcion VARCHAR(25),  
      @RegistroSeq INT OUT  
 AS  
 DECLARE  
      @rc int = 0,  
      @msg varchar(2000)  
 SET @msg = CONVERT(varchar, GETDATE(), 114) + &#39; Se incia el segmento a sincronizar&#39;  
 RAISERROR (@msg, 0, 1) WITH NOWAIT  
 BEGIN TRY  
      BEGIN TRAN  
           SET @msg = CONVERT(varchar, GETDATE(), 114) + &#39; Tratando de obtener el candado&#39;  
           RAISERROR (@msg, 0, 1) WITH NOWAIT  
           -- Se solicita el candado  
           EXEC @rc = sp_getapplock   
                @Resource = &#39;spInsertarRegistro2&#39;, -- Nombre del recurso a bloquear  
                @LockMode = &#39;Exclusive&#39;, -- Tipo de candado  
                @LockOwner = &#39;Transaction&#39;, -- Transaction or Session  
                @LockTimeout = 15000 -- Tiempo de espera máximo, 15 seconds  
           -- Se verifica si se pudo obtener el candado  
           SET @msg =   
                CONVERT(varchar, GETDATE(), 114) +   
                &#39; sp_getapplock retornó &#39; +   
                CONVERT(varchar(30), @rc) +   
                &#39; -- &#39; +   
                CASE  
                     WHEN @rc &amp;lt; 0 THEN &#39;No se pudo obtener el candado&#39;  
                     ELSE &#39;Candado obtenido&#39;  
                END  
           RAISERROR (@msg, 0, 1) WITH NOWAIT  
           IF @rc &amp;gt;= 0  
                BEGIN  
                     SET @msg = CONVERT(varchar, GETDATE(), 114) + &#39; Se iniciará con la sección crítica &#39;  
                     RAISERROR (@msg, 0, 1) WITH NOWAIT  
                     -- Inserciones protegias por código  
                     SET NOCOUNT ON;  
                     SELECT @RegistroSeq = ISNULL(MAX(Registro_Seq_ID), 0) + 1 from Registros;  
                     INSERT INTO Registros(Registro_Seq_ID, Registro_Descripcion) VALUES (@RegistroSeq, @Descripcion);  
                     --   
                     COMMIT TRAN -- Se libera el candado  
                     SET @msg = CONVERT(varchar, GETDATE(), 114) + &#39; Trabajo completado, se libera el candado&#39;  
                     RAISERROR (@msg, 0, 1) WITH NOWAIT  
                END  
           ELSE  
                BEGIN  
                ROLLBACK TRAN  
                SET @rc = 50000  
           END  
 END TRY  
 BEGIN CATCH  
      set @msg = &#39;ERROR: &#39; + ERROR_MESSAGE() + &#39; en &#39;   
       + coalesce(ERROR_PROCEDURE(), &#39;&#39;)  
       + coalesce (&#39; la línea:&#39; + convert(varchar(30), ERROR_LINE()), &#39;&#39;)  
      IF @@Trancount &amp;gt; 1  
           ROLLBACK TRAN;  
      RAISERROR (@msg, 0, 1)  
 END CATCH  
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Ahora realizaremos una modificación a la clase Java para que inserte de manera concurrente registros sin ninguna pausa. Al ser la columna Registro_Seq_ID una clave primaria, si en algún momento llegase a duplicarse, se deberá lanzar un error. El siguiente video evidencia que, a pesar de la concurrencia, todos los registros se están insertando de manera correcta.
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;center&gt;
&lt;iframe allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/eYX86x2LAdM&quot; width=&quot;560&quot;&gt;&lt;/iframe&gt;
&lt;/center&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;
Espero que este post les sea de utilidad y cualquier consulta adicional, no duden en comentarla.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/2302598287879822479/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2018/02/sp-getapplock-sql-server-transact-sql.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/2302598287879822479'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/2302598287879822479'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2018/02/sp-getapplock-sql-server-transact-sql.html' title='Bloqueo de recursos en SQL Server'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS2y631vyMEUMkhTcqfOqZDyJyPrO-0ipJMqKHWhNdA-9TO9WZmoha_qOxs26gH5I8dXF7F3LXvLRrKstg5nfutukUClckX5IaaCmX_h9gRXEOxjt-eiJe9zvJYyxDjqvoutNOOgvHhNs/s72-c/sqlserver2017_2.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-1581853576257390093</id><published>2017-12-05T14:26:00.001-05:00</published><updated>2019-05-15T14:05:32.265-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="aplicaciones web"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="rest"/><category scheme="http://www.blogger.com/atom/ns#" term="webservices"/><title type='text'>API Rest con PHP y MySQL para el manejo de imágenes</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
Las cargas de imágenes son una cosa que siempre se torna bastante complicada y manejar esto a través de una API Rest es aún más retador. En este artículo vamos a ver cómo insertar imágenes y demás datos en una tabla de MySQL a través de servicios web de tipo REST que permitirán ejecutar las diferentes operaciones sobre la base de datos. Como consideraciones iniciales, es importante mencionar que debamos revisar antes el siguiente artículo:&lt;br /&gt;
&lt;a href=&quot;http://blog.rolandopalermo.com/2017/12/slim-composer-php-rest-api-install.html&quot;&gt;http://blog.rolandopalermo.com/2017/12/slim-composer-php-rest-api-install.html&lt;/a&gt;.
&lt;/div&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihEQsbCmhIdOEsKx8NCqYJ5esl-3v8bobGwNLnotqQKOkW9FI8DuVnRRSwYUoQHj7s-HrWZwtfPH1H67bH-82DdGh8LQIAEywWB1Op12HNhInxWK0QyXJjskxiQzfX6rAKgq5X59_uPks/s320/php_rest_api.jpg&quot; style=&quot;display: none;&quot; /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
También tendremos que configurar nuestro servidor Apache para poder tener URL más amigables. Para esto modificar los archivos:&lt;br /&gt;
&lt;br /&gt;
C:\xampp\apache\conf\extra\httpd-vhosts.conf&lt;br /&gt;
C:\Windows\System32\drivers\etc\hosts&lt;br /&gt;
&lt;br /&gt;
Los cuales deberán quedarnos con el siguiente contenido:&lt;br /&gt;
&lt;br /&gt;
Archivo httpd-vhosts.conf
&lt;/div&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;NameVirtualHost *:80

&amp;lt;VirtualHost *:80&amp;gt;
    DocumentRoot &quot;C:/xampp/htdocs/rest-api/public&quot;
    ServerName rest-api
&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost *:80&amp;gt;
    DocumentRoot &quot;C:/xampp/htdocs/rest-api-demo/public&quot;
    ServerName rest-api-demo
&amp;lt;/VirtualHost&amp;gt;
&lt;/pre&gt;
Archivo hosts
&lt;br /&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;127.0.0.1 rest-api-demo
&lt;/pre&gt;
&lt;br /&gt;
Recuerden que a lo largo de todo el artículo haré referencia a la ruta &lt;b&gt;C:/xampp&lt;/b&gt; que es donde tengo instalado a mi servidor Xampp.&lt;br /&gt;
&lt;br /&gt;
Como primera parte, tendremos una base de datos con una tabla para gestionar usuarios. El script es el siguiente:
&lt;br /&gt;
&lt;pre class=&quot;brush:sql&quot;&gt;CREATE DATABASE IF NOT EXISTS rest_api_base;
USE rest_api_base;

--
-- Definition of table `user`
--

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id_user` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `avatar` blob NOT NULL,
  PRIMARY KEY (`id_user`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
&lt;/pre&gt;
Ahora la clase PHP para conectarnos a la base de datos:
&lt;br /&gt;
&lt;pre class=&quot;brush:php&quot;&gt;&amp;lt;?php

class DB {

    private $db_host = &#39;localhost&#39;;
    private $db_user = &#39;root&#39;;
    private $db_pass = &#39;123456&#39;;
    private $db_name = &#39;rest_api_base&#39;;

    public function connect() {
        $mysql_connect_str = &quot;mysql:host=$this-&amp;gt;db_host;dbname=$this-&amp;gt;db_name&quot;;
        $dbConnection = new PDO($mysql_connect_str, $this-&amp;gt;db_user, $this-&amp;gt;db_pass);
        $dbConnection-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        return $dbConnection;
    }

}
&lt;/pre&gt;
Y la clase que mapea a la tabla &lt;b&gt;users&lt;/b&gt; de la base de datos.
&lt;br /&gt;
&lt;pre class=&quot;brush:php&quot;&gt;&amp;lt;?php

class User {

    public $idUser;
    public $name;
    public $avatar;

    function __construct($idUser, $name, $avatar) {
        $this-&amp;gt;idUser = $idUser;
        $this-&amp;gt;name = $name;
        $this-&amp;gt;avatar = $avatar;
    }

}
&lt;/pre&gt;
También las clase DAO donde se implementarán las operaciones sobre la base de datos.
&lt;br /&gt;
&lt;pre class=&quot;brush:php&quot;&gt;&amp;lt;?php

require &#39;../src/model/user.php&#39;;

class UserDAO {

    public function findAll() {
        $sql = &quot;SELECT * FROM user;&quot;;
        try {
            $db = new DB();
            $db = $db-&amp;gt;connect();
            if (is_null($db)) {
                echo &#39;{&quot;error&quot;: true, &quot;message&quot;: &quot;text&quot;: &quot;No se pudo conectar a la base de datos.&quot;}&#39;;
            } else {
                $stmt = $db-&amp;gt;query($sql);
                $usuarios = $stmt-&amp;gt;fetchAll();
                $arr_usuarios = array();  //array to parse jason from
                $db = null;
                foreach ($usuarios as $row) {
                    $usr = new User($row[0], $row[1], base64_encode($row[2]));
                    $arr_usuarios[] = $usr;
                }
                echo &#39;{&quot;error&quot;: false, &quot;data&quot;: &#39; . json_encode($arr_usuarios) . &#39;}&#39;;
            }
        } catch (PDOException $ex) {
            echo &#39;{&quot;error&quot;: true, &quot;message&quot;: &quot;&#39; . $ex-&amp;gt;getMessage() . &#39;&quot;}}&#39;;
        }
    }

    public function findOne($idUser) {
        $sql = &quot;SELECT * FROM user WHERE id_user=?;&quot;;
        try {
            $db = new DB();
            $db = $db-&amp;gt;connect();
            if (is_null($db)) {
                echo &#39;{&quot;error&quot;: true, &quot;message&quot;: &quot;text&quot;: &quot;No se pudo conectar a la base de datos.&quot;}&#39;;
            } else {
                $stmt = $db-&amp;gt;prepare($sql);
                $array = array($idUser);
                $stmt-&amp;gt;execute($array);
                $usuarios = $stmt-&amp;gt;fetchAll();
                $arr_usuarios = array();  //array to parse jason from
                foreach ($usuarios as $row) {
                    $usr = new User($row[0], $row[1], base64_encode($row[2]));
                    $arr_usuarios[] = $usr;
                }
                echo &#39;{&quot;error&quot;: false, &quot;data&quot;: &#39; . json_encode($arr_usuarios) . &#39;}&#39;;
            }
        } catch (PDOException $ex) {
            echo &#39;{&quot;error&quot;: true, &quot;message&quot;: &quot;&#39; . $ex-&amp;gt;getMessage() . &#39;&quot;}}&#39;;
        }
    }

    public function put($user) {
        $sql = &quot;INSERT INTO user(name, avatar) VALUES (?,?)&quot;;
        try {
            $db = new DB();
            $db = $db-&amp;gt;connect();
            if (is_null($db)) {
                echo &#39;{&quot;error&quot;: true, &quot;message&quot;: &quot;text&quot;: &quot;No se pudo conectar a la base de datos.&quot;}&#39;;
            } else {
                $stmt = $db-&amp;gt;prepare($sql);
                $array = array($user-&amp;gt;name, base64_decode($user-&amp;gt;avatar));
                $stmt-&amp;gt;execute($array);
                $id_producto_insertado = $db-&amp;gt;lastInsertId();
                $db = null;
                echo &#39;{&quot;error&quot;: false, &quot;data&quot;: &#39; . $id_producto_insertado . &#39;}&#39;;
            }
        } catch (PDOException $ex) {
            echo &#39;{&quot;error&quot;: true, &quot;message&quot;: &quot;&#39; . $ex-&amp;gt;getMessage() . &#39;&quot;}}&#39;;
        }
    }
    
    public function update($user) {
        $sql = &quot;UPDATE user SET name=?, avatar=? WHERE id_user=?&quot;;
        try {
            $db = new DB();
            $db = $db-&amp;gt;connect();
            if (is_null($db)) {
                echo &#39;{&quot;error&quot;: true, &quot;message&quot;: &quot;text&quot;: &quot;No se pudo conectar a la base de datos.&quot;}&#39;;
            } else {
                $stmt = $db-&amp;gt;prepare($sql);
                $array = array($user-&amp;gt;name, base64_decode($user-&amp;gt;avatar),$user-&amp;gt;idUser);
                $stmt-&amp;gt;execute($array);
//                $id_producto_insertado = $db-&amp;gt;lastInsertId();
                $db = null;
                echo &#39;{&quot;error&quot;: false, &quot;data&quot;: &quot;Usuario actualizado&quot;}&#39;;
            }
        } catch (PDOException $ex) {
            echo &#39;{&quot;error&quot;: true, &quot;message&quot;: &quot;&#39; . $ex-&amp;gt;getMessage() . &#39;&quot;}}&#39;;
        }
    }

}
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Ahora, como mencioné al inicio del artículo, utilizaremos el Framework Slim cuya instalación la expliqué en el post del cual hice referencia al inicio de este artículo. En esta clase se definirán las rutas y los métodos a través de los cuales se accederá a las distintas opciones de nuestra API.
&lt;/div&gt;
&lt;pre class=&quot;brush:php&quot;&gt;&amp;lt;?php

use PsrHttpMessageServerRequestInterface as Request;
use PsrHttpMessageResponseInterface as Response;

//$app_productos = new SlimApp;

require &#39;../src/dao/user_dao.php&#39;;

$app_dapp-&amp;gt;get(&#39;/api/users/findall&#39;, function(Request $request, Response $response) {
    $dao = new UserDAO();
    $dao-&amp;gt;findAll();
});

$app_dapp-&amp;gt;get(&#39;/api/users/find/{idUser}&#39;, function(Request $request, Response $response) {
    $dao = new UserDAO();
    $dao-&amp;gt;findOne($request-&amp;gt;getAttribute(&#39;idUser&#39;));
});

$app_dapp-&amp;gt;post(&#39;/api/users/put&#39;, function(Request $request, Response $response) {
    $dao = new UserDAO();
    $user = new User(null, $request-&amp;gt;getParam(&#39;name&#39;), $request-&amp;gt;getParam(&#39;avatar&#39;));
    $dao-&amp;gt;put($user);
});

$app_dapp-&amp;gt;post(&#39;/api/users/update&#39;, function(Request $request, Response $response) {
    $dao = new UserDAO();
    $user = new User($request-&amp;gt;getParam(&#39;idUser&#39;), $request-&amp;gt;getParam(&#39;name&#39;), $request-&amp;gt;getParam(&#39;avatar&#39;));
    $dao-&amp;gt;update($user);
});
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Si todo ha marchado bien, podremos acceder desde cualquier cliente y visualizar la información que se solicite. Por ejemplo, lanzado una petición a través de POSTMAN a la opción de listar los usuarios, tendremos lo siguiente:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;838&quot; data-original-width=&quot;1453&quot; height=&quot;370&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYdpHWTx09YVW-3FvO7ZloxJQOBGWqMXepWsD3h0VBczlRrxqFL6vrMv7uA9J75rETiTCoMZSUuVEs3yoYrYYveZAc2J_x4bAQXvf_QfvVjcQWT6_P7NXluSwoSz1kDAMTmYP61uPLBDs/s640/resultado_php_rest.jpg&quot; width=&quot;640&quot; /&gt;
&lt;br /&gt;
&lt;br /&gt;
En este caso, las imágenes fueron tratas en su codificación de Base64. Ahora, si queremos más de cerca nuestra API en acción, podemos utilizar POSTMAN para insertar una imagen:&lt;br /&gt;
&lt;br /&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;604&quot; data-original-width=&quot;1452&quot; height=&quot;266&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-r7x5u15OwiOB6JHi7G_QeIL0oMFqvQZ_wDo5kdCBFk3hcxiWkmI_73d3pMfcyWdZbbI8u00ZPhKSnaIBiAW0-HlAjPanbuZABCh2UN0R1oQ4de0BiPvQDRMPj_w0Rdb1NoHBPD8xpI0/s640/rest-php-insert.jpg&quot; width=&quot;640&quot; /&gt;
&lt;br /&gt;
&lt;br /&gt;
También podemos escribir un sencillo cliente en PHP. El código sería el siguiente:
&lt;br /&gt;
&lt;pre class=&quot;brush:php&quot;&gt;&amp;lt;?php

$url = &quot;http://rest-api-demo/api/users/findall&quot;;
$client = curl_init($url);
curl_setopt($client, CURLOPT_RETURNTRANSFER, 1);
$curl_response = curl_exec($client);
//echo $curl_response;
$obj_response = json_decode($curl_response);
$array_data = $obj_response-&amp;gt;data;
//header(&quot;Content-type: image/gif&quot;);
foreach($array_data as $item) {
 echo $item-&amp;gt;name . &#39;&amp;lt;br&amp;gt;&#39;;
 echo &#39;&amp;lt;img width=&quot;150&quot; src=&quot;data:image/gif;base64,&#39; . $item-&amp;gt;avatar . &#39;&quot; /&amp;gt;&#39;;
 echo &#39;&amp;lt;br&amp;gt;&#39;;
}
&lt;/pre&gt;
Y deberíamos tener algo similar a esto:&lt;br /&gt;
&lt;br /&gt;
&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhbd2csVvWKCAOv8eEBX0bZeYcUxkIJFEZ91e4lIcYAmqTzyW9UM5jXKxrftjfWY83lMQo2z5XKX3Rk5njDunJxTTGnLKuCZY6Gpn-tg2GuO7Ytixn6DUYeVqrgrMB5wKIdtzByjdLx1Y/s320/post.jpg&quot; /&gt;&lt;br /&gt;
&lt;br /&gt;
El proyecto completo lo pueden encontrar en Github y lo pueden descargar del siguiente enlace:
&lt;br /&gt;
&lt;a href=&quot;https://github.com/rolandopalermo/rest-api-demo&quot; imageanchor=&quot;1&quot;&gt;https://github.com/rolandopalermo/rest-api-demo&lt;/a&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;
Espero que este artículo les sea de utilidad y no olviden seguirme a través de &lt;a href=&quot;https://www.facebook.com/rolandopalermo.biz/&quot;&gt;Facebook&lt;/a&gt;.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/1581853576257390093/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2017/12/http-rest-api-file-uploads-php.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/1581853576257390093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/1581853576257390093'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2017/12/http-rest-api-file-uploads-php.html' title='API Rest con PHP y MySQL para el manejo de imágenes'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihEQsbCmhIdOEsKx8NCqYJ5esl-3v8bobGwNLnotqQKOkW9FI8DuVnRRSwYUoQHj7s-HrWZwtfPH1H67bH-82DdGh8LQIAEywWB1Op12HNhInxWK0QyXJjskxiQzfX6rAKgq5X59_uPks/s72-c/php_rest_api.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-2359528529041740839</id><published>2017-12-04T10:30:00.001-05:00</published><updated>2018-02-24T14:57:03.196-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="programación"/><category scheme="http://www.blogger.com/atom/ns#" term="sql"/><category scheme="http://www.blogger.com/atom/ns#" term="sql server"/><category scheme="http://www.blogger.com/atom/ns#" term="utilitarios"/><title type='text'>String split with Transact-SQL</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
In spite of The STRING_SPLIT function is now available under compatibility level 130, knowing how to implement this function is something that is definitely worthwhile.
&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAyeH-Kl0japF3TBWZLxbEETbBu-lpjUe_LVJrLm7MpmTPwJEsgEz0QXKr3tXWcwGVRYJEhm7psXNlBreMuhuHFcQPfzJN-Tev8oz93b-Avll9tioAUGIyWSpj49NYhMoSpcBLADHppA0/s320/sql_server.png&quot; style=&quot;display: none;&quot; /&gt;
&lt;/div&gt;
&lt;pre class=&quot;brush:sql&quot;&gt;CREATE FUNCTION [dbo].[fnSplitString] 
( 
    @string NVARCHAR(MAX), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
) 
BEGIN 
    DECLARE @start INT, @end INT 
    SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 
    WHILE @start &amp;lt; LEN(@string) + 1 BEGIN 
        IF @end = 0  
            SET @end = LEN(@string) + 1
       
        INSERT INTO @output (splitdata)  
        VALUES(SUBSTRING(@string, @start, @end - @start)) 
        SET @start = @end + 1 
        SET @end = CHARINDEX(@delimiter, @string, @start)
        
    END 
    RETURN 
END
GO
&lt;/pre&gt;
How to use:
&lt;br /&gt;
&lt;pre class=&quot;brush:sql&quot;&gt;DECLARE
    @_txt_tmp  NVARCHAR(MAX),
    @full_string NVARCHAR(MAX) = &quot;Hello World From Transact-SQL&quot;
DECLARE
    @cursor_for_spliting CURSOR
    SET @cursor_for_spliting = CURSOR FOR SELECT splitdata FROM [dbo].[fnSplitString](@full_string,&#39;&#39;)
    OPEN @cursor_for_spliting FETCH NEXT FROM @cursor_for_spliting INTO @_txt_tmp
    WHILE @@FETCH_STATUS = 0
    BEGIN
        -- Do whatever with @_txt_tmp
    FETCH NEXT FROM @cursor_for_spliting INTO @_txt_tmp
END;
CLOSE @cursor_for_spliting ;
DEALLOCATE @cursor_for_spliting;
&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/2359528529041740839/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2017/12/split-function-transact-sql.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/2359528529041740839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/2359528529041740839'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2017/12/split-function-transact-sql.html' title='String split with Transact-SQL'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAyeH-Kl0japF3TBWZLxbEETbBu-lpjUe_LVJrLm7MpmTPwJEsgEz0QXKr3tXWcwGVRYJEhm7psXNlBreMuhuHFcQPfzJN-Tev8oz93b-Avll9tioAUGIyWSpj49NYhMoSpcBLADHppA0/s72-c/sql_server.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-3779880015367903443</id><published>2017-12-02T15:44:00.002-05:00</published><updated>2019-05-15T14:07:07.478-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="aplicaciones web"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="rest"/><category scheme="http://www.blogger.com/atom/ns#" term="webservices"/><title type='text'>Creando una REST Api para PHP con el Framework Slim 3</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
Slim es un framework para crear microservicios REST utilizando PHP. En este post se va a mostrar la manera cómo instalar Slim utilizando una herramienta para la gestión de dependencias en PHP llamada Composer. Resumiento, para poder seguir este artículo, necesitaremos lo siguiente:
&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0ghulbH9F2_90sDDCoOZc6Xh8aFDaLyJKJUwKPP6gkqajKjyUdVrRFLJ6gHHixgIl8F8NHy2g2u4k4tAxIAjA6fnj14KrM_NnLhOyZPylaFKblveUnlY7eXJzu-S3OxCjjZ-h82GhY0E/s320/slim-php-rest.png&quot; style=&quot;display: none;&quot; /&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;XAMPP/Apache&lt;/li&gt;
&lt;li&gt;Slim (&lt;a href=&quot;https://www.slimframework.com/&quot;&gt;https://www.slimframework.com/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Composer (&lt;a href=&quot;https://getcomposer.org/&quot;&gt;https://getcomposer.org/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;SublimeText (ocpional)&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Una vez tengamos instaladas todas estas herramientas, procederemos a descargar Slim vía Composer. Para esto, primero debemos crear nuestra carpeta de trabajo llamada rest-api dentro del directo C:\xampp\htdocs (&lt;b&gt;La ruta dependerá de dónde hayan instalado Xampp pero se recomiendo no utilizar nombres muy largos&lt;/b&gt;), situarnos en la carpeta utilizando un CDM y descargar la versión 3 del Framework Slim.
&lt;/div&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;C:\xampp\htdocs\rest-api&amp;gt;cd C:\xampp\htdocs\rest-api
C:\xampp\htdocs\rest-api&amp;gt;composer require slim/slim &quot;^3.0&quot;
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Ahora utilizaremos SublimeText para abrir la carpeta, en donde podremos visualizar todos los archivos de dependencias que se nos ha creado. Dentro de la carpeta rest-api crearemos dos subcarpetas: public y src. La siguiente imagen ilustra lo descrito anteriormente:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;503&quot; data-original-width=&quot;921&quot; height=&quot;349&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcHbAKsmfqg1PBK6QH0cPUgW5-JlDlP2-ACI2qrUuJrwjt6jSmrA-2iKf-GJ_6r2Lp5HkyLoP_RqRk9r_mPvCSExmILS-K-2cHzwDih3-F0KPxdKGIMTeWgdMtClA7ERFif9GCUxH2pNk/s640/php-slim-rest.png&quot; width=&quot;640&quot; /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ahora crearemos un archivo en la carpeta public llamada index.php cuyo contenido será el siguiente:
&lt;br /&gt;
&lt;pre class=&quot;brush:php&quot;&gt;&amp;lt;?php
use PsrHttpMessageServerRequestInterface as Request;
use PsrHttpMessageResponseInterface as Response;

require &#39;../vendor/autoload.php&#39;;

$app = new SlimApp;
$app-&amp;gt;get(&#39;/hello/{name}&#39;, function (Request $request, Response $response) {
    $name = $request-&amp;gt;getAttribute(&#39;name&#39;);
    $response-&amp;gt;getBody()-&amp;gt;write(&quot;Hello, $name&quot;);

    return $response;
});
$app-&amp;gt;run();
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
El código anterior es un ejemplo sencillo de un servicio Rest que recibe como parámetro un nombre y retorna un saludo. Y ahora, para poder verificar el funcionamiento de nuestra api podemos ingresar a la siguiente URL: http://localhost/rest-api/public/index.php/hello/rolando. En este punto quiero hacer algunas anotaciones, en primer lugar la ruta depende de la carpeta que hayan creado, en mi caso dicha carpeta se llama rest-api. Es importante también no olvidar que debemos escribir la ruta completa incluído el nombre del archivo index.php sino obtendremos de respuesta un error 404.&lt;br /&gt;
&lt;br /&gt;
Espero que este post les sea de ayuda para iniciarse en el mundo de los Microservicios con PHP. No se olviden seguirme a través de mis redes sociales de Facebook haciendo clic &lt;a href=&quot;https://www.facebook.com/rolandopalermo.biz/&quot;&gt;aquí&lt;/a&gt;.
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/3779880015367903443/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2017/12/slim-composer-php-rest-api-install.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/3779880015367903443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/3779880015367903443'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2017/12/slim-composer-php-rest-api-install.html' title='Creando una REST Api para PHP con el Framework Slim 3'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0ghulbH9F2_90sDDCoOZc6Xh8aFDaLyJKJUwKPP6gkqajKjyUdVrRFLJ6gHHixgIl8F8NHy2g2u4k4tAxIAjA6fnj14KrM_NnLhOyZPylaFKblveUnlY7eXJzu-S3OxCjjZ-h82GhY0E/s72-c/slim-php-rest.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-1750133156081439056</id><published>2017-11-28T14:15:00.003-05:00</published><updated>2019-05-15T14:07:38.769-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="programación"/><title type='text'>Diferencia entre git push -u y git push</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
En el post de hoy vamos a explicar las diferencias entre los comandos &lt;b&gt;git push -u origin master&lt;/b&gt; y &lt;b&gt;git push origin master&lt;/b&gt;. Aunque ambos comandos sirven para enviar nuestros cambios a un repositorio remoto, la bandera -u permite también agregar referencias ascendentes de seguimiento; en otras palabras, a partir de este punto, Git sabrá hacia dónde enviar y de dónde obtener los cambios sin la necesidad de utilizar argumentos en los comandos git push y git pull.&lt;br /&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG3s8qjjy5ZrQcVwRiLUkcaFgKXwWusurVARwqduYsSggON99wDq-A_XPqw8sBPIiH41L8wZxav1z0-kv4aa7kfLrgYcF5ISNUpsV9x0aED7SI4q9OEBN2ui3b70Xz6gwqX1D7wUMRUjU/s320/git_push_u_origin_master.png&quot; style=&quot;display: none;&quot; /&gt;&lt;/div&gt;
&lt;br /&gt;
Si no establecemos el upstream para el seguimiento, cuando invoquemos al comando git pull, se nos presentará un error indicándonos que no existe información de seguimiento para la rama actual. La siguiente imagen ilustra este escenario.&lt;br /&gt;
&lt;br /&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;423&quot; data-original-width=&quot;803&quot; height=&quot;338&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRSFbdMpd44k6WoQfZMBp8N8-hBxg5NmnC7puxdPNjPwBLUh7TVO6oA6rjgDMPH6WtV8-fMD5JPZSpQTcTHarGuHZJQY4tPfK2zDR60IvL_Gw-FGwnmjnNQ0yLNVtlzUxmAFDZiKEt3BU/s640/git_push_u_origin_master.jpg&quot; width=&quot;640&quot; /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;
Por otra parte, si ejecutamos el comando con la bandera -u, a partir de ese momento se creará una referencia de trazabilidad que nos permitirá invocar, por ejemplo, al comando &lt;b&gt;git pull&lt;/b&gt; sin la necesidad de argumentos.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;207&quot; data-original-width=&quot;808&quot; height=&quot;164&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMtj12x7bRbe_sPFZP7ROzm1866_7gh3dQrP1AWKtFZTdS4lQdSzomKnD4T0e5nV7BeVHntt8MKPzcEeXRw8NjVteMdcEqdlMICbZrkuUbD70fo6UAC5518ZjfyjT1TT-n8AKXZ44pAgE/s640/git_push_u_origin_master.jpg&quot; width=&quot;640&quot; /&gt;</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/1750133156081439056/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2017/11/diferencia-git-push-u-origin-master-git.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/1750133156081439056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/1750133156081439056'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2017/11/diferencia-git-push-u-origin-master-git.html' title='Diferencia entre git push -u y git push'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG3s8qjjy5ZrQcVwRiLUkcaFgKXwWusurVARwqduYsSggON99wDq-A_XPqw8sBPIiH41L8wZxav1z0-kv4aa7kfLrgYcF5ISNUpsV9x0aED7SI4q9OEBN2ui3b70Xz6gwqX1D7wUMRUjU/s72-c/git_push_u_origin_master.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-1357237961588844597</id><published>2017-11-25T00:40:00.001-05:00</published><updated>2019-05-15T14:10:33.296-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="aplicaciones web"/><category scheme="http://www.blogger.com/atom/ns#" term="glassfish"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="redes"/><title type='text'>Crear dominio en Servidor Glassfish</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaAyvEYUIzVvRFW4ikxkcmc1s6jWG1OXia5aIE49KJiLB2j114MVPXbv-AvYtosbn1VBYJPPyqvXScjQgC-grfsEIrE7TJm4DDd77qGrlQ4kk9Fsx3ej3bdadvFj3MBcNTGMQuOmfeihs/s320/glassfish.png&quot; style=&quot;display: none;&quot; /&gt;
Un &lt;b&gt;dominio Glassfish&lt;/b&gt; es un conjunto de instancias o espacio de nombres administrativos que se pueden administrar de forma conjunta. Este mismo proporciona una configuración preconfigurada para todas las aplicaciones del usuario o cliente, en este caso se pueden editar acorde a lo que necesitemos. Para crear un dominio, lo primero que debemos hacer es ubicarnos en la instalación de nuestro &lt;b&gt;Glassfish &lt;/b&gt;y a continuación ejecutar el comando:
&lt;/div&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;asadmin create-service domain1
&lt;/pre&gt;
Si todo se realizó correctamente, obtendremos el mensaje mostrado en la siguiente imagen:&lt;br /&gt;
&lt;br /&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;510&quot; data-original-width=&quot;1006&quot; height=&quot;324&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWw3WIZKSC5KPL9yVU8dIp5UTNjP7in1_fJLUJS4Dlc_g4QwXGs6_E7Z30AL79CeOUahO7fmpHV9bkW22WQc2vEe1UdzkDmy79xVpaxmfBZXLf8oJCCItVQPaJr2TFiI9uxgdt44OwvTk/s640/create_domain_glassfish.jpg&quot; width=&quot;640&quot; /&gt;&lt;br /&gt;
&lt;br /&gt;
Ahora inicimos nuestro Glassfish a través del comando:
&lt;br /&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;asadmin start-domain
&lt;/pre&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;510&quot; data-original-width=&quot;1006&quot; height=&quot;324&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT2hg7n5Q-IcXhcf_q9_DalZb6HNXiC0ikqnKIke_Lip0ndIvWzA_3btyDgkEvtfdz3pKLVnz6PISRYD8znS-RYY7NKgpwYjOlQYE6tDbBg0O1ZZ1vLZxsu5YAsXG7R2IEpsbNJyuSG2Q/s640/iniciar_dominio_glassfish.png&quot; width=&quot;640&quot; /&gt;&lt;br /&gt;
&lt;br /&gt;
Si todo se ejecutó correctamente, al acceder a la ruta http://localhost:8080, podremos visualizar la consola de administración de nuestro contenedor de aplicaciones.
&lt;br /&gt;
Para reiniciar nuestro dominio podemos usar el comando:
&lt;br /&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;asadmin restart-domain domain1
&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/1357237961588844597/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2017/11/crear-administrar-domio-glassfish-server.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/1357237961588844597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/1357237961588844597'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2017/11/crear-administrar-domio-glassfish-server.html' title='Crear dominio en Servidor Glassfish'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaAyvEYUIzVvRFW4ikxkcmc1s6jWG1OXia5aIE49KJiLB2j114MVPXbv-AvYtosbn1VBYJPPyqvXScjQgC-grfsEIrE7TJm4DDd77qGrlQ4kk9Fsx3ej3bdadvFj3MBcNTGMQuOmfeihs/s72-c/glassfish.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-88819464578674557</id><published>2017-11-22T17:58:00.000-05:00</published><updated>2019-06-02T20:20:01.715-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="rest"/><category scheme="http://www.blogger.com/atom/ns#" term="spring"/><category scheme="http://www.blogger.com/atom/ns#" term="webservices"/><title type='text'>RestController con Spring Boot</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
En este post vamos a revisar un ejemplo sencillo de lo que sería los servicios Rest utilizando Spring Framework. Las tecnologías requeridas para este proyecto son:
&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfEU_yOBFe2H-NHVdVh0QwwDB18MGnq9SGdqrKXX5emFIzCi0-Mq3Jf-zTFDASyFTRb-V5CAFpxR2cg_ABp21FDUV7I_qNqrH5XjRiq-VuXWw612oFOfbM-3C1ROwq3-Nu_wgOQDz4Hbc/s320/spring_rest.png&quot; style=&quot;display: none;&quot; /&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Spring Boot&lt;/li&gt;
&lt;li&gt;H2&lt;/li&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;JDK 8&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
A continuación se muestra la estructura del proyecto Maven. En este proyecto, utilizaremos una base de datos H2 la cual podremos manipular a través de tres servicios Rest ya sea para insertar, consultar un registro o listar una tabla.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;415&quot; data-original-width=&quot;292&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimqENj6ckGTHXKkMhoPT8j234XRh4tAkQy0NryPBcmGsVTdLivvmrwRKgYhix3iJs706oqkiK7QM4LQKsmF9wybPRGhMMWOD92cuNR7VJnNqZkmcAouHpLaLTDZ0Je8Ub1tLw5aqb8SHg/s320/src.jpg&quot; width=&quot;225&quot; /&gt;
&lt;br /&gt;
&lt;br /&gt;
El archivo POM de dependencias Maven es el siguiente:
&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
 xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&amp;gt;
 &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;
 &amp;lt;groupId&amp;gt;com.rolandopalermo.git&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;base-api-rest-springboot&amp;lt;/artifactId&amp;gt;
 &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;
 &amp;lt;packaging&amp;gt;jar&amp;lt;/packaging&amp;gt;
 
 &amp;lt;parent&amp;gt;
        &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;spring-boot-starter-parent&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.4.0.RELEASE&amp;lt;/version&amp;gt;
    &amp;lt;/parent&amp;gt;
    
    &amp;lt;properties&amp;gt;
        &amp;lt;project.build.sourceEncoding&amp;gt;UTF-8&amp;lt;/project.build.sourceEncoding&amp;gt;
        &amp;lt;project.reporting.outputEncoding&amp;gt;UTF-8&amp;lt;/project.reporting.outputEncoding&amp;gt;
        &amp;lt;java.version&amp;gt;1.8&amp;lt;/java.version&amp;gt;
    &amp;lt;/properties&amp;gt;
    
 &amp;lt;dependencies&amp;gt;
  
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;spring-boot-starter-data-jpa&amp;lt;/artifactId&amp;gt;
  &amp;lt;/dependency&amp;gt;
 
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;spring-boot-starter-web&amp;lt;/artifactId&amp;gt;
  &amp;lt;/dependency&amp;gt;
  
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;com.h2database&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;h2&amp;lt;/artifactId&amp;gt;
  &amp;lt;/dependency&amp;gt;
 &amp;lt;/dependencies&amp;gt;
 &amp;lt;build&amp;gt;
  &amp;lt;finalName&amp;gt;base-api-rest-springboot&amp;lt;/finalName&amp;gt;
 &amp;lt;/build&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;
La clase principal utilizada para iniciar Spring Boot es la siguiente:
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.rest.base;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

 public static void main(String[] args) {
  SpringApplication.run(Application.class, args);
 }

}
&lt;/pre&gt;
La siguiente clase representa el bean que será utilizado para manipular nuestra base de datos. Este bean utilizará anotaciones las cuales le permitirán validar la correcta estructura de campos en cualquier instancia así como también manipular este bean como objeto JSON.
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.rest.base.model;

import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;

import org.hibernate.validator.constraints.NotBlank;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;

@Entity
public class User {

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;

 @JsonProperty(&quot;user_name&quot;)
 @NotBlank
 private String userName;

 @JsonProperty(&quot;last_name&quot;)
 @NotBlank
 private String lastName;

 @JsonProperty(&quot;gender&quot;)
 @NotNull
 private Gender gender;

 @JsonProperty(&quot;age&quot;)
 @Min(value = 18)
 @Max(value = 150)
 @NotNull
 private Integer age;

 @JsonProperty(&quot;birth&quot;)
 @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = &quot;dd-MM-yyyy&quot;)
 @Past
 @NotNull
 private Date dateOfBirth;

 public Long getId() {
  return id;
 }

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

 public String getUserName() {
  return userName;
 }

 public void setUserName(String userName) {
  this.userName = userName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 public Gender getGender() {
  return gender;
 }

 public void setGender(Gender gender) {
  this.gender = gender;
 }

 public Integer getAge() {
  return age;
 }

 public void setAge(Integer age) {
  this.age = age;
 }

 public Date getDateOfBirth() {
  return dateOfBirth;
 }

 public void setDateOfBirth(Date dateOfBirth) {
  this.dateOfBirth = dateOfBirth;
 }

}
&lt;/pre&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.rest.base.model;

public enum Gender {
    MALE, FEMALE;
}
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Esta clase se encargá de definir los métodos para acceder a base de datos. En este caso se reutilizará la clase genérica CrudRepository.
&lt;/div&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.rest.base.repository;

import org.springframework.data.repository.CrudRepository;

import com.rolandopalermo.rest.base.model.User;
 
public interface UserRepository extends CrudRepository&amp;lt;User, Long&amp;gt; {
 
}
&lt;/pre&gt;
La clase UserService conformará la capa de servicio y es en donde se invocará a los métodos definidos en la clase UserRepository que vendría siendo nuestra capa de datos.
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.rest.base.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.rolandopalermo.rest.base.model.User;
import com.rolandopalermo.rest.base.repository.UserRepository;

@Service
public class UserService {

 @Autowired
 private UserRepository repository;

 public User get(long userId) {
  return repository.findOne(userId);
 }

 public List&amp;lt;User&amp;gt; list() {
  Iterable&amp;lt;User&amp;gt; users = repository.findAll();
  List&amp;lt;User&amp;gt; list = new ArrayList&amp;lt;User&amp;gt;();
  for(User user : users) {
   list.add(user);
  }
  return list;
 }

 public User create(User user) {
  return repository.save(user);
 }
}
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
La clase UserController expondrá los diversos métodos para manipular la tabla de Usuarios. Estos serán para insertar, consultar un registro o listarlos todos. Estos servicios serán expuestos a través de los métodos POST y GET.
&lt;/div&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.rest.base.controller;

import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.rolandopalermo.rest.base.model.User;
import com.rolandopalermo.rest.base.service.UserService;

@RestController
public class UserController {

 @Autowired
 private UserService userService;

 @RequestMapping(value = &quot;/users&quot;, method = RequestMethod.GET)
 public ResponseEntity&amp;lt;User&amp;gt; list() {
  List&amp;lt;User&amp;gt; users = userService.list();
  return new ResponseEntity(users, HttpStatus.OK);
 }

 @RequestMapping(value = &quot;/user&quot;, method = RequestMethod.GET)
 public ResponseEntity&amp;lt;User&amp;gt; userById(@RequestParam(value = &quot;id&quot;) long id) {
  User user = userService.get(id);
  return new ResponseEntity(user, HttpStatus.OK);
 }

 @RequestMapping(value = &quot;/create&quot;, method = RequestMethod.POST)
 public ResponseEntity&amp;lt;User&amp;gt; create(@Valid @RequestBody User user) {
  User userCreated = userService.create(user);
  return new ResponseEntity(userCreated, HttpStatus.CREATED);
 }

}
&lt;/pre&gt;
Al ejecutar el proyecto, tendremos lo siguiente:&lt;br /&gt;
&lt;br /&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;290&quot; data-original-width=&quot;1007&quot; height=&quot;184&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOTvx4zqHLkif956FANO5CRrAGrqB8V4M4CmA22XsfYkRFPC0TW6IYJh3kf9orV8vN_wgFW_BAtMmvucShX2DuJvtVIbAbYZf39MLaX2usTYhnu1mHOJSm1X9Ncy3i6DeD_p4QlsJuQZw/s640/resultado_springboot.jpg&quot; width=&quot;640&quot; /&gt;&lt;br /&gt;
&lt;br /&gt;
Al enviar la siguiente petición utilizando POSTMAN, el resultado será el siguiente:
&lt;br /&gt;
&lt;pre class=&quot;brush:javascript&quot;&gt;{
   &quot;id&quot;:1,
   &quot;user_name&quot;:&quot;Juan&quot;,
   &quot;last_name&quot;:&quot;Perez&quot;,
   &quot;gender&quot;:&quot;MALE&quot;,
   &quot;age&quot;:23,
   &quot;birth&quot;:&quot;12-10-1994&quot;
}
&lt;/pre&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;512&quot; data-original-width=&quot;956&quot; height=&quot;342&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxo84J8tul8KnE1ZqtutYfkhjRXmK13J9FYp6GEb-VFBsAKyYgwdz6Bhk10rhmya9ZOkoiKfVcDde6ictnmTpaB2C4BqETyPgYicZ0Q6NAehVz4GhDXPqz2AzVmWH8qTnVnQMR82XoZI8/s640/resultado_springboot_2.jpg&quot; width=&quot;640&quot; /&gt;&lt;br /&gt;
&lt;br /&gt;
Cuando consultemos los registros ingresados, obtendremos lo siguiente:
&lt;br /&gt;
&lt;pre class=&quot;brush:javascript&quot;&gt;[
    {
        &quot;id&quot;: 1,
        &quot;user_name&quot;: &quot;Juan&quot;,
        &quot;last_name&quot;: &quot;Perez&quot;,
        &quot;gender&quot;: &quot;MALE&quot;,
        &quot;age&quot;: 23,
        &quot;birth&quot;: &quot;12-10-1994&quot;
    },
    {
        &quot;id&quot;: 2,
        &quot;user_name&quot;: &quot;Juan&quot;,
        &quot;last_name&quot;: &quot;De Arco&quot;,
        &quot;gender&quot;: &quot;FEMALE&quot;,
        &quot;age&quot;: 23,
        &quot;birth&quot;: &quot;12-10-1994&quot;
    }
]
&lt;/pre&gt;
&lt;img border=&quot;0&quot; data-original-height=&quot;564&quot; data-original-width=&quot;959&quot; height=&quot;376&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_7Y0kk2Uenh6eA2kSHXopsEmvcfPzV0d55I7Bp-08xWsf2GmGQRWboYmB18yuzKnv8EVVqDRyIIpK12SevgsZUfRrSmpPtGeUahLPDlIN_FRjMRxTstY4DbjNPh2LbvlOstZzt0_Pk4A/s640/resultado_springboot_3.jpg&quot; width=&quot;640&quot; /&gt;</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/88819464578674557/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2017/11/rest-api-springboot-java.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/88819464578674557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/88819464578674557'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2017/11/rest-api-springboot-java.html' title='RestController con Spring Boot'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfEU_yOBFe2H-NHVdVh0QwwDB18MGnq9SGdqrKXX5emFIzCi0-Mq3Jf-zTFDASyFTRb-V5CAFpxR2cg_ABp21FDUV7I_qNqrH5XjRiq-VuXWw612oFOfbM-3C1ROwq3-Nu_wgOQDz4Hbc/s72-c/spring_rest.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-7533245668787857410</id><published>2017-11-14T21:37:00.000-05:00</published><updated>2019-05-15T14:44:44.868-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="aplicaciones web"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="webservices"/><title type='text'>Creating Web Services with PHP and SOAP</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlECW6cJQYE7Hr0V-sPMqliPGmlPMSTx1uAcx4ZLXrJ5vyq1CYKn4ZsBHGQrEnHN9oHoyJ8647pzXQS0goJcwpR60UObcer63T32_q0ebqoVidMP_omId79wsE4PODHOU6h8tAkfezeQ8/s320/php.jpg&quot; style=&quot;display: none;&quot; /&gt;
There are two basic approaches that are used to create web services from scratch. In this first of a two part series on web services I’ll talk about the &#39;top-down&#39; approach. According with this approach, we need to produce the XML description of the service before it is implemented. So the service is fully described in terms of what it does, how it can be called and what result(s) it returns, but is not actually implemented. This (WSDL) specification is then used as a guide to writing the code that implements the service.&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;The project structure&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrs-YlK-WKmSTDKWcvFsoE-0bALcoeEyzyvGXDrZz4oqtjmaACFeTg7pnFE8ghr03-s7MZ9LqqzOlctQs6auVCb6Zccrn5Ra-_ZnpTvjIGMCEHAvh7pzYPkvQTbkwebbz59OSLamQOpi4/s1600/tree_php.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;143&quot; data-original-width=&quot;555&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrs-YlK-WKmSTDKWcvFsoE-0bALcoeEyzyvGXDrZz4oqtjmaACFeTg7pnFE8ghr03-s7MZ9LqqzOlctQs6auVCb6Zccrn5Ra-_ZnpTvjIGMCEHAvh7pzYPkvQTbkwebbz59OSLamQOpi4/s1600/tree_php.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;
The webservice will receive a string parameter and it will return the &#39;hello&#39; string concatenated with the input parameter. For example, if the input is &#39;Andrea&#39;, then the output will be &#39;Hello Andrea&#39;. In order to achieve this, we need to define the WSDL descriptor.&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;The descriptor.wsdl&lt;/b&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;wsdl:definitions name=&quot;HelloWS&quot;
      targetNamespace=&quot;http://ws.rolandopalermo.com/&quot;
      xmlns:tns=&quot;http://ws.rolandopalermo.com/&quot;
                  xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot;
                  xmlns:soap=&quot;http://schemas.xmlsoap.org/wsdl/soap/&quot;
                  xmlns:wsdl=&quot;http://schemas.xmlsoap.org/wsdl/&quot;&amp;gt;

 &amp;lt;wsdl:types&amp;gt;
 &amp;lt;/wsdl:types&amp;gt;
  
 &amp;lt;wsdl:message name=&quot;helloRequest&quot;&amp;gt;
  &amp;lt;wsdl:part name=&quot;name&quot; type=&quot;xsd:string&quot;&amp;gt;&amp;lt;/wsdl:part&amp;gt;
 &amp;lt;/wsdl:message&amp;gt;
 
 &amp;lt;wsdl:message name=&quot;helloResponse&quot;&amp;gt;
  &amp;lt;wsdl:part name=&quot;result&quot; type=&quot;xsd:string&quot;&amp;gt;&amp;lt;/wsdl:part&amp;gt;
 &amp;lt;/wsdl:message&amp;gt;
  
 &amp;lt;wsdl:portType name=&quot;HelloWS&quot;&amp;gt;
  &amp;lt;wsdl:operation name=&quot;hello&quot;&amp;gt;
            &amp;lt;wsdl:input message=&quot;tns:helloRequest&quot;/&amp;gt;
            &amp;lt;wsdl:output message=&quot;tns:helloResponse&quot;/&amp;gt;
        &amp;lt;/wsdl:operation&amp;gt;
 &amp;lt;/wsdl:portType&amp;gt;
  
 &amp;lt;wsdl:binding name=&quot;HelloWSPortBinding&quot; type=&quot;tns:HelloWS&quot;&amp;gt;
  &amp;lt;soap:binding style=&quot;rpc&quot; transport=&quot;http://schemas.xmlsoap.org/soap/http&quot;/&amp;gt;
  &amp;lt;wsdl:operation name=&quot;hello&quot;&amp;gt;
   &amp;lt;soap:operation soapAction=&quot;http://localhost/soap_demo/server.php&quot;/&amp;gt;
   &amp;lt;wsdl:input&amp;gt;
    &amp;lt;soap:body use=&quot;literal&quot;/&amp;gt;
   &amp;lt;/wsdl:input&amp;gt;
   &amp;lt;wsdl:output&amp;gt;
    &amp;lt;soap:body use=&quot;literal&quot;/&amp;gt;
   &amp;lt;/wsdl:output&amp;gt;
  &amp;lt;/wsdl:operation&amp;gt;
 &amp;lt;/wsdl:binding&amp;gt;
  
 &amp;lt;wsdl:service name=&quot;HelloWS&quot;&amp;gt;
  &amp;lt;wsdl:port name=&quot;HelloWSPort&quot; binding=&quot;tns:HelloWSPortBinding&quot;&amp;gt;
   &amp;lt;soap:address location=&quot;http://localhost/soap_demo/server.php&quot;/&amp;gt;
  &amp;lt;/wsdl:port&amp;gt;
 &amp;lt;/wsdl:service&amp;gt;
 
&amp;lt;/wsdl:definitions&amp;gt;
&lt;/pre&gt;
We also need to implement the hello method in a php file.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The server.php file&lt;/b&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:php&quot;&gt;&amp;lt;?php
// turn off WSDL caching
ini_set(&quot;soap.wsdl_cache_enabled&quot;,&quot;0&quot;);

function hello($name)
{
 return &#39;Hello &#39;.&#39; &#39;.$name;
}

// initialize SOAP Server
$server = new SoapServer(&quot;descriptor.wsdl&quot;,[]);
// register available functions
$server-&amp;gt;addFunction(&#39;hello&#39;);
// start handling requests
$server-&amp;gt;handle();
&lt;/pre&gt;
Now, we can import the WSDL file into SoapUI for example  and the results should look like this:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The SOAP request.&lt;/b&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;soapenv:Envelope xmlns:soapenv=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot; xmlns:ws=&quot;http://ws.rolandopalermo.com/&quot;&amp;gt;
   &amp;lt;soapenv:Header/&amp;gt;
   &amp;lt;soapenv:Body&amp;gt;
      &amp;lt;ws:hello&amp;gt;
         &amp;lt;name&amp;gt;Andrea&amp;lt;/name&amp;gt;
      &amp;lt;/ws:hello&amp;gt;
   &amp;lt;/soapenv:Body&amp;gt;
&amp;lt;/soapenv:Envelope&amp;gt;
&lt;/pre&gt;
&lt;b&gt;The SOAP response.&lt;/b&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;SOAP-ENV:Envelope xmlns:SOAP-ENV=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;&amp;gt;
   &amp;lt;SOAP-ENV:Body&amp;gt;
      &amp;lt;SOAP-ENV:helloResponse&amp;gt;
         &amp;lt;result&amp;gt;Hello  Andrea&amp;lt;/result&amp;gt;
      &amp;lt;/SOAP-ENV:helloResponse&amp;gt;
   &amp;lt;/SOAP-ENV:Body&amp;gt;
&amp;lt;/SOAP-ENV:Envelope&amp;gt;
&lt;/pre&gt;
Do not forget to &lt;b&gt;enable the SOAP extension&lt;/b&gt; in the &lt;b&gt;php.ini&lt;/b&gt; file. To do this, you have to find extension=php_soap.dll in php.ini, remove the semicolon(;) and restart the server.</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/7533245668787857410/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2017/11/creating-web-services-php-soap.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/7533245668787857410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/7533245668787857410'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2017/11/creating-web-services-php-soap.html' title='Creating Web Services with PHP and SOAP'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlECW6cJQYE7Hr0V-sPMqliPGmlPMSTx1uAcx4ZLXrJ5vyq1CYKn4ZsBHGQrEnHN9oHoyJ8647pzXQS0goJcwpR60UObcer63T32_q0ebqoVidMP_omId79wsE4PODHOU6h8tAkfezeQ8/s72-c/php.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-7845137823221683075</id><published>2017-07-09T21:44:00.003-05:00</published><updated>2019-05-15T14:51:32.036-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="facturacion electronica"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="webservices"/><title type='text'>Nuevo Esquema Offline de Documentos Electrónicos | SRI</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
Desde la publicación de la Resolución NAC-DGERCGC14-00790, el SRI puso en marcha un nuevo esquema para la emisión de comprobantes electrónicos: el esquema Off-line. Actualmente este esquema, con el propósito de que los emisores de comprobantes que lo deseen puedan realizar pruebas y ajustar sus servicios a este nuevo esquema, está disponible en las siguientes URL&#39;s:&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Uno es para el ambiente de Pruebas en donde cada contribuyente certificará que su aplicación funcione correctamente con cada tipo de comprobante electrónico.&lt;/div&gt;
&lt;br /&gt;
&lt;a href=&quot;https://celcer.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl&quot;&gt;https://celcer.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://celcer.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl&quot;&gt;https://celcer.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
El segundo es para el ambiente de Producción, al cual cada contribuyente deberá acceder una vez que ha realizado las pruebas y esté seguro que su aplicación funciona
correctamente, las direcciones del los WS son las siguientes:&lt;/div&gt;
&lt;br /&gt;
&lt;a href=&quot;https://cel.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl&quot;&gt;https://cel.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://cel.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl&quot;&gt;https://cel.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Con el nuevo esquema Off-line, se puede generar un comprobante en tres sencillos pasos; ya que el cambio más significativo se encuentra en que los comprobantes serán enviados al mismo tiempo tanto al receptor como al SRI. Es decir, el mismo comprobante que recibe el SRI para su validación es el que recibirán sus socios de negocio.
&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Figura 1. Diferencias entre el esquema ONLINE y el nuevo esquema OFFLINE (Fuente: SRI)
&lt;/span&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;831&quot; data-original-width=&quot;1014&quot; height=&quot;524&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKQwdHViVD2GH2JpOSQDIfMfN5AdmBhQQ5oL_ZMHSpuhhFCXBCoqYMCQBAAYzl2uTvZ6k-AICzvvQMsqQmsVoq7q0JsHHFLf1Bc9IXJwJOveTzFkPRVBQne8Yxy-bGg_nbSYmTlPIPXm8/s640/e-invoice-rolandopalermo.jpg&quot; width=&quot;640&quot; /&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
En RP Consulting ya disponemos del nuevo esquema Off-line. Más de 20 clientes en Ecuador confirman la calidad de nuestro servicio de consultoría y capacitación en temas de facturación electrónica.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Te invitamos a ponerte en contacto con nosotros en el siguiente formulario para evaluar la integración de este nuevo esquema, ya sea a través de librerías, dll, apis o servicios Web. Contamos con los consultores más especializados en el tema.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;b&gt;Datos de contacto&lt;/b&gt;
&lt;br /&gt;
&lt;table style=&quot;border: 1px solid black; width: 100%;&quot;&gt;
  &lt;tbody&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;b&gt;Skype&lt;/b&gt;&lt;/td&gt;
    &lt;td&gt;rolandopalermo&lt;/td&gt; 
  &lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;b&gt;Email&lt;/b&gt;&lt;/td&gt;
    &lt;td&gt;rolando.roc@gmail.com&lt;/td&gt; 
  &lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;b&gt;Facebook&lt;/b&gt;&lt;/td&gt;
    &lt;td&gt;fb.com/rolandopalermo&lt;/td&gt; 
  &lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;b&gt;Licenciamiento&lt;/b&gt;&lt;/td&gt;
    &lt;td&gt;No posee restricciones de licencia&lt;/td&gt; 
  &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/7845137823221683075/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2017/07/esquema-offline-java-sri-ecuador.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/7845137823221683075'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/7845137823221683075'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2017/07/esquema-offline-java-sri-ecuador.html' title='Nuevo Esquema Offline de Documentos Electrónicos | SRI'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKQwdHViVD2GH2JpOSQDIfMfN5AdmBhQQ5oL_ZMHSpuhhFCXBCoqYMCQBAAYzl2uTvZ6k-AICzvvQMsqQmsVoq7q0JsHHFLf1Bc9IXJwJOveTzFkPRVBQne8Yxy-bGg_nbSYmTlPIPXm8/s72-c/e-invoice-rolandopalermo.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-2765509323546316112</id><published>2017-05-01T10:50:00.001-05:00</published><updated>2019-05-15T14:57:12.834-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="diseño web"/><category scheme="http://www.blogger.com/atom/ns#" term="html"/><category scheme="http://www.blogger.com/atom/ns#" term="latex"/><title type='text'>HTML y Latex: MathJax</title><content type='html'>MathJax es un motor de visualización JavaScript de código abierto para la notación LaTeX, MathML y ​​AsciiMath que funciona en todos los navegadores modernos. Para utilizar este motor, basta con agregarel código que muestro a continuación:
&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0hjmUBv1BrMzKXCsFP5RiV4qhE-esqHv1GXFFDqVuZb4XpDGqX7CNRMAihxU0pX9gksyJ2QSsSGokY2mKoGELf-FVFDR5s2ZrovnYOPUTyyI_z6vuDvtRDhMNdcLeSiGB4vkCSxZ5y3o/s320/mathjax-sample.png&quot; style=&quot;display: none;&quot; /&gt;

&lt;br /&gt;
&lt;pre class=&quot;brush:html&quot;&gt;&amp;lt;script type=&quot;text/x-mathjax-config&quot;&amp;gt;
   MathJax.Hub.Config({&quot;HTML-CSS&quot;: { preferredFont: &quot;TeX&quot;, availableFonts: [&quot;STIX&quot;,&quot;TeX&quot;], linebreaks: { automatic:true }, EqnChunk: (MathJax.Hub.Browser.isMobile ? 10 : 50) },
       tex2jax: { inlineMath: [ [&quot;$&quot;, &quot;$&quot;], [&quot;\\(&quot;,&quot;\\)&quot;] ], displayMath: [ [&quot;$$&quot;,&quot;$$&quot;], [&quot;\[&quot;, &quot;\]&quot;] ], processEscapes: true, ignoreClass: &quot;tex2jax_ignore|dno&quot; },
       TeX: { 
           noUndefined: { attributes: { mathcolor: &quot;red&quot;, mathbackground: &quot;#FFEEEE&quot;, mathsize: &quot;90%&quot; } }, Macros: { href: &quot;{}&quot; } },
       messageStyle: &quot;none&quot;
   });
&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS_HTML-full&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/pre&gt;
Los resultados son tan asombrosos como los ejemplos que muestro a continuación:

&lt;pre class=&quot;brush:html&quot;&gt;&amp;lt;p&amp;gt;
When (a ne 0), there are two solutions to (ax^2 + bx + c = 0) and they are
$$x = {-b pm sqrt{b^2-4ac} over 2a}.$$
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
$$\text{When }(a \ne 0)\text{, there are two solutions to }(ax^2 + bx + c = 0)\text{ and they are}$$
$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$

&lt;pre class=&quot;brush:html&quot;&gt;&amp;lt;p&amp;gt;
$$sum_{i=0}^n i^2 = frac{(n^2+n)(2n+1)}{6}$$
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
$$\sum_{i=0}^n i^2 = \frac{(n^2+n)(2n+1)}{6}$$

&lt;pre class=&quot;brush:html&quot;&gt;&amp;lt;p&amp;gt;
$$sum_{i=0}^n i^2 = frac{(n^2+n)(2n+1)}{6}$$
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
$$\sum_{i=0}^n i^2 = \frac{(n^2+n)(2n+1)}{6}$$

&lt;pre class=&quot;brush:html&quot;&gt;&amp;lt;p&amp;gt;
$$
begin{array}{c|lcr}
n &amp;amp; text{Left} &amp;amp; text{Center} &amp;amp; text{Right} \
hline
1 &amp;amp; 0.24 &amp;amp; 1 &amp;amp; 125 \
2 &amp;amp; -1 &amp;amp; 189 &amp;amp; -8 \
3 &amp;amp; -20 &amp;amp; 2000 &amp;amp; 1+10i
end{array}
$$
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
$$
\begin{array}{c|lcr}
n &amp;amp; \text{Left} &amp;amp; \text{Center} &amp;amp; \text{Right} \\
\hline
1 &amp;amp; 0.24 &amp;amp; 1 &amp;amp; 125 \\
2 &amp;amp; -1 &amp;amp; 189 &amp;amp; -8 \\
3 &amp;amp; -20 &amp;amp; 2000 &amp;amp; 1+10i
\end{array}
$$

&lt;pre class=&quot;brush:html&quot;&gt;&amp;lt;p&amp;gt;
$$underset{j=1}{overset{infty}{LARGEmathrm K}}frac{a_j}{b_j}=cfrac{a_1}{b_1+cfrac{a_2}{b_2+cfrac{a_3}{b_3+ddots}}}$$
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
$$\underset{j=1}{\overset{\infty}{\LARGE\mathrm K}}\frac{a_j}{b_j}=\cfrac{a_1}{b_1+\cfrac{a_2}{b_2+\cfrac{a_3}{b_3+\ddots}}}$$

&lt;pre class=&quot;brush:html&quot;&gt;&amp;lt;p&amp;gt;
$require{AMScd}$
begin{CD}
A @&amp;amp;gt;a&amp;amp;gt;&amp;amp;gt; B\
@V b V V= @VV c V\
C @&amp;amp;gt;&amp;amp;gt;d&amp;amp;gt; D
end{CD}
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
$\require{AMScd}$
\begin{CD}
A @&amp;gt;a&amp;gt;&amp;gt; B\\
@V b V V= @VV c V\\
C @&amp;gt;&amp;gt;d&amp;gt; D
\end{CD}

&lt;div style=&quot;text-align: justify;&quot;&gt;
Un claro ejemplo donde podemos visualizar MathJax en todo su potencial es en &lt;a href=&quot;https://math.stackexchange.com/&quot;&gt;math.stackexchange.com&lt;/a&gt;. Les invito a revisar el proyecto que definitivamente es de mucha ayuda a la publicación de resultados para la gente inmersa en la ciencia.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/2765509323546316112/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2017/05/mathjax-sample-html.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/2765509323546316112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/2765509323546316112'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2017/05/mathjax-sample-html.html' title='HTML y Latex: MathJax'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0hjmUBv1BrMzKXCsFP5RiV4qhE-esqHv1GXFFDqVuZb4XpDGqX7CNRMAihxU0pX9gksyJ2QSsSGokY2mKoGELf-FVFDR5s2ZrovnYOPUTyyI_z6vuDvtRDhMNdcLeSiGB4vkCSxZ5y3o/s72-c/mathjax-sample.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-1739730257769271107</id><published>2017-04-30T23:34:00.001-05:00</published><updated>2019-05-15T14:59:57.904-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="aplicaciones web"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="jquery"/><category scheme="http://www.blogger.com/atom/ns#" term="spring"/><title type='text'>Raphael JS Pie Chart and Spring MVC</title><content type='html'>Raphael JS is a lightweight JavaScript framework which allows you to draw vector graphics in a browser. In this post, I will introduce you a basic example in order to explain how to create a Pie Chart from a given set of data which will be provided by a Spring Controller and a Ajax calling.
&lt;img src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2WFJXZH11QHr7oC7MDOmRceMh5E55FC_hS7wjqCWJ6c9RgcQT55Dixz8Nb6I_CSKbDUntvs0OrRP5zoUoRfZoKUcNI3SRs3Z3e_U5-Sbn5e9yF0sPcekzjwn5qAs-m7MkUoJY2SSAsLw/s320/raphaeljs-banner.png&quot; style=&quot;display: none;&quot; /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Required Software to Run Example:&lt;/b&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Java 7&lt;/li&gt;
&lt;li&gt;Eclipse Mars&lt;/li&gt;
&lt;li&gt;Apache Tomcat 8.0&lt;/li&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://dmitrybaranovskiy.github.io/raphael/&quot;&gt;Raphael JS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;Project Structure in Netbeans&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;img border=&quot;0&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBDNPwWkIV3RknEwuBu7chybpjpqslS842enW5ltsQ2lfP6FBFdJHdNl-uQdplaz-ZCE5Ux5lOdT_mH5037qbGBJYWGpNHxqM3G12r3UEVXsWJ2yr3ojAv3gRFdPgjYbF9xeLxbCqgUeQ/s400/rapahel-js-spring-mvc.jpg&quot; width=&quot;280&quot; /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;POM.xml&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
 xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&amp;gt;
 &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;
 &amp;lt;groupId&amp;gt;com.rolandopalermo.web&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;spring-raphael&amp;lt;/artifactId&amp;gt;
 &amp;lt;packaging&amp;gt;war&amp;lt;/packaging&amp;gt;
 &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;
 &amp;lt;name&amp;gt;spring-raphael Maven Webapp&amp;lt;/name&amp;gt;
 &amp;lt;url&amp;gt;http://maven.apache.org&amp;lt;/url&amp;gt;
 &amp;lt;dependencies&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;javax.servlet&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;jstl&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;1.2&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;junit&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;junit&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;3.8.1&amp;lt;/version&amp;gt;
   &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;!-- Spring --&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;spring-core&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;4.3.5.RELEASE&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;spring-webmvc&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;4.3.5.RELEASE&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;!-- JSON --&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;com.fasterxml.jackson.core&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;jackson-core&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;2.7.3&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;com.fasterxml.jackson.core&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;jackson-databind&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;2.7.3&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
 &amp;lt;/dependencies&amp;gt;
 &amp;lt;build&amp;gt;
  &amp;lt;finalName&amp;gt;spring-raphael&amp;lt;/finalName&amp;gt;
 &amp;lt;/build&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;
&lt;b&gt;Pie.js&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:javascript&quot;&gt;Raphael.fn.pieChart = function(cx, cy, r, values, labels, stroke) {
 var paper = this;
 var rad = Math.PI / 180;// degrees to radians
 var chart = this.set();
 var angle = 0, total = 0, start = 0;
 // Draw a sector
 function sector(cx, cy, r, startAngle, endAngle, params) {
  console.log(params.fill);
  var x1 = cx + r * Math.cos(-startAngle * rad), x2 = cx + r
    * Math.cos(-endAngle * rad), y1 = cy + r
    * Math.sin(-startAngle * rad), y2 = cy + r
    * Math.sin(-endAngle * rad);
  return paper.path(
    [ &quot;M&quot;, cx, cy, &quot;L&quot;, x1, y1, &quot;A&quot;, r, r, 0,
      +(endAngle - startAngle &amp;gt; 180), 0, x2, y2, &quot;z&quot; ]).attr(
    params);
 }

 process = function(j) {
  var value = values[j], angleplus = 360 * value / total, popangle = angle
    + (angleplus / 2), color = Raphael.hsb(start, .75, 1), ms = 500, delta = 30, bcolor = Raphael
    .hsb(start, 1, 1), p = sector(cx, cy, r, angle, angle
    + angleplus, {
   fill : &quot;90-&quot; + bcolor + &quot;-&quot; + color,
   stroke : stroke,
   &quot;stroke-width&quot; : 3
  }), txt = paper.text(cx + (r + delta + 55) * Math.cos(-popangle * rad),
    cy + (r + delta + 25) * Math.sin(-popangle * rad), labels[j])
    .attr({
     fill : bcolor,
     stroke : &quot;none&quot;,
     opacity : 0,
     &quot;font-size&quot; : 20
    });
  p.mouseover(function() {
   p.stop().animate({
    transform : &quot;s1.1 1.1 &quot; + cx + &quot; &quot; + cy
   }, ms, &quot;elastic&quot;);
   txt.stop().animate({
    opacity : 1
   }, ms, &quot;elastic&quot;);
  }).mouseout(function() {
   p.stop().animate({
    transform : &quot;&quot;
   }, ms, &quot;elastic&quot;);
   txt.stop().animate({
    opacity : 0
   }, ms);
  });
  angle += angleplus;
  chart.push(p);
  chart.push(txt);
  start += .1;
 };
 for (var i = 0, ii = values.length; i &amp;lt; ii; i++) {
  total += values[i];
 }
 for (i = 0; i &amp;lt; ii; i++) {
  process(i);
 }
 return chart;
};

$(function() {
 $.ajax({
  method: &quot;POST&quot;,
        url: &#39;get-full-report&#39;,
        dataType: &#39;json&#39;,
        crossDomain: true,
        beforeSend: function (xhr) {
            //Set authentication headers
        },
        success: function (data, textStatus, jqXHR) {
         if (data.error) {
                alert(data.message);
            } else {
             var values = [], labels = [];
             $.each(data, function(i, item) {
              values.push(parseInt(data[i].percentageOfUse, 10));
              labels.push(data[i].name);
             });
             Raphael(&quot;holder&quot;, 700, 700).pieChart(350, 350, 200, values, labels, &quot;#fff&quot;);
            }
        },
        error: function (xhr) { // if error occured
            alert(&#39;No se pudo procesar la solicitud.&#39;);
        },
        complete: function () {
        },
        xhrFields: {
            withCredentials: true
        }
 });
});
&lt;/pre&gt;
&lt;b&gt;Spring Controller&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.rolandopalermo.web.bean.Language;
import com.rolandopalermo.web.util.ReportUtil;
import com.rolandopalermo.web.util.ResponseList;

@Controller
public class HomeController {

 @RequestMapping(value = { &quot;/&quot;, &quot;/home&quot; }, method = RequestMethod.GET)
 public ModelAndView home() {
  ModelAndView model = new ModelAndView();
  model.setViewName(&quot;index&quot;);
  return model;
 }

 @RequestMapping(value = { &quot;get-full-report&quot; }, method = RequestMethod.POST)
 @CrossOrigin(origins = &quot;*&quot;, allowCredentials = &quot;true&quot;)
 @ResponseBody
 public String getReport() {
  String jsonResponse = &quot;&quot;;
  ResponseList&amp;lt;Language&amp;gt; list = ReportUtil.generateReport();
  if (list == null || list.isEmpty()) {
   jsonResponse = &quot;{&quot;error&quot; : true, &quot;message&quot;: &quot;No available data&quot;}&quot;;
  } else {
   jsonResponse = list.toString();
  }
  return jsonResponse;
 }

}
&lt;/pre&gt;
&lt;br /&gt;
And your output should look like:
&lt;br /&gt;
&lt;br /&gt;
&lt;img border=&quot;0&quot; height=&quot;488&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYt-94Fpi_JQ28efAk4BekRl7JXEd6M-K_9hImux5QPYR8EkmRHK-gcioONggJnVMVR0sIBuH5AYe69CH3eNebiaG062X7daN-FpTBD6bNhZUkkS4DzdLbNkGOB55h73z46GDFwcluObI/s640/raphaelspring-js.jpg&quot; width=&quot;640&quot; /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Download the full source code from Github and enjoy it! &lt;a href=&quot;https://github.com/rolandopalermo/spring-raphael&quot;&gt;https://github.com/rolandopalermo/spring-raphael&lt;/a&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/1739730257769271107/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2017/04/raphael-js-spring-mvc-java.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/1739730257769271107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/1739730257769271107'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2017/04/raphael-js-spring-mvc-java.html' title='Raphael JS Pie Chart and Spring MVC'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2WFJXZH11QHr7oC7MDOmRceMh5E55FC_hS7wjqCWJ6c9RgcQT55Dixz8Nb6I_CSKbDUntvs0OrRP5zoUoRfZoKUcNI3SRs3Z3e_U5-Sbn5e9yF0sPcekzjwn5qAs-m7MkUoJY2SSAsLw/s72-c/raphaeljs-banner.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-4590935853826613766</id><published>2017-04-24T21:47:00.002-05:00</published><updated>2019-05-15T15:01:46.850-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="jquery"/><category scheme="http://www.blogger.com/atom/ns#" term="json"/><category scheme="http://www.blogger.com/atom/ns#" term="mvc"/><category scheme="http://www.blogger.com/atom/ns#" term="spring"/><title type='text'>How to use Jquery datatable in Spring MVC</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
Creating a table data along with features like pagination, filtering the records, sorting, no of records to show etc. is a challenger job for developers because it involves lot of designs and coding. But now it becomes very easy to develop with the help of jQuery datatable plugin. In this post we will show how to use jQuery datatable in Spring MVC 4 application.
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAGVhYOjJWiQMaw7bD79uh-oZMObh1oHnVQt0DFPZFxZfcBzNyowlbP8GmOlFa7WrTTMcNibLGFR13Q0bw1BuH9d_YfPOv7F9SFZ4-bNvSzhpt7-eKP18VYyF8YVUB0zHfA-1GH2wlkmU/s1600/datatables_edit_cell.png&quot; style=&quot;display: none;&quot; /&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Required Software to Run Example:&lt;/b&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Java 7&lt;/li&gt;
&lt;li&gt;Netbeans&lt;/li&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;Project Structure in Netbeans&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE2QJ5WJqTZ5yOWWWRCfind2lDGFxK2AECZDplAUchpLFfci_jeh_X3hi5D2dY9RPw4bmil7lwE3l5Ns9fHSiT7qsvJ_AztHWr8iATMmaFCEbV1Os21L2plbiXEow90XkabZlJtiQjaQE/s1600/tree.jpg&quot; /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;POM.xml&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&amp;gt;
    &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;

    &amp;lt;groupId&amp;gt;com.rolandopalermo.web&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-datatable&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
    &amp;lt;packaging&amp;gt;war&amp;lt;/packaging&amp;gt;

    &amp;lt;name&amp;gt;spring-datatable&amp;lt;/name&amp;gt;

    &amp;lt;properties&amp;gt;
        &amp;lt;endorsed.dir&amp;gt;${project.build.directory}/endorsed&amp;lt;/endorsed.dir&amp;gt;
        &amp;lt;project.build.sourceEncoding&amp;gt;UTF-8&amp;lt;/project.build.sourceEncoding&amp;gt;
    &amp;lt;/properties&amp;gt;
    
    &amp;lt;dependencies&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;javax&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;javaee-web-api&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;7.0&amp;lt;/version&amp;gt;
            &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
        
        &amp;lt;!-- Spring --&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-core&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;4.3.5.RELEASE&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-webmvc&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;4.3.5.RELEASE&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        
        &amp;lt;!-- Jackson --&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.fasterxml.jackson.core&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;jackson-core&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;2.7.3&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.fasterxml.jackson.core&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;jackson-databind&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;2.7.3&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;

    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;3.1&amp;lt;/version&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;source&amp;gt;1.7&amp;lt;/source&amp;gt;
                    &amp;lt;target&amp;gt;1.7&amp;lt;/target&amp;gt;
                    &amp;lt;compilerArguments&amp;gt;
                        &amp;lt;endorseddirs&amp;gt;${endorsed.dir}&amp;lt;/endorseddirs&amp;gt;
                    &amp;lt;/compilerArguments&amp;gt;
                &amp;lt;/configuration&amp;gt;
            &amp;lt;/plugin&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;2.3&amp;lt;/version&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;failOnMissingWebXml&amp;gt;false&amp;lt;/failOnMissingWebXml&amp;gt;
                &amp;lt;/configuration&amp;gt;
            &amp;lt;/plugin&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-dependency-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;2.6&amp;lt;/version&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;phase&amp;gt;validate&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;copy&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;outputDirectory&amp;gt;${endorsed.dir}&amp;lt;/outputDirectory&amp;gt;
                            &amp;lt;silent&amp;gt;true&amp;lt;/silent&amp;gt;
                            &amp;lt;artifactItems&amp;gt;
                                &amp;lt;artifactItem&amp;gt;
                                    &amp;lt;groupId&amp;gt;javax&amp;lt;/groupId&amp;gt;
                                    &amp;lt;artifactId&amp;gt;javaee-endorsed-api&amp;lt;/artifactId&amp;gt;
                                    &amp;lt;version&amp;gt;7.0&amp;lt;/version&amp;gt;
                                    &amp;lt;type&amp;gt;jar&amp;lt;/type&amp;gt;
                                &amp;lt;/artifactItem&amp;gt;
                            &amp;lt;/artifactItems&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;
&lt;b&gt;POJO Class used in Example&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.domain;

import com.rolandopalermo.util.EmployeeStatus;
import com.rolandopalermo.util.JsonConverter;
import java.io.Serializable;

/**
 *
 * @author rolan
 */
public class Employee implements Serializable {

    private int id;
    private String name;
    private String surname;
    private int age;
    private String address;
    private EmployeeStatus status;

    public Employee(int id, String name, String surname, int age, String address, EmployeeStatus status) {
        this.id = id;
        this.name = name;
        this.surname = surname;
        this.age = age;
        this.address = address;
        this.status = status;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
    
    public EmployeeStatus getStatus() {
        return status;
    }

    public void setStatus(EmployeeStatus status) {
        this.status = status;
    }

    @Override
    public String toString() {
        String json = JsonConverter.INSTANCE.asJsonString(this);
        return json;
    }

}
&lt;/pre&gt;
&lt;b&gt;Spring MVC Controller&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.controller;

import com.rolandopalermo.domain.Employee;
import com.rolandopalermo.test.DummyDAO;
import com.rolandopalermo.util.ResponseList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

/**
 *
 * @author rolan
 */
@Controller
public class HomeController {

    @RequestMapping(value = {&quot;/&quot;, &quot;/home&quot;}, method = RequestMethod.GET)
    public ModelAndView home() {
        ModelAndView model = new ModelAndView();
        model.setViewName(&quot;home&quot;);
        return model;
    }

    @RequestMapping(value = {&quot;/get-all-employees&quot;}, method = RequestMethod.POST)
    @CrossOrigin(origins = &quot;*&quot;, allowCredentials = &quot;true&quot;)
    @ResponseBody
    public String getAllEmployees(HttpServletRequest request, HttpServletResponse response) {
        String json;
        try {
            ResponseList&amp;lt;Employee&amp;gt; lstInvoices = DummyDAO.getAllEmployees();
            json = lstInvoices.toString();
        } catch (Exception e) {
            json = &quot;{&quot;error&quot; : true, &quot;message&quot;: &quot;&quot; + e.getMessage() + &quot;.&quot;}&quot;;
        }
        return json;
    }
}
&lt;/pre&gt;
&lt;b&gt;Javascript&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:javascript&quot;&gt;$(document).ready(function () {
    $.ajax({
        method: &quot;POST&quot;,
        url: &#39;get-all-employees&#39;,
        dataType: &#39;json&#39;,
        crossDomain: true,
        beforeSend: function (xhr) {
            //Set authentication headers
        },
        success: function (data, textStatus, jqXHR) {
            if (data.error) {
                alert(data.message);
            } else {
                var selector = $(&quot;#applications&quot;);
                selector.html(&quot;&quot;);
                selector.append(JSON.stringify(data));
                data = $.parseJSON(selector.text());
                console.log(data);
                table = $(&quot;#employees&quot;).DataTable({
                    data: data,
                    scrollX: true,
                    scrollCollapse: true,
                    fixedColumns: true,
                    columns: [{
                            data: &quot;id&quot;,
                            visible: false
                        }, {
                            data: &quot;name&quot;
                        }, {
                            data: &quot;surname&quot;
                        }, {
                            data: &quot;age&quot;
                        }, {
                            data: &quot;address&quot;
                        }, {
                            data: &quot;status&quot;,
                            render: function (value) {
                                switch (value) {
                                    case &quot;ACTIVE&quot;:
                                        return &#39;&amp;lt;span class=active&amp;gt;&amp;lt;/span&amp;gt;&#39;;
                                    case &quot;PENDING&quot;:
                                        return &#39;&amp;lt;span class=pending&amp;gt;&amp;lt;/span&amp;gt;&#39;;
                                    case &quot;INACTIVE&quot;:
                                        return &#39;&amp;lt;span class=inactive&amp;gt;&amp;lt;/span&amp;gt;&#39;;
                                    case &quot;DELETED&quot;:
                                        return &#39;&amp;lt;span class=deleted&amp;gt;&amp;lt;/span&amp;gt;&#39;;
                                    default:
                                        return &#39;&amp;lt;span class=active&amp;gt;&amp;lt;/span&amp;gt;&#39;;
                                }
                            }
                        }
                    ]
                });
            }
        },
        error: function (xhr) { // if error occured
            alert(&#39;No se pudo procesar la solicitud.&#39;);
        },
        complete: function () {
        },
        xhrFields: {
            withCredentials: true
        }
    });
});
&lt;/pre&gt;
&lt;b&gt;WebAppInitializer&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:html&quot;&gt;&amp;lt;%-- 
    Document   : view
    Created on : Jan 20, 2017, 7:15:31 PM
    Author     : Rolando
--%&amp;gt;

&amp;lt;%@ page language=&quot;java&quot; pageEncoding=&quot;UTF-8&quot; contentType=&quot;text/html;charset=UTF-8&quot; %&amp;gt;
&amp;lt;%@taglib prefix=&quot;spring&quot; uri=&quot;http://www.springframework.org/tags&quot;%&amp;gt;
&amp;lt;%@taglib prefix=&quot;c&quot; uri=&quot;http://java.sun.com/jsp/jstl/core&quot;%&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;&amp;lt;c:url value=&#39;/static/app/third-party/js/jquery-1.12.4.js&#39; /&amp;gt;&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;&amp;lt;c:url value=&#39;/static/app/third-party/datatables/js/jquery.dataTables.min.js&#39; /&amp;gt;&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;&amp;lt;c:url value=&#39;/static/app/third-party/datatables/js/dataTables.buttons.min.js&#39; /&amp;gt;&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;&amp;lt;c:url value=&#39;/static/app/js/home.js&#39; /&amp;gt;&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;link href=&quot;&amp;lt;c:url value=&#39;/static/app/third-party/datatables/css/jquery.dataTables.min.css&#39;/&amp;gt;&quot; rel=&quot;stylesheet&quot;/&amp;gt;
&amp;lt;link href=&quot;&amp;lt;c:url value=&#39;/static/app/third-party/datatables/css/buttons.dataTables.min.css&#39;/&amp;gt;&quot; rel=&quot;stylesheet&quot;/&amp;gt;
&amp;lt;link href=&quot;&amp;lt;c:url value=&#39;/static/app/css/master.css&#39;/&amp;gt;&quot; rel=&quot;stylesheet&quot;/&amp;gt;

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;/&amp;gt;
        &amp;lt;title&amp;gt;How to use Jquery datatable in Spring MVC&amp;lt;/title&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;div id=&quot;applications&quot; style=&quot;display: none&quot;&amp;gt;&amp;lt;/div&amp;gt;
        &amp;lt;table id=&quot;employees&quot; cellspacing=&quot;0&quot; width=&quot;100%&quot;&amp;gt;
            &amp;lt;thead&amp;gt;
                &amp;lt;tr&amp;gt;
                    &amp;lt;th&amp;gt;ID&amp;lt;/th&amp;gt;
                    &amp;lt;th&amp;gt;Name&amp;lt;/th&amp;gt;
                    &amp;lt;th&amp;gt;Surname&amp;lt;/th&amp;gt;
                    &amp;lt;th&amp;gt;Age&amp;lt;/th&amp;gt;
                    &amp;lt;th&amp;gt;Address&amp;lt;/th&amp;gt;
                    &amp;lt;th&amp;gt;Status&amp;lt;/th&amp;gt;
                &amp;lt;/tr&amp;gt;
            &amp;lt;/thead&amp;gt;
            &amp;lt;tbody&amp;gt;
            &amp;lt;/tbody&amp;gt;
        &amp;lt;/table&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;
And your output should looks like:
&lt;br /&gt;
&lt;br /&gt;
&lt;img border=&quot;0&quot; height=&quot;305&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKsPtyaYLXaB5fC06OyXKd1xYlpNwBFh2GkXibW6WWZeCDEA0mDe5_KOUaSAHdJC1LCvLAok34Ukn8h7H3Pq9t8hGKkm5ddUw8RIzcOLuSLh6sAnURRmsP_OgdGFNHLrukeYIBCgy6bik/s640/output.jpg&quot; width=&quot;640&quot; /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Download the full source code from Github and enjoy it! &lt;a href=&quot;https://github.com/rolandopalermo/spring-datatable&quot;&gt;https://github.com/rolandopalermo/spring-datatable&lt;/a&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/4590935853826613766/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2017/04/spring-mvc-jquery-datatables-json.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/4590935853826613766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/4590935853826613766'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2017/04/spring-mvc-jquery-datatables-json.html' title='How to use Jquery datatable in Spring MVC'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAGVhYOjJWiQMaw7bD79uh-oZMObh1oHnVQt0DFPZFxZfcBzNyowlbP8GmOlFa7WrTTMcNibLGFR13Q0bw1BuH9d_YfPOv7F9SFZ4-bNvSzhpt7-eKP18VYyF8YVUB0zHfA-1GH2wlkmU/s72-c/datatables_edit_cell.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-1405924321642374659</id><published>2017-04-23T18:06:00.000-05:00</published><updated>2019-05-15T15:04:09.302-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jquery"/><category scheme="http://www.blogger.com/atom/ns#" term="maven"/><category scheme="http://www.blogger.com/atom/ns#" term="mybatis"/><category scheme="http://www.blogger.com/atom/ns#" term="spring"/><title type='text'>Spring 4 and MyBatis Java Full Annotations</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
In this post, we will provide MyBatis 3 annotations example with a simple application example. These annotations are declared in interface on methods for select, insert, update and delete operation. Now this interface will act as Mapper for SQL queries. We need to register mapper interface in MyBatis configuration XML. To map POJO and table columns, MyBatis provides Results annotation which works same as Resultmap tag in XML mapper. @Results helps to get query result by @Select annotation.
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4T1HEr2OolebMEfhNxZr1CS2KJe2oSTFuhPaRt64WIkh3pz0Idf6QkcRXUqWAWb1KrIwA33dlXM26Sv5F6QBGu6v9IuVhsADk0J7rOllj5qU-kOhi7D4aIebnvQ-laiqWteBgaOXbYYg/s1600/spring.png&quot; style=&quot;display: none;&quot; /&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Required Software to Run Example:&lt;/b&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Java 7&lt;/li&gt;
&lt;li&gt;Netbeans&lt;/li&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;Project Structure in Netbeans&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3WMZQxsFR82pqeHaZiQfAx3Xb3puBqvEXMuKG31qmA2nRTECJ2JiyA0nCiOV2degDkFbZ4qMv2zXjrQUtLl3GhVOv_LjtwEpUKktHw49tqg3z30zegAyTk3NIj7hRRAyRidqK92ShBkE/s1600/tree.jpg&quot; /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Table Schema&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:sql&quot;&gt;CREATE TABLE `mybatis-spring`.`product` (
  `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL,
  `price` DOUBLE NOT NULL,
  `description` TEXT NOT NULL,
  PRIMARY KEY (`id`)
)
ENGINE = InnoDB;
&lt;/pre&gt;
&lt;b&gt;POM.xml&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&amp;gt;
    &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;

    &amp;lt;groupId&amp;gt;com.rolandopalermo.web&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-mybatis&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
    &amp;lt;packaging&amp;gt;war&amp;lt;/packaging&amp;gt;

    &amp;lt;name&amp;gt;spring-mybatis&amp;lt;/name&amp;gt;

    &amp;lt;properties&amp;gt;
        &amp;lt;endorsed.dir&amp;gt;${project.build.directory}/endorsed&amp;lt;/endorsed.dir&amp;gt;
        &amp;lt;project.build.sourceEncoding&amp;gt;UTF-8&amp;lt;/project.build.sourceEncoding&amp;gt;
        &amp;lt;mysql.connector.version&amp;gt;5.1.31&amp;lt;/mysql.connector.version&amp;gt;
    &amp;lt;/properties&amp;gt;
    
    &amp;lt;dependencies&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;javax&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;javaee-web-api&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;7.0&amp;lt;/version&amp;gt;
            &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
        
        &amp;lt;!-- Spring --&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-core&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;4.3.5.RELEASE&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-webmvc&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;4.3.5.RELEASE&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-jdbc&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;4.2.1.RELEASE&amp;lt;/version&amp;gt;
            &amp;lt;type&amp;gt;jar&amp;lt;/type&amp;gt;
            &amp;lt;scope&amp;gt;compile&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
        
        &amp;lt;!-- Mybatis --&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.mybatis&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;mybatis&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;3.3.0&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.mybatis&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;mybatis-spring&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.2.2&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        
        &amp;lt;!-- MySQL --&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;mysql&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;mysql-connector-java&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;${mysql.connector.version}&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;

    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;3.1&amp;lt;/version&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;source&amp;gt;1.7&amp;lt;/source&amp;gt;
                    &amp;lt;target&amp;gt;1.7&amp;lt;/target&amp;gt;
                    &amp;lt;compilerArguments&amp;gt;
                        &amp;lt;endorseddirs&amp;gt;${endorsed.dir}&amp;lt;/endorseddirs&amp;gt;
                    &amp;lt;/compilerArguments&amp;gt;
                &amp;lt;/configuration&amp;gt;
            &amp;lt;/plugin&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;2.3&amp;lt;/version&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;failOnMissingWebXml&amp;gt;false&amp;lt;/failOnMissingWebXml&amp;gt;
                &amp;lt;/configuration&amp;gt;
            &amp;lt;/plugin&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-dependency-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;2.6&amp;lt;/version&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;phase&amp;gt;validate&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;copy&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;outputDirectory&amp;gt;${endorsed.dir}&amp;lt;/outputDirectory&amp;gt;
                            &amp;lt;silent&amp;gt;true&amp;lt;/silent&amp;gt;
                            &amp;lt;artifactItems&amp;gt;
                                &amp;lt;artifactItem&amp;gt;
                                    &amp;lt;groupId&amp;gt;javax&amp;lt;/groupId&amp;gt;
                                    &amp;lt;artifactId&amp;gt;javaee-endorsed-api&amp;lt;/artifactId&amp;gt;
                                    &amp;lt;version&amp;gt;7.0&amp;lt;/version&amp;gt;
                                    &amp;lt;type&amp;gt;jar&amp;lt;/type&amp;gt;
                                &amp;lt;/artifactItem&amp;gt;
                            &amp;lt;/artifactItems&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;
&lt;b&gt;POJO Class used in Example&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.web.domain;

/**
 *
 * @author rolan
 */
public class Product {

    private long id;
    private String name;
    private double price;
    private String description;

    public long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

}
&lt;/pre&gt;
&lt;b&gt;Mapper Interface Using MyBatis Annotation&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.web.mapper;

import com.rolandopalermo.web.domain.Product;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

/**
 *
 * @author rolan
 */
public interface ProductMapper {

    @Results({
        @Result(property = &quot;id&quot;, column = &quot;id&quot;),
        @Result(property = &quot;name&quot;, column = &quot;name&quot;),
        @Result(property = &quot;price&quot;, column = &quot;price&quot;),
        @Result(property = &quot;description&quot;, column = &quot;description&quot;)
    })
    @Select(&quot;SELECT id, name, price, description from product WHERE id = #{id}&quot;)
    Product selectProduct(int id);

    @Insert(&quot;INSERT into product(name, price, description) VALUES(#{name}, #{price}, #{description})&quot;)
    void insertProduct(Product product);

    @Update(&quot;UPDATE product SET name=#{name}, price =#{price}, description =#{description} WHERE id =#{id}&quot;)
    void updateProduct(Product product);

    @Delete(&quot;DELETE FROM product WHERE id =#{id}&quot;)
    void deleteProduct(int id);
    
    @Results({
        @Result(property = &quot;id&quot;, column = &quot;id&quot;),
        @Result(property = &quot;name&quot;, column = &quot;name&quot;),
        @Result(property = &quot;price&quot;, column = &quot;price&quot;),
        @Result(property = &quot;description&quot;, column = &quot;description&quot;)
    })
    @Select(&quot;SELECT id, name, price, description from product&quot;)
    List&amp;lt;Product&amp;gt; selectAllProduct();

}
&lt;/pre&gt;
&lt;b&gt;DataConfig&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
//import org.apache.commons.dbcp.BasicDataSource;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

/**
 *
 * @author Rolando
 */
@Configuration
@PropertySource(&quot;classpath:data.properties&quot;)
@MapperScan(basePackages = {&quot;com.rolandopalermo.web.mapper&quot;}, sqlSessionFactoryRef = &quot;sqlSessionFactory&quot;)
public class DataConfig {

    @Value(&quot;${mysql.driver}&quot;)
    private String driver;

    @Value(&quot;${mysql.url}&quot;)
    private String url;

    @Value(&quot;${mysql.user}&quot;)
    private String username;

    @Value(&quot;${mysql.password}&quot;)
    private String password;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
        return sqlSessionFactoryBean.getObject();
    }

}
&lt;/pre&gt;
&lt;b&gt;MvcConfig&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.web.config;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

/**
 *
 * @author Rolando
 */
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {&quot;com.rolandopalermo.web&quot;})
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(&quot;/resources/**&quot;).addResourceLocations(&quot;/resources/&quot;);
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public InternalResourceViewResolver jspViewResolver() {
        InternalResourceViewResolver bean = new InternalResourceViewResolver();
        bean.setPrefix(&quot;/WEB-INF/jsp/&quot;);
        bean.setSuffix(&quot;.jsp&quot;);
        return bean;
    }

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename(&quot;classpath:messages&quot;);
        messageSource.setDefaultEncoding(&quot;UTF-8&quot;);
        return messageSource;
    }

}
&lt;/pre&gt;
&lt;b&gt;WebAppInitializer&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;package com.rolandopalermo.web.config;

import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

/**
 *
 * @author Rolando
 */
public class WebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
        // Create the &#39;root&#39; Spring application context
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
//        rootContext.register(ServiceConfig.class, JPAConfig.class, SecurityConfig.class);
        rootContext.register(MvcConfig.class, DataConfig.class);
        // Manage the lifecycle of the root application context
        container.addListener(new ContextLoaderListener(rootContext));
        // Create the dispatcher servlet&#39;s Spring application context
        AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
        dispatcherServlet.register(MvcConfig.class);
        // Register and map the dispatcher servlet
        ServletRegistration.Dynamic dispatcher = container.addServlet(&quot;dispatcher&quot;, new DispatcherServlet(dispatcherServlet));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping(&quot;/&quot;);
    }

}
&lt;/pre&gt;
&lt;b&gt;Home.jsp&lt;/b&gt;&lt;br /&gt;
Now we will test our application.
&lt;br /&gt;
&lt;pre class=&quot;brush:html&quot;&gt;&amp;lt;%@page contentType=&quot;text/html&quot; pageEncoding=&quot;UTF-8&quot;%&amp;gt;
&amp;lt;%@ taglib uri=&quot;http://java.sun.com/jsp/jstl/core&quot; prefix=&quot;c&quot; %&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&amp;gt;
        &amp;lt;title&amp;gt;JSP Page&amp;lt;/title&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;h1&amp;gt;Products&amp;lt;/h1&amp;gt;
        &amp;lt;c:forEach var=&quot;item&quot; items=&quot;${products}&quot;&amp;gt;
            &amp;lt;c:out value=&quot;${item.name} ${item.price}&quot;/&amp;gt;
            &amp;lt;br&amp;gt;
        &amp;lt;/c:forEach&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;
And your output should looks like:
&lt;br /&gt;
&lt;br /&gt;
&lt;img border=&quot;0&quot; height=&quot;388&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWuWzmoY2K3JyVm-DmGxnPbTECB2h-PHaGYg8i2bGabJuKdSyhseQj8Lz5_FRzPvzJFJ7YBk1zFuyypdWYearzsYVMaeAntV7hcDUw01SerbcdxvCR6q0-NJXAUmGItrbq_7puk8aTF9k/s640/result-jsp.jpg&quot; width=&quot;640&quot; /&gt;&lt;br /&gt;
&lt;span style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;span style=&quot;text-align: center;&quot;&gt;Download the full source code from Github and enjoy it!
&lt;/span&gt;&lt;a href=&quot;https://github.com/rolandopalermo/spring-mybatis&quot; style=&quot;text-align: center;&quot;&gt;https://github.com/rolandopalermo/spring-mybatis&lt;/a&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/1405924321642374659/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2017/04/spring-4-mybatis-annotations-select.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/1405924321642374659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/1405924321642374659'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2017/04/spring-4-mybatis-annotations-select.html' title='Spring 4 and MyBatis Java Full Annotations'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4T1HEr2OolebMEfhNxZr1CS2KJe2oSTFuhPaRt64WIkh3pz0Idf6QkcRXUqWAWb1KrIwA33dlXM26Sv5F6QBGu6v9IuVhsADk0J7rOllj5qU-kOhi7D4aIebnvQ-laiqWteBgaOXbYYg/s72-c/spring.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-3490454527525077267</id><published>2016-10-26T13:45:00.004-05:00</published><updated>2016-10-26T15:05:08.208-05:00</updated><title type='text'>Integración Java+Azure utilizando REST</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
Cuando escuchamos de Azure, inmediatamente se nos viene a la mente el SDK de esta &lt;strike&gt;interesante &lt;/strike&gt;plataforma de Microsoft, sin embargo algunos desarrolladores preferimos invocar a los servicios de Azure directamente desde &amp;nbsp;su API REST, sin utilizar bibliotecas específicas. En este artículo encontrarás un ejemplo completo de cómo comunicarnos con Azure Blob Storage.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-fTh_F0tM_ZXtD7nsOkMan1FG_b_0mlwIwLhJOAUvR9k57Sz70buIbZYhnFf4iyk8hdw8bk-KtbjHLAz7rKQuyXoPYE1hq-Z9sx_5ve1_XrugMBtOqAoXhThiWeIFhgOZuU1O24fzZyg/s1600/azure_java.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-fTh_F0tM_ZXtD7nsOkMan1FG_b_0mlwIwLhJOAUvR9k57Sz70buIbZYhnFf4iyk8hdw8bk-KtbjHLAz7rKQuyXoPYE1hq-Z9sx_5ve1_XrugMBtOqAoXhThiWeIFhgOZuU1O24fzZyg/s1600/azure_java.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
A continuación, se muestra la clase java que se encarga de realizar la comunicación:&lt;/div&gt;
&lt;pre class=&quot;brush:java&quot;&gt;/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

/**
 *
 * @author Rolando
 */
public class Util {

    private static Base64 base64 = new Base64();

    public static void signRequestSK(HttpURLConnection request, String account, String key) throws Exception {
        SimpleDateFormat fmt = new SimpleDateFormat(&quot;EEE, dd MMM yyyy HH:mm:ss&quot;);
        fmt.setTimeZone(TimeZone.getTimeZone(&quot;GMT&quot;));
        String date = fmt.format(Calendar.getInstance().getTime()) + &quot; GMT&quot;;

        StringBuilder sb = new StringBuilder();
        sb.append(&quot;GET\n&quot;); // method
        sb.append(&quot;\n&quot;); // content encoding
        sb.append(&quot;\n&quot;); // content language
        sb.append(&quot;\n&quot;); // content length
        sb.append(&quot;\n&quot;); // md5 (optional)
        sb.append(&quot;\n&quot;); // content type
        sb.append(&quot;\n&quot;); // legacy date
        sb.append(&quot;\n&quot;); // if-modified-since
        sb.append(&quot;\n&quot;); // if-match
        sb.append(&quot;\n&quot;); // if-none-match
        sb.append(&quot;\n&quot;); // if-unmodified-since
        sb.append(&quot;\n&quot;); // range
        sb.append(&quot;x-ms-date:&quot; + date + &quot;\n&quot;); // headers
        sb.append(&quot;x-ms-version:2015-12-11\n&quot;);
        sb.append(&quot;/&quot; + account + request.getURL().getPath() + &quot;\ncomp:list&quot;);
        Mac mac = Mac.getInstance(&quot;HmacSHA256&quot;);
        mac.init(new SecretKeySpec(base64.decode(key), &quot;HmacSHA256&quot;));
        String authKey = new String(base64.encode(mac.doFinal(sb.toString().getBytes(&quot;UTF-8&quot;))));
        String auth = &quot;SharedKey &quot; + account + &quot;:&quot; + authKey;
        request.setRequestProperty(&quot;x-ms-date&quot;, date);
        request.setRequestProperty(&quot;x-ms-version&quot;, &quot;2015-12-11&quot;);
        request.setRequestProperty(&quot;Authorization&quot;, auth);
        request.setRequestProperty(&quot;Accept-Charset&quot;, &quot;UTF-8&quot;);
        request.setRequestProperty(&quot;Accept&quot;, &quot;application/atom+xml,application/xml&quot;);
        request.setRequestMethod(&quot;GET&quot;);
    }

    public static void main(String args[]) throws Exception {
        //To use fiddler
        System.setProperty(&quot;http.proxyHost&quot;, &quot;127.0.0.1&quot;);
        System.setProperty(&quot;https.proxyHost&quot;, &quot;127.0.0.1&quot;);
        System.setProperty(&quot;http.proxyPort&quot;, &quot;8888&quot;);
        System.setProperty(&quot;https.proxyPort&quot;, &quot;8888&quot;);
        //--
        //Inputs
        String account = &quot;&amp;lt;Nombre_Cuenta&amp;gt;&quot;;
        String key = &quot;&amp;lt;Access_Key&amp;gt;&quot;;
        //--
        HttpURLConnection connection = (HttpURLConnection) (new URL(&quot;http://&quot; + account + &quot;.blob.core.windows.net/?comp=list&quot;)).openConnection();
        signRequestSK(connection, account, key);
        connection.connect();
        StringBuffer text = new StringBuffer();
        InputStreamReader in = new InputStreamReader((InputStream) connection.getContent());
        BufferedReader buff = new BufferedReader(in);
        String line;
        do {
            line = buff.readLine();
            text.append(line + &quot;\n&quot;);
        } while (line != null);
        System.out.println(text);
    }
}
&lt;/pre&gt;
Entonces, si utilizamos Fiddler, podremos ver que este sería el Request:
&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;GET http://&quot;&amp;lt;Nombre_Cuenta&amp;gt;&quot;.blob.core.windows.net/?comp=list HTTP/1.1
x-ms-date: Wed, 26 Oct 2016 18:35:49 GMT
x-ms-version: 2015-12-11
Authorization: SharedKey &quot;&amp;lt;Nombre_Cuenta&amp;gt;&quot;:psyT2FlwpU3BU7/kKqtfi+ZBTuUpEX8bnsZ45O/1rUk=
Accept-Charset: UTF-8
Accept: application/atom+xml,application/xml
User-Agent: Java/1.8.0_92
Host: &quot;&amp;lt;Nombre_Cuenta&amp;gt;&quot;.blob.core.windows.net
Connection: keep-alive
&lt;/pre&gt;
Y el response quedaría de la siguiente manera:
&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&amp;gt;
&amp;lt;EnumerationResults ServiceEndpoint=&quot;http://&quot;&amp;lt;Nombre_Cuenta&amp;gt;&quot;.blob.core.windows.net/&quot;&amp;gt;
    &amp;lt;Containers&amp;gt;
        &amp;lt;Container&amp;gt;
            &amp;lt;Name&amp;gt;sas&amp;lt;/Name&amp;gt;
            &amp;lt;Properties&amp;gt;
                &amp;lt;Last-Modified&amp;gt;Tue, 25 Oct 2016 19:19:46 GMT&amp;lt;/Last-Modified&amp;gt;
                &amp;lt;Etag&amp;gt;&quot;0x8D3FD0BE1F7E8D0&quot;&amp;lt;/Etag&amp;gt;
                &amp;lt;LeaseStatus&amp;gt;unlocked&amp;lt;/LeaseStatus&amp;gt;
                &amp;lt;LeaseState&amp;gt;available&amp;lt;/LeaseState&amp;gt;
            &amp;lt;/Properties&amp;gt;
        &amp;lt;/Container&amp;gt;
    &amp;lt;/Containers&amp;gt;
    &amp;lt;NextMarker /&amp;gt;
&amp;lt;/EnumerationResults&amp;gt;
&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/3490454527525077267/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2016/10/azure-api-rest-client-java.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/3490454527525077267'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/3490454527525077267'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2016/10/azure-api-rest-client-java.html' title='Integración Java+Azure utilizando REST'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-fTh_F0tM_ZXtD7nsOkMan1FG_b_0mlwIwLhJOAUvR9k57Sz70buIbZYhnFf4iyk8hdw8bk-KtbjHLAz7rKQuyXoPYE1hq-Z9sx_5ve1_XrugMBtOqAoXhThiWeIFhgOZuU1O24fzZyg/s72-c/azure_java.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-82774501195019096</id><published>2016-10-21T10:38:00.000-05:00</published><updated>2016-10-26T13:42:46.391-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="rest"/><category scheme="http://www.blogger.com/atom/ns#" term="webservices"/><title type='text'>Servicios Web REST y PHP</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
En este artículo les mostraré cómo implementar una aplicación CRUD con PHP y servicios Web RESTFul. Los requisitos son los siguientes:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;PHP 4.0 o superior&lt;/li&gt;
&lt;li&gt;MySQL 4.0 o superior&lt;/li&gt;
&lt;li&gt;Integración PHP+MySQL realizada correctamente.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Y la estructura de archivos es como se muestra a continuación:&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;rest_api&lt;br /&gt;|-- dao.php&lt;br /&gt;|-- index.php&lt;br /&gt;|-- model.php&lt;br /&gt;|-- service.php&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Como primer paso, crear una base de datos y crear la tabla &lt;b&gt;test&lt;/b&gt; con la estructura que se muestra a continuación.&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4psukyN8xG_W7Mwe_tf3q1Vm-KHZGfbWMvHxUcZlN9kJDi9t-OYXnCvY0EXf45mqFhPkYE8Sr3bFVWYxkAdS8IaN8CIymfi1TIAF9eolLPGadytLulYQ7_AVFW65yl3ApNWo75ux3q38/s1600/Screenshot_20161021_103909.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4psukyN8xG_W7Mwe_tf3q1Vm-KHZGfbWMvHxUcZlN9kJDi9t-OYXnCvY0EXf45mqFhPkYE8Sr3bFVWYxkAdS8IaN8CIymfi1TIAF9eolLPGadytLulYQ7_AVFW65yl3ApNWo75ux3q38/s1600/Screenshot_20161021_103909.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Crear el archivo &lt;b&gt;model.php&lt;/b&gt;, en donde se especificará una &quot;clase entidad&quot; que corresponderá con la tabla test de nuestra base de datos [Lo sé, no es java =(]. El hecho de no utilizar el concepto de encapsulación es debido a la versión de PHP que se utilizó para este post (4.0).
&lt;br /&gt;
&lt;pre class=&quot;brush:php&quot;&gt;&amp;lt;?php

class Test {

    var $id;
    var $nombres;
    var $apellidos;

}
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
También tendremos una clase PHP exclusivamente para el acceso a base de datos. En el archivo &lt;b&gt;dao.php&lt;/b&gt;, se implementarán todas las operaciones sobre base de datos.&lt;/div&gt;
&lt;pre class=&quot;brush:php&quot;&gt;&amp;lt;?php

class DAO {

    var $server;
    var $db;
    var $dblog;
    var $dbpass;

    function DAO() {
        $this-&amp;gt;server = &#39;localhost&#39;;
        $this-&amp;gt;db = &#39;test&#39;;
        $this-&amp;gt;dblog = &#39;root&#39;;
        $this-&amp;gt;dbpass = &#39;123456&#39;;
    }

    function connect() {
        $this-&amp;gt;cnn = new MySQL(array(&#39;host&#39; =&amp;gt; $this-&amp;gt;server, &#39;user&#39; =&amp;gt; $this-&amp;gt;dblog, &#39;password&#39; =&amp;gt; $this-&amp;gt;dbpass, &#39;database&#39; =&amp;gt; $this-&amp;gt;db));
    }

    function insert($test) {
        $this-&amp;gt;connect();
        $sql = &quot;INSERT INTO test(nombres, apellidos) VALUES (&#39;&quot; . $test-&amp;gt;nombres . &quot;&#39;,&#39;&quot; . $test-&amp;gt;apellidos . &quot;&#39;&quot; . &quot;)&quot;;
        $rs = $this-&amp;gt;cnn-&amp;gt;query($sql);
    }

    function findAll() {
        $this-&amp;gt;connect();
        $sql = &quot;SELECT * FROM test&quot;;
        $result = $this-&amp;gt;cnn-&amp;gt;query($sql);
        $rs = $result-&amp;gt;fetchall(MYSQL_ASSOC);
        return $rs;
    }

    function find($id) {
        $this-&amp;gt;connect();
        $sql = &quot;SELECT * FROM test WHERE id=&quot; . $id;
        $result = $this-&amp;gt;cnn-&amp;gt;query($sql);
        $rs = $result-&amp;gt;fetchRow(MYSQL_ASSOC);
        return $rs;
    }

    function update($test) {
        $this-&amp;gt;connect();
        $sql = &quot;UPDATE test SET nombres =&#39;&quot; . $test-&amp;gt;nombres . &quot;&#39;, apellidos=&#39;&quot; . $test-&amp;gt;apellidos . &quot;&#39; WHERE id=&#39;&quot; . $test-&amp;gt;id . &quot;&#39;&quot;;
        $this-&amp;gt;cnn-&amp;gt;query($sql);
    }

    function delete($id) {
        $this-&amp;gt;connect();
        $sql = &quot;DELETE FROM test WHERE id=&#39;&quot; . $id . &quot;&#39;&quot;;
        $this-&amp;gt;cnn-&amp;gt;query($sql);
    }

}
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Las funciones de la clase DAO serán invocadas a través de una capa de servicio, la cual se encargará de procesar las peticiones y determinar qué tipo de servicio REST es el consultado. El archivo tendrá el nombre &lt;b&gt;service.php&lt;/b&gt;.&lt;/div&gt;
&lt;pre class=&quot;brush:php&quot;&gt;&amp;lt;?php

require_once(&quot;dao.php&quot;);
require_once(&quot;model.php&quot;);

$method = $_SERVER[&#39;REQUEST_METHOD&#39;];

$dao = new DAO();
$json_service = new Services_JSON();

//call DAO based on HTTP method
switch ($method) {
    case &#39;GET&#39;:
        $result = $dao-&amp;gt;findAll();
        $json_response = $json_service-&amp;gt;encode($result);
        echo $json_response;
        break;
    case &#39;POST&#39;:
        $test = new Test();
        $test-&amp;gt;nombres = $_POST[&#39;nombres&#39;];
        $test-&amp;gt;apellidos = $_POST[&#39;apellidos&#39;];
        $dao-&amp;gt;insert($test);
        break;
    case &#39;PUT&#39;:
        parse_str(file_get_contents(&quot;php://input&quot;), $post_vars);
        $test = new Test();
        $test-&amp;gt;id = $post_vars[&#39;id&#39;];
        $test-&amp;gt;nombres = $post_vars[&#39;nombres&#39;];
        $test-&amp;gt;apellidos = $post_vars[&#39;apellidos&#39;];
        $dao-&amp;gt;update($test);
        break;
    case &#39;DELETE&#39;:
        parse_str(file_get_contents(&quot;php://input&quot;), $post_vars);
        $id = $post_vars[&#39;id&#39;];
        $dao-&amp;gt;delete($id);
        break;
}
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Finalmente, escribimos la parte de código correspondiente al lado del cliente en el archivo &lt;b&gt;index.php&lt;/b&gt;. A través de una URL, accedemos a los servicios publicados y utilizamos sus funcionalidades dependiendo de la manera en cómo los invoquemos. (GET/POST/PUT/DELETE).&lt;/div&gt;
&lt;pre class=&quot;brush:php&quot;&gt;&amp;lt;?php

$url = &quot;http://localhost/res_api/service.php&quot;;

if (!function_exists(&#39;http_build_query&#39;)) {

    function http_build_query($data, $prefix = null, $sep = &#39;&#39;, $key = &#39;&#39;) {
        $ret = array();
        foreach ((array) $data as $k =&amp;gt; $v) {
            $k = urlencode($k);
            if (is_int($k) &amp;amp;&amp;amp; $prefix != null) {
                $k = $prefix . $k;
            }

            if (!empty($key)) {
                $k = $key . &quot;[&quot; . $k . &quot;]&quot;;
            }

            if (is_array($v) || is_object($v)) {
                array_push($ret, http_build_query($v, &quot;&quot;, $sep, $k));
            } else {
                array_push($ret, $k . &quot;=&quot; . urlencode($v));
            }
        }

        if (empty($sep)) {
            $sep = ini_get(&quot;arg_separator.output&quot;);
        }

        return implode($sep, $ret);
    }

}

/* GET Client */
$client = curl_init($url);
curl_setopt($client, CURLOPT_RETURNTRANSFER, 1);
$curl_response = curl_exec($client);
echo $curl_response;

/* POST Client */
$curl_post_data = array(
    &#39;nombres&#39; =&amp;gt; &#39;Roger Manuel&#39;,
    &#39;apellidos&#39; =&amp;gt; &#39;Rodriguez Alfaro&#39;
);
$client = curl_init($url);
curl_setopt($client, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($client, CURLOPT_POST, 1);
curl_setopt($client, CURLOPT_POSTFIELDS, $curl_post_data);
$curl_response = curl_exec($client);
echo $curl_response;

/* PUT Client */
$client = curl_init($url);
curl_setopt($client, CURLOPT_RETURNTRANSFER, true);
curl_setopt($client, CURLOPT_CUSTOMREQUEST, &quot;PUT&quot;);
$curl_put_data = array(
    &#39;id&#39; =&amp;gt; &#39;14&#39;,
    &#39;nombres&#39; =&amp;gt; &#39;Enma&#39;,
    &#39;apellidos&#39; =&amp;gt; &#39;Cruz Ticle&#39;
);
curl_setopt($client, CURLOPT_POSTFIELDS, http_build_query($curl_put_data));
$curl_response = curl_exec($client);
if ($response === false) {
    $info = curl_getinfo($client);
    curl_close($client);
    die(&#39;error occured during curl exec. Additioanl info: &#39; . var_export($info));
}
curl_close($client);
echo $curl_response;


/* DELETE Client */
$client = curl_init($url);
curl_setopt($client, CURLOPT_RETURNTRANSFER, true);
curl_setopt($client, CURLOPT_CUSTOMREQUEST, &quot;DELETE&quot;);
$curl_post_data = array(
    &#39;id&#39; =&amp;gt; &#39;15&#39;
);
curl_setopt($client, CURLOPT_POSTFIELDS, http_build_query($curl_post_data));
$curl_response = curl_exec($client);
curl_close($client);
echo $curl_response;
&lt;/pre&gt;
Evidentemente, estaría restando la parte de la vista, pero eso ya será tema de otro post. Recuerden que es mi primer post de PHP, por lo que les pido comprensión si algunos conceptos o separaciones de capas no las hago correctamente, la idea es aportar no? :D</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/82774501195019096/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2016/10/php-4-rest-webservices-crud.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/82774501195019096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/82774501195019096'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2016/10/php-4-rest-webservices-crud.html' title='Servicios Web REST y PHP'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4psukyN8xG_W7Mwe_tf3q1Vm-KHZGfbWMvHxUcZlN9kJDi9t-OYXnCvY0EXf45mqFhPkYE8Sr3bFVWYxkAdS8IaN8CIymfi1TIAF9eolLPGadytLulYQ7_AVFW65yl3ApNWo75ux3q38/s72-c/Screenshot_20161021_103909.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-6526357445870261211</id><published>2016-09-27T23:00:00.002-05:00</published><updated>2019-05-15T15:06:06.907-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="mysql"/><category scheme="http://www.blogger.com/atom/ns#" term="sql"/><title type='text'>Columnas virtuales con MySQL</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
Las columnas virtuales son una de las características más resaltantes de MySQL 5.7. Estas columnas tienen la característica de ser definidas en la tabla como el resultado de funciones de otras columnas, por ejemplo:
&lt;/div&gt;
&lt;pre class=&quot;brush:sql&quot;&gt;create database demo;
use demo;
create table tabla(campo1 int, campo2 int, campo3 int generated always as (campo1*campo2) virtual);
insert into tabla values (10, 20, default);
select * from tabla;
+--------+--------+--------+
| campo1 | campo2 | campo3 |
+--------+--------+--------+
|     10 |     20 |    200 |
+--------+--------+--------+
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
La tabla creada con estas sentencias SQL tendrá dos columnas que almacenarán números enteros y una tercera columna que será el resultado de la multiplicación de las dos columnas anteriores, tal como se muestra en la siguiente figura:&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbBGslAwFjzVUbZkJEA2UqQ3WD_Sz1JqESfuwM8tkKrryMmboop6BNLFE1zo43SjxtjvdPkK6o4A_y8N22bfBYDOhInUStaIA30RZ_GsCJ4Mj4CZpeg5X_1n3f-V6kG2UoBHrO6ZwQDT8/s1600/virtual.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;370&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbBGslAwFjzVUbZkJEA2UqQ3WD_Sz1JqESfuwM8tkKrryMmboop6BNLFE1zo43SjxtjvdPkK6o4A_y8N22bfBYDOhInUStaIA30RZ_GsCJ4Mj4CZpeg5X_1n3f-V6kG2UoBHrO6ZwQDT8/s640/virtual.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Dichas columnas virtuales son cálculadas sobre la marcha, cada vez que los campos son recuperados. Una de las limitantes es que no podemos utilizar columnas virtuales definidas después de la actual, esto debido a que las columnas virtuales se calculan en el orden en que se definen.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Existe otro tipo de columnas generadas, llamadas columnas almancenadas, pero éstas serán revisadas en otro artículo.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/6526357445870261211/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2016/09/columnas-virtuales-con-mysql.html#comment-form' title='2 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/6526357445870261211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/6526357445870261211'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2016/09/columnas-virtuales-con-mysql.html' title='Columnas virtuales con MySQL'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbBGslAwFjzVUbZkJEA2UqQ3WD_Sz1JqESfuwM8tkKrryMmboop6BNLFE1zo43SjxtjvdPkK6o4A_y8N22bfBYDOhInUStaIA30RZ_GsCJ4Mj4CZpeg5X_1n3f-V6kG2UoBHrO6ZwQDT8/s72-c/virtual.jpg" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-7943012302564533278</id><published>2016-09-19T11:27:00.004-05:00</published><updated>2019-05-15T15:14:32.497-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="aplicaciones web"/><category scheme="http://www.blogger.com/atom/ns#" term="glassfish"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><title type='text'>Secure Admin must be enabled to access the DAS remotely</title><content type='html'>En este corto artículo les presento la solución al error:&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: red;&quot;&gt;Secure Admin must be enabled to access the DAS remotely&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Que ocurre cuando queremos acceder remotamente a un servidor glassfish recientemente instalado. La solución es tan sencilla como ejecutar el siguiente comando:&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&quot;brush:js&quot;&gt;asadmin --host [host] --port [port] enable-secure-admin
&lt;/pre&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_bWj3Ksf2gfDCxk_L0LcCFo9cXpsLyQ8vp_51DRYtIu7D7jwBbvOb4ooOven8VLodxyKripCwPhwSpfvYrKy_wXwjwLmPIBIeyrCLDj9RYPTGQjPbEwMdfyJJu1VBVyh15tri5xYcc0A/s1600/solucion.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_bWj3Ksf2gfDCxk_L0LcCFo9cXpsLyQ8vp_51DRYtIu7D7jwBbvOb4ooOven8VLodxyKripCwPhwSpfvYrKy_wXwjwLmPIBIeyrCLDj9RYPTGQjPbEwMdfyJJu1VBVyh15tri5xYcc0A/s1600/solucion.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Recuerden reiniciar el servicio para que los cambios tomen efecto. Saludos!</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/7943012302564533278/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2016/09/secure-admin-must-be-enabled-to-access.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/7943012302564533278'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/7943012302564533278'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2016/09/secure-admin-must-be-enabled-to-access.html' title='Secure Admin must be enabled to access the DAS remotely'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_bWj3Ksf2gfDCxk_L0LcCFo9cXpsLyQ8vp_51DRYtIu7D7jwBbvOb4ooOven8VLodxyKripCwPhwSpfvYrKy_wXwjwLmPIBIeyrCLDj9RYPTGQjPbEwMdfyJJu1VBVyh15tri5xYcc0A/s72-c/solucion.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3243236739421377577.post-5060422727906097062</id><published>2016-09-13T23:25:00.000-05:00</published><updated>2019-05-15T15:16:01.631-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ciencia de la computación"/><category scheme="http://www.blogger.com/atom/ns#" term="mysql"/><title type='text'>How to Install and Configure MySQL Cluster on Windows</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
MySQL Clúster es una versión de alta disponibilidad, alta redundancia de MySQL adaptada para el entorno de computación distribuida. Usa el motor de almacenamiento NDB Cluster para permitir la ejecución de varios servidores MySQL en un clúster. Este motor de almacenamiento está disponible en las distribuciones binarias de MySQL 5.0, Los sistemas en los que está disponible son Linux, Solaris y Windows.

En este artículo vamos a revisar la manera cómo configurarlo.&lt;/div&gt;
&lt;br /&gt;
La infraestructura que utilizaremos será la siguiente:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV1ypSUpmtgB2BvHs2QKbNk7xXDX35n7PXJsqJMFChD0f7hvrk_rJwKpw9BWsei9DXdnWKSHG3M6UyeOTLSMGFaVcnMo46l7Cq84M2E7g8rKbQJKxmRFIvynEsrkyUY8XNGzTX9_xdKRY/s1600/Sin+t%25C3%25ADtulo-1.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;290&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV1ypSUpmtgB2BvHs2QKbNk7xXDX35n7PXJsqJMFChD0f7hvrk_rJwKpw9BWsei9DXdnWKSHG3M6UyeOTLSMGFaVcnMo46l7Cq84M2E7g8rKbQJKxmRFIvynEsrkyUY8XNGzTX9_xdKRY/s320/Sin+t%25C3%25ADtulo-1.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Los requerimientos son los siguientes:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;MySQL cluster. En este artículo se usó la versión 7.2.10. (&lt;a href=&quot;https://downloads.mysql.com/archives/cluster/&quot; target=&quot;_blank&quot;&gt;https://downloads.mysql.com/archives/cluster/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;3 computadoras con Windows XP con configuración de IP&#39;s por DHCP&lt;/li&gt;
&lt;/ul&gt;
Las recomendaciones son estas:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Desactivar firewall&lt;/li&gt;
&lt;li&gt;Desactivar antivirus&lt;/li&gt;
&lt;li&gt;Desinstalar y limpiar versiones anteriores de MySQL&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;text-align: justify;&quot;&gt;Una vez descargada la versión, descomprimir el contenido en una carpeta en el disco C, a la cual llamaremos &lt;/span&gt;&lt;b style=&quot;text-align: justify;&quot;&gt;mysqlc&lt;/b&gt;&lt;span style=&quot;text-align: justify;&quot;&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
En cada uno de los tres nodos de la figura mostrada anteriormente, crear la estructura de carpetas y su contenido a partir del comando:
&lt;/div&gt;
&lt;pre class=&quot;brush:java&quot;&gt;C:\&amp;gt;mkdir my_cluster my_cluster\ndb_data my_cluster\mysqld_data my_cluster\conf
C:\&amp;gt;mkdir my_cluster\mysqld_data\mysql my_cluster\mysqld_data\ndbinfo
C:\&amp;gt;copy c:\mysqlc\data\mysql my_cluster\mysqld_data\mysql 
C:\&amp;gt;copy c:\mysqlc\data\ndbinfo my_cluster\mysqld_data\ndbinfo
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Nodo Administrador&lt;/b&gt;
&lt;br /&gt;
Crear el archivo &lt;b&gt;config.ini&lt;/b&gt; en la carpeta c:\my_cluster\conf con el siguiente contenido:
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;[ndb_mgmd]
HostName=192.168.1.100
DataDir=c:\my_cluster\ndb_data
Nodeid=1

[Ndbd default]
NoOfReplicas=2

[Ndbd]
HostName=192.168.1.101
Nodeid=3

[Ndbd]
HostName=192.168.1.102
Nodeid=4
[Mysqld]
[Mysqld]
&lt;/pre&gt;
Iniciar el nodo administrador ejecutando el siguiente comando y &lt;b&gt;dejando la consola abierta&lt;/b&gt;.
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;C:\my_cluster&amp;gt;/mysqlc/bin/ndb_mgmd -f conf/config.ini --initial --configdir=c:\my_cluster\conf\
&lt;/pre&gt;
En otra consola de comandos del nodo administrador, ejecutar el programa para verificar el estado de nuestro cluster.
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;C:\&amp;gt;C:\mysqlc\bin\ndb_mgm -e show
&lt;/pre&gt;
El resultado deberá ser similar al mostrado a continuación:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiHPcuRXV-tfakVY3T0D9bhABA5kMhLJZQq58oOnvXgLiQyMxgEeLpSUqfGoV4pfZTZ_a1Xam7Uu50OtryQcHYuoHlDYhXy8iFuRf4oeNBTFdUArvDlxwlW5OeUd5qsQgRNooSo04b5yU/s1600/001.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiHPcuRXV-tfakVY3T0D9bhABA5kMhLJZQq58oOnvXgLiQyMxgEeLpSUqfGoV4pfZTZ_a1Xam7Uu50OtryQcHYuoHlDYhXy8iFuRf4oeNBTFdUArvDlxwlW5OeUd5qsQgRNooSo04b5yU/s1600/001.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;Nodos de Datos&lt;/b&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
En cada uno de los nodos de datos, crear el archivo &lt;b&gt;my.cnf&lt;/b&gt; en la carpeta c:\my_cluster\conf. El puerto debe ser diferente para cada nodo de dato y de preferencia mayor a 5000.
&lt;/div&gt;
&lt;pre class=&quot;brush:java&quot;&gt;[mysqld]
ndbcluster
datadir=c:\my_cluster\mysqld_data
port=15002
ndb-connectstring = 192.168.1.100

[mysql_cluster]
ndb-connectstring = 192.168.1.100
&lt;/pre&gt;
Ahora nos conectamos con el nodo administrador ejecutando el siguiente comando en cada uno de los dos nodos de datos
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;C:\&amp;gt;c:\mysqlc\bin\ndbd -c 192.168.1.100:1186
&lt;/pre&gt;
Sin embargo, al ejecutar en el nodo administrador el siguiente comando.
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;C:\&amp;gt;C:\mysqlc\bin\ndb_mgm -e show
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Podemos notar que, a pesar que la conexión al nodo administrador ha sido hecha, los nodos SQL aún no están habilitados (&lt;b&gt;not connected, accepting connect from any host&lt;/b&gt;).
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijxqYpilVDaXUs5_vo6gPg4Qd9fHtNTRLGJ_WRRdDyoyXg_XeeqaBfs07RTvf_AfVbtd5x8z74poHeLt-ly_QfroHx3jB3v7IMWAzzrAVzkneuBH6OYKuW_bsr_0lqKB0faj17qMp-qS8/s1600/001.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijxqYpilVDaXUs5_vo6gPg4Qd9fHtNTRLGJ_WRRdDyoyXg_XeeqaBfs07RTvf_AfVbtd5x8z74poHeLt-ly_QfroHx3jB3v7IMWAzzrAVzkneuBH6OYKuW_bsr_0lqKB0faj17qMp-qS8/s1600/001.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Para levantar las API&#39;s, ejecutar en cada nodo de datos el siguiente comando en una consola nueva:
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;C:\my_cluster&amp;gt;c:\mysqlc\bin\mysqld --defaults-file=conf/my.cnf --console
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Al volver a ejecutar el comando de visualización de conexiones en el nodo administrador, la salida será la siguiente:
&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiETxoqlFxW7BT1nYO2guYhnff_R2zZiKAnSp3m6uCXhP0cuaXryh1bOq9HsrGBRA18HCGHeXgF4mBfqq0MAjLe1ZuHUmx4CF_A666cfbonW73IAE-5ngwJL000ZwikjgDU9u6SLL14LB8/s1600/001.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiETxoqlFxW7BT1nYO2guYhnff_R2zZiKAnSp3m6uCXhP0cuaXryh1bOq9HsrGBRA18HCGHeXgF4mBfqq0MAjLe1ZuHUmx4CF_A666cfbonW73IAE-5ngwJL000ZwikjgDU9u6SLL14LB8/s1600/001.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Ahora sólo resta conectarnos al motor de base de datos de cada nodo utilizando una nueva consola para ejecutar el siguiente comando, teniendo en cuenta el puerto establecido en el archivo &lt;b&gt;my.cnf&lt;/b&gt;. En este caso, mostraremos la conexión en el nodo que utiliza el puerto 15002.
&lt;/div&gt;
&lt;pre class=&quot;brush:java&quot;&gt;c:\my_cluster&amp;gt;c:\mysqlc\bin\mysql -P15002 -u root
&lt;/pre&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Al levantar los dos motores, cualquier sentencia SQL ejecuta en uno de ellos deberá verse automáticamente reflejada en la otra instancia. La siguiente imagen ilustra esto:
&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN-Iq34wIF29B7oEp2YPpq4wx9kO91P2995nCBSEr2n70lFHHpziHtx6EkCy1MYfFVvqdbg4N8yPNqFX27lQXOCsLhAf-JOSq4EJR9IswC2GXc0MKJVEdIzMg07DZK_5i6XvS-KM1vgV0/s1600/001.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;244&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN-Iq34wIF29B7oEp2YPpq4wx9kO91P2995nCBSEr2n70lFHHpziHtx6EkCy1MYfFVvqdbg4N8yPNqFX27lQXOCsLhAf-JOSq4EJR9IswC2GXc0MKJVEdIzMg07DZK_5i6XvS-KM1vgV0/s640/001.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Inicialmente, en la consola azul habían las mismas base de datos que en la consola blanca, sin embargo al crear la base de datos clusterdb en esta última, la instancia azul reflejó automáticamente los cambios.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
Para finalizar, les dejo los comandos para finalizar el servicio de manera segura:&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;#Ejecutar por cada nodo de datos, teniendo en cuenta el puerto
C:\my_cluster&amp;gt;c:\mysqlc\bin\mysqladmin -u root -h 127.0.0.1 -P15000 shutdown
#Nodo administrador
C:\my_cluster&amp;gt;c:\mysqlc\bin\ndb_mgm -e shutdown
#Ver puertos
netstat -oan
&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://rolandopalermo.blogspot.com/feeds/5060422727906097062/comments/default' title='Comentarios de la entrada'/><link rel='replies' type='text/html' href='http://rolandopalermo.blogspot.com/2016/09/how-to-install-and-configure-mysql.html#comment-form' title='0 Comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/5060422727906097062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3243236739421377577/posts/default/5060422727906097062'/><link rel='alternate' type='text/html' href='http://rolandopalermo.blogspot.com/2016/09/how-to-install-and-configure-mysql.html' title='How to Install and Configure MySQL Cluster on Windows'/><author><name>Rolando</name><uri>http://www.blogger.com/profile/14493339473572566456</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV1ypSUpmtgB2BvHs2QKbNk7xXDX35n7PXJsqJMFChD0f7hvrk_rJwKpw9BWsei9DXdnWKSHG3M6UyeOTLSMGFaVcnMo46l7Cq84M2E7g8rKbQJKxmRFIvynEsrkyUY8XNGzTX9_xdKRY/s72-c/Sin+t%25C3%25ADtulo-1.jpg" height="72" width="72"/><thr:total>0</thr:total></entry></feed>