Monday, June 30, 2014

sencha cmd, skip theme build.

Found Newbridge Green's bootstrap theme for Extjs4. Looks pretty good.

Except, he understands how this crap actually works and wrote the thing in plain sass. (not the extjs theme extension thing). So, I can't really add it to the framework generated by
sencha generate app

So, I don't. Now I need to figure out how to automatically copy his css over when I do
sencha app build
and figure out how to get rid of the stupid ruby compass compilation thingy that takes forever anyways.

I also want to not use YUI to compress, but rather uglifyjs2. This can be put into a grunt task.

Here's how you get rid of the sass build and slicing.
Go to
.sencha/app/sencha.cfg
and add the lines
skip.sass=1
skip.slice=1

Finally got rid of that crap.
Now, we want to stop using YUI.
Go to
.sencha/app/build.properties
and set the following lines.
build.compression.yui=0
build.compression.closure=1

build.compression.uglify=0

When I tried to use Uglify, I got the following error:
[ERR] 
[ERR] BUILD FAILED
[ERR] java.lang.UnsupportedOperationException: Not Yet Implemented
[ERR] 

[ERR] Total time: 10 seconds
Laughable.

Since closure takes forever, the best option is probably just to not use compression, and just use a grunt task to build after everything is concatenated. That includes uglifying the concatenated app.js file, copying the bootstrap theme to the build folder, and gzipping both of those files.

Here's the gruntfile config:

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    shell: {
      sencha_app_build: {
        command: 'sencha app build'
      }
    },

    jshint: {
      options: {
        reporter: require('jshint-stylish')
      },
      main: ['Gruntfile.js', 'app/**/*.js']
    },

    uglify: {
      options: {
        banner: '/*\n Copyright <%= pkg.author %> \n <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> \n*/\n'
      },
      main: {
        files: {
           'build/production/<%= pkg.name %>/app.js': 'build/production/<%= pkg.name %>/app.js'
        }
      }
    },

    copy: {
      main: {
        src: 'resources/css/bootstrap.css',
        dest: 'build/production/<%= pkg.name %>/resources/'
      }
    },

    compress: {
      options: {
        mode: 'gzip'
      },
      js: {
        expand: true, //use whole filename
        src: ['build/production/<%= pkg.name %>/*.js'],
        dest: '.'
      },
      css: {
        expand: true,
        src: ['build/production/<%= pkg.name %>/resources/*.css'],
        dest: '.'
      }
    }

  });

  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-compress');
  grunt.loadNpmTasks('grunt-shell');  //or grunt-exec, unsure which is better

  grunt.registerTask('default', ['shell', 'uglify', 'copy', 'compress']);


};



And that will do it! Just make sure that

  1. your package name in package.json is the same as your Sencha project name
  2. bootstrap.css is under resources/css
  3. you have all the dependencies in npm and run npm install!

Friday, June 27, 2014

New server, nginx + nodejs, github

Got a new AWS server.

Decided to switch from apache to nginx.

Had to figure out how to configure it.

Default inst. locations on RedHat are:
  • webroot at /usr/share/nginx/html
  • config file at /etc/nginx/nginx.conf
I followed some other tutorials to figure out how to configure the reverse proxy for node and nginx. The current method that I'm using is probably not THE best, but certainly works.

Needed to learn how to clone a private repo from a new machine. Also trying to actually learn how to use Github.

And check out this nice site: https://www.atlassian.com/git/

http://stackoverflow.com/questions/2505096/cloning-a-private-github-repo
Oh, so cloning private repos uses the git@github.com:username/repo.git format...
You also need to generate SSH keys to authenticate with Github:
https://help.github.com/articles/generating-ssh-keys#platform-linux

Terse.

Tuesday, May 6, 2014

Combining OAuth2 and Phonegap

So you've made a web application. You use OAuth2 for authentication and authorization. Now, you want it to have a mobile client. You don't fancy coding all your mobile apps natively -- at least not yet. You use Phonegap.

Then, the inevitable question: how can my Phonegap app support OAuth? It must be redirected to the OAuth page, and the user must grant consent. But then he's redirected to my original webpage created for the browser!

Here's how I've done it.
I started with a tutorial here.

Step 1: Download Phonegap's In App Browser. (If you have Phonegap 3.0 or above) Do this from your Cordova directory (the one with the .cordova folder. For me, since I am using SenchaCMD, it's under the phonegap folder of the main project directory)

cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-inappbrowser.git
Bam, downloaded. Great.

Step 2: Test your In App Browser:

function onBtnClick() {
    var ref = window.open('http://apache.org', '_blank', 'location=yes');
    ref.addEventListener('loadstart', function(event) { alert('start: ' + event.url); });
    ref.addEventListener('loadstop', function(event) { alert('stop: ' + event.url); });
    ref.addEventListener('loaderror', function(event) { alert('error: ' + event.message); });
    ref.addEventListener('exit', function(event) { alert(event.type); });
}
It should work quite well. You get event listeners for stuff. Yay.

Step 3: Direct it to the right URI!
Go to https://developers.google.com/accounts/docs/OAuth2WebServer to figure out what all the GET query parameters are.

Then, go test stuff out at the Google OAuth2 Playground! Here's what I got from the playground thing:

(Yes, I could have used better styling on this. Oops).

========================================================================

Google OAuth 2 Scheme:
Request / Response
HTTP/1.1 302 Found

GET /oauthplayground/?code=4/QrO4XICKVwOcWRoIjcD9hS_ftIjb.0v99D-kGD1cY3oEBd8DOtND9QdaliwI HTTP/1.1
Host: developers.google.com

Exchange Auth Code for Tokens
Request
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-length: 250
content-type: application/x-www-form-urlencoded
user-agent: google-oauth-playground
code=4%2FQrO4XICKVwOcWRoIjcD9hS_ftIjb.0v99D-kGD1cY3oEBd8DOtND9QdaliwI&redirect_uri=https%3A%2F%2Fdevelopers.google.com%2Foauthplayground&client_id=407408718192.apps.googleusercontent.com&scope=&client_secret=************&grant_type=authorization_code

Response
HTTP/1.1 200 OK
Alternate-protocol: 443:quic
Content-length: 1071
X-xss-protection: 1; mode=block
X-content-type-options: nosniff
Content-disposition: attachment; filename="json.txt"; filename*=UTF-8''json.txt
Expires: Fri, 01 Jan 1990 00:00:00 GMT
X-google-cache-control: remote-fetch
Server: GSE
Via: HTTP/1.1 GWA
Pragma: no-cache
Cache-control: no-cache, no-store, max-age=0, must-revalidate
Date: Tue, 06 May 2014 19:01:39 GMT
X-frame-options: SAMEORIGIN
Content-type: application/json; charset=utf-8
-content-encoding: gzip
{
  "access_token": "ya29.1.AADtN_UYHaNZzrpYU_fyR98OPAbWCiPN39olWxlWiJiVEXOxsafxy1qu2p6ANDc", 
  "token_type": "Bearer", 
  "expires_in": 3600, 
  "refresh_token": "1/geII4ucPZGDTgn_rfwyVhkUAdtWGzp2H4A5kpO3EAEQ", 
  "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjZkNTFhZjgwYzQ4NGIwZWZjZTI4Zjk0NjQ1YWQ4YjY0YjA4ZGNhNGEifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiaWQiOiIxMDgwNTAzMDY2Njg5Mzg4ODEzNTYiLCJzdWIiOiIxMDgwNTAzMDY2Njg5Mzg4ODEzNTYiLCJhenAiOiI0MDc0MDg3MTgxOTIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJlbWFpbCI6ImppYW5ndHNAc3RhbmZvcmQuZWR1IiwiYXRfaGFzaCI6IjBWZjBlVFhUVV9oMDNleFRVSGozR2ciLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXVkIjoiNDA3NDA4NzE4MTkyLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiaGQiOiJzdGFuZm9yZC5lZHUiLCJ0b2tlbl9oYXNoIjoiMFZmMGVUWFRVX2gwM2V4VFVIajNHZyIsInZlcmlmaWVkX2VtYWlsIjp0cnVlLCJjaWQiOiI0MDc0MDg3MTgxOTIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJpYXQiOjEzOTk0MDI1OTksImV4cCI6MTM5OTQwNjQ5OX0.vG2RVojWyn0cHl6-PhIoAZIhS5HVUXmOJ-X0nxDvJX4RwwWLv3yGLF4-V1QlfaRRVmqBwZc7PrJx5peGQmFyBKN-6IXRFwsiyJ5WRPlmeY1LuzPGi_KKrzT-S9hAB4Pjgi-3HYyJh01T3E34m59PspPkjzcKt5Fb05NL6g3kGjU"
}



Refresh Request (Optional)
Request
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-length: 163
content-type: application/x-www-form-urlencoded
user-agent: google-oauth-playground
client_secret=************&grant_type=refresh_token&refresh_token=1%2FgeII4ucPZGDTgn_rfwyVhkUAdtWGzp2H4A5kpO3EAEQ&client_id=407408718192.apps.googleusercontent.com

Response
HTTP/1.1 200 OK
Alternate-protocol: 443:quic
Content-length: 1002
X-xss-protection: 1; mode=block
X-content-type-options: nosniff
Content-disposition: attachment; filename="json.txt"; filename*=UTF-8''json.txt
Expires: Fri, 01 Jan 1990 00:00:00 GMT
X-google-cache-control: remote-fetch
Server: GSE
Via: HTTP/1.1 GWA
Pragma: no-cache
Cache-control: no-cache, no-store, max-age=0, must-revalidate
Date: Tue, 06 May 2014 19:02:08 GMT
X-frame-options: SAMEORIGIN
Content-type: application/json; charset=utf-8
-content-encoding: gzip
{
  "access_token": "ya29.1.AADtN_UeoAgso1pgdnAtlFnLWtlxA0pfSlKM6EAOBvzoMzTs0v-NcCQHdpUVXfc", 
  "token_type": "Bearer", 
  "expires_in": 3600, 
  "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjZkNTFhZjgwYzQ4NGIwZWZjZTI4Zjk0NjQ1YWQ4YjY0YjA4ZGNhNGEifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiaWQiOiIxMDgwNTAzMDY2Njg5Mzg4ODEzNTYiLCJzdWIiOiIxMDgwNTAzMDY2Njg5Mzg4ODEzNTYiLCJhenAiOiI0MDc0MDg3MTgxOTIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJlbWFpbCI6ImppYW5ndHNAc3RhbmZvcmQuZWR1IiwiYXRfaGFzaCI6Im5KS2hKM0dMdjROX1RHX0NReEF6aVEiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXVkIjoiNDA3NDA4NzE4MTkyLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiaGQiOiJzdGFuZm9yZC5lZHUiLCJ0b2tlbl9oYXNoIjoibkpLaEozR0x2NE5fVEdfQ1F4QXppUSIsInZlcmlmaWVkX2VtYWlsIjp0cnVlLCJjaWQiOiI0MDc0MDg3MTgxOTIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJpYXQiOjEzOTk0MDI2MjgsImV4cCI6MTM5OTQwNjUyOH0.pfWKLrTA3426WErPPoFnx_iYgaDjw4XQRJYG3Bpcl5514T5nDfiYuidgc-h_AHCQah13zLHIjPyQht1TByrXTyebkbLw7HFKmt1JpmSE2h6NI8FBNhj5E950JQTBZL6OYewYnLweKN6BkHdP7vCvcrp6vmddiUgn-tlYR6NrEsE"
}


Configure request to API 
(To: https://www.googleapis.com/oauth2/v2/userinfo)
Request
GET /oauth2/v2/userinfo HTTP/1.1
Host: www.googleapis.com
Content-length: 0
Authorization: Bearer ya29.1.AADtN_UeoAgso1pgdnAtlFnLWtlxA0pfSlKM6EAOBvzoMzTs0v-NcCQHdpUVXfc

Response
HTTP/1.1 200 OK
Content-length: 277
X-xss-protection: 1; mode=block
X-content-type-options: nosniff
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Server: GSE
Pragma: no-cache
Cache-control: no-cache, no-store, max-age=0, must-revalidate
Date: Tue, 06 May 2014 19:03:15 GMT
X-frame-options: SAMEORIGIN
Content-type: application/json; charset=UTF-8
{
  "family_name": "", 
  "name": "", 
  "email": "[your_email_addr]@stanford.edu", 
  "given_name": "", 
  "id": "[long string of numbers here]", 
  "hd": "stanford.edu", 
  "verified_email": true

}

========================================================================



So, this is all nice. It works. All I had to do was implement a method on the server side that
did the Exchange Auth Code for Tokens request, get the response, and do another request to the actual API at https://www.googleapis.com/oauth2/v2/userinfo.

So, in all for the user, they're only redirected to a set of 3 pages. First, the Google Login Page. Then, the grant consent page. Then, Google redirects them to my REST call that does this 2 step dance (get tokens from auth code and call the API). Then, they get a response.

My hack to get the response page to actually be a real page was to return an HTML that redirects the user (for the last time) to my application page. My redirect HTML response also sets a cookie with the auth stuff in it on the browser.

So, everything is super nice and hunky dory until this step. How will my redirect page differentiate between mobile and browser clients? We don't want the client to get redirected to my browser client if they're on mobile.

We can solve this one without too much trouble. Google's OAuth API query parameters let you send a state param, which you can set to be "mobile" when you're on a mobile client. Then, google's redirect will include this as a query parameter to your 2 step dance method. You can use this query param to determine whether or not you redirect to the set of browser pages. This is fine.

But then we have another problem: How do we set a cookie on Phonegap's In App Browser?

This one took some creativity, but here's my hackish solution. The only way (as far as I could tell) that the In App Browser can communicate information to the actual Phonegap app is through some properties of the InAppBrowserEvent object. These properties are:
  • type: the eventname, either loadstartloadstoploaderror, or exit(String)
  • url: the URL that was loaded. (String)
  • code: the error code, only in the case of loaderror(Number)
  • message: the error message, only in the case of loaderror(String)
So, what's the only one that we have a lot of control over? URL!
So, what's the trick?

After you get the token information and all that other jazz from the endpoint of the OAuth process (ie, the return html of your favorite 2 step dance REST API), you redirect to another page which contains all this information in the url. Then, you use JS to tell the window to close itself (which is an event that can be listened for).

Then, you get the InAppBrowserEvent object, you ask for its URL, and bam! You've gotten all the information you need within your Phonegap app.

Hacky, but that's how it goes.

A lot of these last few paragraphs probably makes sense to nobody but me. For anyone who stumbles upon this, it may be no surprise that it was intended to be read by me :)

Cheers
Allan




Tuesday, April 29, 2014

Postgres on Windows...

Yeah, why did I do this to myself? Well, I'm usually on a Mac, but Apple is dumb in that it doesn't support JEE6, which is what I used to write the sign-out app.

So, I needed to get the database onto the Windows machine where I wrote the sign-out app in JEE6.
So, I downloaded Postgres in a one-click exe file. Then it took me forever how to inflate a database from a pg_dump.

Well, after about 30 minutes of tinkering, here's how

how to run it from command line:

"\Program Files\PostgreSQL\9.3\bin\psql.exe" -U postgres ...



http://www.postgresql.org/docs/8.1/static/backup.html#BACKUP-DUMP-RESTORE

23.1.1. Restoring the dump

The text files created by pg_dump are intended to be read in by the psql program. The general command form to restore a dump is
psql dbname < infile
where infile is what you used as outfile for the pg_dump command. The database dbname will not be created by this command, you must create it yourself from template0 before executing psql (e.g., with createdb -T template0 dbname). psql supports options similar to pg_dump for controlling the database server location and the user name. See psql's reference page for more information.

Thursday, April 10, 2014

Using Sencha CMD 4.0.2 Architecture for ST2

So you have a ST2 project that's all big and uncompiled, and you want to minify it with CMD and even port it to XCode.

Here's how.

You should already have an MVC architecture, with models, views, and controllers separated into separate folders.

Get Sencha CMD4 and perform
sencha -sdk /path/to/sdk generate app AppName /app/folder/

If everything's working, cmd should create an app under /app/folder with a ton of goodies in it.
Check out it's folder structure and stuff. To change themes, access the hidden .sencha folder.

Just for satisfaction, run
sencha app build

There should now be a build folder in your project directory. Go look inside and find the minified code. Hooray!
Now, simply migrate your MVC code into the /app folder generated by cmd.
Run the app build command again. Given your code is structured correctly, and you have made all the proper changes to the app.js file, everything should work.

You now have a minified js and css file! Awesome!

For the phonegap component: check out this website http://www.sencha.com/blog/getting-started-with-sencha-touch-2-build-a-weather-utility-app-part-3
For the tl;dr version, do
sencha app build production 
sencha phonegap init <APP-ID> <APP-NAME>

Now, you should have a phonegap folder, and config.xml file. Check out the config.xml and read it, and make all the obvious changes that you need to make.

Finally, run a
sencha app build native

You should find the /phonegap/platforms/ios folder, inside of which will be an xcode project.

Please comment if you have questions!

Wednesday, April 2, 2014

Mavericks update woes continue.

Now, in Python, the up arrow key give me the previous command in the interactive session.

This is crap.

Here is a link to the solution. You need to recompile Python...
http://stackoverflow.com/questions/893053/python-shell-arrow-keys-do-not-work-on-remote-machine

Updating to OSX mavericks...

Mavericks is pretty horrible... meh.

For one, everything is now slower. Just to get XCode5 dev tools and multiple tabs in the finder, this is not really worth it.

On another note, I continually got this error in Python.

>>> import networkx as nx
>>> nx.Graph()

Segmentation fault: 11

This is ridiculous. Why would they break python?

I found the fix. 


Pretty much, do this stuff. Who knows what it does? It works.

cd /Library/Frameworks/Python.framework/Versions/3.3
cd ./lib/python3.3/lib-dynload 
sudo mv readline.so readline.so.disabled

Sunday, March 23, 2014

ooph... getting owned by asynchronicity...

You thought I would have learned how asynchronous stuff works after claiming to be a javascript fan.

Well, I guess I haven't tried putting callbacks inside javascript for loops... **it doesn't work**!!


Here is a nice post on how to do it.
http://www.richardrodger.com/2011/04/21/node-js-how-to-write-a-for-loop-with-callbacks/#.Uy9m1uddXWN

What you need to do is

var array = [...];
repeater(i){
    if(i < array.length){
        asynch(array[i], function(){
            //do your stuff here...
            repeater(i++);
        }
    }
}
repeater(0);

Pretty tricky indeed!

Sunday, March 9, 2014

Hot Code Loading in Node.js




Source: http://romeda.org/blog/2010/01/hot-code-loading-in-nodejs.html




Reading through Fever today, this post by Jack Moffitt caught my eye. In it, he discusses a hack to allow a running Python process to dynamically reload code. While the hack itself, shall we say, lacks subtlety, Jack's post got me thinking. It's true, Erlang's hot code loading is a great feature, enabling Erlang's 99.9999999% uptime claims. It occurred to me that it wouldn't be terribly difficult to implement for node.js' CommonJS-based module loader.
A few hours (and a tasty home-made Paella later), here's my answer: Hotload node branch.

Umm… What does it do?

var requestHandler = require('./myRequestHandler');

process.watchFile('./myRequestHandler', function () {
  module.unCacheModule('./myRequestHandler');
  requestHandler = require('./myRequestHandler');
}

var reqHandlerClosure = function (req, res) {
  requestHandler.handle(req, res);
}

http.createServer(reqHandlerClosure).listen(8000);
Now, any time you modify myRequestHandler.js, the above code will notice and replace the local requestHandler with the new code. Any existing requests will continue to use the old code, while any new incoming requests will use the new code. All without shutting down the server, bouncing any requests, prematurely killing any requests, or even relying on an intelligent load balancer.

Awesome! How does it work?

Basically, all node modules are created as sandboxes, so that as long as you don't use global variables, you can be sure that any modules you write won't stomp on others' code, and vice versa, you can be sure that others' modules won't stomp on your code.
Modules are loaded by require()ing them and assigning the return to a local variable, like so:
var http = require('http');
The important insight is that the return value of require() is a self-contained closure. There's no reason it has to be the same each time. Essentially, require(file) says "read file, seal it in a protective case, and return that protective case." require() is smart, though, and caches modules so that multiple attempts torequire() the same module don't waste time (synchronously) reading from disk. Those caches don't get invalidated, though, and even though we can detect when files change, we can't just call require() again, since the cached version takes precedence.
There are a few ways to fix this, but the subtleties rapidly complicate matters. If the ultimate goal is to allow an already-executing module (e.g., an http request handler) to continue executing while new code is loaded, then automatic code reloading is out, since changing one module will change them all. In the approach I've taken here, I tried to achieve two goals:
  1. Make minimal changes to the existing node.js require() logic.
  2. Ensure that any require() calls within an already-loaded module will return functions corresponding to the pre-hot load version of the code.
The latter goal is important because a module expects a specific set of behaviour from the modules on which it depends. Hot loading only works so long as modules have a consistent view of the world.
To accomplish these goals, all I've done is move the module cache from a global one into the module itself. Reloading is minimised by copying parent's caches into child modules (made fast and efficient thanks to V8's approach to variable handling). Any module can load a new version of any loaded modules by first removing that module from its local cache. This doesn't affect any other modules (including dependent modules), but will ensure that any sub-modules are reloaded, as long as they're not in the parent's cache.
By taking a relatively conservative approach to module reloading, I believe this is a flexible and powerful approach to hot code reloading. Most server applications have a strongly hierarchical code structure; as long as code reloading is done at the top-level, before many modules have been required, it can be done simply and efficiently.
While I hope this patch or a modified one will make it into node.js, this approach can be adapted to exist outside of node's core, at the expense of maintaining two require() implementations.

Friday, February 21, 2014

External files CMD/ST3... sadness.

If you created your app with Sencha Command then you should not edit index.html. Instead you should add JS files to the js property of app.json.

http://www.sencha.com/forum/showthread.php?211153-How-to-include-my-own-javascript-files

This is like, annoying at best.

Wednesday, February 12, 2014

Sencha Touch is different from ExtJS

I've done Extjs4 for awhile and thought ST2 would be the same way. In fact, I've even built an app with ST2. Turns out I didn't know a few basic things.

One of them is that classes take a config object. This is important! My form just kept on never displaying because I was used to putting fields on the class itself not in the form object.

Also, scaffolds are very very useful. Use them!
http://www.sencha.com/blog/getting-started-with-sencha-touch-2-build-a-weather-utility-app-part-1

Wednesday, February 5, 2014

jakarta mapping

to get the apache server to redirect to tomcat,
(to find it, run locate httpd.conf)
change workers2.properties
and run apachectl -k restart

Friday, January 24, 2014

Accessing Postgres UUID with JPA

http://stackoverflow.com/questions/11284359/persisting-uuid-in-postgresql-using-jpa

JPA 2.1 provides a very easy way to use the PostgreSQL uuid column type and java.util.UUID as the type of the corresponding entity field:
@javax.persistence.Converter(autoApply = true)
public class PostgresUuidConverter implements AttributeConverter<UUID, UUID> {

    @Override
    public UUID convertToDatabaseColumn(UUID attribute) {
        return attribute;
    }

    @Override
    public UUID convertToEntityAttribute(UUID dbData) {
        return dbData;
    }

}
Just add this class to your persistence configuration and annotate UUID fields with@Column(columnDefinition="uuid").

Requests.py

I needed to do some RESTful calls via command line.
Naturally, I could have used curl, but I wanted to save my commands.

I remember I used Python a long time ago, so I was investigating curling via Python. There is a pycurl library, but this one seemed simple and fun.

To set up,

Get the Code

Requests is actively developed on GitHub, where the code is always available.
You can either clone the public repository:
git clone git://github.com/kennethreitz/requests.git
Download the tarball:
$ curl -OL https://github.com/kennethreitz/requests/tarball/master
Or, download the zipball:
$ curl -OL https://github.com/kennethreitz/requests/zipball/master
Once you have a copy of the source, you can embed it in your Python package, or install it into your site-packages easily:
$ python setup.py install

Super simple, very fun!
It just works!

Sunday, January 12, 2014

Secure JAX-RS REST endpoints

Doesn't at all qualify for a 5 minute Google, but
searching "spring security jersey example"
gave me the following two links that are important.

http://stackoverflow.com/questions/18086048/jax-rs-how-to-secure-rest-endpoints
http://stackoverflow.com/questions/6795568/jersey-jax-rs-spring-security-application-sample

Saturday, January 11, 2014

Grabbing ajax parameters in Jersey

According to the website http://docs.oracle.com/cd/E19798-01/821-1841/gipzz/index.html:


To obtain a general map of parameter names and values for query and path parameters, use the following code:
@GET
public String get(@Context UriInfo ui) {
    MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
    MultivaluedMap<String, String> pathParams = ui.getPathParameters();
}
The following method extracts header and cookie parameter names and values into a map:
@GET
public String get(@Context HttpHeaders hh) {
    MultivaluedMap<String, String> headerParams = ui.getRequestHeaders();
    Map<String, Cookie> pathParams = ui.getCookies();
}
In general, @Context can be used to obtain contextual Java types related to the request or response.
For form parameters, it is possible to do the following:

@POST
@Consumes("application/x-www-form-urlencoded")
public void post(MultivaluedMap<String, String> formParams) {
    // Store the message
}

http://docs.oracle.com/cd/E19798-01/821-1841/gipzz/index.html
info about jax-rs applications here
http://docs.oracle.com/cd/E19798-01/821-1841/gipzz/index.html

Wednesday, January 8, 2014

Adding new users to postgres

http://www.cyberciti.biz/faq/howto-add-postgresql-user-account/

Access postgres with database you want to share,
do
CREATE USER new_user WITH PASSWORD 'password'; 
and then

GRANT ALL PRIVILEGES ON DATABASE database to new_user;

Tuesday, January 7, 2014

No 'Access-Control-Allow-Origin' problem...

I never learned how to map my localhost:8000 to localhost and localhost:8080 to localhost to avoid this problem...

Note to Self... Java Web Projects

I've had to relearn this for the second time, so I'll write about it.

I installed netbeans on my mac and am using JEE5 (:P), and Netbeans 7.3.1

Create a Java Web > Web Application,
and choose the Spring configuration (because I felt like it... I'm not sure if I will use it yet, but Spring plugins are attractive)

Then, go to terminal and create a few tables on postgres. Put some fake data in them.

Go back and create entities from database. Connect to the db correctly, localhost:5432 blah blah.
On the 3rd page (or something), don't use information_schema, use public. That's where the tables are.

Then, create RESTful service from entities. They'll make a bunch of RESTFacade files (in JEE6 it made me resource classes...). Then, get rid of the aopalliance error by downloading the jar and adding it to your jars. Also, add your jdbc driver into your jars.

After that, you can run and deploy it on your tomcat server (which you should have hooked up to your netbeans ide)

ALSO, to make it output JSON instead of XML, download the jersey-json jar here.

Nobody's gonna find this helpful, this was a note to self.

Don't say "but"

An interesting Quora article...

"A very smart woman I worked with once told me that if I eliminated the word "but" from my professional vocabulary, I'd find greater acceptance for my ideas, and greater cooperation from my team members. She said people would have a very different perception of me if I could change this one thing.

The reason, she said, is because the word "but" negates everything that precedes it, and you cast a negative spin on anything you say when you use it. 

Consider, for example, "We can do it this way, but it'll be way too expensive given our budget," versus "We can do it this way, and if we do, we'll need to cut back on other important features." The first indicates that we can't even consider the option. The second acknowledges possibility and describes consequences.

"But" is exclusive and isolating, "and" is inclusive and welcoming.

She was absolutely right, and it's advice I have used with great success for the past 30 years of my life."

Saturday, January 4, 2014

Securrrty

http://web.mit.edu/kerberos/www/dialogue.html

A really nice story to help understand Kerberos security (and another by-product of trying to clean out my inbox)

Magnus on USChess

A non-coding related post, but here's an interesting (set of) video(s) on early Carlsen

http://main.uschess.org/content/view/11623/658/


Code for a baby...

I like to email myself stuff back that I've done. (As a result, I have a super cluttered inbox).

Here's an email that I found from 4/4/12 when I just started js.