<?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-8324889730441663172</id><updated>2024-11-01T13:19:05.121+01:00</updated><category term="php"/><category term="android"/><category term="javascript"/><category term="jquery"/><category term="folio"/><category term="tablet"/><category term="ajax"/><category term="cyanogen"/><category term="devops"/><category term="google api"/><category term="ice cream sandwich"/><category term="jolie"/><category term="kubernetes"/><category term="linux"/><category term="mobile"/><category term="tinygrammar"/><category term="web services"/><category term="websockets"/><category term=".NET Core"/><category term="Azure"/><category term="Azure Functions"/><category term="Office 365"/><category term="ansible"/><category term="autobahn"/><category term="automation"/><category term="c#"/><category term="composer"/><category term="cross platform"/><category term="csharp"/><category term="dependency manager"/><category term="docker"/><category term="e-commerce"/><category term="gingerbread"/><category term="html5"/><category term="ingress"/><category term="jelly bean"/><category term="json"/><category term="json patch"/><category term="lightbox"/><category term="micro services"/><category term="microservices"/><category term="nodejs"/><category term="open source"/><category term="opensuse"/><category term="payment gateway"/><category term="programming languages"/><category term="python"/><category term="serverless"/><category term="soa"/><category term="toshiba folio"/><category term="visual studio code"/><category term="wordpress"/><category term="wsl"/><title type='text'>El canton de Marco (Marco&#39;s corner)</title><subtitle type='html'>Technology, coding, fun and politics (in random order)</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Unknown</name><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>23</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8324889730441663172.post-5348215741357358747</id><published>2020-06-04T14:07:00.001+02:00</published><updated>2020-06-05T12:28:24.413+02:00</updated><title type='text'>Jolie on Azure Functions</title><content type='html'>Hi all.
Some weeks ago Azure Functions&#39; team released (as a preview) &lt;a href=&quot;https://docs.microsoft.com/en-gb/azure/azure-functions/functions-custom-handlers&quot; target=&quot;_blank&quot;&gt;custom handlers&lt;/a&gt;.&lt;br /&gt;
From the official doc:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;i&gt;Custom handlers are best suited for situations where you want to:&lt;/i&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;Implement a function app &lt;u&gt;in a language that&#39;s not officially supported&lt;/u&gt;. &lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Implement a function app in a language version or runtime not supported by default.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Provide more granular control over the function app execution environment.&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
I think this is a really powerful feature and you can actually find a lot of articles showing how to leverage it to write functions in Go, PHP, etc&lt;br /&gt;
Now I&#39;m going to add yet another programming language to the list: &lt;a href=&quot;https://www.jolie-lang.org/&quot; target=&quot;_blank&quot;&gt;Jolie&lt;/a&gt;.&lt;br /&gt;
Again, from the documentation:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;i&gt;To implement a custom handler, you need the following aspects to your application:&lt;/i&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;A host.json file at the root of your app&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;A function.json file for each function (inside a folder that matches the function name)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;A command, script, or executable, which runs a web server&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
In addition, you have to supply all is needed for your function to run because we are going to deploy to a stateless environment (obviously JDK support is required on the target platform as Jolie is Java dependent).&lt;br /&gt;
I added a full Jolie distribution (what you find in JOLIE_HOME path) to my function project in &lt;i&gt;jolie_bin&lt;/i&gt; directory and modified the launch script to point to it.&lt;br /&gt;
&lt;br /&gt;
So my &lt;i&gt;host.json&lt;/i&gt; looks like that:&lt;br /&gt;
&lt;div style=&quot;line-height: 22px;&quot;&gt;
&lt;div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;{&lt;br /&gt;&amp;nbsp; &quot;version&quot;:  &quot;2.0&quot;,&lt;br /&gt;     &amp;nbsp; &quot;httpWorker&quot;: {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &quot;description&quot;: {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;arguments&quot;: [&quot;jolie_services.ol&quot;],&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;defaultExecutablePath&quot;: &quot;jolie_func_executor.sh&quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; },&lt;br /&gt;&amp;nbsp; &amp;nbsp; &quot;extensionBundle&quot;: {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;id&quot;: &quot;Microsoft.Azure.Functions.ExtensionBundle&quot;,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;version&quot;: &quot;[1.*, 2.0.0)&quot;&lt;br /&gt;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;/span&gt;&lt;/blockquote&gt;
where &lt;i&gt;jolie_services.ol&lt;/i&gt; actually contains the function&#39;s code.&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/AVvXsEiHzsggD6z7MEs9Gap6PACQXOvHehTJXlFSqDUrMbl2pcJrGtjVfBA0MVMzXTsRfpgBnj4lnGlOonz_Ru7t4zlQ2dOCLQZROxUcXztn_GEZnDr_Dc3O4FVKf8JM2Hu9NUiYujXJg4ZyLj8/s1600/Screenshot_1.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;607&quot; data-original-width=&quot;888&quot; height=&quot;271&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHzsggD6z7MEs9Gap6PACQXOvHehTJXlFSqDUrMbl2pcJrGtjVfBA0MVMzXTsRfpgBnj4lnGlOonz_Ru7t4zlQ2dOCLQZROxUcXztn_GEZnDr_Dc3O4FVKf8JM2Hu9NUiYujXJg4ZyLj8/s400/Screenshot_1.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Jolie native support for HTTP protocol makes it really easy to write a &quot;webserver&quot;.&lt;/div&gt;
&lt;/div&gt;
Unfortunately there&#39;s a problem because Azure Functions Host communicates with custom handlers on a dynamic port, on which your application has to be listening.&lt;br /&gt;
This port can be read by the FUNCTIONS_HTTPWORKER_PORT environment variable but when you define an InputPort in Jolie the Location parameter is static, for instance:&lt;br /&gt;
&lt;div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;inputPort MyInput {&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;background-color: yellow;&quot;&gt;Location: &quot;socket://localhost:8180&quot;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Protocol: http&lt;br /&gt;&amp;nbsp; &amp;nbsp; Interfaces: MyInterface&lt;br /&gt;}&lt;/span&gt;&lt;/blockquote&gt;
&lt;div&gt;
Dynamic Locations aren&#39;t yet available in Jolie but there&#39;s a workaround using a constant.&lt;/div&gt;
&lt;div&gt;
In Location&#39;s definition, we refer to this constant:&lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;Location: AzureFunctionsPort&lt;/span&gt;&lt;/blockquote&gt;
In the launch command, we read the environment variable and pass it to our Jolie program setting the constant value:&lt;br /&gt;
&lt;div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;-C AzureFunctionsPort=&quot;\&quot;socket://localhost:$FUNCTIONS_HTTPWORKER_PORT\&quot;&quot;&lt;/span&gt;&lt;/blockquote&gt;
&lt;a href=&quot;https://github.com/mmontesi/jolie-azure-functions&quot; target=&quot;_blank&quot;&gt;Here&lt;/a&gt; you can find a simple working example with detailed instructions to start from scratch.&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/AVvXsEhwNH6fyFXBZBi4Z_ZY50Z6UFlEGuAbB-3F4xrPhV8KcBus0GNw13uP39_5U_j-reWEqIlpJKhQpOu_jdn-i3Ehnh3PTc8n-_wHGAFFf5wZT8sAxEX6toORg_KTyK4efn8zcixdxJ7m8Ic/s1600/Jolie_wsl.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;622&quot; data-original-width=&quot;1056&quot; height=&quot;376&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwNH6fyFXBZBi4Z_ZY50Z6UFlEGuAbB-3F4xrPhV8KcBus0GNw13uP39_5U_j-reWEqIlpJKhQpOu_jdn-i3Ehnh3PTc8n-_wHGAFFf5wZT8sAxEX6toORg_KTyK4efn8zcixdxJ7m8Ic/s640/Jolie_wsl.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/5348215741357358747/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2020/06/jolie-on-azure-functions.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/5348215741357358747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/5348215741357358747'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2020/06/jolie-on-azure-functions.html' title='Jolie on Azure Functions'/><author><name>Unknown</name><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/AVvXsEiHzsggD6z7MEs9Gap6PACQXOvHehTJXlFSqDUrMbl2pcJrGtjVfBA0MVMzXTsRfpgBnj4lnGlOonz_Ru7t4zlQ2dOCLQZROxUcXztn_GEZnDr_Dc3O4FVKf8JM2Hu9NUiYujXJg4ZyLj8/s72-c/Screenshot_1.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8324889730441663172.post-4414868992127999935</id><published>2020-03-15T19:31:00.000+01:00</published><updated>2020-03-29T16:03:05.615+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="docker"/><category scheme="http://www.blogger.com/atom/ns#" term="jolie"/><category scheme="http://www.blogger.com/atom/ns#" term="kubernetes"/><title type='text'>Jolie micro services on Kubernetes</title><content type='html'>&lt;a href=&quot;https://www.jolie-lang.org/&quot; target=&quot;_blank&quot;&gt;Jolie&lt;/a&gt; is a (micro) service-oriented language.&lt;br /&gt;
Jolie&#39;s capabilities work well with Docker and you can find an example in the official documentation &lt;a href=&quot;https://jolielang.gitbook.io/docs/containerization/docker#deploying-a-jolie-service-in-a-container-docker&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
So d&lt;span style=&quot;white-space: pre;&quot;&gt;eploying a Jolie service in a Docker container is quite easy.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;Now it&#39;s time to go onboard with Kubernetes ;-)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
This is only a little demo on how to set up a Kubernetes environment on your PC (thanks to minikube) and build up a scalable clusterized version of Jolie&#39;s &quot;Hello world&quot; example.&lt;br /&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;You can find Jolie examples on &lt;a href=&quot;https://github.com/jolie/examples&quot; target=&quot;_blank&quot;&gt;this GitHub project&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
What we are going to do now is to transform &quot;01_getting_started&quot; sample (which simply twices a number) into a powerful Kubernetes scalable app (doing exactly the same thing, but in a cool way).&lt;br /&gt;
&lt;br /&gt;
If you object that this is very unreasonable, I have to remind you that it is perfectly aligned with today&#39;s software industry standards. :-P&lt;br /&gt;
&lt;br /&gt;
To be honest I&#39;m not going to explain what Kubernetes is and how it does what it does, so please go read a tutorial or the beautiful official documentation.&lt;br /&gt;
&lt;br /&gt;
My favourite starting point is &lt;a href=&quot;https://www.cncf.io/phippy/&quot;&gt;this&lt;/a&gt; (it&#39;s not a joke).&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;First of all, let&#39;s set up your box!&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;You need:&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Linux (tested on Ubuntu 18.04) or Windows 10 Pro (tested on 1909) with HyperV support enabled&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;a href=&quot;https://www.jolie-lang.org/index.html&quot; target=&quot;_blank&quot;&gt;Jolie language&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/install/&quot; target=&quot;_blank&quot;&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kubernetes.io/docs/tasks/tools/install-minikube/&quot; target=&quot;_blank&quot;&gt;Minikube&lt;/a&gt;&amp;nbsp;(on Win10 I suggest you to force version 1.5.0 installation to avoid some fresh annoying bugs)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Ok, ready?&lt;/div&gt;
&lt;div&gt;
Now you can clone this &lt;a href=&quot;https://github.com/mmontesi/jolie-k8s-sample&quot; target=&quot;_blank&quot;&gt;repository&lt;/a&gt;&amp;nbsp;and go ahead.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;STEP 1 - Create a Docker image containing your Jolie application&lt;/span&gt;&lt;/h4&gt;
As previously said this is very simple following the official documentation and using images available on Docker Hub.&lt;br /&gt;
&lt;br /&gt;
This is our Dockerfile to build an image exposing the &quot;twice-a-number&quot; server on 8000 port:&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; white-space: pre;&quot;&gt;FROM jolielang/jolie&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; white-space: pre;&quot;&gt;EXPOSE 8000&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; white-space: pre;&quot;&gt;COPY server.ol server.ol&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; white-space: pre;&quot;&gt;COPY twiceInterface.iol twiceInterface.iol&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; white-space: pre;&quot;&gt;CMD jolie server.ol&lt;/span&gt;&lt;/blockquote&gt;
Before creating the image we have to configure Docker&#39;s environment to point to minikube, otherwise images wouldn&#39;t be available to your local cluster.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Linux&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;$ eval $(minikube docker-env)&lt;/span&gt;&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Win10 (on PowerShell)&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;PS&amp;gt; &amp;amp; minikube docker-env | Invoke-Expression&lt;/span&gt;&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Ok, now we can build our image (if not specified commands are the same on both platforms, don&#39;t miss the final dot):&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;$ docker build -t jolie-k8s-sample .&lt;/span&gt;&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
and verify all went as expected:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;$ docker images&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;REPOSITORY&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; TAG&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;IMAGE ID&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;jolie-k8s-sample&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; latest&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 2df927523a30&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h4&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;STEP 2 - Create a Kubernetes deployment &lt;/span&gt;&lt;/h4&gt;
So we are ready to use our brand new image in a Kubernetes deployment, setting replicas parameter to 2.&lt;br /&gt;
&lt;br /&gt;
This means Kubernetes ensures to have always 2 pods (the furry blue little animals Phippy introduced to you) running our container.&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;apiVersion: apps/v1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;kind: Deployment&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;metadata:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; name: jolie-sample-deployment&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; labels:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; app: jolie-sample&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;spec:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; replicas: 2&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; selector:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; matchLabels:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; app: jolie-sample&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; template:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; metadata:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; labels:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; app: jolie-sample&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; spec:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; containers:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - name: jolie-k8s-sample&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; image: jolie-k8s-sample&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ports:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - containerPort: 8000&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; imagePullPolicy: IfNotPresent&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;To start deployment roll-out just type:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;  white-space: pre;&quot;&gt;$ kubectl apply -f jolie-k8s-deployment.yml&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small; white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: inherit; white-space: pre;&quot;&gt;And after a few seconds you can see your pods up and running:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit; white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;  white-space: pre;&quot;&gt;$ kubectl get pods&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small; white-space: pre;&quot;&gt;NAME                                       READY   STATUS    RESTARTS   AGE&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small; white-space: pre;&quot;&gt;jolie-sample-deployment-655f8b759d-bmzk7   1/1     Running   0          4s&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small; white-space: pre;&quot;&gt;jolie-sample-deployment-655f8b759d-mq8cn   1/1     Running   0          4s&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;  white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: inherit; white-space: pre;&quot;&gt;Exciting!&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;STEP 3 - E&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;xpose deployment by a service&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
Now we have 2 running instances of our (micro)service but we lack a communication channel to reach the container&#39;s port 8000 from outside of Kubernetes virtual network.&lt;br /&gt;
Kubernetically speaking this is a service.&lt;br /&gt;
Just follow the&amp;nbsp;&lt;a href=&quot;https://kubernetes.io/docs/tutorials/hello-minikube/#create-a-service&quot;&gt;minikube tutorial&lt;/a&gt; and type:&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; &quot;&gt;$ kubectl expose deployment jolie-sample-deployment --type=LoadBalancer --port=8000&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; white-space: pre;&quot;&gt;$ kubectl get services&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;NAME                      TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
jolie-sample-deployment   LoadBalancer   10.109.47.147   &amp;lt;pending&amp;gt;     8000:30095/TCP   13s
kubernetes                ClusterIP      10.96.0.1       &amp;lt;none&amp;gt;        443/TCP      &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;So there&#39;s a service exposing pods&#39; port 8000 on cluster&#39;s port 30095.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;To make this visible from your host you have to go through a &quot;minikube service&quot;:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;$ minikube service jolie-sample-deployment&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;|-----------|-------------------------|-------------|-----------------------------|
| NAMESPACE |          NAME           | TARGET PORT |             URL             |
|-----------|-------------------------|-------------|-----------------------------|
| default   | jolie-sample-deployment |             | http://&lt;span style=&quot;background-color: yellow;&quot;&gt;192.168.99.100:30095&lt;/span&gt; |
|-----------|-------------------------|-------------|-----------------------------&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;|&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;* Opening service default/jolie-sample-deployment in default browser...&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;Close the automatically opened browser and let&#39;s go on.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h4&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;Step 4 - Invoke micro services from client&lt;/span&gt;&lt;/h4&gt;
As final step we want to call the Jolie service running inside Kubernetes cluster.&lt;br /&gt;
Open client.ol with a text editor and modify line 5, setting IP and port of exposed minikube service:&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;Location: &quot;socket://192.168.99.100:30095&quot;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;Save and try:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;$ jolie client.ol 
jolie-sample-deployment-655f8b759d-&lt;span style=&quot;background-color: yellow;&quot;&gt;mq8cn&lt;/span&gt; -&amp;gt; 10
$ jolie client.ol 
jolie-sample-deployment-655f8b759d-&lt;span style=&quot;background-color: lime;&quot;&gt;bmzk7&lt;/span&gt; -&amp;gt; 10
$ jolie client.ol 
jolie-sample-deployment-655f8b759d-&lt;span style=&quot;background-color: yellow;&quot;&gt;mq8cn&lt;/span&gt; -&amp;gt; 10
$ jolie client.ol 
jolie-sample-deployment-655f8b759d-&lt;span style=&quot;background-color: lime;&quot;&gt;bmzk7&lt;/span&gt;&lt;span style=&quot;background-color: white;&quot;&gt; &lt;/span&gt;-&amp;gt; 10&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
As you can see we are getting the right response (client.ol has an hardcoded 5 value as input) and so we demonstrated Kuberntes can at least multiply an integer by another integer!&lt;br /&gt;
But server.ol running on containers was modified from the example&#39;s original to write out the hostname too:&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;white-space: pre;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;  getenv@Runtime( &quot;HOSTNAME&quot; )( hostname_env )
  result = hostname_env + &quot; -&amp;gt; &quot; + number * 2&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
And that allow us to verify that:&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;our Jolie server is running on multiple pods&lt;/li&gt;
&lt;li&gt;the infrastructure is hidden to clients&lt;/li&gt;
&lt;li&gt;calls are automatically managed and balanced by Kubernetes engine (output shows each call gets its response from different pod)&lt;/li&gt;
&lt;li&gt;BONUS if you need more power to multiply number 5 you can scale up your deployment:&lt;br /&gt;&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: small;&quot;&gt;$ kubectl scale deployment jolie-sample-deployment --replicas=&amp;lt;N&amp;gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/4414868992127999935/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2020/03/jolie-micro-services-on-kubernetes.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/4414868992127999935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/4414868992127999935'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2020/03/jolie-micro-services-on-kubernetes.html' title='Jolie micro services on Kubernetes'/><author><name>Unknown</name><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-8324889730441663172.post-5148321809710799183</id><published>2019-04-18T10:46:00.001+02:00</published><updated>2019-04-18T10:51:57.987+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="automation"/><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><category scheme="http://www.blogger.com/atom/ns#" term="ingress"/><category scheme="http://www.blogger.com/atom/ns#" term="json patch"/><category scheme="http://www.blogger.com/atom/ns#" term="kubernetes"/><title type='text'>Kubernetes NGINX Ingress - Automating dynamic rules management</title><content type='html'>A few points to ensure you&#39;re interested in this argument.&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;You set up a Kubernetes cluster where you deployed your brand new containerized application.&lt;/li&gt;
&lt;li&gt;You set up an NGINX based Ingress to expose it and manage TLS termination.&lt;/li&gt;
&lt;li&gt;You need to handle a lot of routing rules (growing from some to thousands) and, more important, you need automation.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
I assume steps 1 and 2 are done, so let&#39;s dive in rules management and its automation.&lt;/div&gt;
&lt;div&gt;
The first option Kubernetes gives you is this cli &lt;a href=&quot;https://kubernetes.io/docs/reference/kubectl/cheatsheet/#editing-resources&quot; target=&quot;_blank&quot;&gt;command&lt;/a&gt;:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;kubectl edit ingress &amp;lt;your_ingress_name&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
An editor comes up you can modify the ingress resource, when you save the configuration is&amp;nbsp;&amp;nbsp;automatically updated.&lt;/div&gt;
&lt;div&gt;
That&#39;s ok and really useful, but not suitable if you need automation, and a DevOps guy should automate everything! :-P&lt;/div&gt;
&lt;div&gt;
So I&#39;ve found resources can also be &lt;a href=&quot;https://kubernetes.io/docs/reference/kubectl/cheatsheet/#patching-resources&quot; target=&quot;_blank&quot;&gt;patched&lt;/a&gt;, supplying a json string.&lt;/div&gt;
&lt;div&gt;
As an example you can create a file with json patch definition:&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;[{&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;op&quot;: &quot;add&quot;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;path&quot;: &quot;/spec/rules/-&quot;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;value&quot;: {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;host&quot;: &quot;&amp;lt;your_url&amp;gt;&quot;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;http&quot;: {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;paths&quot;: [&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;backend&quot;: {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;serviceName&quot;: &quot;&amp;lt;your_dest_service&amp;gt;&quot;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;servicePort&quot;: your_service_port&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ]&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;}]&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;And apply it to your resource:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;kubectl patch ingress &amp;lt;your_ingress&amp;gt; --type json -p &quot;$(cat &amp;lt;your_json_file&amp;gt;&quot;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;This appends the new rule to rules array in ingress definition, see JSON Patch format details &lt;a href=&quot;http://jsonpatch.com/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;
The great advantage is that you focus on a single rule and the process can be easily automated.&lt;br /&gt;
I faced some more difficulties when I first tried to remove a rule.&lt;br /&gt;
Obviuosly you can edit the entire ingress definition, manually remove the lines regarding the rule to be removed and save.&lt;br /&gt;
But what about automation?&lt;br /&gt;
This is my solution using again Kubernetes&#39; patching capabilities.&lt;br /&gt;
The main idea is to leverage the JSON Patch replace operation.&lt;br /&gt;
For instance this command removes the first rule from your Ingress:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;kubectl patch ingress &amp;lt;your_ingress&amp;gt; --type json -p &quot;[{\&quot;op\&quot;: \&quot;remove\&quot;, \&quot;path\&quot;: \&quot;/spec/rules/0\&quot;}]&quot;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Unfortunately JSON Patch supports only positional path for arrays, so my problem was to get the target rule position inside rules array.&lt;br /&gt;
I achieved that using jq command:&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: xx-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;kubectl get ingress &amp;lt;your_ingress&amp;gt; -o json | jq &quot;.spec.rules | map(.host == \&quot;&amp;lt;url_to_be_removed&amp;gt;\&quot;) | index(true)&quot;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
So, putting all together, this Bash script does the trick:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;#!/bin/bash&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;index=$(kubectl get ingress &amp;lt;your_ingress&amp;gt; -o json | jq &quot;.spec.rules | map(.host == \&quot;&amp;lt;url_to_be_removed&amp;gt;\&quot;) | index(true)&quot;);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;kubectl patch ingress &amp;lt;your_ingress&amp;gt; --type json -p &quot;[{\&quot;op\&quot;: \&quot;remove\&quot;, \&quot;path\&quot;: \&quot;/spec/rules/$index\&quot;}]&quot;;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
Now you can use this technique in your favourite automation environment.&lt;br /&gt;
As an example I&#39;ve created a couple of Ansible roles, but the real work is done by Bash scripts (no Ansible modules available).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/5148321809710799183/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2019/04/kubernetes-nginx-ingress-automating.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/5148321809710799183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/5148321809710799183'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2019/04/kubernetes-nginx-ingress-automating.html' title='Kubernetes NGINX Ingress - Automating dynamic rules management'/><author><name>Unknown</name><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-8324889730441663172.post-3108119453229374798</id><published>2018-12-06T15:37:00.004+01:00</published><updated>2018-12-20T08:51:21.894+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ansible"/><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="visual studio code"/><category scheme="http://www.blogger.com/atom/ns#" term="wsl"/><title type='text'>Ansible, Azure &amp; WSL survival guide (VS Code bonus track)</title><content type='html'>Hi all you new DevOps!&lt;br /&gt;
This guide is meant for poor Windows&#39; users struggling to get Ansible working on their workstations, like me few days ago :-(&lt;br /&gt;
Scenario: you&#39;re involved in a brand new cloud project on Azure, you&#39;re trying to make things work with Ansible and your company provides you a Windows 10 ™ PC, but Ansible DO NOT RUN on Windows.&lt;br /&gt;
In addiction you&#39;re lazy and bored to start yet another virtual machine, just to type &quot;git pull&quot; and &quot;ansible-palybook&quot; :-D (by the way your precious SSD is getting dangerously full).&lt;br /&gt;
And you &lt;u&gt;do want&lt;/u&gt; your memory greed Visual Studio Code, with autocompletion, syntax highlight, all-known languages modules and other silly stuff.&lt;br /&gt;
&lt;br /&gt;
First of all, let&#39;s install WSL (if you don&#39;t know what WSL is, google it):&lt;br /&gt;
&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/wsl/install-win10&quot; rel=&quot;noreferrer noopener&quot; style=&quot;-webkit-font-smoothing: antialiased; background-color: white; box-sizing: border-box; color: #6264a7; font-family: &amp;quot;Segoe UI&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, Helvetica, Arial, sans-serif; font-size: 14px; text-decoration-line: none;&quot; tabindex=&quot;-1&quot; target=&quot;_blank&quot; title=&quot;https://docs.microsoft.com/en-us/windows/wsl/install-win10&quot;&gt;https://docs.microsoft.com/en-us/windows/wsl/install-win10&lt;/a&gt;&lt;br /&gt;
I assume you installed an Ubuntu 16.04 upon WSL.&lt;br /&gt;
Quite simple, isn&#39;t it?&lt;br /&gt;
Now you should install Ansible and all needed Azure modules.&lt;br /&gt;
There&#39;s a simple guide on Azure documentation portal, let&#39;s follow the &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/virtual-machines/linux/ansible-install-configure?toc=%2Fit-it%2Fazure%2Fansible%2Ftoc.json&amp;amp;bc=%2Fit-it%2Fazure%2Fbread%2Ftoc.json#ubuntu1604-lts&quot; target=&quot;_blank&quot;&gt;Ubuntu&#39;s section&lt;/a&gt;.&lt;br /&gt;
Uhm, did something go wrong with pip&#39;s version and other Python related stuff?&lt;br /&gt;
Ok, you may have SSL certificates issues or pip/Python versions hell (damn it).&lt;br /&gt;
Try to substitute this command:&lt;br /&gt;
&lt;span style=&quot;background-color: white; font-family: &amp;quot;consolas&amp;quot; , &amp;quot;menlo&amp;quot; , &amp;quot;monaco&amp;quot; , &amp;quot;lucida console&amp;quot; , &amp;quot;liberation mono&amp;quot; , &amp;quot;dejavu sans mono&amp;quot; , &amp;quot;bitstream vera sans mono&amp;quot; , &amp;quot;courier new&amp;quot; , monospace , sans-serif; font-size: 14px; white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&lt;span style=&quot;background-color: white; font-size: 14px; white-space: pre;&quot;&gt;sudo pip install ansible&lt;/span&gt;&lt;span style=&quot;background-color: white; font-size: 14px; white-space: pre;&quot;&gt;[azure]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
with:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace;&quot;&gt;&lt;span style=&quot;background-color: white; color: #252423; font-size: 14px;&quot;&gt;pip install pip==9.0.3 --trusted-host=pypi.python.org --trusted-host=pypi.org --trusted-host=files.pythonhosted.org --user&lt;/span&gt;&lt;br style=&quot;-webkit-font-smoothing: antialiased; background-color: white; box-sizing: border-box; color: #252423; font-size: 14px;&quot; /&gt;&lt;span style=&quot;background-color: white; box-sizing: border-box; color: #252423; font-size: 14px;&quot;&gt;pip install ansible --trusted-host=pypi.python.org --trusted-host=pypi.org --trusted-host=files.pythonhosted.org --user&lt;/span&gt;&lt;br style=&quot;-webkit-font-smoothing: antialiased; background-color: white; box-sizing: border-box; color: #252423; font-size: 14px;&quot; /&gt;&lt;span style=&quot;background-color: white; color: #252423; font-size: 14px;&quot;&gt;pip install azure --trusted-host=pypi.python.org --trusted-host=pypi.org --trusted-host=files.pythonhosted.org --user&lt;/span&gt;&lt;br style=&quot;-webkit-font-smoothing: antialiased; background-color: white; box-sizing: border-box; color: #252423; font-size: 14px;&quot; /&gt;&lt;span style=&quot;background-color: white; color: #252423; font-size: 14px;&quot;&gt;pip install ansible[azure] --trusted-host=pypi.python.org --trusted-host=pypi.org --trusted-host=files.pythonhosted.org --user&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
and cross your fingers, it worked for me.&lt;br /&gt;
And now the last tips to make you an happy hybrid environment developer.&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Ansible complains you&#39;re reading the config from from a world-writable current working directory? Go &lt;a href=&quot;https://docs.ansible.com/ansible/devel/reference_appendices/config.html#cfg-in-world-writable-dir&quot; target=&quot;_blank&quot;&gt;there&lt;/a&gt;&amp;nbsp;and follow the instructions you find &lt;a href=&quot;https://blogs.msdn.microsoft.com/commandline/2018/01/12/chmod-chown-wsl-improvements/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;&amp;nbsp;to properly mount Windows disk.&lt;/li&gt;
&lt;li&gt;You edit files in your WSL home directory from Windows and you loose ownership, permissions, etc ?&lt;br /&gt;Go &lt;a href=&quot;https://blogs.msdn.microsoft.com/commandline/2018/01/12/chmod-chown-wsl-improvements/&quot; target=&quot;_blank&quot;&gt;there&lt;/a&gt;&amp;nbsp;and &lt;a href=&quot;https://blogs.msdn.microsoft.com/wsl/2016/06/15/wsl-file-system-support/&quot; target=&quot;_blank&quot;&gt;there&lt;/a&gt; (a bit technical).&lt;/li&gt;
&lt;li&gt;And finally enjoy &lt;a href=&quot;https://daverupert.com/2018/04/developing-on-windows-with-wsl-and-visual-studio-code/&quot; target=&quot;_blank&quot;&gt;coding with VS Code&lt;/a&gt;&lt;br /&gt;I had to specify &lt;i&gt;C:\WINDOWS\System32\wsl.exe &lt;/i&gt;as integrated shell path (bash.exe didn&#39;t work for me).&lt;/li&gt;
&lt;/ol&gt;
</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/3108119453229374798/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2018/12/ansible-azure-wsl-survival-guide-vs.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/3108119453229374798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/3108119453229374798'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2018/12/ansible-azure-wsl-survival-guide-vs.html' title='Ansible, Azure &amp; WSL survival guide (VS Code bonus track)'/><author><name>Unknown</name><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-8324889730441663172.post-1891794947621224048</id><published>2018-04-08T17:55:00.000+02:00</published><updated>2018-04-09T08:38:26.153+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".NET Core"/><category scheme="http://www.blogger.com/atom/ns#" term="cross platform"/><category scheme="http://www.blogger.com/atom/ns#" term="jolie"/><category scheme="http://www.blogger.com/atom/ns#" term="microservices"/><category scheme="http://www.blogger.com/atom/ns#" term="tinygrammar"/><title type='text'>Faa(m)s - Fuffa as a microservice [seconda parte]</title><content type='html'>Dopo aver esplorato in maniera pressoché esaustiva nel &lt;a href=&quot;http://mmontesi.blogspot.it/2018/03/faas-fuffa-as-service-prima-parte.html&quot; target=&quot;_blank&quot;&gt;post precedente&lt;/a&gt; la potenza del Serverless Cloud Computing, in questa seconda puntata ho pensato di orientarmi verso altre 2 tematiche-totem dell&#39;informatica contemporanea: la cross-platformitidune e l&#39;architettura a microservizi.&lt;br /&gt;
Qualunque progetto che ambisca ad essere al passo con i tempi non può prescindere da queste buzzwords!&lt;br /&gt;
In realtà il punto &lt;i&gt;cross-platform&lt;/i&gt; era già stato smarcato mentre preparavo il materiale per il primo post: grazie all&#39;avvento di &lt;a href=&quot;https://docs.microsoft.com/it-it/dotnet/core/&quot; target=&quot;_blank&quot;&gt;.NET Core&lt;/a&gt; è stata M$ stessa a risolvere la questione alla radice.&lt;br /&gt;
L&#39;unico problema era portare la libreria TinyGrammar da .NET Framework a .NET Core (anzi a &lt;a href=&quot;https://docs.microsoft.com/it-it/dotnet/standard/net-standard&quot; target=&quot;_blank&quot;&gt;.NET Standard&lt;/a&gt; per essere precisi), per fortuna la cosa si è rivelata molto semplice seguendo &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/core/porting/index&quot; target=&quot;_blank&quot;&gt;questa guida&lt;/a&gt;.&lt;br /&gt;
Libreria e unit test non hanno praticamente richiesto nessuna modifica, la console app l&#39;ho dovuta riscrivere, nel senso che ho dovuto fare copia e incolla dentro il progetto vuoto di VS2017:&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/AVvXsEid_l2NH_tJQ7O5Oc0EFpXSSCJIJFgp2UXKpdbHVVzjb0Kk3NZJ_csTEliOQV19_k4g04bmDUuQ4AqK3NTAkny71Q2P5yiDvOu8lan4rbgh4Ud0Zx3VHHMJhyEaXlQyO8X3XZPlcCgtOzU/s1600/new_console_app.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;157&quot; data-original-width=&quot;690&quot; height=&quot;90&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid_l2NH_tJQ7O5Oc0EFpXSSCJIJFgp2UXKpdbHVVzjb0Kk3NZJ_csTEliOQV19_k4g04bmDUuQ4AqK3NTAkny71Q2P5yiDvOu8lan4rbgh4Ud0Zx3VHHMJhyEaXlQyO8X3XZPlcCgtOzU/s400/new_console_app.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
A breve pubblicherò su GitHub il progetto completo, appena gli avrò dato una sistemata, giusto quel tanto che basta per non essere citato nel gruppo Facebook &quot;I peggiori programmatori di merda&quot;.&lt;br /&gt;
Avendo quindi agevolmente fatto il porting su Linux/Mac non restava che imboccare con tracotanza la strada verso una modernissima architettura a microservizi, stuzzicato dalla critica del mio &lt;a href=&quot;https://www.linkedin.com/in/fmontesi/&quot; target=&quot;_blank&quot;&gt;fratellino professore&lt;/a&gt;: &quot;Divertente, ma manca una versione international, almeno in inglese...&quot;&lt;br /&gt;
Come dargli torto!&lt;br /&gt;
A quel punto ho deciso di stare sulle spalle dei giganti (&lt;a href=&quot;https://en.wikipedia.org/wiki/Standing_on_the_shoulders_of_giants&quot; target=&quot;_blank&quot;&gt;spiegone&lt;/a&gt;):&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;usare il servizio di traduzione di Google&lt;/li&gt;
&lt;li&gt;usare il linguaggio nativamente orientato ai servizi, &lt;a href=&quot;http://www.jolie-lang.org/&quot; target=&quot;_blank&quot;&gt;Jolie&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
Per fortuna &lt;a href=&quot;https://ctrlq.org/code/19909-google-translate-api&quot; target=&quot;_blank&quot;&gt;qualcuno&lt;/a&gt; aveva già trovato il modo di utilizzare le API di Google Translate senza passare per il servizio business, va bene la modernità, ma meglio se aggratis.&lt;/div&gt;
&lt;div&gt;
Seguendo l&#39;approccio &lt;i&gt;&lt;a href=&quot;https://martinfowler.com/bliki/MonolithFirst.html&quot; target=&quot;_blank&quot;&gt;monolith first&lt;/a&gt; &lt;/i&gt;ben descritto da Fabrizio &lt;a href=&quot;http://fmontesi.github.io/2015/06/09/non-distributed-microservices.html&quot; target=&quot;_blank&quot;&gt;in salsa Jolie&lt;/a&gt;, ho scritto una manciata di righe (scopiazzate da &lt;a href=&quot;http://fmontesi.github.io/2017/12/01/jolie-duckduckgo.html&quot; target=&quot;_blank&quot;&gt;qua&lt;/a&gt;) per redirigere l&#39;output di TinyGrammar al servizio di traduzione:&lt;/div&gt;
&lt;script src=&quot;https://gist.github.com/mmontesi/848ed97460ff667eaee7bfd050ab9d53.js&quot;&gt;&lt;/script&gt;

&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Se la sintassi di Jolie vi risulta poco familiare, scaricatelo e &lt;a href=&quot;https://docs.jolie-lang.org/&quot; target=&quot;_blank&quot;&gt;studiatelo&lt;/a&gt;, in un paio d&#39;ore sarete dei maestri&amp;nbsp;:-P&lt;br /&gt;
Questo incoraggiante esempio di &lt;a href=&quot;https://en.wikipedia.org/wiki/Software_prototyping&quot; target=&quot;_blank&quot;&gt;fast software prototyping&lt;/a&gt;&amp;nbsp;mi ha portato al secondo step, ovvero la realizzazione di un elegante microservizio HTTP che trovate &lt;a href=&quot;https://github.com/mmontesi/TinyGrammar-Jolie-Wrapper&quot; target=&quot;_blank&quot;&gt;qua&lt;/a&gt;.&lt;br /&gt;
Nessun container, nessun host, just works!&lt;br /&gt;
Per chi obiettasse che non c&#39;è la benché minima traccia di fault handling rispondo che si tratta di&amp;nbsp;throwaway prototyping :-P&lt;br /&gt;
E per sfregio ritorno un vetusto XML che solo a vederlo si sente puzza di legacy.&lt;br /&gt;
Ovviamente per il corretto funzionamento avrete bisogno di &lt;a href=&quot;http://www.jolie-lang.org/downloads.html&quot; target=&quot;_blank&quot;&gt;Jolie&lt;/a&gt;&amp;nbsp;e di &lt;a href=&quot;https://www.microsoft.com/net/download/windows&quot; target=&quot;_blank&quot;&gt;.NET Core&lt;/a&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/AVvXsEhy5rCrdiMD2Ftu9E7w3yUO7b0BfO3x5n6Kf8sKS4JIyRraVztVIR4t2JVJZI8kyGzr039cNULTMrjxAfjMfzfELaQyowK_wdVF5kTYdy_reTac5aSTNtXiKssBavT94FyFw6hdzenQ7go/s1600/Screenshot_Faas_2.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;243&quot; data-original-width=&quot;935&quot; height=&quot;102&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy5rCrdiMD2Ftu9E7w3yUO7b0BfO3x5n6Kf8sKS4JIyRraVztVIR4t2JVJZI8kyGzr039cNULTMrjxAfjMfzfELaQyowK_wdVF5kTYdy_reTac5aSTNtXiKssBavT94FyFw6hdzenQ7go/s400/Screenshot_Faas_2.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/1891794947621224048/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2018/04/faams-fuffa-as-microservice-seconda.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/1891794947621224048'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/1891794947621224048'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2018/04/faams-fuffa-as-microservice-seconda.html' title='Faa(m)s - Fuffa as a microservice [seconda parte]'/><author><name>Unknown</name><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/AVvXsEid_l2NH_tJQ7O5Oc0EFpXSSCJIJFgp2UXKpdbHVVzjb0Kk3NZJ_csTEliOQV19_k4g04bmDUuQ4AqK3NTAkny71Q2P5yiDvOu8lan4rbgh4Ud0Zx3VHHMJhyEaXlQyO8X3XZPlcCgtOzU/s72-c/new_console_app.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8324889730441663172.post-3057079969290682727</id><published>2018-03-25T18:10:00.000+02:00</published><updated>2018-03-25T18:22:23.276+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Azure"/><category scheme="http://www.blogger.com/atom/ns#" term="Azure Functions"/><category scheme="http://www.blogger.com/atom/ns#" term="c#"/><category scheme="http://www.blogger.com/atom/ns#" term="csharp"/><category scheme="http://www.blogger.com/atom/ns#" term="micro services"/><category scheme="http://www.blogger.com/atom/ns#" term="mobile"/><category scheme="http://www.blogger.com/atom/ns#" term="Office 365"/><category scheme="http://www.blogger.com/atom/ns#" term="serverless"/><category scheme="http://www.blogger.com/atom/ns#" term="tinygrammar"/><title type='text'>FaaS - Fuffa as a Service [Prima parte]</title><content type='html'>Qualche tempo fa qualcuno mi ha segnalato questa pagina:&lt;br /&gt;
&lt;a href=&quot;http://www.massimobarbieri.it/it/Tecnichese/&quot;&gt;http://www.massimobarbieri.it/it/Tecnichese/&lt;/a&gt;&lt;br /&gt;
In pratica si tratta di un sofisticato generatore di supercazzole in gergo tecnico, basato su solide &lt;a href=&quot;https://en.wikipedia.org/wiki/Generative_grammar&quot; target=&quot;_blank&quot;&gt;basi teoriche&lt;/a&gt;&amp;nbsp;(guardate anche l&#39;altro &lt;a href=&quot;http://www.massimobarbieri.it/en/SonicPiGenerator/&quot; target=&quot;_blank&quot;&gt;esempio&lt;/a&gt; di utilizzo di TinyGrammar, ne vale la pena).&lt;br /&gt;
Dopo aver fatto diversi click sul pulsante &quot;Genera altro tecnichese&quot; ho constatato (con le lacrime agli occhi per le risate) che il tool è robusto ed affidabile :-P&lt;br /&gt;
Il contagio si è rapidamente sparso tra i colleghi, scatenando la facile ironia di chi faceva notare quanto le frasi generate fossero praticamente indistinguibili da alcuni discorsi sentiti durante serissime riunioni di lavoro.&lt;br /&gt;
A questo punto, siccome non so se sono più nerd o più cazzaro, mi sono accorto che Barbieri (grazie Massimo) ha pubblicato su GitHub la sua &lt;a href=&quot;https://github.com/barmassimo/Tiny-Grammar&quot; target=&quot;_blank&quot;&gt;libreria&lt;/a&gt;&amp;nbsp;con licenza GPL e che sarebbe stato facile modificare il dizionario della grammatica per renderlo ancora più affine al mio ambito aziendale (nomi di prodotti, team di sviluppo, tecnologie specifiche, etc).&lt;br /&gt;
In pochi minuti clono il progetto, compilo la console app e modifico il file di esempio della grammatica; il risultato è irresistibile: serpeggia anche l&#39;idea di sostituire analisti e project manager con questo strumento economico e funzionale.&lt;br /&gt;
Tutto si sarebbe esaurito così se non fosse che negli ultimi mesi mi sto interessando di cloud computing; più di una volta, essendo un newbie, i discorsi degli esperti e la documentazione tecnica consultata mi sono sembrati delle incomprensibili supercazzole.&lt;br /&gt;
La mia sottile e perfida rivalsa sarebbe stata questa: avrei implementato un &lt;i&gt;generatore di fuffa full cloud, stateless, serverless, intrinsecamente scalabile e cross platform, fruibile da web e da mobile app tramite una API REST&lt;/i&gt;.&lt;br /&gt;
Qua si serve solo migliore tecnologia mio pappa diceva (&lt;a href=&quot;https://www.youtube.com/watch?v=FE7bLg0XAYI&quot; target=&quot;_blank&quot;&gt;questa &lt;/a&gt;è un po&#39; di nicchia, ma sta uscendo &lt;a href=&quot;https://www.youtube.com/watch?v=iE9a9wmZ_mM&quot; target=&quot;_blank&quot;&gt;Ready Player One&lt;/a&gt; e citare gli anni &#39;80 va di moda).&lt;br /&gt;
Nella prima puntata (si, perché ho altre idee in serbo) vediamo cosa si può fare su Azure e più in generale con l&#39;ecosistema Micro$oft.&lt;br /&gt;
Per cominciare al giorno d&#39;oggi NON puoi considerarti un moderno developer se non scrivi microservizi, preferibilmente su architettura &lt;a href=&quot;https://en.wikipedia.org/wiki/Serverless_computing&quot; target=&quot;_blank&quot;&gt;serverless&lt;/a&gt;,&amp;nbsp;su Azure mamma M$ ci mette a disposizione &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/azure-functions/functions-overview&quot; target=&quot;_blank&quot;&gt;Azure Functions&lt;/a&gt;.&lt;br /&gt;
Dopo aver dato un&#39;occhiata alle prime pagine della doc mi sembra che si possa creare in modo semplice una function che risponda a chiamate HTTP, bene, ci siamo.&lt;br /&gt;
Con una googlata trovo anche questo &lt;a href=&quot;https://blogs.msdn.microsoft.com/benjaminperkins/2017/04/13/how-to-add-assembly-references-to-an-azure-function-app/&quot; target=&quot;_blank&quot;&gt;articolo&lt;/a&gt; che spiega passo passo come referenziare un assembly nella mia function: ottimo! Così riciclo la libreria TinyGrammar &lt;i&gt;as is&lt;/i&gt;&amp;nbsp; per ridurre notevolmente il &lt;i&gt;time to market&lt;/i&gt; (notate la sapiente commistione di nerdese con alcune espressioni che possano compiacere l&#39;eventuale project manager fuffoso).&lt;br /&gt;
A questo punto per fare il figo dovrei mettere i file di testo delle grammatiche su uno storage account e leggerlo dalla function, ma io sono pigro e quindi ficco dentro tutto il testo in una bella stringa :-P&lt;br /&gt;
Risultato &lt;b&gt;funzionante &lt;/b&gt;(da notare la finezza che ritorno HTTP 200 anche se va in errore):&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/mmontesi/bb0ab46a0ec8527ab00c4afd969fe4cc.js&quot;&gt;&lt;/script&gt;

&lt;br /&gt;
Sono &lt;i&gt;serverless&lt;/i&gt;, &lt;i&gt;stateless&lt;/i&gt; e &lt;i&gt;useless&lt;/i&gt;, mi sento sulla cresta dell&#39;onda.&lt;br /&gt;
Arrivati qua ci si potrebbe accontentare di puntare all&#39;URL della nostra function per ottenere fuffa randomica sul nostro browser, ma come si fa a presentare un progetto senza UI? La &lt;i&gt;user experience&lt;/i&gt; non è per nulla soddisfacente e non si dimostra di essere &lt;i&gt;full stack&lt;/i&gt;!&lt;br /&gt;
Il primo esperimento è stato creare un &lt;a href=&quot;https://docs.microsoft.com/it-it/azure/architecture/patterns/static-content-hosting&quot; target=&quot;_blank&quot;&gt;sito statico sempre hostato su uno storage account di Azure&lt;/a&gt;, con una &lt;a href=&quot;https://developer.mozilla.org/it/docs/Web/API/Fetch_API/Using_Fetch&quot; target=&quot;_blank&quot;&gt;fetch()&lt;/a&gt;&amp;nbsp;che richiama il nostro servizio il gioco è fatto e dimostro di avere notevoli competenze Javascript :-P&lt;br /&gt;
Ma se al giorno d&#39;oggi non fornisci un&#39;app mobile che sviluppatore sei? Probabilmente il mercato dell&#39;&lt;i&gt;industry 4.0&lt;/i&gt; non ti si fila nemmeno.&lt;br /&gt;
Per fortuna ho anche un&#39;account di Office 365 e avevo giocherellato con &lt;a href=&quot;https://emea.flow.microsoft.com/en-us/&quot; target=&quot;_blank&quot;&gt;Microsoft Flow&lt;/a&gt;, che il client mobile già ce l&#39;ha.&lt;br /&gt;
L&#39;adozione di Flow non si deve certo alla mia innata pigrizia (nooo!) ma alla pervicace intenzione di non indulgere in dannosi &lt;a href=&quot;https://en.wikipedia.org/wiki/Anti-pattern&quot; target=&quot;_blank&quot;&gt;anti-pattern&lt;/a&gt;, come il famigerato &lt;a href=&quot;https://en.wikipedia.org/wiki/Not_invented_here#In_computing&quot; target=&quot;_blank&quot;&gt;NIH&lt;/a&gt;.&lt;br /&gt;
Vabbè, insomma questo era pronto e con 4 click è venuto fuori questo gioiellino: Fuffa as a Service &lt;i&gt;on demand&lt;/i&gt; con &lt;i&gt;notifiche push&lt;/i&gt; su app mobile (vedi sotto)!&lt;br /&gt;
Nei prossimi episodi (in ordine sparso): conversione in .NET Standard e console app .NET Core per girare su Linux, porting su AWS, verie ed eventuali.&lt;br /&gt;
See you.&lt;br /&gt;
&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/AVvXsEj4MkT7-iU5h0CHmXYFPVx-7YRl0iNXZIa_ZD-DjsFZBuf2v1z4fVqminTNYHpIcR0e2Ss-l4on6IdnXiTKxdzYEFqYIwgEWkoiMzycyqK6g063cdAVpJ-APmrqBoKlwhrCcUAL73LaIGM/s1600/FaaS_Screenshot2.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1316&quot; data-original-width=&quot;1080&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4MkT7-iU5h0CHmXYFPVx-7YRl0iNXZIa_ZD-DjsFZBuf2v1z4fVqminTNYHpIcR0e2Ss-l4on6IdnXiTKxdzYEFqYIwgEWkoiMzycyqK6g063cdAVpJ-APmrqBoKlwhrCcUAL73LaIGM/s320/FaaS_Screenshot2.jpg&quot; width=&quot;262&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvFgfJKmmihF0cEvVPg_qCF3qOAJ3FZz4PaKz4PpAyKTTbEQbumMB3vNz3kb3xz4VA3i5FRL5yLqqwwE_crPV1JdLNn8BAbLH4y8YH6U2vcqp98JQLs9NmndRHn9l-K9SZvSWpezLIqd0/s1600/FaaS_Screenshot.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1600&quot; data-original-width=&quot;900&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvFgfJKmmihF0cEvVPg_qCF3qOAJ3FZz4PaKz4PpAyKTTbEQbumMB3vNz3kb3xz4VA3i5FRL5yLqqwwE_crPV1JdLNn8BAbLH4y8YH6U2vcqp98JQLs9NmndRHn9l-K9SZvSWpezLIqd0/s320/FaaS_Screenshot.jpg&quot; width=&quot;180&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/3057079969290682727/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2018/03/faas-fuffa-as-service-prima-parte.html#comment-form' title='2 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/3057079969290682727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/3057079969290682727'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2018/03/faas-fuffa-as-service-prima-parte.html' title='FaaS - Fuffa as a Service [Prima parte]'/><author><name>Unknown</name><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/AVvXsEj4MkT7-iU5h0CHmXYFPVx-7YRl0iNXZIa_ZD-DjsFZBuf2v1z4fVqminTNYHpIcR0e2Ss-l4on6IdnXiTKxdzYEFqYIwgEWkoiMzycyqK6g063cdAVpJ-APmrqBoKlwhrCcUAL73LaIGM/s72-c/FaaS_Screenshot2.jpg" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8324889730441663172.post-2051939605074756420</id><published>2012-09-16T13:15:00.004+02:00</published><updated>2012-09-16T13:22:32.642+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="jelly bean"/><category scheme="http://www.blogger.com/atom/ns#" term="toshiba folio"/><title type='text'>Jelly Bean on Toshiba Folio</title><content type='html'>&lt;div&gt;
&lt;div dir=&quot;ltr&quot;&gt;
Only few weeks with ICS, it&#39;s time for Jelly Bean on my Folio!&lt;br /&gt;
I just followed the instructions on this &lt;a href=&quot;http://forum.xda-developers.com/showthread.php?t=1864774&quot; target=&quot;_blank&quot;&gt;post &lt;/a&gt;(only cache wipe required).&lt;br /&gt;
This ROM is CyanogenMod 10 based and works really &lt;u&gt;fine&lt;/u&gt;.&lt;/div&gt;
&lt;div dir=&quot;ltr&quot;&gt;
By the way I did the entire procedure within the tablet, no PC need, just download, reboot and flash!&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div dir=&quot;ltr&quot;&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/AVvXsEhzIXTr1sFEFeT8_Je4ps7Hpdr3OH2Wfg8f4DqfmNlKSCgTorfxr8Mysws7fm2xc4z8uxw3r4VKI-fI5MSGJQHWgqm7VgKUwgVOt2_xCWiOAY3FimrhfQ8EQ0LM0dTKYJ3OA-9ap2Iy7Ew/s1600/PicsArt_1347792909006.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;232&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzIXTr1sFEFeT8_Je4ps7Hpdr3OH2Wfg8f4DqfmNlKSCgTorfxr8Mysws7fm2xc4z8uxw3r4VKI-fI5MSGJQHWgqm7VgKUwgVOt2_xCWiOAY3FimrhfQ8EQ0LM0dTKYJ3OA-9ap2Iy7Ew/s400/PicsArt_1347792909006.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/2051939605074756420/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2012/09/jelly-bean-on-toshiba-folio.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/2051939605074756420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/2051939605074756420'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2012/09/jelly-bean-on-toshiba-folio.html' title='Jelly Bean on Toshiba Folio'/><author><name>Unknown</name><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/AVvXsEhzIXTr1sFEFeT8_Je4ps7Hpdr3OH2Wfg8f4DqfmNlKSCgTorfxr8Mysws7fm2xc4z8uxw3r4VKI-fI5MSGJQHWgqm7VgKUwgVOt2_xCWiOAY3FimrhfQ8EQ0LM0dTKYJ3OA-9ap2Iy7Ew/s72-c/PicsArt_1347792909006.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8324889730441663172.post-7584677868565098941</id><published>2012-08-20T11:16:00.000+02:00</published><updated>2012-08-20T11:16:59.598+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="folio"/><category scheme="http://www.blogger.com/atom/ns#" term="ice cream sandwich"/><category scheme="http://www.blogger.com/atom/ns#" term="tablet"/><title type='text'>Yet another Folio update (ICS 4.0.4)</title><content type='html'>Nell&#39;&lt;a href=&quot;http://mmontesi.blogspot.it/2012/06/its-time-for-ice-cream-sandwich.html&quot; target=&quot;_blank&quot;&gt;ultimo articolo&lt;/a&gt; riguardante il mio povero Toshiba Folio avevo accennato al fatto che, per avere a disposizione il bluetooth, non avevo utilizzato l&#39;ultima versione disponibile della ROM di Ice Cream Sandwich.&lt;br /&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;div&gt;
Purtroppo quella versione (alpha 4) si è rivelata piuttosto instabile e quindi, come suggerivo nell&#39;articolo, sono passato alla alpha 5.&lt;/div&gt;
&lt;div&gt;
Basta semplicemente flashare (per sicurezza anche le Gapps) e fila tutto liscio: ha mantenuto le applicazioni, le impostazioni, la cache, tutto.&lt;/div&gt;
&lt;div&gt;
Purtroppo, per chi ne ha bisogno, niente bluetooth :(&lt;/div&gt;
&lt;div&gt;
Attendo con ansia Jelly Bean.&lt;/div&gt;
&lt;div&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;http://4.bp.blogspot.com/-SGDdTeWcQoQ/UDEZZWGNRLI/AAAAAAAAA0o/NK83_NzzSlA/s1600/12+-+1&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;231&quot; src=&quot;http://4.bp.blogspot.com/-SGDdTeWcQoQ/UDEZZWGNRLI/AAAAAAAAA0o/NK83_NzzSlA/s400/12+-+1&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/7584677868565098941/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2012/08/yet-another-folio-update-ics-404.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/7584677868565098941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/7584677868565098941'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2012/08/yet-another-folio-update-ics-404.html' title='Yet another Folio update (ICS 4.0.4)'/><author><name>Unknown</name><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="http://4.bp.blogspot.com/-SGDdTeWcQoQ/UDEZZWGNRLI/AAAAAAAAA0o/NK83_NzzSlA/s72-c/12+-+1" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8324889730441663172.post-5409651076522323266</id><published>2012-07-27T18:16:00.001+02:00</published><updated>2012-07-30T10:44:10.523+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="autobahn"/><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="opensuse"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="websockets"/><title type='text'>Autobahn part 1: installing on Opensuse</title><content type='html'>As every web developer should do, I&#39;m exploring the new wonderful capabilities of modern browsers.&lt;br /&gt;
On of the most powerful is &lt;a href=&quot;http://en.wikipedia.org/wiki/WebSocket&quot; target=&quot;_blank&quot;&gt;websocket technology&lt;/a&gt;:&lt;br /&gt;
&lt;i&gt;WebSocket is a web technology providing for bi-directional, full-duplex communications channels over a single TCP connection.&lt;/i&gt;&lt;br /&gt;
Nice, isn&#39;t it?&lt;br /&gt;
By the way I am learning Python and first examples are very boring, so I decided to try something really interesting: &lt;a href=&quot;http://autobahn.ws/&quot; target=&quot;_blank&quot;&gt;Autobahn&lt;/a&gt;.&lt;br /&gt;
From official site:&amp;nbsp;&lt;i&gt;Autobahn provides Open-Source client and server implementations of &lt;a href=&quot;http://tools.ietf.org/html/rfc6455&quot;&gt;WebSocket&lt;/a&gt; and &lt;a href=&quot;http://wamp.ws/&quot;&gt;WAMP&lt;/a&gt;.&lt;/i&gt;&lt;br /&gt;
I thought this could be a good start point to improve knowledge of Python and websockets at the same time.&lt;br /&gt;
So I pointed to &lt;a href=&quot;http://autobahn.ws/python/getstarted&quot;&gt;http://autobahn.ws/python/getstarted&lt;/a&gt; and followed the instructions, but on my OpenSuse 12.1 I couldn&#39;t get Autobahn installed.&lt;br /&gt;
In this first post you can find how to get it running.&lt;br /&gt;
The two suggested methods (from package and from source) have the same problem, so I&#39;ll use the &lt;i&gt;package method&lt;/i&gt;, because there are less instructions to write and, you know, I&#39;m lazy.&lt;br /&gt;
You should &amp;nbsp;use the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;easy_install autobahn&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
but this produces errors about missing headers during compilation.&lt;br /&gt;
With a little help from Google I found how to get rid of these errors.&lt;br /&gt;
You have to install Python&#39;s development package (and GCC, if is not already installed):&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;zypper in python-devel&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;zypper in gcc&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Now you can go on to the first example, which is perfectly working.&lt;br /&gt;
If you copy and paste the code into your editor you just have to modify line 29 in myclient.html&amp;nbsp;removing the whitespace in &amp;lt;/script&amp;gt; tag.&lt;br /&gt;
I&#39;m reading the tutorials and I&#39;ll be back with something useful soon (hope so).</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/5409651076522323266/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2012/07/autobahn-part-1-installing-on-opensuse.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/5409651076522323266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/5409651076522323266'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2012/07/autobahn-part-1-installing-on-opensuse.html' title='Autobahn part 1: installing on Opensuse'/><author><name>Unknown</name><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-8324889730441663172.post-5458934149155446069</id><published>2012-07-16T15:02:00.000+02:00</published><updated>2012-07-16T15:13:19.841+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="programming languages"/><category scheme="http://www.blogger.com/atom/ns#" term="soa"/><category scheme="http://www.blogger.com/atom/ns#" term="web services"/><title type='text'>Chor, a brand new language</title><content type='html'>Yes, yet another programming language: &lt;a href=&quot;http://www.chor-lang.org/&quot; target=&quot;_blank&quot;&gt;Chor&lt;/a&gt;&lt;br /&gt;
As the name suggests Chor is a new programming language for communicating systems, based on choreographies ( I&#39;m not talking about dance of course :P ).&lt;br /&gt;
There are many reasons to give it a chance.&lt;br /&gt;
First of all&amp;nbsp;is a creature of my brother &lt;a href=&quot;http://www.itu.dk/people/fabr/&quot; target=&quot;_blank&quot;&gt;Fabrizio&lt;/a&gt;, then because it&#39;s very promising and has solid formal foundations.&lt;br /&gt;
It&#39;s still in alpha state but you can see it in action in this video:&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/TZ6-CiMseUc&quot; width=&quot;560&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Nice job Fabrizio!&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/5458934149155446069/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2012/07/chor-brand-new-language.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/5458934149155446069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/5458934149155446069'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2012/07/chor-brand-new-language.html' title='Chor, a brand new language'/><author><name>Unknown</name><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://img.youtube.com/vi/TZ6-CiMseUc/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8324889730441663172.post-1169388642644522503</id><published>2012-06-19T18:35:00.001+02:00</published><updated>2012-07-13T19:23:19.390+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="cyanogen"/><category scheme="http://www.blogger.com/atom/ns#" term="folio"/><category scheme="http://www.blogger.com/atom/ns#" term="ice cream sandwich"/><category scheme="http://www.blogger.com/atom/ns#" term="tablet"/><title type='text'>It&#39;s time for an Ice Cream Sandwich (on Toshiba Folio)</title><content type='html'>Visto il caldo torrido che sta facendo ho pensato bene di rinfrescare il vecchio Toshiba Folio con un buon biscotto gelato :-)&lt;br /&gt;
In un vecchio &lt;a href=&quot;http://mmontesi.blogspot.it/2011/12/gingerbread-android-23-su-toshiba-folio.html&quot; target=&quot;_blank&quot;&gt;post&lt;/a&gt;&amp;nbsp;avevo descritto sommariamente la procedura che aveva portato Android 2.3.7 sul mio tablet, ora sono passato alla versione 4.0.3 (Ice Cream Sandwich, appunto).&lt;br /&gt;
Se l&#39;altra volta ero stato stringato oggi lo sarò ancora di più: semplicemente scaricate ROM, Gapps e (soprattutto) la recovery di Nopy come descritto in &lt;a href=&quot;http://forum.xda-developers.com/showthread.php?t=1470823&quot; target=&quot;_blank&quot;&gt;questo post&lt;/a&gt;&amp;nbsp;e seguite scrupolosamente le istruzioni.&lt;br /&gt;
Io per avere il bluetooth ho usato la Alpha 4, se non vi interessa vi consiglio la Alpha 5, che dovrebbe aver risolto qualche piccolo bug.&lt;br /&gt;
In ogni caso si tratta di pre-release di Cyanogen 9, quindi bugs e instabilità potrebbero essere sempre in agguato.&lt;br /&gt;
Se questo non vi spaventa in meno di mezz&#39;ora ecco cosa vi aspetta:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&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/AVvXsEhDDC8HYrGM6kiEpNPp3WAeFmGiQUi81UB4Da8dj-oxafRvRWK_KcEjTAEa1EHnwyFs4GBOmQEgP2eEARjq_NRT_wO3RraQxH_T41B9KH1Vpy2-yVBHHB_c6dAsluoFmDUMJEm9_Mz9Qrw/s1600/image.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;233&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDDC8HYrGM6kiEpNPp3WAeFmGiQUi81UB4Da8dj-oxafRvRWK_KcEjTAEa1EHnwyFs4GBOmQEgP2eEARjq_NRT_wO3RraQxH_T41B9KH1Vpy2-yVBHHB_c6dAsluoFmDUMJEm9_Mz9Qrw/s400/image.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&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/AVvXsEi1JWmm6FNVFlW6fZRKdVF2rzCYxgPF7TvdaMAg4B2Be6MIKYsrvOHsDRwgKzbrLBSYGzcaYVM7JxFKNSdtGL4SkEVB6E20lTEHMjiI_6LbCO1F9aRuCOcIqvkZfzS6QJiBtwWOxa4J_xw/s1600/Screenshot_2012-06-19-18-16-02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;233&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1JWmm6FNVFlW6fZRKdVF2rzCYxgPF7TvdaMAg4B2Be6MIKYsrvOHsDRwgKzbrLBSYGzcaYVM7JxFKNSdtGL4SkEVB6E20lTEHMjiI_6LbCO1F9aRuCOcIqvkZfzS6QJiBtwWOxa4J_xw/s400/Screenshot_2012-06-19-18-16-02.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/1169388642644522503/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2012/06/its-time-for-ice-cream-sandwich.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/1169388642644522503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/1169388642644522503'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2012/06/its-time-for-ice-cream-sandwich.html' title='It&#39;s time for an Ice Cream Sandwich (on Toshiba Folio)'/><author><name>Unknown</name><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/AVvXsEhDDC8HYrGM6kiEpNPp3WAeFmGiQUi81UB4Da8dj-oxafRvRWK_KcEjTAEa1EHnwyFs4GBOmQEgP2eEARjq_NRT_wO3RraQxH_T41B9KH1Vpy2-yVBHHB_c6dAsluoFmDUMJEm9_Mz9Qrw/s72-c/image.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8324889730441663172.post-2217680484225369242</id><published>2012-06-19T10:22:00.000+02:00</published><updated>2012-06-19T10:22:54.304+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="composer"/><category scheme="http://www.blogger.com/atom/ns#" term="dependency manager"/><category scheme="http://www.blogger.com/atom/ns#" term="html5"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="websockets"/><title type='text'>PHP &amp; Websockets</title><content type='html'>Il supporto offerto dai browser &quot;moderni&quot; alle funzionalità HTML5 sta favorendo il fiorire di un numero impressionante di progetti volti a rendere più immediato il loro utilizzo con i linguaggi classici dello sviluppo web.&lt;br /&gt;
Una tecnologia molto interessante è quella dei &lt;a href=&quot;http://www.websocket.org/&quot; target=&quot;_blank&quot;&gt;websockets&lt;/a&gt;, in parole povere si tratta di un canale di comunicazione bidirezionale che si instaura tra browser e server, &lt;a href=&quot;http://socketo.me/docs/&quot; target=&quot;_blank&quot;&gt;superando&lt;/a&gt; di fatto lo schema classico delle web apps (request-response).&lt;br /&gt;
Utilizzando principalmente PHP ho cercato cosa fosse stato realizzato in questo campo per il &lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/phpwebsocket/&quot; target=&quot;_blank&quot;&gt;PHP and WebSockets&lt;/a&gt;&lt;br /&gt;Sembra che non sia più sviluppato attivamente.&lt;/li&gt;
&lt;li&gt;&lt;span itemprop=&quot;description&quot;&gt;&lt;a href=&quot;http://code.google.com/p/phpws/&quot; target=&quot;_blank&quot;&gt;WebSocket Server and Client library for PHP&lt;/a&gt;&lt;br /&gt;Simile al precedente, non richiede altre librerie o componenti, progetto attivo.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://socketo.me/&quot; target=&quot;_blank&quot;&gt;Ratchet&lt;/a&gt;&lt;br /&gt;Sembra il più ricco di funzionalità, sfrutta alcuni componenti di Symfony.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
Spendo qualche parola in più su Ratchet perché mi ha fatto scoprire un altro tool interessante: &lt;a href=&quot;http://getcomposer.org/&quot; target=&quot;_blank&quot;&gt;composer&lt;/a&gt;, ovvero un dependency manager per PHP.&lt;/div&gt;
&lt;div&gt;
Pur essendo un progetto ancora giovane, Ratchet è molto ben strutturato e sfrutta diverse librerie, per cui gli sviluppatori hanno deciso di tagliare la testa al toro:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: white; color: #333333; font-family: &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 13px; line-height: 18px;&quot;&gt;The best (and currently only) way to install Ratchet is using&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://getcomposer.org/&quot; rel=&quot;external&quot; style=&quot;background-color: white; background-image: url(http://socketo.me/assets/img/link_external.png); background-position: 100% 50%; background-repeat: no-repeat no-repeat; color: #0088cc; font-family: &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 13px; line-height: 18px; padding-right: 13px; text-decoration: none;&quot;&gt;composer&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 13px; line-height: 18px;&quot;&gt;.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
L&#39;impatto non è stato semplice perché il classico approccio scarica/scompatta mi ha fuorviato e non riuscivo neanche ad eseguire gli esempi, che trovate &lt;a href=&quot;https://github.com/cboden/Ratchet-examples&quot; target=&quot;_blank&quot;&gt;qui&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
Questo perché non solo Ratchet stesso deve essere installato con composer, ma anche il progetto con gli esempi (bastava notare il file composer.json nella root, che contiene tutte le informazioni sulle dipendenze)!&lt;/div&gt;
&lt;div&gt;
Insomma alla fine bastava scaricare i sorgenti e digitare:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;color: #222222; font-family: monospace, monospace; font-size: 16px; line-height: 20px; white-space: pre-wrap;&quot;&gt;$ php composer.phar install&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
per trovarsi un sistema funzionante (ovviamente dovete avere l&#39;estensione &lt;a href=&quot;http://www.php.net/manual/en/book.phar.php&quot; target=&quot;_blank&quot;&gt;phar&lt;/a&gt; di PHP).&lt;/div&gt;
&lt;div&gt;
Spero sia uno spunto interessante.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/2217680484225369242/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2012/06/php-websockets.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/2217680484225369242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/2217680484225369242'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2012/06/php-websockets.html' title='PHP &amp; Websockets'/><author><name>Unknown</name><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-8324889730441663172.post-1381840823858169539</id><published>2012-06-14T16:48:00.001+02:00</published><updated>2012-06-14T16:48:34.773+02:00</updated><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="lightbox"/><title type='text'>Lightbox workaround per pagine non completamente caricate</title><content type='html'>Vi sarà capitato di usare &lt;a href=&quot;http://lokeshdhakar.com/projects/lightbox/&quot; target=&quot;_blank&quot;&gt;Lightbox&lt;/a&gt;&amp;nbsp;in una delle sue tante varianti o script simili per gestire lo zoom di immagini sui vostri siti.&lt;br /&gt;
Semplice, leggero, stilabile, tutto ok.&lt;br /&gt;
Purtroppo soffre di un piccolo problema, non lo chiamo bug perché la documentazione ufficiale recita:&lt;br /&gt;
&lt;span style=&quot;background-color: white; color: #777777; font-family: Verdana, Helvetica, sans-serif; font-size: 0.7em; font-weight: bold; line-height: 17px; text-align: left;&quot;&gt;It doesn&#39;t work if I click an image before the page has finished loading.&lt;/span&gt;&lt;br /&gt;
&lt;dd style=&quot;background-color: white; border-bottom-color: rgb(221, 221, 211); border-bottom-style: dotted; border-bottom-width: 1px; color: #555555; font-family: Verdana, Helvetica, sans-serif; font-size: 0.9em; line-height: 17px; margin: 0px 0px 0.8em; padding: 0px 0px 0.7em; text-align: left;&quot;&gt;This is not a bug, but a side-effect of unobtrusive scripts of this kind.&lt;/dd&gt;&lt;div&gt;
Nella stragrande maggioranza dei casi questo non è un problema, ma a volte può essere fastidioso, soprattutto se la pagina per qualche motivo ha tempi di caricamento elevati.&lt;/div&gt;
&lt;div&gt;
Il mio caso è questo:&lt;/div&gt;
&lt;div&gt;
&lt;a href=&quot;http://www.newgroove.it/articolo.php?item=1530&amp;amp;q=ROLAND-SPD-S&quot;&gt;http://www.newgroove.it/articolo.php?item=1530&amp;amp;q=ROLAND-SPD-S&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
In fondo alla scheda prodotto viene caricata la thumbnail del sito del produttore, generata on the fly da &amp;nbsp;un servizio web.&lt;/div&gt;
&lt;div&gt;
Se l&#39;immagine non risulta nella cache del sistema deve essere generata (visitando la pagina web relativa) e l&#39;operazione può richiedere qualche secondo.&lt;/div&gt;
&lt;div&gt;
Ovviamente nel frattempo Lightbox non funziona e se si clicca per eseguire lo zoom della foto del prodotto si ottiene il comportamento standard del browser per un link ad una immagine.&lt;/div&gt;
&lt;div&gt;
Dovrei usare l&#39;imperfetto perché adesso il funzionamento è quello corretto, ho trovato un workaround, solo che non ho capito fino in fondo PERCHE&#39; funziona :P&lt;/div&gt;
&lt;div&gt;
In realtà una soluzione &quot;sensata&quot; poteva essere questa: eseguire il caricamento della thumbnail tramite uno script PHP richiamato via Ajax, in questo modo il DOM sarebbe stato disponibile al completo anche prima del caricamento dell&#39;immagine.&lt;/div&gt;
&lt;div&gt;
Invece ho provato una soluzione Javascript only, sfruttando jQuery.&lt;/div&gt;
&lt;div&gt;
Questo è il codice finale:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$(document).ready(function() {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; initLightbox();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; setTimeout(&quot;ShowThumb();&quot;,500);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;})&lt;/span&gt;;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Il metodo .ready() risolve parte del problema, come spiegato nella &lt;a href=&quot;http://api.jquery.com/ready/&quot; target=&quot;_blank&quot;&gt;doc ufficiale&lt;/a&gt;:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: #fafafa; color: #222222; font-family: &#39;Trebuchet MS&#39;, Verdana, Helvetica, Arial, sans-serif; font-size: 11px; line-height: 19px;&quot;&gt;While JavaScript provides the&amp;nbsp;&lt;/span&gt;&lt;code style=&quot;background-color: #eeeeee; border: 0px; color: #222222; font-size: 13px; line-height: 19px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;load&lt;/code&gt;&lt;span style=&quot;background-color: #fafafa; color: #222222; font-family: &#39;Trebuchet MS&#39;, Verdana, Helvetica, Arial, sans-serif; font-size: 11px; line-height: 19px;&quot;&gt;&amp;nbsp;event for executing code when a page is rendered, this event does not get triggered until all assets such as images have been completely received.&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;color: #222222; font-family: &#39;Trebuchet MS&#39;, Verdana, Helvetica, Arial, sans-serif;&quot;&gt;&lt;span style=&quot;line-height: 19px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #222222; font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;span style=&quot;line-height: 19px;&quot;&gt;La funzione initLightbox() forza l&#39;inizializzazione di Lightbox; poi non resta che richiamare la funzione ShowThumb(), che molto semplicemente setta l&#39;attributo src dell&#39;immagine che deve contenere la thumbnail.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #222222; font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;span style=&quot;line-height: 19px;&quot;&gt;Peccato che senza aggiungere il piccolo delay introdotto con setTimeout la cosa non funzionava; ho dato un&#39;occhiata a cosa esegue initLightbox e ad &quot;intuito&quot; ho pensato che bastasse dare tempo all&#39;interprete Javascript di terminare il ciclo sui tag &amp;lt;a&amp;gt; prima che l&#39;altra funzione ne modificasse il contenuto.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #222222; font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;span style=&quot;line-height: 19px;&quot;&gt;Ogni buon programmatore non dovrebbe mai accontentarsi di una spiegazione del genere, malgrado la breve euforia per aver accontentato in qualche modo il cliente :D&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #222222; font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;span style=&quot;line-height: 19px;&quot;&gt;Io continuo a pensarci, se qualche guru JS mi illumina gli sarò grato!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;color: #222222; font-family: Arial, Helvetica, sans-serif;&quot;&gt;&lt;span style=&quot;line-height: 19px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/1381840823858169539/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2012/06/lightbox-workaround-per-pagine-non.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/1381840823858169539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/1381840823858169539'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2012/06/lightbox-workaround-per-pagine-non.html' title='Lightbox workaround per pagine non completamente caricate'/><author><name>Unknown</name><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-8324889730441663172.post-6641240467084883473</id><published>2012-06-12T11:45:00.000+02:00</published><updated>2012-06-12T11:46:39.966+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ajax"/><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="nodejs"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="web services"/><title type='text'>NodeJS e PHP, just for fun</title><content type='html'>In questi giorni sto cercando di approfondire la conoscenza di &lt;a href=&quot;http://nodejs.org/&quot; target=&quot;_blank&quot;&gt;Node.js&lt;/a&gt;&amp;nbsp;ed ho iniziato con questo ottimo &lt;a href=&quot;http://www.nodebeginner.org/&quot; target=&quot;_blank&quot;&gt;tutorial&lt;/a&gt;, veramente ben fatto.&lt;br /&gt;
Ovviamente, da bravo smanettone, dopo le prime N pagine mi sembrava di aver preso possesso dei concetti base e che fosse arrivato il momento di passare a qualche esempio &quot;utile&quot;.&lt;br /&gt;
Ovviamente sono iniziate le grane...&lt;br /&gt;
Poiché sviluppo principalmente in PHP la mia idea era questa: realizzare con Node.js una sorta di dispatcher di eventi, per sostituire il long polling Ajax, lasciando la logica associata agli eventi negli script PHP.&lt;br /&gt;
Ho cominciato a cercare articoli e tutorial in rete e qualcosa ho combinato :)&lt;br /&gt;
Punto di partenza &lt;a href=&quot;http://www.gianlucaguarini.com/blog/?p=272&quot; target=&quot;_blank&quot;&gt;questo&lt;/a&gt; ottimo spunto di Gianluca Guarini, che implementa un push notification server con Node.js e &lt;a href=&quot;http://socket.io/&quot; target=&quot;_blank&quot;&gt;socket.io&lt;/a&gt;; in pratica un semplice script Node.js gestisce la comunicazione con il client tramite websocket.&lt;br /&gt;
Partendo da questo schema ho aggiunto la possibilità di richiamare un servizio scritto in PHP, in risposta ad un evento intercettato da Node.js, tramite &lt;a href=&quot;http://api.jquery.com/jQuery.ajax/&quot; target=&quot;_blank&quot;&gt;chiamata asincrona con jQuery&lt;/a&gt;.&lt;br /&gt;
L&#39;unico vero problema incontrato è che il server Node.js sta in ascolto su una porta diversa da quella utilizzata da Apache per esporre i servizi scritti in PHP e quindi il browser blocca la comunicazione a causa della protezione per il cross domain scripting.&lt;br /&gt;
Per evitare questo inconveniente sono possibili 2 strade:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;usare mod_rewrite per mascherare le richieste a Node.js come descritto &lt;a href=&quot;http://arguments.callee.info/2010/04/20/running-apache-and-node-js-together/&quot; target=&quot;_blank&quot;&gt;qui&lt;/a&gt;, oppure sfruttare mod_proxy (esempio &lt;a href=&quot;http://stackoverflow.com/questions/6109089/how-do-i-run-node-js-on-port-80&quot; target=&quot;_blank&quot;&gt;qui&lt;/a&gt; );&lt;/li&gt;
&lt;li&gt;utilizzare JSONP per le chiamate Ajax.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
Siccome la soluzione 1 non richiede alcuna modifica al codice mi sono divertito ad implementare la 2, garzie alle dritte che ho trovato in questo &lt;a href=&quot;http://www.fbloggs.com/2010/07/09/how-to-access-cross-domain-data-with-ajax-using-jsonp-jquery-and-php/&quot; target=&quot;_blank&quot;&gt;post&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Dopo qualche tentativo ecco il frutto delle mie fatiche ( ovviamente sono pigro e c&#39;è un bel mix dei vari script, un po&#39; in inglese, un po&#39; in italiano :P ).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;echo_service.php&lt;/b&gt;&lt;/div&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQTdJCGBtBOCKrh_8qaGgrZIQF_rDblAIl6KgOCHj0ZIFjOvije17Jm_vziyU4sV3GVaLr4UY-o76pwMfO9LnAaxze5SxOSHK-Ygd1OAali8UDP1feuvOFoIbS7iSDCiRecxL-qxlLg67H/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;1:  &amp;lt;?php  
2:  header(&quot;content-type: application/json&quot;);  
3:  echo $_GET[&#39;jsonp_callback&#39;]. &#39;(&#39;. json_encode($_GET[&#39;message&#39;].&#39; alle &#39;. Date(&quot;H:i:s&quot;)) . &#39;)&#39;;   
4:  ?&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;server.js&lt;/b&gt;&lt;br /&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQTdJCGBtBOCKrh_8qaGgrZIQF_rDblAIl6KgOCHj0ZIFjOvije17Jm_vziyU4sV3GVaLr4UY-o76pwMfO9LnAaxze5SxOSHK-Ygd1OAali8UDP1feuvOFoIbS7iSDCiRecxL-qxlLg67H/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;1:  var http = require(&#39;http&#39;)  
2:  , url = require(&#39;url&#39;)  
3:  , fs = require(&#39;fs&#39;)  
4:  , server;  
5:  server = http.createServer(function(req, res){  
6:    // your normal server code  
7:    var path = url.parse(req.url).pathname;  
8:    switch (path){  
9:      case &#39;/&#39;:  
10:        res.writeHead(200, {&#39;Content-Type&#39;: &#39;text/html&#39;});  
11:        res.write(&#39;&amp;lt;h1&amp;gt;Hello! Try the &amp;lt;a href=&quot;/socketio-test.html&quot;&amp;gt;Socket.io Test&amp;lt;/a&amp;gt;&amp;lt;/h1&amp;gt;&#39;);  
12:        res.end();  
13:        break;  
14:      case &#39;/socketio-test.html&#39;:  
15:        fs.readFile(__dirname + path, function(err, data){  
16:        if (err) return send404(res);  
17:        res.writeHead(200, {&#39;Content-Type&#39;: path == &#39;json.js&#39; ? &#39;text/javascript&#39; : &#39;text/html&#39;})  
18:        res.write(data, &#39;utf8&#39;);  
19:        res.end();  
20:        });  
21:        break;  
22:      default: send404(res);  
23:    }  
24:  }),  
25:  send404 = function(res){  
26:    res.writeHead(404);  
27:    res.write(&#39;404&#39;);  
28:    res.end();  
29:  };  
30:  server.listen(8080);  
31:  // socket.io, I choose you  
32:  var io = require(&#39;socket.io&#39;).listen(server);  
33:  // on a &#39;connection&#39; event  
34:  io.sockets.on(&#39;connection&#39;, function(socket){  
35:   console.log(&quot;Connection &quot; + socket.id + &quot; accepted.&quot;);  
36:   // now that we have our connected &#39;socket&#39; object, we can   
37:   // define its event handlers  
38:   socket.on(&#39;message&#39;, function(message){  
39:      console.log(&quot;Received message: &quot; + message + &quot; - from client &quot; + socket.id);  
40:      socket.emit( &#39;message&#39;, &#39;Messaggio ricevuto&#39;);  
41:   });  
42:   socket.on(&#39;disconnect&#39;, function(){  
43:    console.log(&quot;Connection &quot; + socket.id + &quot; terminated.&quot;);  
44:   });  
45:  });  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;socketio_test.html&lt;/b&gt;&lt;br /&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQTdJCGBtBOCKrh_8qaGgrZIQF_rDblAIl6KgOCHj0ZIFjOvije17Jm_vziyU4sV3GVaLr4UY-o76pwMfO9LnAaxze5SxOSHK-Ygd1OAali8UDP1feuvOFoIbS7iSDCiRecxL-qxlLg67H/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;1:  &amp;lt;!doctype html&amp;gt;  
2:  &amp;lt;html&amp;gt;  
3:   &amp;lt;head&amp;gt;  
4:    &amp;lt;title&amp;gt;Socket.io Test&amp;lt;/title&amp;gt;  
5:    &amp;lt;script src=&quot;/socket.io/socket.io.js&quot;&amp;gt;&amp;lt;/script&amp;gt;  
6:    &amp;lt;script src=&quot;http://code.jquery.com/jquery-1.7.1.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;  
7:   &amp;lt;/head&amp;gt;  
8:   &amp;lt;body&amp;gt;  
9:    &amp;lt;script&amp;gt;  
10:    var socket;  
11:    var firstconnect = true;  
12:    function connect() {  
13:     if(firstconnect) {  
14:      socket = io.connect(null);  
15:      socket.on(&#39;message&#39;, function(data){ message(data); });  
16:      socket.on(&#39;connect&#39;, function(){ status_update(&quot;Connected to Server&quot;); });  
17:      socket.on(&#39;disconnect&#39;, function(){ status_update(&quot;Disconnected from Server&quot;); });  
18:      socket.on(&#39;reconnect&#39;, function(){ status_update(&quot;Reconnected to Server&quot;); });  
19:      socket.on(&#39;reconnecting&#39;, function( nextRetry ){ status_update(&quot;Reconnecting in &quot;   
20:       + nextRetry + &quot; seconds&quot;); });  
21:      socket.on(&#39;reconnect_failed&#39;, function(){ message(&quot;Reconnect Failed&quot;); });  
22:      firstconnect = false;  
23:     }  
24:     else {  
25:      socket.socket.reconnect();  
26:     }  
27:    }  
28:    function disconnect() {  
29:     socket.disconnect();  
30:    }  
31:    function message(data) {  
32:      $.ajax({  
33:        dataType: &#39;jsonp&#39;,  
34:        data: &#39;message=&#39; + data,  
35:        jsonp: &#39;jsonp_callback&#39;,  
36:        jsonpCallback: &#39;jsonpcallback&#39;,  
37:        url: &#39;http://&amp;lt;your_apache_root&amp;gt;/echo_service.php&#39;  
38:      });      
39:    }  
40:    function jsonpcallback( rtndata ) {  
41:      $(&#39;#message&#39;).html( rtndata );  
42:    }  
43:    function status_update(txt){  
44:     document.getElementById(&#39;status&#39;).innerHTML = txt;  
45:    }  
46:    function esc(msg){  
47:     return msg.replace(/&amp;lt;/g, &#39;&amp;amp;lt;&#39;).replace(/&amp;gt;/g, &#39;&amp;amp;gt;&#39;);  
48:    }  
49:    function send() {  
50:     socket.send(&quot;Hello Server!&quot;);    
51:    };      
52:    &amp;lt;/script&amp;gt;  
53:    &amp;lt;h1&amp;gt;Socket.io Test&amp;lt;/h1&amp;gt;  
54:    &amp;lt;div&amp;gt;&amp;lt;p id=&quot;status&quot;&amp;gt;Waiting for input&amp;lt;/p&amp;gt;&amp;lt;/div&amp;gt;  
55:    &amp;lt;div&amp;gt;&amp;lt;p id=&quot;message&quot;&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/div&amp;gt;   
56:    &amp;lt;button id=&quot;connect&quot; onClick=&#39;connect()&#39;/&amp;gt;Connect&amp;lt;/button&amp;gt;  
57:    &amp;lt;button id=&quot;disconnect&quot; onClick=&#39;disconnect()&#39;&amp;gt;Disconnect&amp;lt;/button&amp;gt;  
58:    &amp;lt;button id=&quot;send&quot; onClick=&#39;send()&#39;/&amp;gt;Send Message&amp;lt;/button&amp;gt;  
59:   &amp;lt;/body&amp;gt;  
60:  &amp;lt;/html&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/6641240467084883473/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2012/06/nodejs-e-php-just-for-fun.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/6641240467084883473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/6641240467084883473'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2012/06/nodejs-e-php-just-for-fun.html' title='NodeJS e PHP, just for fun'/><author><name>Unknown</name><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-8324889730441663172.post-3375882557554529313</id><published>2012-05-18T18:35:00.002+02:00</published><updated>2012-06-16T23:57:26.591+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ajax"/><category scheme="http://www.blogger.com/atom/ns#" term="jquery"/><category scheme="http://www.blogger.com/atom/ns#" term="open source"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><title type='text'>Software Open Source per le Camere di Commercio</title><content type='html'>Da poche settimane ho ultimato un software per la gestione di contratti e appalti commissionato da una Camera di Commercio.&lt;br /&gt;
L&#39;applicazione è scritta in PHP e sfrutta il framework &lt;a href=&quot;http://sourceforge.net/projects/ampoliros/&quot; target=&quot;_blank&quot;&gt;Ampoliros&lt;/a&gt; e la libreria &lt;a href=&quot;http://www.jquery.com/&quot; target=&quot;_blank&quot;&gt;JQuery&lt;/a&gt;.&lt;br /&gt;
Visto che si tratta di un software destinato alla PA si è scelto di rilasciarlo con licenza GPL.&lt;br /&gt;
A causa della mia solita pigrizia per ora ho fatto solo alcuni screenshot (forse) seguirà un breve video dimostrativo.&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;embed flashvars=&quot;host=picasaweb.google.com&amp;amp;captions=1&amp;amp;hl=it&amp;amp;feat=flashalbum&amp;amp;RGB=0x000000&amp;amp;feed=https%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2F110373656360084352107%2Falbumid%2F5743908129143360529%3Falt%3Drss%26kind%3Dphoto%26authkey%3DGv1sRgCJDbyaH07veoIg%26hl%3Dit&quot; height=&quot;267&quot; pluginspage=&quot;http://www.macromedia.com/go/getflashplayer&quot; src=&quot;https://picasaweb.google.com/s/c/bin/slideshow.swf&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;400&quot;&gt;&lt;/embed&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/3375882557554529313/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2012/05/software-open-source-per-le-camere-di.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/3375882557554529313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/3375882557554529313'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2012/05/software-open-source-per-le-camere-di.html' title='Software Open Source per le Camere di Commercio'/><author><name>Unknown</name><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-8324889730441663172.post-7062823097742547760</id><published>2012-04-27T11:57:00.001+02:00</published><updated>2012-04-27T19:39:19.818+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="e-commerce"/><category scheme="http://www.blogger.com/atom/ns#" term="payment gateway"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="wordpress"/><title type='text'>Gateway Consorzio Triveneto per WP e-commerce</title><content type='html'>&lt;div&gt;Recentemente ho dovuto integrare il gateway di pagamento del &lt;a href=&quot;http://www.constriv.it/&quot; target=&quot;_blank&quot;&gt;Consorzio Triveneto&lt;/a&gt;&amp;nbsp;nel plugin &lt;a href=&quot;http://getshopped.org/&quot; target=&quot;_blank&quot;&gt;WP e-commerce&lt;/a&gt;, uno dei più noti plugin di commercio elettronico per Wordpress.&lt;br /&gt;
All&#39;inizio pensavo di utilizzare l&#39;ottima classe &lt;a href=&quot;http://www.m4ss.net/os-open-source/payment-gateway-consorzio-triveneto-php-class/&quot; target=&quot;_blank&quot;&gt;PgConsTriv&lt;/a&gt;&amp;nbsp;di Davide Gullo, poi ho realizzato un&#39;integrazione veramente minimale partendo dagli esempi forniti dal Consorzio e dalla &lt;a href=&quot;http://getshopped.org/resources/docs/get-involved/writing-a-new-payment-gateway/&quot; target=&quot;_blank&quot;&gt;documentazione&lt;/a&gt; di WP e-commerce.&lt;br /&gt;
E&#39; puro spaghetti-code ma forse a qualcuno può tornare utile :)&lt;br /&gt;
Di seguito il codice del nuovo gateway da salvare nel folder&amp;nbsp;/wp-content/plugins/wp-e-commerce/wpsc-merchants/ del vostro server.&lt;br /&gt;
Tutte le funzioni andrebbero raccolte in un unico file (compresi i callback di ritorno dal gateway), per intenderci $responseURL dovrebbe essere qualcosa del genere:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;get_option(&#39;siteurl&#39;).&quot;/?constriv=ok&quot;;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;e quindi tutte le azioni verrebbero gestite dalla funzione&amp;nbsp;&lt;/span&gt;&lt;b style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;gateway_constriv_gateway,&amp;nbsp;&lt;/b&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;purtroppo ho avuto qualche problema nella gestione degli indirizzi da parte del gateway e siccome sono pigro, non ho investigato più di tanto:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;Alla fine ho utilizzato un work-around che segue passo-passo l&#39;esempio fornito nella documentazione: ho usato i file receipt.php ed error.php per gestire la comunicazione con il gateway, questi poi fanno un redirect per completare la gestione dell&#39;ordine e la visualizzazione di eventuali messaggi.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;Nel file receipt.php dovreste implementare eventuali meccanismi di verifica della provenienza della transazione tramite i parametri udf*, io ho usato udf3 per trasportare l&#39;id di sessione necessario a completare le operzioni sull&#39;ordine.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;constriv.merchant.php&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQTdJCGBtBOCKrh_8qaGgrZIQF_rDblAIl6KgOCHj0ZIFjOvije17Jm_vziyU4sV3GVaLr4UY-o76pwMfO9LnAaxze5SxOSHK-Ygd1OAali8UDP1feuvOFoIbS7iSDCiRecxL-qxlLg67H/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;1:  &amp;lt;?php  
2:  /**  
3:    * Gateway wp e-commerce per Consorzio Triveneto  
4:    * Marco Montesi 2012-04-26  
5:    * marco.montesi@gmail.com  
6:   *  
7:   * @package wp-e-comemrce  
8:   * @since 3.7.6  
9:   * @subpackage wpsc-merchants  
10:   */  
11:  $nzshpcrt_gateways[$num][&#39;name&#39;] = &#39;Consorzio Triveneto&#39;;  
12:  $nzshpcrt_gateways[$num][&#39;internalname&#39;] = &#39;constriv_gateway&#39;;  
13:  $nzshpcrt_gateways[$num][&#39;function&#39;] = &#39;gateway_constriv_gateway&#39;;  
14:  $nzshpcrt_gateways[$num][&#39;form&#39;] = &quot;form_constriv_gateway&quot;;  
15:  $nzshpcrt_gateways[$num][&#39;submit_function&#39;] = &quot;submit_constriv_gateway&quot;;  
16:  // admin form per memorizzare ID e password dell&#39;account del cliente  
17:  function form_constriv_gateway()  
18:  {  
19:    $output =&#39;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&#39;;  
20:    $output.=&#39;&amp;lt;input name=&quot;constriv_tranportalid&quot; type=&quot;text&quot; value=&quot;&#39;.get_option(&#39;constriv_tranportalid&#39;).&#39;&quot;/&amp;gt;&#39;;  
21:    $output.=&#39;TranPortalID&#39;;  
22:    $output.=&#39;&amp;lt;input name=&quot;constriv_password&quot; type=&quot;text&quot; value=&quot;&#39;.get_option(&#39;constriv_password&#39;).&#39;&quot;/&amp;gt;&#39;;  
23:    $output.=&#39;Password&#39;;  
24:    $output .=&#39;&amp;lt;/tr&amp;gt;&amp;lt;/td&amp;gt;&#39;;  
25:    return $output;  
26:  }  
27:  //  
28:  function submit_constriv_gateway()  
29:  {  
30:    if($_POST[&#39;constriv_tranportalid&#39;] != null) {  
31:      update_option(&#39;constriv_tranportalid&#39;, $_POST[&#39;constriv_tranportalid&#39;]);  
32:    }  
33:    if($_POST[&#39;constriv_password&#39;] != null) {  
34:      update_option(&#39;constriv_password&#39;, $_POST[&#39;constriv_password&#39;]);  
35:    }  
36:    return true;  
37:  }  
38:  // gateway   
39:  function gateway_constriv_gateway($seperator, $sessionid)  
40:  {  
41:    global $wpdb, $wpsc_cart;  
42:    //This grabs the purchase log id from the database  
43:    //that refers to the $sessionid  
44:    $purchase_log = $wpdb-&amp;gt;get_row( &quot;SELECT * FROM `&quot;.WPSC_TABLE_PURCHASE_LOGS.&quot;` WHERE `sessionid`= &quot;.$sessionid.&quot; LIMIT 1&quot;, ARRAY_A) ;  
45:    // costruisco la stringa da passare al gateway per l&#39;auth  
46:    $ID     = get_option(&#39;constriv_tranportalid&#39;);  
47:    $Password = get_option(&#39;constriv_password&#39;);  
48:    $Action   = &quot;4&quot;;  
49:    $Amt    = number_format($wpsc_cart-&amp;gt;total_price,2);  
50:    // sostituire con il proprio dominio  
51:    $ResponseURL = &quot;&amp;lt;il_mio_dominio&amp;gt;/constriv/receipt.php&quot;;  
52:    $ErrorURL =  &quot;&amp;lt;il_mio_dominio&amp;gt;/constriv/error.php&quot;;  
53:    $TrackId = &quot;&amp;lt;il_mio_dominio&amp;gt;-&quot;.$purchase_log[&#39;id&#39;];  
54:    $DataToSend =&quot;id=$ID&amp;amp;password=$Password&amp;amp;action=$Action&amp;amp;amt=$Amt&amp;amp;currencycode=978&amp;amp;langid=ITA&amp;amp;responseURL= $ResponseURL&amp;amp;errorURL=$ErrorURL&amp;amp;trackid=$TrackId&amp;amp;udf1=AA&amp;amp;udf2=BB&amp;amp;udf3=$sessionid&amp;amp;udf4=DD&amp;amp;udf5=EE&quot;;   
55:    // ambiente di test, da sostituire con URL di produzione  
56:    $URL = &quot;https://test4.constriv.com/cg301/servlet/PaymentInitHTTPServlet&quot;;  
57:    //Apro la connessione  
58:    $ch=curl_init($URL);   
59:    //Imposto gli headers HTTP  
60:    //imposto curl per protocollo https  
61:    curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, FALSE);  
62:    curl_setopt($ch,CURLOPT_POST,1);  
63:    //Invio i dati  
64:    curl_setopt($ch,CURLOPT_POSTFIELDS,$DataToSend);  
65:    //imposta la variabile PHP   
66:    curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);   
67:    //Ricevo la risposta dal server  
68:    $varResponse=curl_exec($ch);   
69:    //chiudo la connessione   
70:    curl_close($ch);   
71:    if (substr($varResponse,0,7) == &#39;!ERROR!&#39;) {  
72:      echo $varResponse;  
73:    } else {  
74:      //Separo il contenuto della stringa ricevuta (PaymentID:RedirectURL)  
75:      $varPosiz= strpos($varResponse, &#39;:http&#39;);  
76:      $varPaymentId= substr($varResponse,0,$varPosiz);  
77:      $nc=strlen($varResponse);  
78:      $nc=($nc-17);  
79:      $varRedirectURL=substr($varResponse,$varPosiz+1);  
80:      //Creo l&#39;URL di redirezione  
81:      $varRedirectURL =&quot;$varRedirectURL?PaymentID=$varPaymentId&quot;;  
82:      //echo $varRedirectURL;  
83:      //Redirezione finale del browser sulla HPP  
84:      //echo $varRedirectURL;  
85:      echo &quot;&amp;lt;meta http-equiv=\&quot;refresh\&quot; content=\&quot;0;URL=$varRedirectURL\&quot;&amp;gt;&quot;;  
86:    }  
87:  }  
88:  function nzshpcrt_constriv_callback()  
89:  {  
90:   global $wpdb;  
91:   if( isset($_GET[&#39;constriv&#39;]) &amp;amp;&amp;amp; ($_GET[&#39;constriv&#39;] == &#39;transok&#39;)) {  
92:      $sessionid = $_REQUEST[&quot;udf3&quot;];  
93:      $PayID=$_REQUEST[&quot;paymentid&quot;];  
94:      $TransID=$_REQUEST[&quot;tranid&quot;];  
95:      $ResCode=$_REQUEST[&quot;resultcode&quot;];  
96:      $AutCode=$_REQUEST[&quot;auth&quot;];  
97:      $PosDate=$_REQUEST[&quot;postdate&quot;];  
98:      $TrckID=$_REQUEST[&quot;trackid&quot;];  
99:      $Brand = $_REQUEST[&quot;cardtype&quot;];  
100:      $Protocol = $_REQUEST[&quot;payinst&quot;];  
101:      $Protection = $_REQUEST[&quot;liability&quot;];  
102:      $HostResponseCode = $_REQUEST[&quot;responsecode&quot;];  
103:      $Mistake = $_REQUEST[&quot;Error&quot;];  
104:      $MistakeText = $_REQUEST[&quot;ErrorText&quot;];  
105:      if( strlen(trim($AutCode)) and $ResCode == &#39;APPROVED&#39; ) {  
106:        $sql = &quot;UPDATE `&quot;.WPSC_TABLE_PURCHASE_LOGS.&quot;` SET `processed`= &#39;3&#39; WHERE `sessionid`=&quot;.$sessionid;  
107:        $wpdb-&amp;gt;query($sql);  
108:        $transact_url = get_option(&#39;transact_url&#39;);  
109:        unset($_SESSION[&#39;WpscGatewayErrorMessage&#39;]);  
110:        echo &#39;&amp;lt;script&amp;gt;document.location=&quot;&#39;.$transact_url.&#39;&amp;amp;sessionid=&#39;.$sessionid.&#39;&amp;amp;status=ok&quot;;&amp;lt;/script&amp;gt;&#39;;        
111:      } else {  
112:        $sql = &quot;UPDATE `&quot;.WPSC_TABLE_PURCHASE_LOGS.&quot;` SET `processed`= &#39;5&#39; WHERE `sessionid`=&quot;.$sessionid;  
113:        $wpdb-&amp;gt;query($sql);  
114:        $transact_url = get_option(&#39;transact_url&#39;);  
115:        $_SESSION[&#39;WpscGatewayErrorMessage&#39;] = $Mistake.&#39; &#39;.$MistakeText;  
116:        echo &#39;&amp;lt;script&amp;gt;document.location=&quot;&#39;.$transact_url.&#39;&amp;amp;sessionid=&#39;.$sessionid.&#39;&amp;amp;status=ko&quot;;&amp;lt;/script&amp;gt;&#39;;        
117:      }  
118:    }  
119:    if( isset($_GET[&#39;constriv&#39;]) &amp;amp;&amp;amp; ($_GET[&#39;constriv&#39;] == &#39;transko&#39;)) {  
120:      $sql = &quot;UPDATE `&quot;.WPSC_TABLE_PURCHASE_LOGS.&quot;` SET `processed`= &#39;5&#39; WHERE `sessionid`=&quot;.$sessionid;  
121:      $wpdb-&amp;gt;query($sql);  
122:      $transact_url = get_option(&#39;transact_url&#39;);  
123:      $_SESSION[&#39;WpscGatewayErrorMessage&#39;] = $Mistake.&#39; &#39;.$MistakeText;  
124:      echo &#39;&amp;lt;script&amp;gt;document.location=&quot;&#39;.$transact_url.&#39;&amp;amp;sessionid=&#39;.$sessionid.&#39;&quot;;&amp;lt;/script&amp;gt;&#39;;    
125:    }  
126:  }  
127:  //  
128:  add_action(&#39;init&#39;, &#39;nzshpcrt_constriv_callback&#39;);  
129:  ?&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;b style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;receipt.php&lt;/b&gt;&lt;br /&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQTdJCGBtBOCKrh_8qaGgrZIQF_rDblAIl6KgOCHj0ZIFjOvije17Jm_vziyU4sV3GVaLr4UY-o76pwMfO9LnAaxze5SxOSHK-Ygd1OAali8UDP1feuvOFoIbS7iSDCiRecxL-qxlLg67H/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;1:  &amp;lt;?php   
2:  $PayID=$_POST[&quot;paymentid&quot;];  
3:  $TransID=$_POST[&quot;tranid&quot;];  
4:  $ResCode=$_POST[&quot;result&quot;];  
5:  $AutCode=$_POST[&quot;auth&quot;];  
6:  $PosDate=$_POST[&quot;postdate&quot;];  
7:  $TrckID=$_POST[&quot;trackid&quot;];  
8:  $UD1=$_POST[&quot;udf1&quot;];  
9:  $UD2=$_POST[&quot;udf2&quot;];  
10:  $UD3=$_POST[&quot;udf3&quot;];  
11:  $UD4=$_POST[&quot;udf4&quot;];  
12:  $UD5=$_POST[&quot;udf5&quot;];  
13:  $Brand = $_POST[&quot;cardtype&quot;];  
14:  $Protocol = $_POST[&quot;payinst&quot;];  
15:  $Protection = $_POST[&quot;liability&quot;];  
16:  $HostResponseCode = $_POST[&quot;responsecode&quot;];  
17:  $Mistake = $_POST[&quot;Error&quot;];  
18:  $MistakeText = $_POST[&quot;ErrorText&quot;];  
19:  // Nell URL seguente inserire l&#39;indirizzo corretto del proprio server  
20:  if( strlen(trim($AutCode)) and $ResCode == &#39;APPROVED&#39; and $UD1==&#39;AA&#39; and $UD2 == &#39;BB&#39; ) {  
21:    $ReceiptURL=&quot;REDIRECT=http://&amp;lt;mio_dominio&amp;gt;/?page_id=&amp;lt;id_carrello&amp;gt;&amp;amp;constriv=transok&amp;amp;PaymentID=&quot;.$PayID.&quot;&amp;amp;TransID=&quot;.$TransID.&quot;&amp;amp;TrackID=&quot;.$TrckID.&quot;&amp;amp;postdate=&quot;.$PosDate.&quot;&amp;amp;resultcode=&quot;.$ResCode.&quot;&amp;amp;auth=&quot;.$AutCode.&quot;&amp;amp;Error=&quot;.$Mistake.&quot;&amp;amp;ErrorText=&quot;.$MistakeText.&quot;&amp;amp;cardtype=&quot;.$Brand.&quot;&amp;amp;payinst=&quot;.$Protocol.&quot;&amp;amp;liability=&quot;.$Protection.&quot;&amp;amp;responsecode=&quot;.$HostResponseCode.&quot;&amp;amp;udf3=&quot;.$UD3;       
22:  } else {  
23:    $ReceiptURL=&quot;REDIRECT=http://&amp;lt;mio_dominio&amp;gt;/?page_id=&amp;lt;id_carrello&amp;gt;&amp;amp;constriv=transko&amp;amp;PaymentID=&quot;.$PayID.&quot;&amp;amp;TransID=&quot;.$TransID.&quot;&amp;amp;TrackID=&quot;.$TrckID.&quot;&amp;amp;postdate=&quot;.$PosDate.&quot;&amp;amp;resultcode=&quot;.$ResCode.&quot;&amp;amp;auth=&quot;.$AutCode.&quot;&amp;amp;Error=&quot;.$Mistake.&quot;&amp;amp;ErrorText=&quot;.$MistakeText.&quot;&amp;amp;cardtype=&quot;.$Brand.&quot;&amp;amp;payinst=&quot;.$Protocol.&quot;&amp;amp;liability=&quot;.$Protection.&quot;&amp;amp;responsecode=&quot;.$HostResponseCode.&quot;&amp;amp;udf3=&quot;.$UD3;       
24:  }  
25:  echo $ReceiptURL;   
26:  ?&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-family: Arial, Helvetica, sans-serif;&quot;&gt;error.php&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQTdJCGBtBOCKrh_8qaGgrZIQF_rDblAIl6KgOCHj0ZIFjOvije17Jm_vziyU4sV3GVaLr4UY-o76pwMfO9LnAaxze5SxOSHK-Ygd1OAali8UDP1feuvOFoIbS7iSDCiRecxL-qxlLg67H/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;1:  &amp;lt;?php   
2:  $PayID=$_POST[&quot;paymentid&quot;];  
3:  $TransID=$_POST[&quot;tranid&quot;];  
4:  $ResCode=$_POST[&quot;result&quot;];  
5:  $AutCode=$_POST[&quot;auth&quot;];  
6:  $PosDate=$_POST[&quot;postdate&quot;];  
7:  $TrckID=$_POST[&quot;trackid&quot;];  
8:  $UD1=$_POST[&quot;udf1&quot;];  
9:  $UD2=$_POST[&quot;udf2&quot;];  
10:  $UD3=$_POST[&quot;udf3&quot;];  
11:  $UD4=$_POST[&quot;udf4&quot;];  
12:  $UD5=$_POST[&quot;udf5&quot;];  
13:  $Brand = $_POST[&quot;cardtype&quot;];  
14:  $Protocol = $_POST[&quot;payinst&quot;];  
15:  $Protection = $_POST[&quot;liability&quot;];  
16:  $HostResponseCode = $_POST[&quot;responsecode&quot;];  
17:  $Mistake = $_POST[&quot;Error&quot;];  
18:  $MistakeText = $_POST[&quot;ErrorText&quot;];  
19:  $ReceiptURL=&quot;REDIRECT=http://&amp;lt;mio_dominio&amp;gt;/?page_id=&amp;lt;id_carrello&amp;gt;&amp;amp;constriv=transko&amp;amp;PaymentID=&quot;.$PayID.&quot;&amp;amp;TransID=&quot;.$TransID.&quot;&amp;amp;TrackID=&quot;.$TrckID.&quot;&amp;amp;TransID=&quot;.$TransID.&quot;&amp;amp;TrackID=&quot;.$TrckID.&quot;&amp;amp;postdate=&quot;.$PosDate.&quot;&amp;amp;resultcode=&quot;.$ResCode.&quot;&amp;amp;auth=&quot;.$AutCode.&quot;&amp;amp;Error=&quot;.$Mistake.&quot;&amp;amp;ErrorText=&quot;.$MistakeText.&quot;&amp;amp;cardtype=&quot;.$Brand.&quot;&amp;amp;payinst=&quot;.$Protocol.&quot;&amp;amp;liability=&quot;.$Protection.&quot;&amp;amp;responsecode=&quot;.$HostResponseCode.&quot;&amp;amp;udf3=&quot;.$UD3;       
20:  echo $ReceiptURL;   
21:  ?&amp;gt;  
&lt;/code&gt;&lt;/pre&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/7062823097742547760/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2012/04/gateway-consorzio-triveneto-per-wp-e.html#comment-form' title='6 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/7062823097742547760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/7062823097742547760'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2012/04/gateway-consorzio-triveneto-per-wp-e.html' title='Gateway Consorzio Triveneto per WP e-commerce'/><author><name>Unknown</name><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>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8324889730441663172.post-1133647315561068019</id><published>2011-12-01T17:30:00.001+01:00</published><updated>2011-12-02T15:59:20.988+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="cyanogen"/><category scheme="http://www.blogger.com/atom/ns#" term="folio"/><category scheme="http://www.blogger.com/atom/ns#" term="gingerbread"/><category scheme="http://www.blogger.com/atom/ns#" term="tablet"/><title type='text'>Gingerbread (Android 2.3) su Toshiba Folio</title><content type='html'>Salve a tutti, qualche settimana fa mi hanno praticamente regalato un Toshiba Folio.&lt;br /&gt;
Toshiba ha prodotto questo bel tablet Tegra2 e ci ha messo su un Android 2.2 castrato del market e delle applicazioni Google.&lt;br /&gt;
La frustrazione di avere tra le mani un hardware ancora quasi al top con un software deprimente è stata tale che mi sono deciso a provare la via del modding.&lt;br /&gt;
La cosa non è stata tanto facile perché Toshiba, oltre ad aver fatto questa scelta a dir poco discutibile sul sistema installato, ha pensato bene di aggiornare il firmware in modo tale che non fosse possibile flashare ROM alternative :)&lt;br /&gt;
Ovviamente l&#39;esemplare in mio possesso aveva il firmware aggiornato...&lt;br /&gt;
Comunque, per farla breve, alla fine sono riuscito ad installare Cyanogen 7.1, ovvero Android 2.3.7, e adesso il tablet è una bomba: tutte le Google Apps, Flash, Firefox, giochini 3D, etc etc&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/AVvXsEhmYSrKnztflFd6Sb0OakwMhoqHB1PiklfLzJSnLzUMvkbeqAtfDpPUM0TheRl-2pnJJvp3diqskW25dZQhuzz5HzKLdTWQlPz9BQiCGIioAXrGdOqDS1vRThgIHQVFhpY7R0kQwQU8VHo/s1600/screenshot-1322759102461.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;232&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmYSrKnztflFd6Sb0OakwMhoqHB1PiklfLzJSnLzUMvkbeqAtfDpPUM0TheRl-2pnJJvp3diqskW25dZQhuzz5HzKLdTWQlPz9BQiCGIioAXrGdOqDS1vRThgIHQVFhpY7R0kQwQU8VHo/s400/screenshot-1322759102461.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&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/AVvXsEgCLMy5Bfb07OqU_Z5COPEov7y4Jnqrkcr6OhPLO8VUJQ2A2zR58GDvSDFEjmlKHdH8Gx-3HFjqYz7lSpoEOHqNAbgojtvmZnoyU_D_EidV9kADf2UBj24vrfQIxT-fFO3UnkjAhtAn0gE/s1600/screenshot-1322759186120.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;233&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCLMy5Bfb07OqU_Z5COPEov7y4Jnqrkcr6OhPLO8VUJQ2A2zR58GDvSDFEjmlKHdH8Gx-3HFjqYz7lSpoEOHqNAbgojtvmZnoyU_D_EidV9kADf2UBj24vrfQIxT-fFO3UnkjAhtAn0gE/s400/screenshot-1322759186120.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Di seguito riassumo i passi da fare se volete cimentarvi, e siccome sono un po&#39; bastardo dentro non metto le istruzioni passo passo (troppa fatica) ma solo i link delle risorse ;)&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;Rootare il Folio;&lt;/b&gt;&lt;br /&gt;di guide ce ne sono una marea;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Scaricare e flashare un firmware pre-aggiornamento&lt;/b&gt;&lt;br /&gt;ho usato la recovery della FolioMod più o meno come dice qua &amp;nbsp;&lt;a href=&quot;http://forum.xda-developers.com/showthread.php?t=961826&quot;&gt;http://forum.xda-developers.com/showthread.php?t=961826&lt;/a&gt;&amp;nbsp;;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;opzionale: flashare ClockWorkMod per Folio;&lt;/b&gt;&lt;br /&gt;probabilmente non è necessario ma poi avrete molte più opzioni:&amp;nbsp;&lt;a href=&quot;http://www.arctablet.com/blog/featured/clockworkmod-recovery-v3-0-0-5-toshiba-folio100/&quot;&gt;http://www.arctablet.com/blog/featured/clockworkmod-recovery-v3-0-0-5-toshiba-folio100/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;scaricare e flashare Cyanogen per Folio per update a 2.3.5;&lt;/b&gt;&lt;br /&gt;avevo provato a mettere direttamente la 2.3.7 ma non riuscivo a flashare;&lt;br /&gt;&lt;a href=&quot;http://forum.xda-developers.com/showthread.php?t=933989&amp;amp;page=53&quot; moz-do-not-send=&quot;true&quot;&gt;http://forum.xda-developers.com/showthread.php?t=933989&amp;amp;page=53&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;scaricare e flashare le Google Apps;&lt;/b&gt;ovviamente scegliete la versione per Cyanogen 7:&lt;br /&gt;&lt;a class=&quot;moz-txt-link-freetext&quot; href=&quot;http://wiki.cyanogenmod.com/index.php?title=Latest_Version/Google_Apps&quot; moz-do-not-send=&quot;true&quot;&gt;http://wiki.cyanogenmod.com/index.php?title=Latest_Version/Google_Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;aggiornare a 2.3.7;&lt;/b&gt;&lt;br /&gt;addirittura forse adesso c&#39;è qualcosa di più aggiornato, andate a spulciare qua:&lt;br /&gt;&lt;a href=&quot;http://forum.xda-developers.com/showthread.php?t=933989&quot;&gt;http://forum.xda-developers.com/showthread.php?t=933989&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;enjoy.&lt;/b&gt;&lt;/li&gt;
&lt;/ol&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/AVvXsEh3VKH1AJoHJkLEVLMNXAtsY20pCrS5wtfzCpvEcJsvhrFyZkJUcUJEAO9BFKd9uU5xVFeT85AVMZGx2B6NQ8-ZOrHinaf1U_Q9QmXSRLblP1s4N8tVnDu_3Dtk2t8-a_-BNHbBdZYRUVk/s1600/screenshot-1322759126901.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;233&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3VKH1AJoHJkLEVLMNXAtsY20pCrS5wtfzCpvEcJsvhrFyZkJUcUJEAO9BFKd9uU5xVFeT85AVMZGx2B6NQ8-ZOrHinaf1U_Q9QmXSRLblP1s4N8tVnDu_3Dtk2t8-a_-BNHbBdZYRUVk/s400/screenshot-1322759126901.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/1133647315561068019/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2011/12/gingerbread-android-23-su-toshiba-folio.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/1133647315561068019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/1133647315561068019'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2011/12/gingerbread-android-23-su-toshiba-folio.html' title='Gingerbread (Android 2.3) su Toshiba Folio'/><author><name>Unknown</name><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/AVvXsEhmYSrKnztflFd6Sb0OakwMhoqHB1PiklfLzJSnLzUMvkbeqAtfDpPUM0TheRl-2pnJJvp3diqskW25dZQhuzz5HzKLdTWQlPz9BQiCGIioAXrGdOqDS1vRThgIHQVFhpY7R0kQwQU8VHo/s72-c/screenshot-1322759102461.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8324889730441663172.post-5765843762362366191</id><published>2011-08-25T17:46:00.001+02:00</published><updated>2011-08-25T17:54:28.731+02:00</updated><title type='text'>Widget jQuery su Ampoliros</title><content type='html'>Un piccolo esempio dell&#39;utilizzo della libreria jQuery e di alcuni widget jQuery UI.&lt;br /&gt;
La piattaforma di sviluppo è &lt;a href=&quot;http://sourceforge.net/projects/ampoliros/&quot;&gt;Ampoliros&lt;/a&gt;, la libreria AJAX utilizzata è &lt;a href=&quot;http://www.xajax-project.org/&quot;&gt;XAJAX&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
PS ho fatto lo screencast per provare &lt;a href=&quot;http://www.screencast-o-matic.com/&quot;&gt;SOM&lt;/a&gt;: consigliato!&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;345&quot; src=&quot;http://www.youtube.com/embed/_CnjiYvDwUY&quot; width=&quot;560&quot;&gt;&lt;/iframe&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/5765843762362366191/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2011/08/widget-jquery-su-ampoliros.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/5765843762362366191'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/5765843762362366191'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2011/08/widget-jquery-su-ampoliros.html' title='Widget jQuery su Ampoliros'/><author><name>Unknown</name><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://img.youtube.com/vi/_CnjiYvDwUY/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8324889730441663172.post-583597130433588024</id><published>2011-07-17T12:22:00.009+02:00</published><updated>2011-07-17T12:38:10.729+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="google api"/><category scheme="http://www.blogger.com/atom/ns#" term="json"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><title type='text'>Feed stream pubblico Google+ (unofficial)</title><content type='html'>Ancora Google non ha pubblicato le API di G+ ma gli smanettoni si sono dati da fare da subito.&lt;br /&gt;
Ad esempio è possibile ottenere in formato JSON lo stream dei post pubblici di un utente.&lt;br /&gt;
Dopo aver visto &lt;a href=&quot;http://www.reddit.com/r/googleplus/comments/iq21n/getting_the_google_feed_for_any_profile_in_json/&quot;&gt;questo articolo&lt;/a&gt;&amp;nbsp;(grazie &lt;a href=&quot;https://plus.google.com/102211139050524540092&quot;&gt;Gian Angelo&lt;/a&gt;) ho provato subito con qualche riga di PHP.&lt;br /&gt;
Ci sono già &lt;a href=&quot;https://github.com/jmstriegel/php.googleplusapi&quot;&gt;progetti promettenti&lt;/a&gt; in rete, ma io mi sono limitato allo stretto indispensabile.&lt;br /&gt;
Accertatevi di avere attivato il supporto SSL in PHP e sostituite $googleplus_id con l&#39;id utente che vi interessa (basta guardare l&#39;url del profilo):&lt;br /&gt;
&lt;br /&gt;
&lt;code style=&quot;background-color: #f3f3f3;&quot;&gt;  $googleplus_id = &#39;110373656360084352107&#39;;&lt;br /&gt;
$url = &#39;https://plus.google.com/_/stream/getactivities/&#39;.$googleplus_id.&#39;/?sp=%5B1%2C2%2C%22&#39;.$googleplus_id.&#39;%22%2Cnull%2Cnull%2Cnull%2Cnull%2C%22social.google.com%22%2C%5B%5D%5D&#39;; &lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
per recuperare i dati basta usare file_get_contents (a patto che in php.ini abbiate settato allow_url_fopen):&lt;br /&gt;
&lt;br /&gt;
&lt;code style=&quot;background-color: #eeeeee;&quot;&gt; $output = file_get_contents( $url );&lt;/code&gt;&lt;br /&gt;
&lt;code style=&quot;background-color: #eeeeee;&quot;&gt;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
La stringa JSON ottenuta va &quot;ripulita&quot; come indicato nell&#39;articolo citato:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color: #eeeeee;&quot;&gt; $json = substr( $output, 4 );&lt;br /&gt;
$json = str_replace( &#39;[,&#39;, &#39;[&quot;&quot;,&#39;, $json );&lt;br /&gt;
while( strpos( $json, &#39;,,&#39; ) ) $json = str_replace( &#39;,,&#39;, &#39;,&quot;&quot;,&#39;, $json );&lt;/span&gt;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
Finalmente abbiamo una stringa che possiamo dare in pasto a json_decode per ottenere un array contenete i nostri post pubblici su Google+:&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color: #eeeeee;&quot;&gt; $feedArray = json_decode($json);&lt;br /&gt;
foreach( $feedArray[1][0] as $currPost ) {&lt;br /&gt;
echo &#39;Autore: &#39;.$currPost[3].&#39;&amp;lt;br&amp;gt;&#39;;&lt;br /&gt;
echo &#39;Titolo: &#39;.$currPost[4].&#39;&amp;lt;br&amp;gt;&#39;;&lt;br /&gt;
foreach( $currPost[11] as $postLinks ) {&lt;br /&gt;
echo &#39; -&amp;gt; Titolo link: &#39;.$postLinks[3].&#39;&amp;lt;br&amp;gt;&#39;;&lt;br /&gt;
echo &#39; -&amp;gt; Descr. link: &#39;.$postLinks[21].&#39;&amp;lt;br&amp;gt;&#39;;&lt;br /&gt;
echo &#39; -&amp;gt; Url link: &#39;.$postLinks[24][1].&#39;&amp;lt;br&amp;gt;&#39;;&lt;br /&gt;
}&lt;br /&gt;
echo &#39;&amp;lt;br&amp;gt;&#39;;&lt;br /&gt;
}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color: #eeeeee;&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;
That&#39;s all!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Nota&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
Se non volete abilitare allow_url_fopen potete provare con cURL, sostituendo la chiamata a file_get_contents con questo codice:&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;background-color: #eeeeee;&quot;&gt; $ch = curl_init();&lt;br /&gt;
curl_setopt($ch, CURLOPT_URL, $url );&lt;br /&gt;
curl_setopt($ch, CURLOPT_HEADER, 0);&lt;br /&gt;
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1) ;&lt;br /&gt;
$output = curl_exec($ch);&lt;br /&gt;
curl_close($ch);&lt;/span&gt;&lt;br /&gt;
&lt;/code&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/583597130433588024/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2011/07/feed-google-unofficial.html#comment-form' title='1 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/583597130433588024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/583597130433588024'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2011/07/feed-google-unofficial.html' title='Feed stream pubblico Google+ (unofficial)'/><author><name>Unknown</name><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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8324889730441663172.post-3375174856466003600</id><published>2011-07-13T15:48:00.000+02:00</published><updated>2011-07-13T15:48:51.907+02:00</updated><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="mobile"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><title type='text'>Smartphone e drag&amp;drop</title><content type='html'>Al giorno d&#39;oggi se le tue applicazioni non supportano in qualche modo i dispositivi mobili non sei nessuno!&lt;br /&gt;
Mi ritengo fortunato perché da circa 10 anni sviluppo quasi esclusivamente in ambiente web, utilizzando tecnologie standard, quindi le applicazioni sono direttamente visualizzabili su qualunque aggeggio abbia un browser degno di questo nome.&lt;br /&gt;
Ci sono però alcune situazioni che richiedono uno sforzo ulteriore.&lt;br /&gt;
E&#39; il caso di tutti i dispositivi dotati di touch screen e delle funzionalità drag&amp;amp;drop.&lt;br /&gt;
Su iPhone, iPad o sul vostro smartphone Android l&#39;applicazione viene visualizzata correttamente ma se provate a trascinare... il browser scrolla o esegue un pan nella pagina.&lt;br /&gt;
Ad esempio in &lt;a href=&quot;http://www.efficienza-professionale.it/&quot;&gt;Kroneos MP&lt;/a&gt;&amp;nbsp;gli utenti si possono scambiare dei post-it, ovvero semplici messaggi che rimangono &quot;appiccicati&quot; al loro desktop virtuale piuttosto che al monitor reale ;)&lt;br /&gt;
Questi oggetti anche graficamente riprendono l&#39;aspetto di un post-it, il classico quadrato di colori fosforescenti.&lt;br /&gt;
Gli utenti possono spostare i posti-it sullo schermo ed ancorarli in posizioni comode.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://www.efficienza-professionale.it/media/c62cf13065600f4c0ef0f3499d62d5f3&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;207&quot; src=&quot;http://www.efficienza-professionale.it/media/c62cf13065600f4c0ef0f3499d62d5f3&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Con il mouse il tutto avviene in maniera molto naturale.&lt;br /&gt;
Ma su un touch screen è semplicemente impossibile.&lt;br /&gt;
Dei ragazzi italiani hanno scritto una bella classe Javascript che implementa dei div &quot;draggabili&quot; su dispositivi touch:&amp;nbsp;&lt;a href=&quot;http://www.gotproject.com/blog/post2.html&quot;&gt;Drag Drop Library for Ipad &amp;amp; Iphone&lt;/a&gt;&amp;nbsp;(funziona anche con Android).&lt;br /&gt;
L&#39;ho provata, ma su pagine particolarmente cariche ho avuto problemi di prestazioni.&lt;br /&gt;
Per ora l&#39;unica soluzione è stato il classico uovo di Colombo, ovvero ho dovuto rinunciare al drag&amp;amp;drop :P&lt;br /&gt;
Al posto dei foglietti svolazzanti i messaggi li ho impilati in un &lt;a href=&quot;http://jqueryui.com/demos/accordion/&quot;&gt;accordion jQuery UI&lt;/a&gt;&amp;nbsp;(nel caso lo user agent corrisponda ad un iQualcosa o ad un Droide).&lt;br /&gt;
Qualcuno ha avuto un&#39;idea più brillante?</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/3375174856466003600/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2011/07/smartphone-e-drag.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/3375174856466003600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/3375174856466003600'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2011/07/smartphone-e-drag.html' title='Smartphone e drag&amp;drop'/><author><name>Unknown</name><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-8324889730441663172.post-1913025466714138621</id><published>2011-07-08T11:13:00.001+02:00</published><updated>2011-07-08T12:25:56.635+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><title type='text'>Una bella sorpresa: jQuery Mobile</title><content type='html'>Volete realizzare la versione &quot;mobile&quot; del vostro sito?&lt;br /&gt;
Volete che l&#39;aspetto sia il più possibile simile ad una app nativa?&lt;br /&gt;
Volete gradevoli effetti grafici?&lt;br /&gt;
Volete tempi di sviluppo rapidi e semplice integrazione con altri tools?&lt;br /&gt;
Ok,&amp;nbsp;&lt;a href=&quot;http://jquerymobile.com/&quot;&gt;jQuery Mobile&lt;/a&gt; fa per voi.&lt;br /&gt;
Poche ore di lavoro per leggere i tutorial, integrare la libreria nel cms ed ecco il risultato:&amp;nbsp;&lt;a href=&quot;http://www.efficienza-professionale.it/mobile/index.php&quot;&gt;http://www.efficienza-professionale.it/mobile/index.php&lt;/a&gt;&lt;br /&gt;
Tutto in alpha stage, ma il primo contatto è stato ottimo.</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/1913025466714138621/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2011/07/una-bella-scoperta-jquery-mobile.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/1913025466714138621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/1913025466714138621'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2011/07/una-bella-scoperta-jquery-mobile.html' title='Una bella sorpresa: jQuery Mobile'/><author><name>Unknown</name><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-8324889730441663172.post-6400106708402209567</id><published>2011-07-06T16:13:00.002+02:00</published><updated>2011-07-07T17:34:38.972+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="google api"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><title type='text'>Gruppi su GMail con Zend GData</title><content type='html'>&lt;span class=&quot;Apple-style-span&quot;&gt;Da qualche tempo ho realizzato un&#39;integrazione tra l&#39;anagrafica di &lt;a href=&quot;http://www.efficienza-professionale.it/&quot;&gt;Kroneos MP&lt;/a&gt;  ed i contatti di GMail.&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Ho utilizzato &lt;a href=&quot;http://framework.zend.com/download/gdata&quot;&gt;Zend Gdata&lt;/a&gt; visto che avevo già ottenuto buoni risultati nell&#39;integrazione del calendario con GCalendar.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Per la gestione dei contatti però non ho trovato documentazione ed esempi come nel caso degli eventi.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;La fonte migliore che ho trovato in rete è &lt;a href=&quot;http://www.ibm.com/developerworks/opensource/library/x-phpgooglecontact/index.html&quot;&gt;questa&lt;/a&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Nell&#39;articolo non viene trattata la gestione dei gruppi, per cui condivido quello che ho concluso spulciando direttamente le API del protocollo di Google.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Supponendo che abbiate a disposizione un oggetto DOMDocument come descritto nell&#39;articolo:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;code&gt;&lt;/code&gt;&lt;br /&gt;
&lt;div&gt;&lt;div&gt;&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$doc  = new DOMDocument();&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$doc-&amp;gt;formatOutput = true;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$entry = $doc-&amp;gt;createElement(&#39;atom:entry&#39;);&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$entry-&amp;gt;setAttributeNS(&#39;http://www.w3.org/2000/xmlns/&#39; ,&#39;xmlns:atom&#39;, &#39;http://www.w3.org/2005/Atom&#39;);&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$entry-&amp;gt;setAttributeNS(&#39;http://www.w3.org/2000/xmlns/&#39; ,&#39;xmlns:gd&#39;, &#39;http://schemas.google.com/g/2005&#39;);&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$entry-&amp;gt;setAttributeNS(&#39;http://www.w3.org/2000/xmlns/&#39; ,&#39;xmlns:gContact&#39;, &#39;http://schemas.google.com/contact/2008&#39;);&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$doc-&amp;gt;appendChild($entry);&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: monospace;&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;per associare il contatto ad un gruppo basta aggiungere questo codice:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;code&gt;&lt;/code&gt;&lt;br /&gt;
&lt;div&gt;&lt;div&gt;&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$gMembership = $doc-&amp;gt;createElement(&#39;gContact:groupMembershipInfo&#39;);&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$gMembership-&amp;gt;setAttribute(&#39;href&#39;, $groupUrl );&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$gMembership-&amp;gt;setAttribute(&#39;deleted&#39;, &#39;false&#39; );&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$entry-&amp;gt;appendChild($gMembership);&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: monospace;&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;La variabile $groupUrl contiene il riferimento al gruppo che ci interessa.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Se il gruppo non esiste occorre crearlo con una procedura del genere:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$doc  = new DOMDocument();&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$doc-&amp;gt;formatOutput = true;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$entry = $doc-&amp;gt;createElement(&#39;atom:entry&#39;);&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$entry-&amp;gt;setAttributeNS(&#39;http://www.w3.org/2000/xmlns/&#39; , &#39;xmlns:atom&#39;, &#39;http://www.w3.org/2005/Atom&#39;);&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$entry-&amp;gt;setAttributeNS(&#39;http://www.w3.org/2000/xmlns/&#39; , &#39;xmlns:gd&#39;, &#39;http://schemas.google.com/g/2005&#39;);&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$doc-&amp;gt;appendChild($entry);&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;// add category&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$cat = $doc-&amp;gt;createElement(&#39;atom:category&#39;);&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$cat-&amp;gt;setAttribute(&#39;scheme&#39;, &#39;http://schemas.google.com/g/2005#kind&#39; );&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$cat-&amp;gt;setAttribute(&#39;term&#39;, &#39;http://schemas.google.com/contact/2008#group&#39; );&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$entry-&amp;gt;appendChild($cat);&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;// add group name element&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$name = $doc-&amp;gt;createElement(&#39;atom:title&#39;, &lt;nome_gruppo&gt;);&lt;/nome_gruppo&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$name-&amp;gt;setAttribute(&#39;type&#39;, &#39;text&#39; );&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$entry-&amp;gt;appendChild($name);&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$extProp = $doc-&amp;gt;createElement(&#39;gd:extendedProperty&#39;);&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$extProp-&amp;gt;setAttribute(&#39;name&#39;, &lt;descrizione_gruppo&gt;);&lt;/descrizione_gruppo&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$entry-&amp;gt;appendChild($extProp);&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$info = $doc-&amp;gt;createElement(&#39;info&#39;, &lt;info_gruppo&gt;);&lt;/info_gruppo&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$extProp-&amp;gt;appendChild($info);&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$entryResult = $gdata-&amp;gt;insertEntry($doc-&amp;gt;saveXML(), &#39;http://www.google.com/m8/feeds/groups/default/full&#39; );&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;; font-size: small;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;Il riferimento al gruppo si ottiene con&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;; font-size: small;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;font-family: &#39;courier new&#39;;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-size: x-small;&quot;&gt;$groupUrl = $entryResult-&amp;gt;id;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;Apple-style-span&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/6400106708402209567/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2011/07/gruppi-su-gmail-con-zend-gdata.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/6400106708402209567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/6400106708402209567'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2011/07/gruppi-su-gmail-con-zend-gdata.html' title='Gruppi su GMail con Zend GData'/><author><name>Unknown</name><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-8324889730441663172.post-6888003207516035553</id><published>2011-03-06T15:18:00.000+01:00</published><updated>2011-07-06T16:13:39.343+02:00</updated><title type='text'>Primo post</title><content type='html'>Yet another personal blog on the Internet!</content><link rel='replies' type='application/atom+xml' href='http://mmontesi.blogspot.com/feeds/6888003207516035553/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://mmontesi.blogspot.com/2011/03/primo-post.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/6888003207516035553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8324889730441663172/posts/default/6888003207516035553'/><link rel='alternate' type='text/html' href='http://mmontesi.blogspot.com/2011/03/primo-post.html' title='Primo post'/><author><name>Unknown</name><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></feed>