tag:blogger.com,1999:blog-20177220139542309072024-03-05T02:25:15.545-08:00Code.Randomwuherhttp://www.blogger.com/profile/05881990917829152817noreply@blogger.comBlogger9125tag:blogger.com,1999:blog-2017722013954230907.post-54810216290097400302014-03-06T15:28:00.000-08:002014-03-06T21:20:37.418-08:00Testing your HAPI serviceFor the past few weeks I've been building a REST API with <a href="http://spumko.github.io/">h<span id="goog_73065638"></span><span id="goog_73065639"></span>api</a>. It's a bit of a mind shift from middleware based frameworks like Express or Django but so far I'm very happy with it. The design really shows that it was made for building serious services.<br />
<br />
As far as testing goes I couldn't find much material on how to go about and test my API with, say something like <a href="http://visionmedia.github.io/mocha/">Mocha</a>. I suppose I could've just browsed the hapi source code and see how it was tested internally, but what I ended up doing (after some googling) was that I'd actually start the hapi server before each test case and then stop it after each test. In the tests I used mikeal's <a href="https://github.com/mikeal/request">request</a> library to query the API. This worked but it felt a bit awkward compared to, for example, what Django provides.<br />
<br />
Luckily, I ran into Eran's <a href="http://hueniverse.com/2013/01/hapi-hapi-joi-joi/">great talk</a> about hapi where he briefly mentions the <span style="font-family: Courier New, Courier, monospace; font-size: x-small;">server.inject()</span> method. I remember seeing that method before but didn't really understand what it would be good for. But actually with that method you can easily build your API tests. So, I created a generic function for querying my API:<br />
<br />
<pre class="brush: js">/**
* @param {hapi.Server} server - hapi server instance
* @param {object} requestobj - options for making the request
*/
exports.request = function (server, requestobj, callback)
server.inject(requestobj, function (res)
if (res.payload)
res.body = JSON.parse(res.payload);
}
callback(res);
});
</pre>
<br />
<div>
<br /></div>
<div>
In the tests I would do something like this (note that the following test uses Mocha but any test framework should do just fine):</div>
<div>
<br /></div>
<div>
<br /></div>
<pre class="brush: js"> beforeEach(function (done) {
var api = require('../api/api.js');
this.server = api.createServer();
done();
});
it('should GET all players', function (done) {
var request = { url: '/player/', method: 'GET' };
test.request(this.server, request, function (res) {
res.statusCode.should.be.equal(200);
res.body.length.should.be.equal(6);
done();
});
});
</pre>
<div>
And that was it. No more starting and stopping the server all the time.<br />
<br />
<br /></div>wuherhttp://www.blogger.com/profile/05881990917829152817noreply@blogger.com0tag:blogger.com,1999:blog-2017722013954230907.post-44166547249775584042014-02-26T14:26:00.002-08:002014-02-26T14:49:41.418-08:00Ember, Leaflet and Leaflet.DrawI spent some time trying to figure out how to hook all these components together and decided to document the process here in case someone else is struggling with this as well.<br />
<div>
<br /></div>
<div>
I had a minimalistic Ember project in which I wanted to use <a href="http://leafletjs.com/">Leaflet</a> maps. I quickly found out about the <a href="http://gabesmed.github.io/ember-leaflet/">ember-leaflet</a> project. I added the ember-leaflet.js dependency to my index.html and following code into my ember application:</div>
<div>
<br /></div>
<pre class="brush: js">App.TileLayer = EmberLeaflet.TileLayer.extend({
tileUrl: 'http://localhost:7000/tiles/{z}/{x}/{y}.png'
});
App.MapView = EmberLeaflet.MapView.extend({
childLayers: [App.TileLayer],
center: [34.227, -118.55],
zoom: 11
});
</pre>
Only problem I had with this, was that the leaflet map was taking too much space. Basically it filled the whole ember view. So, when I had other stuff in my handlebars template (besides the <span style="font-family: Courier New, Courier, monospace;"><div id="map"></div></span> placeholder), the map would fill the whole template pouring over the other elements that I had in my template. This is why I ended up creating another ember view inside the outer view that would only contain the map. Then in the parent template I would have all my html elements as before but where I previously had the div-placeholder for the map, I put <span style="font-family: Courier New, Courier, monospace;">{{render "map"}}</span> and then in <span style="font-family: Courier New, Courier, monospace;"> map.hbs</span> file just the map-div: <span style="font-family: 'Courier New', Courier, monospace;"><div id="map"></div></span>.
<br />
<br />
So far so good.<br />
<br />
I also needed draw controls and sure enough, <a href="https://github.com/Leaflet/Leaflet.draw">Leaflet.Draw</a> had everything I wanted. I added the css and js files into my project and added following options to my map configuration:<br />
<br />
<pre class="brush: js">App.MapView = EmberLeaflet.MapView.extend({
childLayers: [App.TileLayer],
center: [34.227, -118.55],
zoom: 11,
options: {
drawControl: true
}
});
</pre>
That would show the controls on the map just fine, but I wanted to get the edit controls working as well and as Leaflet.Draw documentation tells us I needed to create the Draw controls myself. I wasn't quite sure where to put that code so I ended up overriding the <span style="font-family: Courier New, Courier, monospace;">didCreateLayer</span> and initialising the drawing controls there. But I still wasn't able to hook to all the events that Leaflet.Draw provides. Of course, I probably could have gotten the leaflet map handle from ember-leaflet and attach my event handler directly there, but that seemed like a hack. Going through the ember-leaflet code I noticed that it internally uses <span style="font-family: Courier New, Courier, monospace;">concatenatedProperties: ['events']</span> to gather all supported events. After that I just introduced that property in my derived view and added all Leaflet.Draw events there. At that point the code looked like this:<br />
<br />
<pre class="brush: js">App.MapView = EmberLeaflet.MapView.extend({
childLayers: [App.TileLayer],
center: [34.227, -118.55],
zoom: 11,
events: [
'draw:created',
'draw:edited',
'draw:deleted',
'draw:drawstart',
'draw:drawstop',
'draw:editstart',
'draw:editstop',
'draw:deletestart',
'draw:deletestop'
],
didCreateLayer: function () {
this._super();
var map = this.get('layer'),
drawnItems = new L.FeatureGroup(),
drawControl;
this.set('drawnItems', drawnItems);
map.addLayer(this.drawnItems);
drawControl = new L.Control.Draw({
edit: {
featureGroup: this.drawnItems
}
});
map.addControl(drawControl);
},
"draw:created": function (e) {
var layer = e.layer,
type = e.layerType,
drawnItems = this.get('drawnItems'),
bounds;
drawnItems.addLayer(layer);
return this;
}
});
</pre>
<div>
That was it. Now I'm able to get all the Leaflet.Draw events to my view.</div>
<span style="font-family: Times, Times New Roman, serif;"></span>
<br />
<div>
<br /></div>
<div>
<br /></div>wuherhttp://www.blogger.com/profile/05881990917829152817noreply@blogger.com1tag:blogger.com,1999:blog-2017722013954230907.post-21981045454162495442014-02-17T11:29:00.001-08:002014-03-28T14:02:19.266-07:00Doctor of LegoSo, I finally got my Ph.D.<br />
<br />
With Professor Cesare Pautasso from University of Lugano being the opponent in my defence, we had good discussions. The topic of my dissertation is "Engineering Web Applications: Architectural Principles for Web Software". In case you are interested in getting the pdf file, <a href="https://dl.dropboxusercontent.com/u/8872754/dissertation-full.pdf">here's the link</a>.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1tv5vhk5hW5HYuaZbgFnwM3m5bXk0HPZdWHzMAuBObP2pyGXywwt6q33XfDlcunW_mOzp8PC7r_Ljs9I4GXrMTJMw5O1Ph0Dpn7w5fgGfN6dqs2UYHMW1yaFBJzGknLMzjwsr89NNsag/s1600/BgnrbTvIIAAN0eA.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1tv5vhk5hW5HYuaZbgFnwM3m5bXk0HPZdWHzMAuBObP2pyGXywwt6q33XfDlcunW_mOzp8PC7r_Ljs9I4GXrMTJMw5O1Ph0Dpn7w5fgGfN6dqs2UYHMW1yaFBJzGknLMzjwsr89NNsag/s1600/BgnrbTvIIAAN0eA.jpg" height="180" width="320" /></a></div>
<br />
The whole process took couple of more years than I was hoping for because I was really caught up with the implementation side of these things in the company I work for. It would've been nice to publish this few years earlier but no harm done. If you're looking for a TL;DR version of my dissertation <a href="http://wuher-random.blogspot.fi/2012/01/single-page-web-apps-and-rest.html">this</a> post is a very brief summary of the subject.wuherhttp://www.blogger.com/profile/05881990917829152817noreply@blogger.com0tag:blogger.com,1999:blog-2017722013954230907.post-2499512005397391832012-01-20T02:23:00.000-08:002012-01-20T02:43:20.732-08:00Single page web apps and REST<div style="text-align: justify;">
I was inspired by the <a href="http://blog.fogcreek.com/the-trello-tech-stack/">Trello tech stack blog post</a>. I've been talking and writing about something similar during the last year or so but never blogged about it. I agree on most of the points made in the post but they could -- and should -- go even further.</div>
<div>
<br /></div>
<div style="text-align: justify;">
Traditionally, web applications are burdened with the spaghetti of too many technologies. The application logic is fragmented over many technologies: HTML/templates, JavaScript and a server side language. This kind of fragmentation makes it very difficult to maintain a consistent code base and to apply proven software patterns like information hiding and responsibility assignment. Web frameworks alleviate problems to some extent but they don't take away the underlying problems. In the end, it's up to the developer to try and maintain the codebase and the responsibilities of different components. On the other hand these frameworks make things even worse because developers become dependent on their features and start using them blindly, maybe even without complete understanding of what goes on behind the scenes. The code they produce and the skillset they end up with is very difficult to reuse.</div>
<div>
<br /></div>
<div style="text-align: justify;">
We have all been there; we start with a clean design, we set up our MVC model as provided by the framework. We implement the application logic on the server and the view becomes more or less a static web page that is presented to the user. Then we realize that our application is too slow and too error prone. Too many page reloads and too many milliseconds there is a blank screen before a new page comes up. Now starts the optimization; we start adding adding stuff into HTML templates for more convenient rendering and especially we start adding JavaScript to make pages more dynamic. Now we have a web application that is implemented in HTML templates, Java and, JavaScript. Moreover, the client and the server are very tightly coupled and any kind of reusability is seriously compromised.</div>
<div>
<br /></div>
<div>
This is not good.</div>
<div>
<div>
<br /></div>
<div style="text-align: justify;">
Highly interactive web applications should be written more like the <a href="https://trello.com/">Trello</a> application; do full MVC on the client side and build an API on the server that the client app consumes directly. Key point here is that you should <b>completely decouple the client and the server</b>. Implement the client as a single page web application that you can either host on a server or wrap it as an application that can be distributed in one (or several) of the web stores. The server on the other hand should be implemented in terms of REST. We are already dealing with HTTP so it makes sense to make best use of it. Another thing that speaks for using REST is its clear separation of responsibilities between the client and the server: the application is responsible for maintaining its state and the server is responsible for maintaining the state of the resources it exposes. There's no more guesswork like "<i>should I implement this functionality in JavaScript, HTML templates or on the server?</i>". You implement the application as much as possible in the client and use the server API only when necessary. </div>
<div>
<br /></div>
<div style="text-align: justify;">
Compared to the traditional way of implementing web applications this approach brings with it many advantages (these points are discussed in further detail in my <a href="http://www.usenix.org/event/webapps11/tech/final_files/Kuuskeri.pdf">paper</a> presented at USENIX WebApps '11, <a href="http://www.slideshare.net/wuher/experiences-on-a-design-approach-for-interactive-web-applications">slides</a>):</div>
</div>
<div>
<ul>
<li style="text-align: justify;"><i>Reusable service interface</i>: the server API becomes reusable. You can use it from another application (possible a mobile app) or you can publish it for others to use.</li>
<li style="text-align: justify;"><i>Reusable client application</i>: if you need the application in another environment, you can build the same REST API on top of that system and be able to use the same client application.</li>
<li style="text-align: justify;"><i>Responsibilities are easier to assign and enforce</i>: REST sets a strict fence between the client and the server. This makes things like data validation, error handling and localization more explicit and easier to implement. Or should I say, more difficult to mess up.</li>
<li style="text-align: justify;"><i>Easier development model</i>: the application logic is not fragmented over different technologies. The client and the server can be developed and especially tested individually and they both have their own internal design and architecture. Implementation of the client application becomes more like implementing a traditional desktop application.</li>
<li style="text-align: justify;"><i>Better user experience</i>: the application is not reloaded all the time, so it's snappier. Moreover, the network traffic is minimized because only the payload data is transferred. After the initial page load (bootstrapping), no more CSS, HTML or JavaScript is transferred.</li>
</ul>
</div>
<div>
<br /></div>
<div style="text-align: justify;">
If you looked at the Trello tech stack, you can see that they did half of what I just explained. They have the single page web app with full MVC and they have the server API too. Only thing missing is the REST API. Actually, it just so happens that they are now also building the <a href="https://trello.com/docs/api/index.html">REST API</a> but it's a different one. What I would like to see is them eating their own dog food and use the API directly from the web application. For some reason this seems to be fairly common these days: many web applications (that even have an API to begin with) have one API for their own use and another API for 3rd party access. If this is due to the fact that they don't want to allow 3rd party access to all of the same resources they have themselves, they should just implement proper authorization scheme. But that's <a href="http://wuher-random.blogspot.com/2011/09/access-control-for-your-restful-api.html">another topic</a>.</div>
<div>
<br />
We have successfully utilized this approach on several of our (closed source / private) products so far. Not only have we been able to reuse the REST API but also the applications. We have implemented the same API on top of another system to be able to use some of the same applications in that setting. Compared to what we were doing before (traditional model 2 web applications) we have seen a serious boost in productivity and reusability.</div>wuherhttp://www.blogger.com/profile/05881990917829152817noreply@blogger.com0tag:blogger.com,1999:blog-2017722013954230907.post-79334093353756781542011-09-30T03:54:00.000-07:002011-09-30T04:08:22.323-07:00Access Control for Your RESTful API<span class="Apple-style-span" style="font-size: large;">Problem</span><br />
<br />
When your RESTful API gains popularity and different types of client applications (browsers, mobile kits, desktop UIs, other programs) start consuming it, it becomes apparent that they are all using your interface differently. Moreover, they all should have different set of resources available for them. Some applications only need to read couple of resources while others need read/write access to most of your resources. At that point, coming up with a flexible access control scheme becomes crucial. You could try to identify the application that is consuming your interface and based on that only allow access to certain resources, but that would be too easy to break. The only secure way of doing the access control, is to check the authorization of each request. This means tying the access control to the logged in user. However, even then there are usually different types of users (groups with different permissions) accessing the interface.<br />
<br />
Let's take an online book store as an example. The API supports three different user groups:<br />
<br />
<ul>
<li><b>Administrator</b> has access to every bit of information supported by the API </li>
<li><b>Merchant</b> may add and remove books from the store</li>
<li><b>Buyer</b> can place orders, cancel them and modify her account details</li>
</ul>
<div>
We also have to deal with more fine grained access control situations when, for example clients fetch a list of orders from the system. What should be requested and what should be returned? They both can do GET request on <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/order/</span> resource but most likely the result will look different for Merchant and Buyer. So, even if the request looks the same, Merchant will see all orders made to her shop whereas User will only see her own orders. Granted, we could alleviate this by providing different URLs for each list (e.g. <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/shop/123/order/</span> and <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/user/jedi/order/</span>) but usually you end up in a situation where you need to filter the results based on user's authorization anyway.</div>
<div>
<br /></div>
<div>
Even more complicated access control rules are required when you actually need to filter out some of the properties from representations. An example of this might be when a client requests user information (<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">GET</span> on <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/user/jedi/</span>) and some of that information -- such as SSN or credit card number -- should be hidden from Merchant but visible to the User.</div>
<div>
<br /></div>
<div>
<span class="Apple-style-span" style="font-size: large;">Solution</span></div>
<div>
<br /></div>
<div>
What I've come up with so far, is what I called <i>4-tier filtering</i>. This access control scheme has the following tiers:</div>
<div>
<ol>
<li><b>Filter resources</b> -- possibility to hide resources from a user</li>
<li><b>Filter methods</b> -- possibility to define which methods (post/get/put/delete) are allowed for a user</li>
<li><b>Filter resultset</b> -- possibility to filter the result of a collection type* resource</li>
<li><b>Filter properties</b> -- possibility to leave out some of the properties (of the representation)</li>
</ol>
<div>
* by <i>collection type resource</i> I mean resources that return list of elements (e.g. <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/order/</span>).</div>
</div>
<div>
<br /></div>
<div>
<span class="Apple-style-span" style="font-size: large;">Implementation</span></div>
<div>
<br /></div>
<div>
Not many REST-frameworks take special interest in fine grained and flexible configuration of access control (please, post links in comments if you can suggest some). Of the 4 tiers defined above, the first two are fairly easy to implement generically while tiers 3 and 4 are much more difficult. What I've been using for the first two tiers so far is a <a href="https://github.com/wuher/Bulldog">Django middleware</a> -- codenamed Bulldog -- that I implemented. I should mention that there's nothing Python or Django specific in this approach; it should be applicable in any environment (I'm actually in the process of doing the same thing in node.js).</div>
<div>
<br /></div>
<div>
Bulldog combines the first and second tiers of the access control in a way we have come to know from relational databases. This requires having <i>users</i>, <i>groups</i> and <i>permissions</i>. The implementation utilizes django's built-in support for these entities. Bulldog defines four permissions (CRUD) for each resource that the given interface supports. These permissions are then assigned to users and groups. A user automatically receives all permissions from the group she belongs to. So, in the permission table we have permissions like (these are automatically populated by the middleware):</div>
<div>
<br /></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">resource_order_post</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">resource_order_get</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">resource_order_put</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">resource_order_delete</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">resource_user_post</span></div>
<div>
....</div>
<div>
<br /></div>
<div>
The format being <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">resource_<resource name>_<method></span>. The <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">resource_</span> prefix is used for making a distinction between permissions dealing with access control tiers one and two and all other permissions. User may have any combination of these resources. That is, she may be able to <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">GET</span> order, but not <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">UPDATE</span> it and she may be able to <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">DELETE</span> a user but not <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">POST</span> (create) it.</div>
<div>
<br /></div>
<div>
<div>
By default Bulldog denies all access to any resource. Only if the user has been granted with any of the resource_* permissions, she is allowed to access those resources. This being a django middleware the incoming HTTP request never sees the REST framework let alone the API implementation if it doesn't have proper authorization.</div>
</div>
<div>
<br /></div>
<div>
<span class="Apple-style-span" style="font-size: large;">Next</span></div>
<div>
<br /></div>
<div>
I haven't yet figured out what's the best way to implement tiers 3 and 4 generically but obviously I'll need a different set of permissions and the implementation will probably need to grant everything by default (as opposed to denying everything).</div>
<div>
<br /></div>
<div>
In theory, tier 3 could also be implemented as a middleware by filtering the resultset before returning it to the client. In practice however, this would be terrible waste of CPU and memory because client would potentially end up doing a full table scan into memory and then filtering out most of the records. More likely, access control for tier 3 will have to be presented using a <a href="http://www.martinfowler.com/apsupp/spec.pdf">specification pattern</a> and that specification instance is passed along with the request. Later on, a <a href="http://martinfowler.com/eaaCatalog/repository.html">repository</a> or another source of data can use the specification to filter the data.</div>
<div>
<br /></div>
<div>
Now, in order to implement tier 4, the REST framework should provide means to define representations using for example, JSON schema or similar. In that definition, I could add annotations (required permissions) for the properties that are subject to access control.</div>
<div>
<br /></div>
<div>
I'll give this some more thought and write a followup with (hopefully) some code...</div>
<div>
<br /></div>
wuherhttp://www.blogger.com/profile/05881990917829152817noreply@blogger.com5tag:blogger.com,1999:blog-2017722013954230907.post-69942637228063268142011-09-21T12:26:00.000-07:002011-09-22T00:26:31.873-07:00Oracle instant client and cx_Oracle on OS X Lion<div>
In case you are doing Python development on a Mac and connecting to an Oracle database, there's a good chance that you've already run into the segfault (Segmentation fault: 11) <a href="http://www.flickr.com/photos/wuher/6170293862/">screen</a>. First, I thought it was something to do with the cx_Oracle that I had just updated but it turns out that the 64-bit version of the Oracle instant client is <a href="http://only4left.jpiwowar.com/2011/08/instant-client-osx-lion-32-bit-only/">busted</a> on the OS X Lion platform.</div>
<div>
<br /></div>
<div>
Only way around this is to use the 32-bit version of the instant client instead. The way you do this is that you download and install the 32-bit instant client (basic-lite and sdk) from Oracle, use Python in 32 bit mode and install cx_Oracle.</div>
<div>
<br /></div>
<div>
<ol>
<li>instant client comes with pretty decent installation instructions, so just follow them (set three env vars and create the symlink)</li>
<li>to run python in 32 bit mode you have two options (this is all explained in Python's <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">man</span> page):</li>
<ol>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">% defaults write com.apple.versioner.python Prefer-32-Bit -bool yes</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">% export VERSIONER_PYTHON_PREFER_32_BIT=yes</span></li>
</ol>
<li>remove the old cx_Oracle by simply removing the .egg under <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">/Library/Python/2.7/site-packages/</span><span class="Apple-style-span" style="font-family: inherit;">. So, for example: </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">% sudo rm /Library/Python/2.7/site-packages/cx_Oracle-5.1-py2.7-macosx-10.7-intel.egg</span></li>
<li>lastly say: <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">sudo -E easy_install cx_Oracle</span></li>
</ol>
<div>
<br /></div>
<div>
These instructions assume you're installing cx_Oracle globally to your system, hence <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo</span>. I actually tried going through this process in a <a href="http://www.virtualenv.org/">virtualenv</a> but it didn't work. However, I only tried once so maybe I missed something.. and I had to do a global install anyway so I haven't bothered with the virtualenv for now. Will try that again later.</div>
</div>
<div>
<br /></div>
<div>
<i>(In case you run into problems, you might want to reboot after the installation because I think OS X leaves some libraries into memory and when you switch back and forth with different versions of libraries, you may actually end up using a different library than what you think.)</i></div>
wuherhttp://www.blogger.com/profile/05881990917829152817noreply@blogger.com3tag:blogger.com,1999:blog-2017722013954230907.post-62352004250725083102011-04-13T05:15:00.000-07:002011-09-21T12:28:33.243-07:00RGB support for google.maps.Polyline strokeColor gone?Suddenly our sites stopped showing some of the polylines drawn on google maps components. I spent half a day debugging and then noticed that the ones that were missing used rgb value for setting the stroke color for the polyline, like so:<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> var color = "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")";</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> return new google.maps.Polyline({</span><br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> path: path,</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> geodesic: true,</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> strokeColor: color,</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> strokeOpacity: 1.0,</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> strokeWeight: 2</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> });</span><br />
<br />
However, as of now (4/13/2011) this doesn't work anymore. I couldn't find anything official about this from google's docs. If somebody has any details on this, comments are welcome.<br />
<br />
For the curious: the reason for this was that the polyline had a fading color, so that the end of the polyline was darker than the beginning.wuherhttp://www.blogger.com/profile/05881990917829152817noreply@blogger.com0tag:blogger.com,1999:blog-2017722013954230907.post-53308769857970746442011-04-13T02:09:00.000-07:002012-01-20T02:25:14.554-08:00Using oracle instant_client from Python on UbuntuI do a lot of Python development in different environments. Ubuntu is one of them. Oracle is not the easiest beast to deal with but the <a href="http://www.oracle.com/technetwork/database/features/instant-client/">instant_client</a> and cx_Oracle make it tolerable. The way I usually set this up is to do following:<br />
<br />
<br />
<ol>
<li>download instant_client basic lite and instant client sdk from oracle</li>
<li>unzip both into same dir (e.g. /home/jedi/instant_client)</li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">export ORACLE_HOME=/home/jedi/instant_client</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">export LD_LIBRARY_PATH=$ORACLE_HOME:$LD_LIBRARY_PATH</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">cd $ORACLE_HOME</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">ln -s libclntsh.so.11.1 libclntsh.so </span><span class="Apple-style-span" style="font-family: inherit;">(replace with your version number)</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo apt-get install python-dev python-setuptools libaio-dev</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo -E easy_install cx_Oracle</span></li>
</ol>
<div>
<span class="Apple-style-span" style="font-family: inherit;">This should do it. You can test it with:</span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$> python</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">>>> import cx_Oracle</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">>>> conn = cx_Oracle.connect("username/password@//example.host.com/orasid")</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">>>> crsr = conn.cursor()</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">>>> crsr.execute("select * from mytable")</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">>>> for row in crsr: print repr(row) # hit enter twice</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">...</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">>>> crsr.close()</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">>>> conn.close()</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">>>> quit()</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;">Credits where credit's due: <a href="http://catherinedevlin.blogspot.com/2008/06/cxoracle-and-oracle-xe-on-ubuntu.html">Catherine's howto for XE</a></span></div>
<div>
<br /></div>wuherhttp://www.blogger.com/profile/05881990917829152817noreply@blogger.com0tag:blogger.com,1999:blog-2017722013954230907.post-70955588074375256552011-04-13T01:40:00.000-07:002011-04-13T03:21:22.089-07:00Initial importThis is my scrapbook of random coding notes, howtos and installation instructions. I used to store that kind of stuff on my home server but it crashed and even though I do have backups I just felt that it was too much work.<br />
<div><br />
</div>wuherhttp://www.blogger.com/profile/05881990917829152817noreply@blogger.com0