<?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: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-2210430163007979587</id><updated>2011-10-16T09:22:00.258+02:00</updated><category term='func'/><category term='func-transmit'/><category term='quartz'/><category term='operation'/><category term='guide'/><category term='runner'/><category term='java'/><category term='dynamic'/><category term='milan'/><category term='byte-code'/><category term='fedora'/><category term='template'/><category term='gdd'/><category term='bindings'/><category term='grails'/><category term='pool'/><category term='classloader'/><category term='plugin'/><category term='groovy'/><category term='script'/><category term='developer'/><category term='symbolic'/><category term='2008'/><category term='google'/><category term='recursion'/><title type='text'>Coding the life... a life coding</title><subtitle type='html'>All things I discovered during my job days and... my sleepless nights!</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-7218249593778410939</id><published>2009-02-10T22:00:00.013+01:00</published><updated>2009-02-10T22:54:51.652+01:00</updated><title type='text'>JavaApplet used to print over Serial Port</title><content type='html'>What I want to share with you today is a way to print on a serial printer (in my case I used a barcode printer).&lt;br /&gt;&lt;br /&gt;Anyone is starting reading this post could thik: "&lt;span style="font-style: italic;"&gt;Yes but is not too difficult to use serial port with Java&lt;/span&gt;". Yes but you have to think to another point: we are talking of a web-application and, our printer, is linked to the client (naturally... maybe my server is &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; directly accessible). And another interesting point is that our installed JRE &lt;span style="font-weight: bold;"&gt;could blocked&lt;/span&gt; the access to computer ports. I say "could" but it surely does if you haven't set the "policy" file or add necessary library to the JRE.&lt;br /&gt;&lt;br /&gt;Anyway... here you are my experience.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Starting Point&lt;/span&gt;&lt;br /&gt;The starting point was &lt;span style="font-style: italic;"&gt;locate the necessary libraries&lt;/span&gt;, and after some tests with official Sun &lt;a href="http://java.sun.com/products/javacomm/"&gt;javax.comm&lt;/a&gt; I've decided to use &lt;a href="http://users.frii.com/jarvi/rxtx/"&gt;RXTX&lt;/a&gt; library because they sort out with all necessary to use them on all operating systems.&lt;br /&gt;&lt;br /&gt;And now... all is very simple to do.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Applet&lt;/span&gt;&lt;br /&gt;As I said before, we need "something" printed on client machine. So we surely need a simple applet, maybe hidden.&lt;br /&gt;&lt;br /&gt;Inside &lt;span style="font-weight: bold;"&gt;init&lt;/span&gt; method you just need to initialize your ports.&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;@Override&lt;br /&gt;public void init() {&lt;br /&gt;try {&lt;br /&gt;  Enumeration portList = CommPortIdentifier.getPortIdentifiers();&lt;br /&gt;&lt;br /&gt;  if (portList.hasMoreElements()) {&lt;br /&gt;      this.portId = ((CommPortIdentifier) portList.nextElement());&lt;br /&gt;  }&lt;br /&gt;} catch (Exception e) {&lt;br /&gt;  e.printStackTrace();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//Opening port to test&lt;br /&gt;try {&lt;br /&gt;  CommPort serialPort = this.portId.open("SerialPort", 200);&lt;br /&gt;  serialPort.close();&lt;br /&gt;} catch (Exception ex) {&lt;br /&gt;  ex.printStackTrace();&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The second part of this code &lt;span style="font-style: italic;"&gt;Opening port to test&lt;/span&gt; is &lt;span style="font-weight: bold;"&gt;necessary&lt;/span&gt; to let your applet always ready to print. During my tests if I didn't try to open the serial port after getting it sometime it does not work.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;After this thing, what you need is a simple method to print what you need. I post here my code that, as I said, is used to print a barcode.&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;public void printBarCode(String code) {&lt;br /&gt;try {&lt;br /&gt;  CommPort serialPort = this.portId.open("SerialPort", 200);&lt;br /&gt;&lt;br /&gt;  PrintStream out = new PrintStream(serialPort.getOutputStream(), true);&lt;br /&gt;  out.println("N\n");&lt;br /&gt;  out.println("D13\n");&lt;br /&gt;  out.println("S2\n");&lt;br /&gt;  out.println("B240,2,0,K,4,5,83,B,\"" + code + "\"\n");&lt;br /&gt;  out.println("P1\n");&lt;br /&gt;&lt;br /&gt;  out.close();&lt;br /&gt;&lt;br /&gt;  serialPort.close();&lt;br /&gt;} catch (Exception ex) {&lt;br /&gt;  ex.printStackTrace();&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;All information I'm sending to print was getting from EPL print manual. Are just information you need to set-up printer, page and barcode style.&lt;br /&gt;&lt;br /&gt;If you need anything special you can consider your applet &lt;span style="font-style: italic;"&gt;ready to use&lt;/span&gt;. You may just package it in a jar and add the jar to your webserver / web-application.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Adding applet to a page&lt;/span&gt;&lt;br /&gt;Inside your page you can just add the applet using &lt;span style="font-style: italic;"&gt;applet&lt;/span&gt; tag or &lt;span style="font-style: italic;"&gt;object&lt;/span&gt; tag. In my case I have used applet one because the object give me some problems. In all tests I've done with applet works correctly both on IE and Firefox with windows and Linux.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;applet name=&amp;quot;barcodeprinter&amp;quot; &lt;br /&gt; id=&amp;quot;barcodeprinter&amp;quot; &lt;br /&gt; archive=&amp;quot;/BarCodeApplet.jar&amp;quot; &lt;br /&gt; code=&amp;quot;com.bytecode.priterapplet.BarCodePrinter&amp;quot; &lt;br /&gt; MAYSCRIPT=&amp;quot;true&amp;quot; &lt;br /&gt; style=&amp;quot;width: 1px; height: 1px; background: white;&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;/applet&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Note&lt;/span&gt; the &lt;span style="font-style: italic;"&gt;mayscript&lt;/span&gt; parameter. Is used to let your browser (javascript) to interact with your applet. In fact if you don't add it what you can do is just load a page with an applet that starts printing a "static text". Not so useful!&lt;br /&gt;&lt;br /&gt;More interesting is sure letting the user the selection of the "code" to print. And you can make this with a &lt;span style="font-weight: bold;"&gt;very simple&lt;/span&gt; javascript code.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;function inventario(code) {&lt;br /&gt;   var applet = document.getElementById(&amp;quot;barcodeprinter&amp;quot;);&lt;br /&gt;    if(code != '') {&lt;br /&gt;       applet.printBarCode(code);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And to call your javascript&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;&amp;lt;a href="#" onclick="inventario('selectedCode');"&amp;gt;Selected Element&amp;lt;/a&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Configuring client&lt;/span&gt;&lt;br /&gt;If you will try to use your applet without setting your JRE you couldn't print anything. What you need is just get &lt;span style="font-style:italic;"&gt;RXTXcomm.jar&lt;/span&gt; to copy in &lt;span style="font-style:italic;"&gt;JRE_HOME/lib/ext&lt;/span&gt; folder, and the correct library (DLL for Windows, .so for linux) and copy it in &lt;span style="font-style:italic;"&gt;JRE_HOME/bin&lt;/span&gt; folder. For Mac the procedure is a little bit different but you can find the instruction for all operating system directly inside the file you have downloaded from RXTX website.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Enhancements&lt;/span&gt;&lt;br /&gt;What I've tried after this thing is the dynamic configuration of the client. What you can do is copy the DLL/SO file in a client folder, load dynamically into JRE but, anyway, you have to set, at least, the .policy file on the client. Is a security setting made inside Java: from a webapplet you can't doing what you want on a client computer.&lt;br /&gt;&lt;br /&gt;Anyway here you are a little example of what I've done&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;if (System.getProperty(&amp;quot;os.name&amp;quot;).toUpperCase().contains(&amp;quot;WINDOWS&amp;quot;)) {&lt;br /&gt;   libraryName = DLL_SERIAL_NAME;&lt;br /&gt;    libraryFile = System.getProperty(&amp;quot;java.io.tmpdir&amp;quot;) + DLL_SERIAL_NAME;&lt;br /&gt;} else if (System.getProperty(&amp;quot;os.name&amp;quot;).toUpperCase().contains(&amp;quot;LINUX&amp;quot;)) {&lt;br /&gt;   if (System.getProperty(&amp;quot;os.arch&amp;quot;).contains(&amp;quot;i386&amp;quot;)) {&lt;br /&gt;       libraryName = SO_SERIAL_NAME_32;&lt;br /&gt;    } else {&lt;br /&gt;        libraryName = SO_SERIAL_NAME_64;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    char fileSeparator = System.getProperty(&amp;quot;file.separator&amp;quot;).charAt(0);&lt;br /&gt;    libraryFile = System.getProperty(&amp;quot;java.io.tmpdir&amp;quot;) + fileSeparator + SO_SERIAL_NAME;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if (!(verifyLibraryExistence(libraryFile))) {&lt;br /&gt;   copyResourceFromJar(libraryFile, libraryName);&lt;br /&gt;}&lt;br /&gt;try {&lt;br /&gt;     System.load(libraryFile);&lt;br /&gt;} catch (Exception e) {&lt;br /&gt;     e.printStackTrace();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;DLL and so files are contained in the applet JAR.&lt;br /&gt;&lt;br /&gt;Hope to be useful to anyone. And write to me if you have any kind of problem!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-7218249593778410939?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/7218249593778410939/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=7218249593778410939' title='41 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/7218249593778410939'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/7218249593778410939'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2009/02/javaapplet-used-to-print-over-serial.html' title='JavaApplet used to print over Serial Port'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><thr:total>41</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-4889575276149509041</id><published>2009-01-09T16:01:00.007+01:00</published><updated>2009-01-09T16:31:18.288+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symbolic'/><category scheme='http://www.blogger.com/atom/ns#' term='fedora'/><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><category scheme='http://www.blogger.com/atom/ns#' term='byte-code'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Symbolic v.1.2.1</title><content type='html'>I'm happy to announce you that &lt;a href="http://www.opensymbolic.org/" target="_blank"&gt;&lt;span style="font-weight: bold;"&gt;Symbolic 1.2.1&lt;/span&gt;&lt;/a&gt; is finally sort out!!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.opensymbolic.org/images/screenshots/home-admin2.png" target="_blank"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 289px; height: 236px;" src="http://www.opensymbolic.org/images/screenshots/home-admin2.png" alt="" border="0" /&gt;&lt;/a&gt;In this minor release we haven't add any kind of new features, but we worked a lot to make the application stable and stronger.&lt;br /&gt;&lt;br /&gt;The new features added are listed below:&lt;br /&gt;- Update graphical icons&lt;br /&gt;- Reviewed running operations window&lt;br /&gt;- Solved bugs during script execution&lt;br /&gt;- Moved engine to use Func 0.23+&lt;br /&gt;- Added some basic operations&lt;br /&gt;- Create a symbolic-setup scripts that help you to setup acls on func folders&lt;br /&gt;- Solved some bugs in VirtualManager execution&lt;br /&gt;- Create a Makefile to simplify the build process&lt;br /&gt;&lt;br /&gt;To make a correct installation of the application you can follow &lt;a href="http://www.opensymbolic.org/docs/v1.2.1/html/Symbolic-Tutorial.html"&gt;this tutorial&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;Any kind of comment is welcome!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-4889575276149509041?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/4889575276149509041/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=4889575276149509041' title='1 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/4889575276149509041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/4889575276149509041'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2009/01/symbolic-v121.html' title='Symbolic v.1.2.1'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-5814575095740129828</id><published>2008-10-23T19:16:00.004+02:00</published><updated>2008-11-05T21:00:46.756+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='developer'/><category scheme='http://www.blogger.com/atom/ns#' term='gdd'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><category scheme='http://www.blogger.com/atom/ns#' term='2008'/><category scheme='http://www.blogger.com/atom/ns#' term='milan'/><title type='text'>Google Developer Day 2008 - Milan</title><content type='html'>For the second year, Google has decide to make a &lt;a href="http://code.google.com/intl/it/events/developerday/2008/home.html"&gt;Google Developer Day&lt;/a&gt; in Milan. For me was the first time at a Google event and I found it &lt;b&gt;really great&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;I arrived at the Hotel got for the event (Nhow Hotel, Via Tortona 35 in Milan) at 9 o'clock in the morning, and there was a huge number of person waiting to get into hall. So I start with a little queue (about 15 minutes waiting for solve my registration) and hoping to enter. In fact I didn't make the registration for the event but I was there to substitute a colleague: no one has asked me any king of document that could prove that I'm the person I was saying to be! :) So really cool... for a day I wasn't me!! :)&lt;br /&gt;&lt;br /&gt;Anyway... after registration where I choose my session (I got all sessions I decided to see... not bad ;)) I start "walking" on the hall, where there was a coffee break for a little breakfast, and looking for the programmers present to the event. As I imagined I met some person I knew! (the IT is a little world!! :P)&lt;br /&gt;At 10 o'clock all people start moving in the "light blue room" to listen the little introduction from the Italian Marketing Manager (I can't remember the name but... was a woman!) and something about Google technologies listening &lt;span style="font-weight: bold;"&gt;Brian Fitzpatrick&lt;/span&gt;, a google software engineer. No news listing this presentation: the message send to all developer was "Google is the best!" ;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;App Engine (&lt;span style="font-style: italic;"&gt;Kevin Gibbs&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;Introduction to Google App Engine technology. Basically you can write your application (in different language) and "deploy" it on Google systems. You have only some limitations in your "free account" but Google can assure you that all applications are completely scalable: if you need more resources (application on cluster) google gives them to you. What you need to do, is just to write your code. You also have some API that help you to make some operations, for example imaging manipulation, and using this API you have an operation that, if it needs more cpu time, for example, it could has it!&lt;br /&gt;Not bad!! Naturally the best thing is the possibility to test this technology for free!&lt;br /&gt;I've tried to ask something about cluster management (if we can for example manage the http session synchronization) and the answer wans't a "NO" but something that was walking about "NO"! :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Google Data API (&lt;span style="font-style: italic;"&gt;Jochen Hartmann&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;This session was really quiet. A panorama about Google Data API, written for many different languages, that you can use to make in communication your application with Google World! Picasa to get Photos, Google Maps, YouTube and all other things.&lt;br /&gt;I've no idea on how I could use all these things... but now I know what can I do and how! :P&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Geo (&lt;span style="font-style: italic;"&gt;Nicola Ferioli&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;Wow an Italian Talk!! I was exited just before the talk because, maybe (or surely) for the presence of an italian speaker, during exposition there were many questions (so many interruption of the talk) and at the end of the talk I didn't have time to talk with Nicola about geo. I hope I'll have time to talk with him in the future.&lt;br /&gt;All of us have tried to use Google Earth and surely Google Maps, here the presentation was about the integration of these tools inside other Web Application. What you can do is really impressive. You can simply insert a map in your page and then add to this "image" a second layer with some markers to shown some point-of-interest on your map. Naturally generated map is the same you can use on google web site, so you can navigate it and change details and zoom levels.&lt;br /&gt;If you "don't like" (or better you don't need) the Google Map, you can also change the "skin" you get from google with your own pictures. So what you get from google is only the engine to navigate your image and add over it some markers.&lt;br /&gt;&lt;br /&gt;Same things could do using the newest Earth plugin: you can insert in you web page an "image" get from Earth and navigate it!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Intro to Android&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Android was the most impressive talk I've seen to GDD. The real "presentation" of operating system was just about the main features offered by Android, what has gotten my attention was the "demo application" that speaker (unfortunately I can't remember the name) has realized using eclipse and android plugin. In 30 minutes, showing also all the features offered by eclipse android plugin, he has created a simple Java application that can read contacts from phone contacts list and show results to the user.&lt;br /&gt;For a Java programmer is really simple to create a new application for the phone and, in my opinion, this will be the cool feature to get the market and move many users to this new phone (both Symbian users and iPhone users ;)).&lt;br /&gt;Yesterday (22 Oct 2008) the &lt;a href="http://www.google.com/intl/en_us/mobile/android/hpp.html"&gt;first Google Phone&lt;/a&gt; (with HTC hardware) is sorted out in the US... We have just to wait to buy phone also here in europe! :)&lt;br /&gt;&lt;br /&gt;Was a really cool events and I have to thanks my colleague Luca for the opportunity! ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-5814575095740129828?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/5814575095740129828/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=5814575095740129828' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/5814575095740129828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/5814575095740129828'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2008/10/google-developer-day-2008-milan.html' title='Google Developer Day 2008 - Milan'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-153501290718627139</id><published>2008-09-04T17:40:00.003+02:00</published><updated>2008-09-04T17:43:27.791+02:00</updated><title type='text'>Going to FudCon</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fedoraproject.org/wiki/FUDCon/FUDConBrno2008"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_mcrRJdyp-jg/SMABvxUYj7I/AAAAAAAAE8c/7gxhL3PFXvY/s400/going-to-fudcon.png" alt="" id="BLOGGER_PHOTO_ID_5242191886463569842" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;It's time to get my baggage and take the plane for Brno.&lt;br /&gt;&lt;br /&gt;See you there guys!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-153501290718627139?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/153501290718627139/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=153501290718627139' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/153501290718627139'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/153501290718627139'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2008/09/going-to-fudcon.html' title='Going to FudCon'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_mcrRJdyp-jg/SMABvxUYj7I/AAAAAAAAE8c/7gxhL3PFXvY/s72-c/going-to-fudcon.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-539667575143892014</id><published>2008-07-30T16:45:00.002+02:00</published><updated>2008-07-30T16:54:09.231+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dynamic'/><category scheme='http://www.blogger.com/atom/ns#' term='plugin'/><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><category scheme='http://www.blogger.com/atom/ns#' term='classloader'/><title type='text'>Grails - Dynamic Plugins - Isolated Classloader</title><content type='html'>To prevent a possible jars conflict during dynamic plugin execution (what I was talking about in my previous post), I found a simple solution that I'm pasting for you here:&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;class DefaultPluginJob {&lt;br /&gt;&lt;br /&gt;   static triggers = { }&lt;br /&gt;&lt;br /&gt;   static cachedClassLoader = [:]&lt;br /&gt;&lt;br /&gt;   def execute(context) {&lt;br /&gt;&lt;br /&gt;       def libraryFolder = context.mergedJobDataMap.get("libraryFolder")&lt;br /&gt;&lt;br /&gt;       if (!cachedClassLoader[context.mergedJobDataMap.get("jobName")]) {&lt;br /&gt;           log.debug "Constructing class loader for ${context.mergedJobDataMap.get("jobName")}"&lt;br /&gt;           def urls = []&lt;br /&gt;           libraryFolder?.eachFile {library -&amp;gt;&lt;br /&gt;               log.debug "Adding file ${library}"&lt;br /&gt;               urls.add(library.toURL())&lt;br /&gt;           }&lt;br /&gt;           cachedClassLoader[context.mergedJobDataMap.get("jobName")] = new URLClassLoader(urls as URL[], this.class.classLoader)&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       def file = context.mergedJobDataMap.get("scriptFile")&lt;br /&gt;&lt;br /&gt;       Binding binding = new Binding(context.mergedJobDataMap);&lt;br /&gt;       GroovyShell shell = new GroovyShell(cachedClassLoader[context.mergedJobDataMap.get("jobName")], binding);&lt;br /&gt;       def scriptResult = shell.evaluate(file.text);&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;A new URLClassLoader will be created for each script that need to be run from my job, and it will contain a copy of parent class loader and new jars needed for the script execution.&lt;br /&gt;&lt;br /&gt;What you can find here is the current solution I'm using in my application: all classloaders are cached in a static map (thanks again to Sergey for suggestion ;)) and passed to GroovyShell for script exection. Using cache for classloader granted that I've only one classloader generation for each script (and not one for each job execution). You loose memory to get perfermance! ;)&lt;br /&gt;&lt;br /&gt;Waiting for comments about this way to run a java web application! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-539667575143892014?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/539667575143892014/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=539667575143892014' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/539667575143892014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/539667575143892014'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2008/07/grails-dynamic-plugins-isolated.html' title='Grails - Dynamic Plugins - Isolated Classloader'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-2109372230513290864</id><published>2008-07-26T11:05:00.003+02:00</published><updated>2008-07-28T12:14:27.823+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dynamic'/><category scheme='http://www.blogger.com/atom/ns#' term='plugin'/><category scheme='http://www.blogger.com/atom/ns#' term='quartz'/><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Grails - Dynamic Plugins for your applications</title><content type='html'>The new functionality offers from Groovy/Grails make you able to write a very dynamical application and the possibility to add some new features to your web application at run-time!! Naturally we are exiting a "little bit" from JEE standards where our library/scritps/class and so on, must be in your war or provided from application server.&lt;br /&gt;What I think about this, is that this way to see the development is a little bit old and could bring java to death! I'm dramatic, I know, but there is lot of confusion inside java, java standard and all java project.&lt;br /&gt;It's time to change!! :)&lt;br /&gt;&lt;br /&gt;Anyway...&lt;br /&gt;&lt;br /&gt;What I'll explain is the way that we are using to add plugins (some functions) to OpenSymbolic, after application installation and, if you want, after webserver startup (I don't know what JBoss thinks about this... I'll do some test when all will be ready).&lt;br /&gt;&lt;br /&gt;Our goal was to obtain a way to add some schedulable functions (Quartz Job) to our application leaving to user the decision about which he needs and which not (in a future article we will see the real usage in Symbolic).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;First step&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Question:&lt;/span&gt; How can I add a Job Dynamically to my scheduler?&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Answer:&lt;/span&gt; at the moment I can't! :(&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Solution:&lt;/span&gt; I called &lt;a href="http://www.linkedin.com/in/nebolsin"&gt;Sergey Nebolsin&lt;/a&gt;, the Quartz plugin developer, exposing my problem, and in ONE NIGHT (underline well ONE), he send me the implementation.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Lesson learned:&lt;/span&gt; If I need something for the following day... I will have to call Sergey!! :P (Really thanks again for your work and help Sergey!!)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Second step&lt;/span&gt;&lt;br /&gt;Writing a bit of code to see if I can really do what I'm thinking.&lt;br /&gt;&lt;br /&gt;Here what I have.&lt;br /&gt;&lt;br /&gt;All my plugins will be contained in a specific folder on my machine (configured in configuration file of my application).&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;/etc/symbolic/plugins&lt;br /&gt;   -&amp;gt; /nagios_plugin&lt;br /&gt;   -&amp;gt; /msn_plugin&lt;br /&gt;   -&amp;gt; /dont_know_plugin&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Each of these folders contains the file I need: in my test a configuration file and one script file.&lt;br /&gt;So... with a simple script I could try to scan these folders look for what I need.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;import org.codehaus.groovy.grails.commons.ConfigurationHolder&lt;br /&gt;&lt;br /&gt;class PluginService {&lt;br /&gt;&lt;br /&gt;   boolean transactional = false&lt;br /&gt;&lt;br /&gt;   static CONFIG_FILE_EXT = 'conf'&lt;br /&gt;   static SCRIPT_FILE_EXT = 'groovy'&lt;br /&gt;   static LIB_FOLDER = 'lib'&lt;br /&gt;&lt;br /&gt;   public void init() {&lt;br /&gt;       //Scan Plugins Folder&lt;br /&gt;       def pluginsFolder = ConfigurationHolder.config.plugin.folder&lt;br /&gt;       log.debug "Scanning plugin folder: ${pluginsFolder}"&lt;br /&gt;       if (pluginsFolder) {&lt;br /&gt;           new File(pluginsFolder).eachDir {dir -&amp;gt;&lt;br /&gt;               log.debug "Directory found: ${dir}"&lt;br /&gt;               def dataMap = [:]&lt;br /&gt;             &lt;br /&gt;               //Read Plugin File and configuring it&lt;br /&gt;               dir.eachFile {file -&amp;gt;&lt;br /&gt;                   if (file.isFile()) {&lt;br /&gt;                       if (file.name.contains(CONFIG_FILE_EXT)) {&lt;br /&gt;                           log.debug "File ${file.name} is the configuration file"&lt;br /&gt;                           def pluginConfiguration = readConfigFile(file)&lt;br /&gt;                           dataMap['pluginName'] = pluginConfiguration.get("job.name")&lt;br /&gt;                           dataMap['cronString'] =  pluginConfiguration.get("job.cron")&lt;br /&gt;                       } else if (file.name.contains(SCRIPT_FILE_EXT)) {&lt;br /&gt;                           log.debug "File ${file.name} is the script file"&lt;br /&gt;                           dataMap['scriptFile'] = file&lt;br /&gt;                       } else {&lt;br /&gt;                           log.debug "File ${file.name} will be ignored!"&lt;br /&gt;                       }&lt;br /&gt;                   } else {&lt;br /&gt;                       if (file.name.equals(LIB_FOLDER)) {&lt;br /&gt;                           log.debug "Lib folder found... adding jars to classpath."&lt;br /&gt;                       }&lt;br /&gt;                   }&lt;br /&gt;               }&lt;br /&gt;               DefaultPluginJob.schedule(dataMap['cronString'], dataMap)&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       else {&lt;br /&gt;           logger.info "No plugins folder set. Nothing to load!"&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   def readConfigFile = {file -&amp;gt;&lt;br /&gt;       Properties prop = new Properties()&lt;br /&gt;       if (file) {&lt;br /&gt;           prop.load (new FileInputStream(file))&lt;br /&gt;       }&lt;br /&gt;       prop&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;It's just a simple test... there are many improvements to do! ;)&lt;br /&gt;&lt;br /&gt;Class "DefaultPluginJob" is a simple Quartz Job, that you can create in a standard grails way, and, with a new plugin release made by Sergey, it has some static methods that you can use to add your job to your quartz scheduler!&lt;br /&gt;&lt;br /&gt;Here is the code of Job:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;import org.quartz.JobDataMap&lt;br /&gt;import org.quartz.JobExecutionContext&lt;br /&gt;&lt;br /&gt;class DefaultPluginJob {&lt;br /&gt;&lt;br /&gt;   static triggers = { }&lt;br /&gt;&lt;br /&gt;   def execute(context) {&lt;br /&gt;&lt;br /&gt;       String instName = context.getJobDetail().getName();&lt;br /&gt;       String instGroup = context.getJobDetail().getGroup();&lt;br /&gt;       def file = context.mergedJobDataMap.get("scriptFile")&lt;br /&gt;&lt;br /&gt;       Binding binding = new Binding();&lt;br /&gt;       GroovyShell shell = new GroovyShell(binding);&lt;br /&gt;&lt;br /&gt;       def scriptResult = shell.evaluate(file.text);&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;It seems very simple, no? :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Third step&lt;/span&gt;&lt;br /&gt;To create a real extension of your application, you may need to add also some libraries used by your script: you cannot add all existing java libraries to your application because someone would create a plugin that will use that libraries! ;)&lt;br /&gt;&lt;br /&gt;A very simple way we have found to solve this problem is adding a lib sub-folder to your plugin folder, where you can put all your libraries.&lt;br /&gt;The plugin server, scanning folders, will add your jars to root class loader in this way:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;this.class.classLoader.rootLoader.addURL(new URL("${file}"))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;By now you can use all classes contained in your added jar files! :D&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Future...&lt;/span&gt;&lt;br /&gt;What I need to solve now, is a way to prevent jar conflict. Add all to root class loader, in fact, could make some problems to your application or simply to your other plugins.&lt;br /&gt;I think that a solution could be write something inside your job, that will add your library only to your job instances during (before) execution of the script!&lt;br /&gt;If anyone has any ideas about that... is welcome! :P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-2109372230513290864?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/2109372230513290864/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=2109372230513290864' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/2109372230513290864'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/2109372230513290864'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2008/07/grails-dynamic-plugins-for-your.html' title='Grails - Dynamic Plugins for your applications'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-5861807106275190282</id><published>2008-07-24T09:02:00.003+02:00</published><updated>2008-12-09T19:10:28.950+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symbolic'/><category scheme='http://www.blogger.com/atom/ns#' term='operation'/><category scheme='http://www.blogger.com/atom/ns#' term='runner'/><title type='text'>Symbolic - Operations Runner</title><content type='html'>Symbolic engine, or OperationRunner, is something like what we have seen for the scripts: a couple of job/thread that going in polling over database, look for ready operation, or completed (success/failed) operations.&lt;br /&gt;All this operation will be completely asynchronous both for user and symbolic application: a ControllerJob will call each "n" seconds to verify the state of ran operation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_mcrRJdyp-jg/SIgpF41wQ2I/AAAAAAAAEdc/vvT8xvP57H8/s1600-h/OperationRunner.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_mcrRJdyp-jg/SIgpF41wQ2I/AAAAAAAAEdc/vvT8xvP57H8/s400/OperationRunner.png" alt="" id="BLOGGER_PHOTO_ID_5226472548697391970" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Select machine(s), decide which operation he want, and complete (if required) the parameters needed for the execution&lt;/li&gt;&lt;li&gt;An entry is stored in database and set in "ready state"&lt;/li&gt;&lt;li&gt;RunnerJob (is not the same job used to run scripts!) check, each "x" seconds, if there's any operation to run.&lt;/li&gt;&lt;li&gt;When it finds something, using func api, he call func and change the operation status in database: running state&lt;/li&gt;&lt;li&gt;Func, through func-transmit script, will call required minion creating an "async job" (the job id will be returned to RunnerJob and stored in database)&lt;/li&gt;&lt;li&gt;Another job, the ControllerJob, verifies if there is any running operation (contacting database) and, using stored job id, it asks to Func the state of that job&lt;/li&gt;&lt;li&gt;When it receives a "complete job" response (could be success or failed) store the information in database setting also the status to correct value (success/error)&lt;/li&gt;&lt;li&gt;User can see the result for the operation he called.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-5861807106275190282?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/5861807106275190282/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=5861807106275190282' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/5861807106275190282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/5861807106275190282'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2008/07/symbolic-operations-runner.html' title='Symbolic - Operations Runner'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_mcrRJdyp-jg/SIgpF41wQ2I/AAAAAAAAEdc/vvT8xvP57H8/s72-c/OperationRunner.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-8155422020637293730</id><published>2008-07-24T07:55:00.001+02:00</published><updated>2008-07-24T07:57:12.627+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symbolic'/><category scheme='http://www.blogger.com/atom/ns#' term='operation'/><category scheme='http://www.blogger.com/atom/ns#' term='guide'/><title type='text'>What is symbolic operations?</title><content type='html'>As official guide illustrates, symbolic administrator can create function users could do, simply adding new operations. An operation is an object built using func module, method and parameters.&lt;br /&gt;&lt;br /&gt;What administrator has to do to add a new operation is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Assign a name that will be shown to users&lt;/li&gt;&lt;li&gt;Select a func operation, selecting module and method over that module. i.e. module: command, method: run&lt;/li&gt;&lt;li&gt;Add some optional parameters to complete the operation. For example if he has coded the operation over module command with method run, he need to decide which linux command function he want to execute.&lt;/li&gt;&lt;li&gt;Add some optional parameters that will be ask to user before operation run. To make completely dynamic the operation coding, in fact, something need to be added during the execution by the user. For example, administrator could decide that for a specific group of users, must be created an operation to make able the execution of all linux command. So he has to code an operation over "command run" and the add a parameter named "Command to run" that users will complete before operation running.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Authority assignment is the last operation he has to do to shown new operation to the user. In fact, all symbolic operations, machines and scripts are shown only to users that are enabled to use.&lt;br /&gt;&lt;br /&gt;At runtime this operation will be completed with machine hostname (the one where user click before operation selection), the (optional) parameters that user must complete and all is stored in a table with "ready state" attached. Will be symbolic engine to select ready operation and call func for the execution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-8155422020637293730?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/8155422020637293730/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=8155422020637293730' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/8155422020637293730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/8155422020637293730'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2008/07/what-is-symbolic-operations.html' title='What is symbolic operations?'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-3410742664100896248</id><published>2008-07-23T20:45:00.003+02:00</published><updated>2008-12-09T19:10:29.061+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pool'/><category scheme='http://www.blogger.com/atom/ns#' term='symbolic'/><category scheme='http://www.blogger.com/atom/ns#' term='operation'/><category scheme='http://www.blogger.com/atom/ns#' term='script'/><title type='text'>Symbolic: Synch Operation Pool</title><content type='html'>Most of the processes, script or operation, you can run using Symbolic are asynchronous, this means that multiprocess/thread control is delegated to func. There are some other situation where you may need run process in synchronous mode: some admin procedures should be run directly waiting for the response (i.e is needed to going on or to complete symbolic configuration).&lt;br /&gt;Following the standard "running channel" used to run async script, can generate a bottleneck: my RunnerJob must wait the end of ran process and so it's impossible to run any other operation till the end of the async one.&lt;br /&gt;&lt;br /&gt;To solve this problem Symbolic has a Pool Manager used and called from RunnerJob. Is a bit more than simple synchronized list of processes: you can decide how many "concurrent" synchronous processes you want and it exposes some method to "book" your process execution, send process and check process status.&lt;br /&gt;&lt;br /&gt;Following diagram exposes how Symbolic manages synch operations.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_mcrRJdyp-jg/SId-LjJKkfI/AAAAAAAAEdU/uLiJi7QdJJg/s1600-h/SyncPool.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_mcrRJdyp-jg/SId-LjJKkfI/AAAAAAAAEdU/uLiJi7QdJJg/s400/SyncPool.png" alt="" id="BLOGGER_PHOTO_ID_5226284629464093170" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;User or administrator "try" to run a synch operation&lt;/li&gt;&lt;li&gt;User calls reach the RunnerJob that, calling PoolManager try to book a place for sync job execution&lt;/li&gt;&lt;li&gt;If there is a place to process user request, PoolManager responds with the position assigned in pool list. If you want this is what happens when you want to book an hotel room or a theater seat: you call, if there's what you ask you received booking number, in any other case you have to wait.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;If JobRunner receives a useful position in the pool list, he start the process asked from the user and then send reference to running process and provided position to PoolManager. If JobRunner receives a "no free places found" it returns an answer the user with an error message.&lt;/li&gt;&lt;li&gt;Process is queued in the pool list and it goes ahead with the execution&lt;/li&gt;&lt;li&gt;Any "X" seconds there is another job, ControllerJob, that calls PoolManager asking if there is any process that has finished the execution&lt;/li&gt;&lt;li&gt;If something is found a messege ControllerJob sends a message to User with the execution result.&lt;/li&gt;&lt;/ol&gt;This kind of implementation is something like asynchronous call for the Symbolic engine because there is no "internal" process that wait for the execution end. It's only an synch call for the user that can do nothing more on the application till the end of the process he ran.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-3410742664100896248?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/3410742664100896248/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=3410742664100896248' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/3410742664100896248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/3410742664100896248'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2008/07/symbolic-synch-operation-pool.html' title='Symbolic: Synch Operation Pool'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_mcrRJdyp-jg/SId-LjJKkfI/AAAAAAAAEdU/uLiJi7QdJJg/s72-c/SyncPool.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-2702148141862850884</id><published>2008-07-22T23:48:00.000+02:00</published><updated>2008-12-09T19:10:29.184+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symbolic'/><category scheme='http://www.blogger.com/atom/ns#' term='script'/><title type='text'>Symbolic - Scripts Runner</title><content type='html'>In this article we will see how Symbolic runs a pre-configured user script in asynchronous mode.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Why we say pre-configured?&lt;/span&gt;&lt;br /&gt;In Symbolic application, the administrator can "upload" on the server a specific "well-formed" script, written in Pyhton, Groovy, Bash or Perl. After this procedure Symbolic recognizes the list of installed scripts and proposes them to enable users. (As we have seen in a previous article)&lt;br /&gt;&lt;br /&gt;This schema illustrates the main steps follow to execute script and propose result to the user.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_mcrRJdyp-jg/SIbcWygSuqI/AAAAAAAAEdE/vcW6P2jd6Uo/s1600-h/ScriptRunner.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_mcrRJdyp-jg/SIbcWygSuqI/AAAAAAAAEdE/vcW6P2jd6Uo/s400/ScriptRunner.png" alt="" id="BLOGGER_PHOTO_ID_5226106701682490018" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;First of all, a logged user has to select a script from the list&lt;/li&gt;&lt;li&gt;This selection produces an entry in Symbolic Database with script information and state READY (like in a MicroProcessor state ready means that operation is waiting the execution).&lt;/li&gt;&lt;li&gt;A "runner-process" (Quartz Job for Java Developers), launched at the application start-up, queries database in polling looking for new ready-state scripts. By default it is configured to wake up each 5 seconds, but the administrator could decide to change this polling time with a simple modification to Symbolic configuration file&lt;/li&gt;&lt;li&gt;When the "runner-process" find a new ready-state script, runs it using a new "System" process (a process external to Symbolic application) and set the state to RUNNING. Whereas the script is to run in async mode, the runner-process job is finished.&lt;/li&gt;&lt;li&gt;The script can communicate with Symbolic application through a provided Xml-RPC Server (embedded in Symbolic and reachable at "symbolic/api/xmlrpc" address).&lt;br /&gt;The access to the server xml-rpc is protected with username and password. This provides an other step in Symbolic security, making only well-formed script able to communicate with Symbolic application.&lt;br /&gt;By default a user "externalscript" is created during the Symbolic installation (with default password externalscript); the administrator could change this credentials so only "really-certified" scripts could communicate with that Symbolic instance.&lt;br /&gt;At the moment Xml-Rpc server exposes only two methods: getAllMachines and postInformation. The first one is used to get list of Symbolic certified and controlled machines; the second one is used to communicate the script execution result to Symbolic.&lt;/li&gt;&lt;li&gt;When postInformation is invoked, xml-rpc server get the result and saved the correct status in the database. Each ran script knows the database ID that must be posted with the result information. This is the only way that make symbolic able to recognized information posted.&lt;/li&gt;&lt;li&gt;If user try to get ran script status in this moment, it find script result information (with associated error or success result).&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-2702148141862850884?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/2702148141862850884/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=2702148141862850884' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/2702148141862850884'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/2702148141862850884'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2008/07/symbolic-scripts-runner.html' title='Symbolic - Scripts Runner'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_mcrRJdyp-jg/SIbcWygSuqI/AAAAAAAAEdE/vcW6P2jd6Uo/s72-c/ScriptRunner.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-546433081300979883</id><published>2008-07-22T23:37:00.000+02:00</published><updated>2008-07-23T09:37:40.403+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symbolic'/><category scheme='http://www.blogger.com/atom/ns#' term='script'/><title type='text'>Well-Formed Symbolic Script</title><content type='html'>The first step to make a well-formed script is to add, at the beginning of the script file in a "commented area", a series of tag that will recognize from Symbolic and adapt the application accordingly to the script.&lt;br /&gt;&lt;br /&gt;To write your own script you can choose between one of the four supported languages: &lt;span style="font-weight: bold;"&gt;Groovy&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;Python&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;Bash&lt;/span&gt;, &lt;span style="font-weight: bold;"&gt;Perl&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The current accepted tag are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;@Name&lt;/span&gt;: the name for your script. Is used to shown to the users your saved script.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;@Author&lt;/span&gt;: name and references of the script's author.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;@Type&lt;/span&gt;: type of your script. Valid values are: python, groovy, bash, perl&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;@Description&lt;/span&gt;: a full description to inform users about what script really does.&lt;/li&gt;&lt;/ul&gt;Putting just this four simple tags at the beginning of your script, and copying your script in symbolic scripts folder, make Symbolic application able to recognized the script so that users can run it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;XML-RPC Communication&lt;/span&gt;&lt;br /&gt;Symbolic exposes a service to which script can connect to get some useful information (like a Symbolic certified machines) and to post execution result.&lt;br /&gt;All "user-runnable" scripts in fact are launched in a way that can we call "asynchronous": Symbolic does not wait the answer from each ran script; so the only way that we can use to communicate the result to Symbolic if calling it through a defined service.&lt;br /&gt;In Symbolic there is an implementation of XML-RPC server that exposes a method to post result from script:postInformation(result). So in your scripts you have to put some lines of code that call XML-RPC server to post the result information.&lt;br /&gt;When Symbolic call a script provides these parameters:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-a&lt;/span&gt;: asynchronous execution. Caller will not wait for script answer, so result must be posted through xml-rpc server&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-p proccesID&lt;/span&gt;: is the Symbolic identification of ran script&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-s serverAddress&lt;/span&gt;: xml-rpc server address.&lt;br /&gt;&lt;br /&gt;For example if you have a python script, symbolic will call it using something like:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;   python script.py -a -p 10 -s http://localhost:8080/symbolic/api/xmlrpc&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;So you need to get this parameters inside your script if you want to communicate with Symbolic.&lt;br /&gt;&lt;br /&gt;The answer that Symbolic expects must be formatted as dictionary/map with these information:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;   ["process_id":SYMBOLIC_PROC_ID,"status":process_status,"response":some_information]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;process_id&lt;/span&gt;: is the process id provided during symbolic script invocation.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;status&lt;/span&gt;: is the result of your script/process (0:Success, 1:Error)&lt;br /&gt;&lt;span style="font-style: italic;"&gt;response&lt;/span&gt;: what you want. It's better something Human-Readable because will be shown to user without any kind of parsing.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Authentication&lt;/span&gt;&lt;br /&gt;The symbolic rpm server is secured behind a password protection. So when you create, inside your script, an instance of xmlrpc client you need to post BasicAuthentication username and password or you will get an "access forbidden error" from Symbolic.&lt;br /&gt;As default setting there is an user that scripts can use to connect to server:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;username: externalscript&lt;br /&gt;password: externalscript&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Symbolic administrator could change this information or create many other script-enable accounts. These account must have associated a custom script authority (like default created during installation) or root authority (it's better to do not use this authority to make script enable to communicate with symbolic!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-546433081300979883?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/546433081300979883/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=546433081300979883' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/546433081300979883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/546433081300979883'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2008/07/well-formed-symbolic-script.html' title='Well-Formed Symbolic Script'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-6641008903471564497</id><published>2008-07-22T23:28:00.000+02:00</published><updated>2008-07-23T09:38:04.414+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='func-transmit'/><category scheme='http://www.blogger.com/atom/ns#' term='func'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='bindings'/><title type='text'>Make a Func Binding - How you can interact with func-transmit</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Func-Transmit&lt;/span&gt;&lt;br /&gt;Func-transmit operates over standard-in/standard-out with data formatted with JSON or YAML (you can choose during invocation) and it's used to make func calls from another language easier than CLI calls. You can call func-transmit making information over stdin to invoke a func call on a specific minion and receiving response over stdout.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;How you can invoke func-transmit&lt;/span&gt;&lt;br /&gt;For your func-transmit invocation you need to decide whitch kind of supported parser/serializer you want to use. At the moment func-trasmit accepts only JSON or YAML messages and responds using the same dialect you have chosen during invocation. This decision was made taking care to serializers and their different language spread. YAML and JSON have both libraries packaged for many languages, so it should be easy to create a func binding using these parsers.&lt;br /&gt;You can invoke func-transmit using a command like this:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;func-transmit --json &amp;lt; data&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;--yaml&lt;/span&gt; instead of &lt;span style="font-style: italic;"&gt;--json&lt;/span&gt; if you want to use YAML parser (could be also &lt;span style="font-style: italic;"&gt;-j &lt;/span&gt;or &lt;span style="font-style: italic;"&gt;-y&lt;/span&gt; for json or yaml)&lt;br /&gt;Data must be send to func-transmit as standard input ('&lt;' in CLI syntax) and could be a file or directly the "String" with all information  &lt;span style="font-weight: bold;"&gt;Information expected during func-transmit invocation&lt;/span&gt;&lt;br /&gt;You have to package your data to invoke func-transmit in a dictionary/map. Here the list of all parameters accepted.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;clients&lt;/span&gt;: (Required) list of client you want to call. Could be list,single string or special character ("*").&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;aysnc&lt;/span&gt;: (Optional-Default False) boolean that say if you want to call func in async mode (True) or in synch mode (False)&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;nforks&lt;/span&gt;: (Optional-Default 1) Number of forks you want to use to execute the calls to your clients. For example, if you have to execute a command on 10 different minions, you can use nforks=2 and each one call and get results on 5 minions.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;module&lt;/span&gt;: (Required**) name of the module you want to call&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;method&lt;/span&gt;: (Required) method inside that module to invoke&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;parameters&lt;/span&gt;: (Optional-Default None) some additional parameters&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;** there are some specific "local" methods that, at the moment, do not need the module parameter (you can set what you want). But it's only to get information such as list_minions or something other local call.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Response returned&lt;/span&gt;&lt;br /&gt;When func-transmit execution ends the response is packaged following the same structure of call. So you will receive a json/yaml message containing a dictionary with machinename and result.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;{"host1": "result for your call", "host2":"result", ...}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The same structure is kept also if you call func-transmit with a single minion.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Async Calls&lt;/span&gt;&lt;br /&gt;Asynchronous calls are an exception to what we have seen so far. In fact func-transmit responds to an invocation with a simple "String" containing the func process id (parsed with the selected dialect... but not really needed).&lt;br /&gt;If you want to get results from a previous func-transmit call, you have to package a message containing:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;clients: "*"&lt;br /&gt;method: "job_status"&lt;br /&gt;parameters: ["your process id"]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;What you get as result of this call is a tuple with process_status and response packaged as "normal" func-transmit response:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;[1, {host1:response, host2:response}]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Possible process statuses are:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;0&lt;/span&gt;: your job is still running&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1&lt;/span&gt;: finished&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2&lt;/span&gt;: "lost in space". We cannot find job associated to provided pid&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3&lt;/span&gt;: partial (executing but hasn't finished yet)&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4&lt;/span&gt;: remote error&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-6641008903471564497?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/6641008903471564497/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=6641008903471564497' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/6641008903471564497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/6641008903471564497'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2008/07/make-func-binding-how-you-can-interact.html' title='Make a Func Binding - How you can interact with func-transmit'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2210430163007979587.post-4101330548553526987</id><published>2008-07-22T07:05:00.000+02:00</published><updated>2008-07-22T12:53:58.321+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='recursion'/><category scheme='http://www.blogger.com/atom/ns#' term='template'/><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Generate a simple tree-menu in Grails</title><content type='html'>&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;It's seems one of the many posts you can find in internet that helps you to generate a tree-menu using javascript/java/... What I want to illustrate is a method that use recursion in back-end (java code that generate the Tree structure) and front-end (a gsp that shown the tree calling itself!!).&lt;br /&gt;&lt;br /&gt;In fact, the start point, is that our page is not a "simple" page but is written as grails templates.&lt;br /&gt;Template is a grails way to get your front-end code structured and provide an highly re-usable mechanism that you can call simply using a defined taglib.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;class TreeMenu {&lt;br /&gt;&lt;br /&gt;    def addNode = {nodeElement, machine, tagList -&amp;gt;&lt;br /&gt;        def nodes = [:]&lt;br /&gt;        nodes[machine.hostName] =  machine&lt;br /&gt;        def newList = tagList - nodeElement&lt;br /&gt;        newList?.each {currentTag -&amp;gt;&lt;br /&gt;            nodes[currentTag.name] = addNode(currentTag, machine, newList)&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        nodes&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Is an extraction of my program codes... in the original version the data structure is not a simple Map but I've a complex object, so I can do, for example, a check if there is a node with current provided name and so on.&lt;br /&gt;What this code try to do, is to add a Machine to each Tree-Tag I'm sending to function as a List.&lt;br /&gt;"nodeName" is the current node where I want my machine&lt;br /&gt;"machine" is the object name I want in my tree&lt;br /&gt;"tagList" is the list of all tree-node where my machine will be put&lt;br /&gt;&lt;br /&gt;For example, I could have this situation&lt;br /&gt;&lt;br /&gt;machine: "TryMachine"&lt;br /&gt;tagList: ["A", "B"]&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;TreeMenu.addNode(&amp;quot;Root&amp;quot;, machine, tagList)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The result of this method invokation will be:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Root &lt;br /&gt; &amp;#124;-&amp;gt; A&lt;br /&gt; &amp;#124;   &amp;#124;-&amp;gt;B&lt;br /&gt; &amp;#124;   &amp;#124;  &amp;#124;TryMachine&lt;br /&gt; &amp;#124;   &amp;#124;TryMachine&lt;br /&gt; &amp;#124;-&amp;gt; B&lt;br /&gt; &amp;#124;   &amp;#124;TryMachine&lt;br /&gt; &amp;#124;   &amp;#124;-&amp;gt; A&lt;br /&gt; &amp;#124;   &amp;#124;   &amp;#124;TryMachine&lt;br /&gt; &amp;#124; TryMachine&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Display the tree&lt;/span&gt;&lt;br /&gt;The extraordinary feature offers by grails is, as I said, the usage of recursion on the front-end, that make you able to create a page without insertion of some java codes: all just with default grails taglibs.&lt;br /&gt;Here an example gets from my code:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;g:each in=&amp;quot;${nodes}&amp;quot; var=&amp;quot;element&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;g:if test=&amp;quot;${element.value instanceof Machine}&amp;quot;&amp;gt;&lt;br /&gt;            ${element.name}&lt;br /&gt;    &amp;lt;/g:if&amp;gt;&lt;br /&gt;    &amp;lt;g:else&amp;gt;&lt;br /&gt;    &amp;lt;g:machineList template=&amp;quot;/templates/machineTree&amp;quot; data=&amp;quot;${element}&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;/g:else&amp;gt;&lt;br /&gt;&amp;lt;/g:each&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And in your page, where you want to put your tree, you can just simply call the template:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;g:machineList template=&amp;quot;/templates/machineTree&amp;quot; data=&amp;quot;${treeData}&amp;quot;/&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Is a just a simple example (and, in fact, I'm not sure that with mods I've done to create this post, all work well :P), If you want you can make some improvements to this code, attaching, for example, javascript functions to get your tree-node opened and closed, or some other kinds of object type.u&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2210430163007979587-4101330548553526987?l=mmornati.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmornati.blogspot.com/feeds/4101330548553526987/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2210430163007979587&amp;postID=4101330548553526987' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/4101330548553526987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2210430163007979587/posts/default/4101330548553526987'/><link rel='alternate' type='text/html' href='http://mmornati.blogspot.com/2008/07/generating-simple-tree-in-grailsu.html' title='Generate a simple tree-menu in Grails'/><author><name>Marco</name><uri>http://www.blogger.com/profile/09410642173147139894</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp0.blogger.com/_mcrRJdyp-jg/SI9oaxYIweI/AAAAAAAAEfo/JYtuaU2-X4Q/S220/CIMG1158.JPG'/></author><thr:total>0</thr:total></entry></feed>
