Basically, I had a ton of issues getting Alfresco 4.2 onto OS X Mavericks and I finally looked up "alfresco 4.2 mavericks install fail" and found that tons of other people had the same problem.
Upon searching "alfresco 5 mavericks install" nobody complained about it not working, so I downloaded it from the link below.
http://sourceforge.net/projects/alfresco/?source=typ_redirect
Now reading the docs http://docs.alfresco.com/5.0/concepts/dev-repo-extension-points.html
Cheers.
a ragtag collection of things I couldn't find in a quick 5-minute search on google, as well as some curiosities and what not.
Saturday, May 30, 2015
Friday, May 29, 2015
Create services in *nix systems using chkconfig
Hello there.
Long time no see because I've been messing around with Ghost blogs on localhost. However, I'm currently on a machine that doesn't have Ghost and I don't want to create another one here due to fragmentation. Eventually I'll be hosting my own Ghost server so I can use that...
I'm installing Tomcat7 on this box. Standard install location is /opt.
I want to make it a service so I can run
service tomcat start|stop|restart.
I remembered there was something called chkconfig to do that, so I looked it up.
http://www.thegeekstuff.com/2011/06/chkconfig-examples/
Whoops, this doesn't exist on Mac OS X. Unsure if it's worth learning how to create services/daemonize things in Mac.
http://batsov.com/articles/2012/12/09/from-linux-to-osx-meet-your-new-apps/
In OS X, you use launchctl...
Long time no see because I've been messing around with Ghost blogs on localhost. However, I'm currently on a machine that doesn't have Ghost and I don't want to create another one here due to fragmentation. Eventually I'll be hosting my own Ghost server so I can use that...
I'm installing Tomcat7 on this box. Standard install location is /opt.
I want to make it a service so I can run
service tomcat start|stop|restart.
I remembered there was something called chkconfig to do that, so I looked it up.
http://www.thegeekstuff.com/2011/06/chkconfig-examples/
Whoops, this doesn't exist on Mac OS X. Unsure if it's worth learning how to create services/daemonize things in Mac.
http://batsov.com/articles/2012/12/09/from-linux-to-osx-meet-your-new-apps/
In OS X, you use launchctl...
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.
When I tried to use Uglify, I got the following error:
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:
And that will do it! Just make sure that
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']);
};
- your package name in package.json is the same as your Sencha project name
- bootstrap.css is under resources/css
- 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:
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.
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
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.
Saturday, May 17, 2014
Securing RESTful APIs with Node and Passport
Stated pretty well
Thursday, May 8, 2014
Really crappy post on Jakarta Connectors
https://tomcat.apache.org/connectors-doc-archive/jk2/jk2/confighowto.html
/etc/httpd/modules/mod_jk2.so
/etc/httpd/conf/httpd.conf
LoadModule jk2_module modules/mod_jk2.so
workers 2 properties
workers 2 properties
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)
Step 2: Test your In App Browser:
========================================================================
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:
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
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
Content-location: https://www.googleapis.com/oauth2/v2/userinfo
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": "",
"picture": "https://lh3.googleusercontent.com/-XdUIqdMkCWA/AAAAAAAAAAI/AAAAAAAAAAA/4252rscbv5M/photo.jpg",
"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
loadstart,loadstop,loaderror, orexit. (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 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:
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!
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
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.
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!
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:
- Make minimal changes to the existing node.js
require()logic. - 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.Sunday, February 23, 2014
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.
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
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
(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.
To set up,
Super simple, very fun!
It just works!
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!
Subscribe to:
Posts (Atom)