<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tales From The Cloud &#187; tools</title>
	<atom:link href="http://blog.newsplore.com/category/tools/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.newsplore.com</link>
	<description>Everything beta</description>
	<lastBuildDate>Tue, 07 Sep 2010 10:40:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Reviewing Google AppEngine for Java (Part 1)</title>
		<link>http://blog.newsplore.com/2009/05/27/reviewing-google-appengine-for-java-part-1</link>
		<comments>http://blog.newsplore.com/2009/05/27/reviewing-google-appengine-for-java-part-1#comments</comments>
		<pubDate>Thu, 28 May 2009 02:08:56 +0000</pubDate>
		<dc:creator>Florin</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[cloud deployment]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Java AppEngine]]></category>

		<guid isPermaLink="false">http://blog.newsplore.com/?p=1093</guid>
		<description><![CDATA[&#160;&#160;&#160;&#160; When Google announced that Java is the second language that the Appengine will support I almost didn&#8217;t believe it given the surge of the new languages and the perception that Java entered legacy but the JVM is a powerful tried-and-true environment and Google saw the potential of using it for what it is bound [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="padding-right:0;margin-top:3px"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.newsplore.com%2F2009%2F05%2F27%2Freviewing-google-appengine-for-java-part-1"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.newsplore.com%2F2009%2F05%2F27%2Freviewing-google-appengine-for-java-part-1" height="61" width="51" /></a></div><table border="0">
<tbody>
<tr>
<td>
<img class="alignnone size-full wp-image-1136" src="http://blog.newsplore.com/wp-content/uploads/2009/05/appengine_lowres.gif" alt="appengine_lowres" width="142" height="109" /></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td>
<div align='justify'>When Google <a href="http://googleappengine.blogspot.com/2009/04/seriously-this-time-new-language-on-app.html">announced</a> that Java is the second language that the Appengine will support I almost didn&#8217;t believe it given the surge of the new languages and the perception that Java entered legacy but the JVM is a powerful tried-and-true environment and Google saw the potential of using it for what it is bound to</div>
</td>
</tr>
</tbody>
</table>
<p>become: a runtime environment for the new and exciting languages (see JRuby and Grails). The JVM is the new gateway drug in the world of languages.</p>
<p><i>Note:</i> I&#8217;ll break down this review into two posts as it&#8217;s too extensive to cover everything at once. This first part is about initial setup, JPA and some local webapp deployment issues. In the second part I&#8217;ll describe how to load data into the datastore, data indexing, how I reached some of the limitations of the AppEngine and how to get around some of them.</p>
<p>I managed to snatch an evaluation account and last few days I have been playing with it. (as of today Google opened the registrations to all). My goal was (<a href="http://blog.newsplore.com/?p=981">again</a>) simple: to port Spincloud to the AppEngine. The prize: free hosting which amounts to $20/month in my case (see my <a href="http://blog.newsplore.com/?p=880">post</a> about Java hosting providers), some cool monitoring tools that I can access on the web and of course the transparent super-scalability that Google is touting, in case I get techcrunched, slashdotted or whatever (slim chances but still&#8230;).<br />
I am a couple of weeks into the migration effort and I can conclude that the current state of the AppEngine is not quite ready for Spincloud as I&#8217;ll detail below but it comes quite close. The glaring omission was scheduling but Google <a href="http://www.techcrunch.com/2009/05/27/live-from-google-io-2009/">announced today</a> that the AppEngine will support it (awesome!) and I plan to use it from day one.</p>
<p>My stated goal is running Spincloud on AppEngine. Here are the technologies I use in Spincloud:<br />
- Spring 3.0 (details <a href="http://blog.newsplore.com/?p=773">here</a>)<br />
- SpringAOP<br />
- SpringSecurity with OpenId<br />
- Webapp management with JMX (I know, it won&#8217;t fly)<br />
- Job scheduling using Spring&#8217;s Timer Task abstraction (<a>not optimistic</a> about this one either)<br />
- SiteMesh (upgraded to 2.4.2 <a href="http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine">as indicated</a>)<br />
- Spatial database support including spatial indexing<br />
- JPA 2.0 (back story <a href="http://blog.newsplore.com/?p=981">here</a>)<br />
- Level 2 JPA cache, query cache.<br />
- Native SQL query support including native SQL spatial queries.<br />
- Image processing (spincloud scraps images and processes pixel-level information to get some weather data)<br />
<span id="more-1093"></span><br />
That&#8217;s a lot of stuff but first things first. I recommend creating a new repository branch (I use Subversion) dedicated to the new environment as there may be many things to change and you still want to continue the development unaffected on your mainline.</p>
<p>I downloaded the latest <a href="http://code.google.com/appengine/downloads.html">SDK</a> and exploded it under the tools/ folder. Make sure you install the Eclipse plugin as it&#8217;s pretty useful.</p>
<p>After the initial setup I started-out with the JPA part since this seemed to be the most challenging piece of technology that I had to change. AppEngine uses DataNucleus JPA provider, a poor choice in my opinion since they are a JDO provider turned to JPA (much like KODO/OpenJPA) and so they drag a lot of JDO baggage along. I haven&#8217;t heard of them before and they don&#8217;t seem to be that popular (why not Hibernate or the new RI: EclipseLink? <i>Update:</i> because JPA is RDBMS oriented while JDO is not and the backing store of GAE is BigTable which is not RDBMS). DataNucleus JPA requires a pre-compilation step that does bytecode enhancement which I completely dislike as it&#8217;s archaic (all modern JPA providers don&#8217;t have this anymore) but I had no choice. So I&#8217;ve followed the <a href="http://code.google.com/appengine/docs/java/datastore/usingjpa.html">reference documentation</a>. The only thing not described there is the ant integration.<br />
Here is what I added to my build.xml</p>
<pre>&lt;project name="weather"  default="build"  basedir="."&gt;
...
  &lt;property name="sdk.dir" value="/Users/florin/tools/appengine-java-sdk-1.2.1"/&gt;
  &lt;import file="${sdk.dir}/config/user/ant-macros.xml" /&gt;

  &lt;path id="enhancer.classpath"&gt;
    &lt;pathelement path="${bin.dir}"/&gt;
    &lt;fileset dir="${sdk.dir}/lib"&gt;
      &lt;include name="appengine-tools-api.jar"/&gt;
    &lt;/fileset&gt;
    &lt;fileset dir="${lib.dir}"&gt;
      &lt;include name="gisjts/jts*.jar"/&gt;
      &lt;include name="appengine/appengine-api-1.0-sdk-1.2.1.jar"/&gt;
    &lt;/fileset&gt;
  &lt;/path&gt;

  &lt;target name="enhance" depends="compile"&gt;
    &lt;enhance verbose="true" classpathref="enhancer.classpath"&gt;
      &lt;fileset dir="${bin.dir}"&gt;
        &lt;include name="com/newsplore/weather/bo/*.class"/&gt;
      &lt;/fileset&gt;
    &lt;/enhance&gt;
  &lt;/target&gt;

  &lt;target name="build-appengine" depends="compile, enhance, jar"/&gt;
...
</pre>
<p>Essentially this is to accommodate the enhancement step (notice how the &#8220;enhance&#8221; target is interposed between compile and jar in the build-appengine target).<br />
I ran the &#8220;build-appengine&#8221; target and noticed the first exception:</p>
<pre>  [enhance] Please see the logs [/tmp/enhance64409.log] for further information.</pre>
<p>That&#8217;s a convoluted way of looking at the errors (why not showing the exception in the console?). Here&#8217;s the actual error found in the said file:</p>
<pre>java.lang.RuntimeException: Unexpected exception
...
   Caused by: java.lang.reflect.InvocationTargetException
...
Caused by: java.lang.NoClassDefFoundError: Lorg/apache/log4j/Logger;
  at java.lang.Class.getDeclaredFields0(Native Method)</pre>
<p>This was because one of my business objects used log4j. Adding the log4j jar file didn&#8217;t help and the solution was to remove the logging from the class altogether.</p>
<p>After cleanup I got this error:</p>
<pre>  [enhance] SEVERE: Class "com.newsplore.weather.bo.GeometryUserType" was not found in the
CLASSPATH. Please check your specification and your CLASSPATH.
  [enhance] org.datanucleus.exceptions.ClassNotResolvedException: Class
"com.newsplore.weather.bo.GeometryUserType" was not found in the CLASSPATH.
    Please check your specification and your CLASSPATH.</pre>
<p>That was because GeometryUserType (a class I used to handle Geometry types in Hibernate) was in the com.newsplore.weather.bo package and the enhancer went through all classes in this package thinking they are all @Entities and failed with this one. Weird, I thought that the enhancer was smarter and filtered-out all non @Entities&#8230; The solution is either to specify all the classes to be enhanced in the &#8220;enhance&#8221; ant target or move the non-entities to other packages (a good practice). In my case I deleted the class since I wasn&#8217;t using it anyway (I used this utility class before Hibernate became a JPA provider).<br />
After this cleanup, the enhance target spat yet another error:</p>
<pre>[enhance]Class com.newsplore.weather.bo.UsForecast has property weatherIconByCode declared
    in MetaData, but its getter method doesnt exist in the class!
  [enhance] May 27, 2009 4:03:50 PM org.datanucleus.enhancer.DataNucleusEnhancer main
[enhance] SEVERE: DataNucleus Enhancer completed with an error. Please review the enhancer
log for full details. Some classes may have been enhanced but some caused errors
  [enhance] Class com.newsplore.weather.bo.UsForecast has property weatherIconByCode
declared in MetaData, but its getter method doesnt exist in the class!
  [enhance] org.datanucleus.metadata.InvalidMetaDataException: Class
com.newsplore.weather.bo.UsForecast has property weatherIconByCode declared in MetaData,
 but its getter method doesnt exist in the class!
  [enhance]     at org.datanucleus.metadata.ClassMetaData
.populateMemberMetaData(ClassMetaData.java:497)</pre>
<p>So a domain object (UsForecast) has a property called weatherIconByCode. Hmm, I didnt remember of such property but looking at the source I saw that the offender was a private utility method called getWeatherIconByCode(String code) that was being processed by the enhancer as if it was a property (I&#8217;m using annotations bound to getters and not to fields). Since adding @Transient didn&#8217;t fix it, the solution is to rename the method not to start with get/set (or move it in an utility class which you shouldn&#8217;t do if you follow DDD).<br />
To my relief, after this fix the build didn&#8217;t yield any more errors so I had a nice webapp folder ready to be deployed. AppEngine has a local sandbox (based on Jetty) that should be used before deploying into the cloud. You can start the appserver using an ant target but I chose to get more control and create a script that accomplishes the same thing. Here it is:</p>
<pre>cd build/webapp
java -classpath &lt;appengine-sdk-home&gt;/lib/appengine-tools-api.jar
com.google.appengine.tools.development.DevAppServerMain --port=8080 --address=localhost</pre>
<p>Save this in a file called startgae.sh (mind the path, you should be able to cd to the webapp folder from it) then make it executable.<br />
Using this script I fired-up the container and got no startup error. This was <a href="http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine">weird</a> since I knew I was using JMX (via Spring and annotations) and as well the task scheduler (using <a href='http://www.opensymphony.com/quartz/'>Quartz</a>) was seemingly up and running.<br />
I hit the home page to see what has been deployed and I get a 404 error. My web.xml has this mapping:</p>
<pre>  &lt;servlet&gt;
    &lt;servlet-name&gt;weather&lt;/servlet-name&gt;
    &lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;
  &lt;/servlet&gt;

  &lt;servlet-mapping&gt;
	&lt;servlet-name&gt;weather&lt;/servlet-name&gt;
	&lt;url-pattern&gt;/&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;</pre>
<p>but this doesn&#8217;t work in the local servlet container. This was quite annoying as not only the home page doesn&#8217;t work, the static folders (css/, js/, img/) are routed through the weather servlet too. Surprisingly as it turns out, this mapping worked perfectly in the AppEngine environment. To be able to continue with the work in the local environment, I had to define fine grained mappings for all the URLs.<br />
After this change, the first URL that started working was the /faq which provided the first breakthrough. Although only the presentation tier is in use on the /faq page, the fact that the page worked provided a bunch of good news: Spring 3.0 DI container, SiteMesh, Spring Security and SpringAOP were all correctly running. </p>
<p>Stay tuned for the <a href='http://blog.newsplore.com/?p=1205'>second part</a> detailing more JPA, datastore indexing, a bunch of the AppEngine limitations, a bit of local environment hacking and how to use &#8220;request welding&#8221; to accomplish long running tasks.</p>
<p class="fbconnect_share"><fb:share-button class="url" href="http://blog.newsplore.com/2009/05/27/reviewing-google-appengine-for-java-part-1" /></p>]]></content:encoded>
			<wfw:commentRss>http://blog.newsplore.com/2009/05/27/reviewing-google-appengine-for-java-part-1/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Choosing a Java hosting provider</title>
		<link>http://blog.newsplore.com/2009/03/14/choosing-a-java-hosting-provider</link>
		<comments>http://blog.newsplore.com/2009/03/14/choosing-a-java-hosting-provider#comments</comments>
		<pubDate>Sat, 14 Mar 2009 05:38:48 +0000</pubDate>
		<dc:creator>Florin</dc:creator>
				<category><![CDATA[hardware]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[hosting]]></category>

		<guid isPermaLink="false">http://blog.newsplore.com/?p=880</guid>
		<description><![CDATA[Selecting a web hosting provider is a tough job for any web developer that wants to put a Java/JEE web application online. The choice is much simpler when it comes to publishing a PHP web site and there are a load of cheap (and sometimes quite reliable) PHP hosting providers to choose from with LAMP [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="padding-right:0;margin-top:3px"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.newsplore.com%2F2009%2F03%2F14%2Fchoosing-a-java-hosting-provider"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.newsplore.com%2F2009%2F03%2F14%2Fchoosing-a-java-hosting-provider" height="61" width="51" /></a></div><p>Selecting a web hosting provider is a tough job for any web developer that wants to put a Java/JEE web application online. The choice is much simpler when it comes to publishing a PHP web site and there are a load of cheap (and sometimes quite reliable) PHP hosting providers to choose from with <a href="http://en.wikipedia.org/wiki/LAMP_(software_bundle)">LAMP</a> being the de facto standard in the web hosting world. But when it comes to Java hosting providers the picture becomes blurrier. The common thing that all these environments need is a Java container. The most popular choice is Tomcat but there are providers that use Resin, Weblogic or Websphere (the latter two are full fledged JEE containers).<br />
With the raise of lightweight J2EE servers started by the <a href='http://springframework.org'>Spring</a> folks, a little revolution began in the Java world: running enterprise-grade JEE webapps without the need for an EJB container; a servlet container is enough. Tomcat should fill the bill for just about any Java web application that doesn&#8217;t use EJBs. The advantage that comes from running a servlet container is the smaller footprint compared with an EJB container. This is critical when it comes to selecting hosting environments since you&#8217;re paying for resources (especially RAM) that have to be sized to accommodate the memory requirements of the web application.</p>
<p><i>Self hosting: Home-based dedicated server (near $0)</i></p>
<table>
<tr>
<td><img class="alignnone size-full wp-image-916" src="http://blog.newsplore.com/wp-content/uploads/2009/03/homepc.png" alt="homepc" width="136" height="206" /></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td valign='top'>You can use your home internet connection and a PC where the web container runs and deploys your web application. There is an obvious advantage since the server is physically located close to the development team: complete control and physical access to the machine. The other big plus is the price: you&#8217;re already paying for the internet connection and chances are you already have a PC that can be transformed into a server. And chances are that you already have a development environment that can be the basis of the production deployment. Here are the shortcomings:</p>
<p>- Bandwidth limitations: the webserver where the webapp lives will <em>upload</em> content to the web browsers that access the application. The upload bandwidth is smaller than the download bandwidth and will result in longer load times for web clients.<br />
- Some internet providers cap the internet traffic so you may run beyond the limit.
</td>
</tr>
</table>
<p>- You may violate contractual obligations you agreed with your Internet provider by running your own web server.<br />
- The internet connection is not reliable: provider&#8217;s downtime directly translates in downtime for your webapp.<br />
<span id="more-880"></span></p>
<div style='height:14px'></div>
<p><i>Managed hosting ($6 and up)</i><br />
This is the cheapest solution but it poses the most restrictions. The main limitation is the inability to deploy webapps that depend on Java bytecode manipulation at runtime, mainly Hibernate and Spring. This is due to classloading security constraints that prevent the bytecode manipulation libraries (CGLIB or javassist) to perform runtime code enhancements.<br />
Working with managed hosting environments poses more limitations:<br />
- Deployment: some popular hosting providers deploy once a day: you drop the war file or the exploded war in a specific folder on the hosted environment and it will be deployed at a specific time picked by the provider (more <a href="http://help.godaddy.com/topic/319/article/67">here</a>). If it fails, you have to wait another day till the app will be redeployed or pick a provider that supports instant drop&amp;deploy.<br />
- Debugging a failed deployment: I couldn&#8217;t make log4j write the log into a location on my hosted file space so I had to resort to a <a href="http://www.dankomannhaupt.de/projects/index.html">JDBC appender</a> to actually see what causes a failed deployment. This required two deployments (one to try a location on  the hosted folder and a second one to use the JDBC appender; that&#8217;s two days due to the deployment constraint detailed above) and the issue turned out to be the classloader security issue preventing CGLIB to change the bytecode. I have only tried to deploy a war file with Hibernate and Spring dependencies in Godaddy&#8217;s Java hosting environment (their <a href="http://www.godaddy.com/gdshop/hosting/shared.asp?ci=9009">Linux Deluxe plan</a>) before I gave up on managed Java hosting.<br />
- Sharing the environment with other webapps. Your app will be deployed along with other applications and compete for the same resources.<br />
- Access to server logs and traffic stats is very limited. You can only use Google Analytics (or similar) but not <a href="http://awstats.sourceforge.net/">Awstats</a> (at least not for free).<br />
- Outgoing traffic may be restricted or blocked.</p>
<div style='height:16px'></div>
<p align="justify"><b>Unmanaged hosting solutions</b><br />
Unmanaged doesn&#8217;t necessarily mean that the hosting company doesn&#8217;t manage anything, they just leave the actual OS administration in your hands so you&#8217;ll have a physical server under your complete control, everything else from network management to hardware maintenance is done by the hosting company. You/your team has to have solid server administration knowledge: Linux, Apache, Java AppServers, software firewall (iptables), backup/restore, monitoring, security, patching, DNS and more. A web administrator inside your team usually takes care of all these details. After the machine is up and running you are free to install and run any Java container and deploy your application.<br />
Below are the options when choosing to run a dedicated server.
<div style='height:14px'></div>
<p><i>Colocated server ($70 and up)</i></p>
<table>
<tr>
<td><img src="http://blog.newsplore.com/wp-content/uploads/2009/03/mountcolo.png" alt="mountcolo" width="233" height="173" class="alignnone size-full wp-image-942" /></td>
<td>&nbsp;&nbsp;&nbsp;</td>
<td>You can <a href="http://en.wikipedia.org/wiki/Colocation_centre">colocate</a> the server which means that you buy then ship your own rack-mountable server to a data centre where it will be installed by on-site technicians. The monthly fee you&#8217;ll pay starts at around $70 (prices are per one unit which is a slot in the rack) and includes the rack space rental, network connectivity, location security, 24/7 power (not counting <a href="http://www.techcrunch.com/2007/11/12/quick-plug-the-internet-back-in-major-rackspace-outage/">mishaps</a>), etc. Denial of Service prevention services are usually provided as part of the package.<br />
There is complete freedom in terms of the deployment environment since you own it. However, there are two problems that come with this solution:</td>
</tr>
</table>
<p>- Initial cost associated with buying rack-mountable servers that usually start from $1.5k (check <a href="http://www.supermicro.com">SuperMicro</a>, they&#8217;re good). These machines contain redundant components to cope with failures.<br />
- Maintenance: When components break you have to manage their replacement. If the whole machine crashes then your website will be offline until the machine is replaced.</p>
<div style='height:14px'></div>
<p><i>Rent a dedicated server ($100 and up)</i></p>
<table>
<tr>
<td><img src="http://blog.newsplore.com/wp-content/uploads/2009/03/fullrack.png" alt="fullrack" width="106" height="143" class="alignnone size-full wp-image-937" /></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td valign='top'>Instead of buying your own server, you can choose to rent a dedicated server from the hosting provider. Kevin Rose unveils how digg.com was initially hosted on dedicated servers rented from <a href="http://www.ev1servers.net/">Ev1Servers.net</a> (see full <a href="http://www.ev1servers.net/">article</a>). The benefit of this solution is the lower initial cost compared to colocation, beginning at around $100/month and of course the complete control over the environment. The drawbacks are the same as colocation except for servicing the box that falls under the hosting provider&#8217;s responsibility.</td>
</tr>
</table>
<div style='height:14px'></div>
<p align="justify"><i> Virtual Private Server ($20 and up)</i></p>
<table>
<tr>
<td><img src="http://blog.newsplore.com/wp-content/uploads/2009/03/vpsnodes.png" alt="vpsnodes" width="129" height="234" class="alignnone size-full wp-image-944" /></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td valign='top'>A <a href="http://en.wikipedia.org/wiki/Virtual_private_server">VPS</a> &#8221; is a method of partitioning a physical server computer into multiple servers&#8221;. Each of these partitions behaves like a full fledged server, has an IP address and can be reachable from the internet. The computers that are VPS partitioned, sit on the hosting provider&#8217;s infrastructure. The provider is responsible for network connectivity, bandwidth and continuity of service in case  of physical server failure. There are two main VPS software providers: Virtuozzo and Xen. Of the two, I recommend Xen-based VPS providers since the virtualized machines cannot be oversold and thus you&#8217;ll get consistent performance for the money (a detailed explanation <a href="http://www.hostcube.com/blog/virtuozzo-vs-xen">here</a>). The main benefit of the VPS is the excellent price/performance ratio starting as low as $20/month. Another big advantage is the ability to &#8220;resize&#8221; the virtual partition on demand in a matter of minutes (you&#8217;ll pay more of course), add more virtual machines to your deployment () as well as &#8220;relocating&#8221; it to a different data center </td>
</tr>
</table>
<p>if the provider has multiple locations (West Coast and East Coast for instance). Root access is also provided. The drawbacks are:<br />
- the operating systems that you can run are controlled by the hosting provider and usually are Linux distributions (here&#8217;s an <a href="https://www.linode.com/faq.cfm">example</a>). However, the choices are very popular Linux distros.<br />
- you have to have server administration expertise.<br />
I run this blog, <a href="http://spincloud.com">spincloud.com</a> and the rest of my web properties on a VPS. I use the excellent <a href="http://linode.com">Linode</a> after I had switched from <a href="http://slicehost.com">Slicehost</a>, having performance issues. I am quite happy with Linode, their service rocks and they&#8217;ve been delivering consistent performance since day one.</p>
<div style='height:14px'></div>
<p><i>Cloud services (EC2: $100 and up)</i></p>
<table>
<tr>
<td><img src="http://blog.newsplore.com/wp-content/uploads/2009/03/cloud.png" alt="cloud" width="138" height="119" class="alignnone size-full wp-image-953" /></td>
<td>&nbsp;&nbsp;&nbsp;</td>
<td valign='top'>Cloud computing is today&#8217;s trend. The company that kick-started the trend was Amazon with their <a href="http://aws.amazon.com/ec2/">Elastic Computing Cloud</a>. EC2 is actually an advanced form of VPS: you can run your own virtual machine image (or AMI) or pick one from the existing stock. After the AMI is booted and configured, you have the liberty of installing any Java environment. You get root access too.<br />
From the high profile websites, <a href="http://smugmug.com">Smugmug</a> uses EC2 and S3 and they <a href="http://blogs.smugmug.com/don/2006/11/10/amazon-s3-show-me-the-money/">save money</a> doing so. In fact Smugmug was one of the early adopters of Amazon&#8217;s cloud services.</td>
</tr>
</table>
<p>Drawbacks:<br />
- If you reboot the machine or if it simply crashes then all data is lost, including any database records you happen to have. This was a real problem for developers until Amazon added the possibility to <a href="http://www.infoq.com/news/2008/04/amazon-storage">mount a persistent S3 volume</a> in an EC2 instance. S3 stands for <a href="http://aws.amazon.com/s3/">Simple Storage Service</a> and is Amazon&#8217;s offering for cloud-based storage.<br />
- You have to learn new terminology and set of skills that are applicable to Amazon&#8217;s problem-set only. You&#8217;ll also tie the solution to a single vendor.<br />
The cost for an EC2+S3 starts at close to $100/month.<br />
<del datetime="2009-05-19T23:21:20+00:00">If you&#8217;re thinking of using the dirt-cheap (starts free) <a href='http://code.google.com/appengine/'>Google AppEngine</a> for deploying a Java application you&#8217;re out of luck, they only support Python.</del> Update: Google has added Java support to Appengine.  at the begining of April. I have a dev account and I&#8217;ll evaluate it in a separate post.</p>
<p><b>Common concerns when selecting a hosting provider</b><br />
<i>Price</i><br />
Don&#8217;t pick a service just because it&#8217;s cheap. Perform some due diligence on the company, where their data centers are located and how good their service is. You don&#8217;t want your website hosted on the wrong side of the world. Monitor <a href='http://www.webhostingtalk.com/'>WebHostingTalk forums</a>; hosting providers often run promotions there.<br />
Look for monthly plans and don&#8217;t commit to yearly plans since you may end-up being unhappy with the provider and with no choice to get out of the contract.<br />
Be suspicious when you see associated setup fees coming with setting-up an account. They are not refundable and good hosting providers simply don&#8217;t have them.</p>
<p><i>Uptime</i><br />
You want no interruption in service for your web servers so <a href="http://en.wikipedia.org/wiki/Uptime">uptime</a> is a must. You can&#8217;t afford to have downtime since it translates directly into lost customers and ultimately lost business. Look for hosting providers that offer SLAs (Service level agreements) and have proven reliability. <a href="http://netcraft.com">Netcraft</a> is a neat tool that measures the reliability of hosting providers on a monthly basis. Look for the providers that guarantee five nines (99.999%) uptime, that is five minutes <i>a year</i>.</p>
<p><i>Technical support</i><br />
My personal experience is that I used the tech support while I was using a shared web hosting. I haven&#8217;t used any after moving to the VPS.</p>
<p><i>Transfer volume</i><br />
Perform some basic calculations for the required traffic based on the expected traffic and data volume sent out. Providers bundle 200GB/month or more in their offerings these days. This should be enough for most of the cases. Make sure your website doesn&#8217;t get cut-off if your traffic spikes and/or you&#8217;re not paying a ridiculous amount of money per GB if you go beyond your quota.</p>
<p><i>Security</i><br />
All hosting providers offer a form of protection against DDOS but you are responsible for the software that runs on the server. I got the online forum I was running for <a href='http://newsplorer.com'>Newsplorer</a> hacked a couple of years ago because I didn&#8217;t upgrade the forum software to patch a security vulnerability that was promptly exploited.</p>
<p><i>Backup</i><br />
Hosting providers offer backups or you can do it yourself with a bit of effort and some cron knowledge. Save the backed-up files on a different location (I use S3 for my backup needs but there are <a href='http://skydrive.live.com/'>free solutions</a> too).</p>
<p class="fbconnect_share"><fb:share-button class="url" href="http://blog.newsplore.com/2009/03/14/choosing-a-java-hosting-provider" /></p>]]></content:encoded>
			<wfw:commentRss>http://blog.newsplore.com/2009/03/14/choosing-a-java-hosting-provider/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Spincloud Labs: Political boundaries overlay in Google maps (Part 2)</title>
		<link>http://blog.newsplore.com/2009/03/01/602-revision-125</link>
		<comments>http://blog.newsplore.com/2009/03/01/602-revision-125#comments</comments>
		<pubDate>Mon, 02 Mar 2009 01:43:15 +0000</pubDate>
		<dc:creator>Florin</dc:creator>
				<category><![CDATA[UNIX]]></category>
		<category><![CDATA[home]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[gis]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[overlay]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.newsplore.com/?p=737</guid>
		<description><![CDATA[In Part 1 we imported world political borders into a database table. In this second part we&#8217;ll use the table and generate a script that will be used to add the borders overlay to Google Maps. We&#8217;ll use the cool Ruby and some fancy GIS words along the way. We left-off with a database table containing [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="padding-right:0;margin-top:3px"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.newsplore.com%2F2009%2F03%2F01%2F602-revision-125"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.newsplore.com%2F2009%2F03%2F01%2F602-revision-125" height="61" width="51" /></a></div><p align="justify">In <a href="http://blog.newsplore.com/?p=531">Part 1</a> we imported world political borders into a database table. In this second part we&#8217;ll use the table and generate a script that will be used to add the borders overlay to Google Maps. We&#8217;ll use the cool Ruby and some fancy GIS words along the way.</p>
<p align="justify">We left-off with a database table containing all borders. The goal today is to produce a Javascript file that will be used for overlaying polygons representing countries, over a map using the <a href="http://code.google.com/apis/maps/">Google Maps API.</a></p>
<p>Let&#8217;s examine the table data first (I&#8217;m using mysql through the command line):</p>
<pre>mysql&gt; desc world_boundaries;
+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| ID        | int(11)      | NO   | PRI | NULL    |       |
| FIPS      | varchar(255) | YES  |     | NULL    |       |
| ISO2      | varchar(255) | YES  |     | NULL    |       |
| ISO3      | varchar(255) | YES  |     | NULL    |       |
| UN        | int(11)      | YES  |     | NULL    |       |
| NAME      | varchar(255) | YES  |     | NULL    |       |
| AREA      | int(11)      | YES  |     | NULL    |       |
| POP2005   | bigint(20)   | YES  |     | NULL    |       |
| REGION    | int(11)      | YES  |     | NULL    |       |
| SUBREGION | int(11)      | YES  |     | NULL    |       |
| LON       | double       | YES  |     | NULL    |       |
| LAT       | double       | YES  |     | NULL    |       |
| ogc_geom  | geometry     | YES  |     | NULL    |       |
+-----------+--------------+------+-----+---------+-------+</pre>
<p>A lot of information here but we&#8217;ll need just these fields: name (country name), iso2 (two letter <a href="http://www.iso.org/iso/english_country_names_and_code_elements">country codes</a>) the_geom, iso2 (border geometry) and region (grouping countries by regions). To check the data-set let&#8217;s examine a small country. I&#8217;ll pick the tiny <a href="http://en.wikipedia.org/wiki/Vatican_City">State of Vatican</a> for its size:</p>
<pre>mysql&gt; select iso2, AsText(ogc_geom), region from world_boundaries where iso2='VA';
+------+---------------------------------------------------------------------------------------------------------------------------------------------------+--------+
| iso2 | AsText(ogc_geom)                                                                                                                                  | region |
+------+---------------------------------------------------------------------------------------------------------------------------------------------------+--------+
| VA   | MULTIPOLYGON(((12.445090330889 41.903117521785,12.451653339581 41.907989033391,12.456660170954 41.901426024699,12.445090330889 41.903117521785))) |    150 |
+------+---------------------------------------------------------------------------------------------------------------------------------------------------+--------+
1 row in set (0.00 sec)</pre>
<p>The only surprise here is that the country border is described as a <a href="http://dev.mysql.com/doc/refman/5.0/en/gis-class-multipolygon.html">MULTIPLOYGON</a> spatial type which describe a collection of polygons that don&#8217;t interset. This is in order to accommodate countries that have islands under ownership.</p>
<p>Let&#8217;s see how these points look on the map. We&#8217;ll use the excellent polygon <a href="http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/encodeForm.html">encoder utility</a> written by Mark McClure. Copy Vatican&#8217;s point set in the &#8220;Input Text&#8221; input box (choose lng/lat option):</p>
<pre>12.445090330889, 41.903117521785
12.451653339581, 41.907989033391
12.456660170954, 41.901426024699
12.445090330889, 41.903117521785</pre>
<p>Here&#8217;s the result:<br />
<img class="alignnone size-full wp-image-628" src="/wp-content/uploads/2009/02/va_polygon.png" alt="va_polygon" width="229" height="176" /><br />
Not very accurate but we&#8217;ll have to live with it, it&#8217;s a free data set after all&#8230;<br />
<span id="more-737"></span><br />
We can also get a glimpse of how the Javascript code containing the encoded polygon looks like  by using the same utility. Click on the &#8220;Show Code&#8221; button; you should see this:</p>
<pre>...
var polyline1_1 = new GPolyline.fromEncoded({
  color: "#0000ff",
  weight: 4,
  opacity: 0.8,
  points: "mew~Fyt}jAm]_h@~g@i^qIhgA",
  levels: "PHIP",
  zoomFactor: 2,
  numLevels: 18
});
map.addOverlay(polyline1_1);</pre>
<p>The last line adds this polygon (i.e. is a polyline but more on that later) to the map.<br />
The &#8220;points&#8221; property of the GPolyline is an encoded string which we&#8217;ll have to generate. The full documentation on how the encoding is performed read <a href="http://code.google.com/apis/maps/documentation/overlays.html#Polylines_Overview">Google&#8217;s polyline documentation</a>.<br />
Let&#8217;s use a bit of pseudocode to describe the steps we want performed:</p>
<pre>for each ogc_geom of countries fetched from DB
  generate encoded points
  create GPolygon Javascript code snippet
  collect snippet to Javascript file
end</pre>
<p>First things first. Since I&#8217;m learning Ruby, I&#8217;m going to use it to implement these requirements. The extras I&#8217;m gonna need are Mysql (for DB connectivity) and <a href="http://georuby.rubyforge.org/">GeoRuby</a> (for processing spatial data types). Installing MySql gem to Ruby is easy (sudo gem install mysql) that is if you don&#8217;t want to get into using 64bit Mysql distributions (you don&#8217;t) so let&#8217;s skip that. Install GeoRuby with a&#8221;sudo gem install GeoRuby&#8221; command.<br />
To verify if both mysql and GeoRuby are enabled, open an irb session then type:</p>
<pre>&gt;&gt; require 'mysql'
=&gt; true
&gt;&gt; require 'geo_ruby'
=&gt; true</pre>
<p>They should both render true.<br />
A word about encoding polygons. Google&#8217;s encoded polyline/polygon API optimizes the rendering by enabling encoding more or less points giving different zoom levels (higher zoom, more points will be used). A well known optimization method is described by the <a href="http://mappinghacks.com/code/PolyLineReduction/">Douglas-Peucker</a> algorithm. However, to make my life easy I devised a simpler algorithm for dealing with this; I term it the <em>straight point reduction algorithm</em> and it replaces the D-P algorithm by uniformly reducing all points up-front and encoding the polygons always using the same number of points for all zoom levels. The rendering of the polygons is not impacted and the actual looks of the country borders is virtually unchanged at all zoom levels. I have found that using one in five points yields respectable performance and doesn&#8217;t impact the shape of the borders. Finally the algorithm used to encode coordinates is described <a href="http://code.google.com/apis/maps/documentation/polylinealgorithm.html">here</a>. The generated javascript has three functions: initializing the overlay (initOverlay) and adding/removing  (addBordersOverlay/removeBordersOverlay)<br />
To check out the code <a href="/wp-content/uploads/2009/02/gen_encpolygons.rb">download</a> the .rb file or <a style="display:none;" id="ddetlink1284503922" href="javascript:expand(document.getElementById('ddet1284503922'))">click to expand.</a>
<div class="ddet_div" id="ddet1284503922"><script language="JavaScript" type="text/javascript">expand(document.getElementById('ddet1284503922'));expand(document.getElementById('ddetlink1284503922'))</script></p>
<pre>
require 'mysql'
require 'geo_ruby'

include GeoRuby::SimpleFeatures

def generate_js_border_overlay(output_file)
  factory = GeometryFactory.new
  wkt_parser = EWKTParser.new(factory)

  borderDB = Mysql::new('localhost', 'root', '', 'bordersdb')
  #region 150 is Europe
  res = borderDB.query("select name, iso2, AsText(ogc_geom), region from
                world_boundaries where region=150")
  encoded_polygon_desc = "";
  remove_warnings_layer = "function removeBordersOverlay() {n"
  add_warnings_layer = "function addBordersOverlay() {n"
  init_borders = "function initBorders() {n"
  res.each do |row|
    name, iso2, multi_polygon, region = *row
    processed_polygon = wkt_parser.parse(multi_polygon);
    encoded_polygon_desc &lt;&lt; "var encodedPolygon_#{iso2};n"
    add_warnings_layer &lt;&lt; "map.addOverlay(encodedPolygon_#{iso2});n"
    remove_warnings_layer &lt;&lt; "map.removeOverlay(encodedPolygon_#{iso2});n"
    init_borders &lt;&lt; "encodedPolygon_#{iso2} =
      new GPolygon.fromEncoded({n
      polylines: ["
    factory.geometry.each do |landmass|
      landmass.rings.each do |ring|
        encoded = encode_by_reducing_pointcount(ring.points)
        init_borders &lt;&lt; "{color: "white",n
        weight: 5,n
        points: '"
        init_borders &lt;&lt; encoded[0].gsub(/\/, '&amp;&amp;') + "',n
        levels: '#{encoded[1]}',n
        zoomFactor: 2,n numLevels: 2}"
        init_borders &lt;&lt; "," unless ring == landmass.rings.last
                 &amp;&amp; landmass == factory.geometry.last
        init_borders &lt;&lt; "n"
      end
    end
    init_borders &lt;&lt; "],nfill:true,n
    opacity:0.7,n
    color: 'white'n
    });"
  end

  add_warnings_layer &lt;&lt; "n}"
  remove_warnings_layer &lt;&lt; "n}"
  init_borders &lt;&lt; "n}"
  File.open(output_file, 'w') {|f|
    f.write(encoded_polygon_desc + "n")
    f.write(add_warnings_layer + "n")
    f.write(remove_warnings_layer + "n")
    f.write(init_borders)
  }
end

def encode_by_reducing_pointcount(points)
  dlat = plng = plat = dlng = 0
  res = ["",""]
  index = -1
  for point in points
    index += 1
    #straight point reduction algorithm: use every 5th point only
    #use all points if their total count is less than 16
    next if index.modulo(5) != 0 &amp;&amp; points.size &gt; 16
    late5 = (point.y * 1e5).floor
    lnge5 = (point.x * 1e5).floor
    dlat = late5 - plat;
    dlng = lnge5 - plng;
    plat = late5;
    plng = lnge5;
    res[0] &lt;&lt; encode_signed_number(dlat)
    res[0] &lt;&lt; encode_signed_number(dlng)
    res[1] &lt;&lt; encode_number(3)
  end
  return res
end

def encode_signed_number(num)
  sig_num = num &lt;&lt; 1
  sig_num = ~sig_num if sig_num &lt; 0
  encode_number(sig_num)
end

def encode_number(num)
  res = ""
  while num  &gt;= 0x20 do
    res &lt;&lt; ((0x20 | (num &amp; 0x1f)) + 63).chr
    num &gt;&gt;= 5
  end
  res &lt;&lt; (num + 63).chr
  return res
end

generate_js_border_overlay("/tmp/bordersOverlay.js")
</pre>
<p></div><br />
I gotta give it to Ruby: it took less than 100 lines to write it all. I choose to skip all exception handling for simplification.<br />
Running program generates a file called bordersOverlay.js in the /tmp folder. You can change the file location by changing the last line of code.<br />
You can also modify the script to filter certain countries based on different criteria by changing the SQL statement at line 11. The line colors, fill colors or opacity can also be changed as needed.<br />
Let&#8217;s put this file to work. I&#8217;m going to generate the border overlay for a single country; I&#8217;ll go with Spain my sunny country of choice. To prepare the script, I&#8217;m changing the SQL query to filter only Spain:</p>
<pre>select name, iso2, AsText(ogc_geom), region from world_boundaries where iso2='ES'")</pre>
<p>I&#8217;m picking a nicely colored background too, electric lime that is; in the ruby script I&#8217;ll update the two occurrences of &#8220;color: &#8221; to &#8220;color: #CCFF00&#8243;.After the script is ran, the file /tmp/bordersOverlay.js is created.</p>
<p>Let&#8217;s put it all together. This is a live embedded map that uses the generated JS script:<br />
[include file=/wp-content/uploads/2009/03/embedmap.html iframe=true width=100% width=520 height=440 scrolling=no]<br />
The usage is straightforward: include the JS file in the HTML snippet</p>
<pre> &lt;script type="text/javascript" src="bordersOverlay.js"&gt;&lt;/script&gt;</pre>
<p>then call these two functions in your JS code after initializing the GMap2 object:</p>
<pre>initBorders();
addBordersOverlay();</pre>
<p>You can also peek at the source code <a href='/wp-content/uploads/2009/03/embedmap.html'>here</a>.<br />
If you zoom-in towards a border area you can observe how approximate the true border is followed. This is due to the straight point reduction algorithm detailed earlier. Spain&#8217;s islands are also colored correctly (Balearic islands to the East of the mainland and the Canary Islands which become visible if you browse off the West coast of Africa).<br />
You can also dynamically change the polygon colors as needed. For the above case we&#8217;ll use the following code:</p>
<pre>encodedPolygon_ES.setFillStyle({color:blue",opacity:1})');</pre>
<p>That&#8217;s all.<br />
The only concern is client-side performance. If there are many polygons to render, the browser may take a long time to render the countries overlay. This is quite apparent when trying <a href="http://spincloud.com">Spincloud</a>&#8216;s Europe weather warnings (Meteoalarm) overlay by using Internet Explorer. Position the map over Europe and click the Meteoalarm button located in the top-left corner of the map. Rendering may take a long time (Chrome handles this the best, it&#8217;s mighty fast).<br />
I&#8217;ll close this tutorial with some colorful maps created using variations of the above code.</p>
<p>All countries in the Mediterranean Basin colored by region:<br />
<img src="http://blog.newsplore.com/wp-content/uploads/2009/03/mediterranean_basin.png" alt="mediterranean_basin" width="460" height="300" /></p>
<p>Countries in <a href="http://en.wikipedia.org/wiki/G7">G7</a>:<br />
<img src="http://blog.newsplore.com/wp-content/uploads/2009/03/g7.png" alt="g7" width="460" height="180" /></p>
<p>Finally, all <a href="http://www.opec.org/">OPEC</a> member countries:<br />
<img class="alignnone size-full wp-image-693" src="http://blog.newsplore.com/wp-content/uploads/2009/03/opec.png" alt="opec" width="460" height="200" /></p>
<p class="fbconnect_share"><fb:share-button class="url" href="http://blog.newsplore.com/2009/03/01/602-revision-125" /></p>]]></content:encoded>
			<wfw:commentRss>http://blog.newsplore.com/2009/03/01/602-revision-125/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Spincloud Labs: Political boundaries overlay in Google maps (Part 1)</title>
		<link>http://blog.newsplore.com/2009/02/22/spincloud-labs-political-boundaries-overlay-in-google-maps-part-1</link>
		<comments>http://blog.newsplore.com/2009/02/22/spincloud-labs-political-boundaries-overlay-in-google-maps-part-1#comments</comments>
		<pubDate>Sun, 22 Feb 2009 21:34:41 +0000</pubDate>
		<dc:creator>Florin</dc:creator>
				<category><![CDATA[UNIX]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[gis]]></category>
		<category><![CDATA[overlay]]></category>

		<guid isPermaLink="false">http://blog.newsplore.com/?p=531</guid>
		<description><![CDATA[One thing I needed when designing the Meteoalarm mashup for Spincloud were the political boundaries for all European countries. With them at hand, I would use the polygon overlay from the Coogle API and fill the country polygons with the respective weather warning colors. This first part is a tutorial on how to import world [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="padding-right:0;margin-top:3px"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.newsplore.com%2F2009%2F02%2F22%2Fspincloud-labs-political-boundaries-overlay-in-google-maps-part-1"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.newsplore.com%2F2009%2F02%2F22%2Fspincloud-labs-political-boundaries-overlay-in-google-maps-part-1" height="61" width="51" /></a></div><p align="justify">One thing I needed when designing the <a href="http://blog.newsplore.com/?p=382">Meteoalarm mashup</a> for <a href="http://spincloud.com">Spincloud</a> were the political boundaries for all European countries. With them at hand, I would use the <a href="http://code.google.com/apis/maps/documentation/overlays.html#Polygons_Overview">polygon overlay</a> from the Coogle API and fill the country polygons with the respective weather warning colors.</p>
<p>This first part is a tutorial on how to import world political borders into a MySQL database table.<br />
The second part in these series will use this table to create a script that will add the country borders overlay to Google Maps.</p>
<p>So after learning that Google Maps API doesn&#8217;t give programatic access to the political boundaries I moved on to doing it myself. I read about the <a href="http://code.google.com/apis/maps/documentation/polylineutility.html">encoded polylines</a> and figured that I only missed the country boundaries as encoded polygons so I started searching for readily-available resources. Sure enough there were nowhere to be found.</p>
<p>The next best thing was to find the country boundaries in some GIS format and generate the polyligons myself. The information seems to be sparse but after a bit of research I found was the <a href="http://www.evl.uic.edu/pape/data/WDB/">CIA World Databank</a> but the format is incomplete, it only defines the polygons with no country names or any other administrative hook that I would be able to use.  I then spent hours trying to find a better resource until I remembered that <a href="http://mappinghacks.com/">Mapping Hacks</a> (an excellent book by the way) has data set for the examples in the book. I had the first breakthrough, the website makes available updated world borders files <a href="http://mappinghacks.com/data/">here</a>, they are mirrored from <a href="http://thematicmapping.org/downloads/world_borders.php">thematicmapping.org</a>.</p>
<p>We&#8217;ll use a utility called <a href="http://kartoweb.itc.nl/RIMapper/code/shp2mysql_0_4.zip">shp2mysql</a> to export the boundaries to SQL. I&#8217;m on a MacBook and no shp2mysql binaries for my platform were available in the original package so we&#8217;ll have to compile it first then run it to be able to export the shapefile to SQL.</p>
<p>Below are detailed all steps needed to to produce the borders SQL file on Leopard 10.5.x (note that you have to have the <a href="http://developer.apple.com/Tools/">Developer Tools</a> installed). In short, copy and run the following script on your mac in a file called process_boundaries.sh. The script creates a file called wb_dump.sql which is ready to be imported into database:<br />
<span id="more-531"></span></p>
<pre>mkdir borders
cd borders
wget http://mappinghacks.com/data/TM_WORLD_BORDERS-0.2.zip
mkdir boundaries_shp
unzip TM_WORLD_BORDERS-0.2.zip -d boundaries_shp
wget http://kartoweb.itc.nl/RIMapper/code/shp2mysql_0_4.zip
unzip shp2mysql_0_4.zip -d shp2mysql_04
wget http://dl.maptools.org/dl/shapelib/shapelib_1_2_10.zip
unzip shapelib_1_2_10.zip
cd shapelib-1.2.10
make
cd ..
rm ./shp2mysql_04/src/*.o
sed 's/^OBJS.*$/OBJS = \.\.\/\.\.\/shapelib-1\.2\.10\/shpopen\.o \.\.\/\.\.\/shapelib-1\.2\.10\/dbfopen\.o/' shp2mysql_04/src/Makefile &gt; shp2mysql_04/src/Makefile2
mv shp2mysql_04/src/Makefile2 shp2mysql_04/src/Makefile
cd shp2mysql_04/src
make
cd ../../
cp shp2mysql_04/src/shp2mysql .
./shp2mysql -d boundaries_shp/TM_WORLD_BORDERS-0.2.shp world_boundaries test_db &gt; wb_dump.sql
rm *.zip
rm -rf shp2mysql_04
rm -rf shapelib-1.2.10
rm -rf boundaries_shp</pre>
<p>Make the above script executable then run it:</p>
<pre>chmod +x process_boundaries.sh
./process_boundaries.sh</pre>
<p>If you&#8217;re interested in the details about this script then read on otherwise <a href="#import-to-DB">happily skip it</a>. The final SQL file is linked at the end of this post.</p>
<p>We&#8217;ll start by bringing the shape files:</p>
<pre>mkdir borders
cd borders
wget http://mappinghacks.com/data/TM_WORLD_BORDERS-0.2.zip
mkdir boundaries_shp
unzip TM_WORLD_BORDERS-0.2.zip -d boundaries_shp</pre>
<p>The files are in ESRI&#8217;s shp format which wasn&#8217;t exactly what I needed. I had to export them in a more usable format, SQL in my case. For this I used the <a href="http://kartoweb.itc.nl/RIMapper/code/shp2mysql_0_4.zip">shp2mysql</a> utility for which I didn&#8217;t find the MacOS executable so we&#8217;ll compile it from source. Since it has a dependency to <a href="http://shapelib.maptools.org/">shapelib</a> we have to download and compile it along:</p>
<pre>mkdir shp2mysql
wget http://kartoweb.itc.nl/RIMapper/code/shp2mysql_0_4.zip
unzip shp2mysql_0_4.zip -d shp2mysql
wget http://dl.maptools.org/dl/shapelib/shapelib_1_2_10.zip
unzip shapelib_1_2_10.zip
cd shapelib-1.2.10
make
cd ..</pre>
<p>Now you should have both shapelib and shp2mysql downloaded with shapelib succesfully compiled.  Now we&#8217;ll compile shp2mysql: we have to delete all .o files (they have been compiled for a different platform), fix the Makefile then issue the <code>make</code> command</p>
<pre>rm shp2mysql/src/*.o
sed 's/^OBJS.*$/OBJS = ../../shapelib-1.2.10/shpopen.o ../../shapelib-1.2.10/dbfopen.o/' shp2mysql/src/Makefile &gt; shp2mysql/src/Makefile2
mv shp2mysql/src/Makefile2 shp2mysql/src/Makefile
cd shp2mysql/src
make
cp shp2mysql/src/shp2mysql .</pre>
<p>which should execute successfully.<br />
We&#8217;re ready to export the world boundaries into SQL format. Switch to the <code>boundaries</code> folder then issue the export command as follows:</p>
<pre>cd ..
./shp2mysql -d boundaries_shp/TM_WORLD_BORDERS-0.2.shp world_boundaries test_db &gt; wb_dump.sql</pre>
<p>this will create a SQL file called wb_dump.sql ready to be loaded into your database.</p>
<p>Running the script will generate a file called wb_dump.sql which is ready to be imported on your spatially enabled database:<br />
<a name="import-to-DB"></a><br />
All we have to do now is to import the sql file into the database. Note that the database has to be spatially enabled (MySQL is by default, I&#8217;m using 5.0). Issue the following command:</p>
<pre>mysql -uroot -p my_database &lt; wb_dump.sql</pre>
<p>Now we should have country borders for the whole world imported in the database.<br />
For convenience, I have made the world boundaries SQL file available for <a href="http://blog.newsplore.com/wp-content/uploads/2009/02/wb_dump.zip">download</a> (4.3 MB).</p>
<p>In the second part of this how-to, we&#8217;ll use this table to create the country borders overlay for Google Maps.</p>
<p class="fbconnect_share"><fb:share-button class="url" href="http://blog.newsplore.com/2009/02/22/spincloud-labs-political-boundaries-overlay-in-google-maps-part-1" /></p>]]></content:encoded>
			<wfw:commentRss>http://blog.newsplore.com/2009/02/22/spincloud-labs-political-boundaries-overlay-in-google-maps-part-1/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Spincloud now integrates with Europe&#8217;s weather warning service Meteoalarm</title>
		<link>http://blog.newsplore.com/2009/01/31/spincloud-integrates-now-with-europes-weather-warning-service-meteoalarm</link>
		<comments>http://blog.newsplore.com/2009/01/31/spincloud-integrates-now-with-europes-weather-warning-service-meteoalarm#comments</comments>
		<pubDate>Sun, 01 Feb 2009 02:28:47 +0000</pubDate>
		<dc:creator>Florin</dc:creator>
				<category><![CDATA[projects]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[mashups]]></category>

		<guid isPermaLink="false">http://blog.newsplore.com/?p=382</guid>
		<description><![CDATA[A short month after the initial public release of Spincloud, I am pleased to announce the addition of a new feature: integration with the European weather warning service Meteoalarm which provides the most relevant information needed to prepare for extreme weather, expected to occur over Europe.  The colors indicate the severity of the danger and [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="padding-right:0;margin-top:3px"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.newsplore.com%2F2009%2F01%2F31%2Fspincloud-integrates-now-with-europes-weather-warning-service-meteoalarm"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.newsplore.com%2F2009%2F01%2F31%2Fspincloud-integrates-now-with-europes-weather-warning-service-meteoalarm" height="61" width="51" /></a></div><div align='justify' style="float:left;padding-right: 14px;"><img src="http://blog.newsplore.com/wp-content/uploads/2009/01/sc_ma.jpg" alt="Spincloud + Meteoalarm" width="220"></div>
<div align='justify'>A short month after the initial public release of Spincloud, I am pleased to announce the addition of a new feature: integration with the European weather warning service <a href="http://www.meteoalarm.eu">Meteoalarm</a> which provides the most relevant information needed to prepare for extreme weather, expected to occur over Europe.  The colors  indicate the severity of the danger and its possible impact:  <font color='red'><b>Red</b></font>: very dangerous, <font color='#FFA60B'><b>Orange</b></font>: dangerous,  <font color='yellow'><b>Yelllow</b></font>: potentially dangerous, <font color='green'><b>Green</b></font>: no warnings.<br />
<br />Currently only the country-level warnings are displayed. You can access the new feature by clicking the &#8220;Meteoalarm&#8221; button located on the top-left corner of the map. Note that the map has to be positioned over Europe for this buttton to be enabled.<br />
More information about Meteoalarm <a href="http://www.meteoalarm.eu/about.asp?lang=EN">here</a>.</p>
<p><i>Important note: </i>When using this new feature, the best experience is with Google&#8217;s Chrome, Mozilla or Safari browsers. Enabling the Meteoalarm overlay is much slower on IE browser which sometimes results in the browser reporting a slow-running script on slower hardware. Wait a few more seconds, the new overlay will render eventually.
</div>
<p class="fbconnect_share"><fb:share-button class="url" href="http://blog.newsplore.com/2009/01/31/spincloud-integrates-now-with-europes-weather-warning-service-meteoalarm" /></p>]]></content:encoded>
			<wfw:commentRss>http://blog.newsplore.com/2009/01/31/spincloud-integrates-now-with-europes-weather-warning-service-meteoalarm/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>@BreakingNewsOn map</title>
		<link>http://blog.newsplore.com/2009/01/10/breakingnewson-a-map</link>
		<comments>http://blog.newsplore.com/2009/01/10/breakingnewson-a-map#comments</comments>
		<pubDate>Sat, 10 Jan 2009 15:57:36 +0000</pubDate>
		<dc:creator>Florin</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[mashups]]></category>

		<guid isPermaLink="false">http://blog.newsplore.com/?p=368</guid>
		<description><![CDATA[I&#8217;m a bit of a news junkie and when I heard that a twitter stream called @BreakingNewsOn existed I did the natural geekish thing, mash it up. Yahoo pipes was my friend here. I haven&#8217;t used the Pipes before but that didn&#8217;t quite matter, Yahoo did a great job keeping this playgroundsy product in the child realm so [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="padding-right:0;margin-top:3px"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.newsplore.com%2F2009%2F01%2F10%2Fbreakingnewson-a-map"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.newsplore.com%2F2009%2F01%2F10%2Fbreakingnewson-a-map" height="61" width="51" /></a></div><p>I&#8217;m a bit of a news junkie and when I heard that a twitter stream called <a href="http://twitter.com/breakingnewson">@BreakingNewsOn</a> <a href="http://www.techcrunch.com/2009/01/08/breakingnewson-from-twitter-account-to-public-news-wire-service/">existed</a> I did the natural geekish thing, mash it up. Yahoo pipes was my friend here. I haven&#8217;t used the Pipes before but that didn&#8217;t quite matter, Yahoo did a great job keeping this playgroundsy product in the child realm so even a caveman could do it. The mashup result -two pipe connections later- is beyond the link:</p>
<p><a href="http://pipes.yahoo.com/newsplore/breakingnewson">http://pipes.yahoo.com/newsplore/breakingnewson</a></p>
<p class="fbconnect_share"><fb:share-button class="url" href="http://blog.newsplore.com/2009/01/10/breakingnewson-a-map" /></p>]]></content:encoded>
			<wfw:commentRss>http://blog.newsplore.com/2009/01/10/breakingnewson-a-map/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gmail themes, skin deep</title>
		<link>http://blog.newsplore.com/2008/11/21/gmail-themes-skin-deep</link>
		<comments>http://blog.newsplore.com/2008/11/21/gmail-themes-skin-deep#comments</comments>
		<pubDate>Fri, 21 Nov 2008 06:08:46 +0000</pubDate>
		<dc:creator>Florin</dc:creator>
				<category><![CDATA[tools]]></category>
		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://blog.newsplore.com/?p=273</guid>
		<description><![CDATA[Today was my lucky day according to least one popular blog. I got the Themes tab enabled in my gmail account, wohoo! I only wish they could change the font sizes too, I&#8217;m up for a microscopic look&#8217;n feel, really small and cozy-cute. My current favorite is the Shiny theme: Now, if only googlers would add a Cover Flow option instead [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="padding-right:0;margin-top:3px"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.newsplore.com%2F2008%2F11%2F21%2Fgmail-themes-skin-deep"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.newsplore.com%2F2008%2F11%2F21%2Fgmail-themes-skin-deep" height="61" width="51" /></a></div><p>Today was my lucky day according to least one popular <a href="http://www.techcrunch.com/2008/11/19/gmail-themes-thats-totally-ninja/"><span>blog.</span></a> I got the Themes tab enabled in my gmail account, wohoo! I only wish they could change the font sizes too, I&#8217;m up for a microscopic look&#8217;n feel, really small and cozy-cute.</p>
<p>My current favorite is the Shiny theme:</p>
<p style="center;"><a href="http://blog.newsplore.com/wp-content/uploads/2008/11/geeshiny.jpg"><img class="size-medium wp-image-278 aligncenter" src="http://blog.newsplore.com/wp-content/uploads/2008/11/geeshiny.jpg" alt="" width="300" height="297" /></a></p>
<p>Now, if only googlers would add a <a href="http://en.wikipedia.org/wiki/Cover_Flow">Cover Flow</a> option instead of that dull message list. Oh, and it should come gratis as usual.</p>
<p>I learned something today too. To take a screenshot on a MacBook, press Shift-Command-4 then select the portion of the screen you want to capture, then find the pic saved conveniently on your Desktop in png format. The karate stance is only required if you want to execute the entire screen capture kata.</p>
<p>[my gmail inbox via <a href="http://www.techcrunch.com/2008/11/19/gmail-themes-thats-totally-ninja/">Techcrunch</a>]</p>
<p class="fbconnect_share"><fb:share-button class="url" href="http://blog.newsplore.com/2008/11/21/gmail-themes-skin-deep" /></p>]]></content:encoded>
			<wfw:commentRss>http://blog.newsplore.com/2008/11/21/gmail-themes-skin-deep/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My very first mac: one with the machine</title>
		<link>http://blog.newsplore.com/2008/10/24/and-im-a-human-being</link>
		<comments>http://blog.newsplore.com/2008/10/24/and-im-a-human-being#comments</comments>
		<pubDate>Fri, 24 Oct 2008 17:04:54 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[tools]]></category>
		<category><![CDATA[computing]]></category>
		<category><![CDATA[mac]]></category>

		<guid isPermaLink="false">http://spincloud.com/blog/?p=85</guid>
		<description><![CDATA[I just bought my first MacBook yesterday. My current laptop (a beaten down Toshiba Satellite) was long overdue and I realized that I didn&#8217;t want yet another boring Win notebook, it just doesn&#8217;t do it for me anymore. I&#8217;m in front of a PC every day at work and I surely don&#8217;t want to see [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="padding-right:0;margin-top:3px"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.newsplore.com%2F2008%2F10%2F24%2Fand-im-a-human-being"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.newsplore.com%2F2008%2F10%2F24%2Fand-im-a-human-being" height="61" width="51" /></a></div><table border="0">
<tbody>
<tr>
<td valign="top"><img style="margin-bottom: 0px; margin-right: 8px" title="my mac" src="http://blog.newsplore.com/wp-content/uploads/2008/10/img_2465_2.jpg" alt="" width="150" height="99" /></td>
<td>I just bought my first MacBook yesterday. My current laptop (a beaten down Toshiba Satellite) was long overdue and I realized that I didn&#8217;t want yet another boring Win notebook, it just doesn&#8217;t do it for me anymore. I&#8217;m in front of a PC every day at</td>
</tr>
</tbody>
</table>
<p>work and I surely don&#8217;t want to see the same things while at home. And so I was determined to buy a Mac. My first Mac. I didn&#8217;t know that much about Apple and still don&#8217;t (imagine that)&#8230;<br />
I waited until the new MacBooks were announced (no rush, I don&#8217;t know much about these machines anyway) and I started to do my research. A $1500 laptop seems a reasonable price for a good laptop and I had two requirements: not that big and not that heavy. MBPs seemed too expensive so my choices were the 2.0 or 2.4 MacBook. I eventually choose the 2.4 version mostly because of the backlit keyboard.</p>
<p><span id="more-85"></span></p>
<p>I ordered it online at the Apple Store and received the box it two days later. I didn&#8217;t set my expectations too high although I hoped that it&#8217;ll suck less than my boring Toshiba.</p>
<p>The first impression was quite pleasant, the machine looks astonishing. It&#8217;s finished to perfection. And pretty light too. OK, first impresion was good. I understood why I keep seeing them in the movies: they&#8217;re damn sexy. Still, skin-deep doesn&#8217;t do it for me. Gotta be more under the hood to really like it.</p>
<p>I&#8217;m a minimalist. I can say that the installation was the shortest I&#8217;ve ever seen. I especially enjoyed the snapshot that is taken when you create the username, nice touch.</p>
<p>Then I saw the interface. I&#8217;ve been around UNIX/Linux since the early &#8217;90s, I developed an attachment to it since my student years. I still remember the HPUX machine we had in the lab, what a gorgeous GUI it had (ah Motif, still miss you). My first contact with Linux was through Slackware, a remarcable distro. But the Leopard OS is a beauty. It resembles the Linux&#8217;s own Gnome (now I know where the inspiration came from) but it has a window manager done right. And again, I realized one more thing: the legions of Apple followers started to look rational. And so do the lineups in the Apple Stores or around wireless carrier&#8217;s outlets that sell iPhones. Revelation time.</p>
<p>As I explored the OS more and more, I noticed that didn&#8217;t miss much from my old PC world. Moreover, I feel more productive than before. The multi-touch trackpad is just good. I&#8217;m a long-tie fan of browser mouse gestures (since Opera) and moving the concept one step ahead is quite refreshing. The Safari browser is much more responsive than Firefox and I&#8217;ve switched to it. There are  less and less differences between browsers these days anyway and I can live without the firefox plugins for a while until I feel that I really need them (especially Ubiquity and delicious).</p>
<p>As a linux guy, I feel at home with the goods that the UNIX OS has to offer. Moving to UNIX was a bright move by Apple: they can access the technological advancements and ideas contributed by the powerful Linux/UNIX communities. A brilliant gambit.</p>
<p>As a Java&amp;web developer I was a bit concerned by the suitability of this notebook as a development machine but I can report that Eclipse, MySQL, Subversion and all the others work just fine. I&#8217;m having a problem with the Maven and SpringIDE plugins but I&#8217;m blaming the Eclipse (it&#8217;s a 3.4 version) at this point. The 13&#8243; screen is just fine for coding, no complaints.</p>
<p>I actually feel more inspired working on this machine. Now I only need the <a class="aligncenter" style="display: inline !important;" title="Mirra" href="http://www.hermanmiller.com/CDA/SSA/Product/1,1592,a10-c440-p205,00.html" target="_self">Mirra</a> and my dream home office will be complete.</p>
<p>Enough already. I switched. There&#8217;s no looking back.</p>
<p class="fbconnect_share"><fb:share-button class="url" href="http://blog.newsplore.com/2008/10/24/and-im-a-human-being" /></p>]]></content:encoded>
			<wfw:commentRss>http://blog.newsplore.com/2008/10/24/and-im-a-human-being/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
