Monday, December 24, 2012

Jersey Server Binary File

To serve a binary file such as a ZIP file with a REST service in Jersey, use the following:


@GET
@Produces("application/zip")
@Path("{itemId}")
public Response downloadItem(@PathParam("itemId") int itemId){
   String fileName = "item" + itemId + ".zip";
   StreamingOutput streamingOutput = new StreamingOutput(){
       public void write(OutputStream output) throws IOException, WebApplicationException {
           // write data to output stream here
       }        
   };
   
   return Response.ok(streamingOutput, "application/zip").header("content-disposition","attachment; filename = "+fileName).build();
}

Sunday, December 23, 2012

Uploading Files to S3 With Ant

This is becoming more and more relevant as S3 is increasingly being used for deployment of software in the cloud.

This is the one I'm currently using.
https://github.com/corley/aws-ant-task
Apparently it's still being actively maintained.

Question on StackOverflow about this: http://stackoverflow.com/questions/3782157/ant-tasks-for-amazon-ec2-s3

Wednesday, December 12, 2012

Using Hibernate Query Cache in Spring

The steps for configuring the EHCache query cache is the same as when not using Spring. The main difference is how queries is being indicated as cacheable. In Spring, queries are made via the a subclass DAO of the HibernateDaoSupport class, which provides a method to indicate whether all queries in the DAO should use the query cache.

This should be called in the initDao method.

   @Override
   protected void initDao() throws Exception {
       super.initDao();

       // this enables the usage of query cache for all queries in this DAO
       this.getHibernateTemplate().setCacheQueries(true);

       // the cache region name that should be used for this entity
       this.getHibernateTemplate().setQueryCacheRegion(“XXXXXXX”);

       // optional, for enabling statistics collection for profiling
       this.getHibernateTemplate().getSessionFactory().getStatistics().setStatisticsEnabled(true);
   }


Note that this is for the query cache, not the second-level cache, the latter which is used for "get" operations.

Tuesday, December 4, 2012

Cocos2D: Z Order

The higher the number, the closer the object is to the viewer.

The lower the number, the further the object is to the viewer.

Jackson Pretty Print

Some of the solutions posted online is deprecated.

Here's the way to do it with a recent version of Jackson.


ObjectWriter jsonWriter = (new ObjectMapper()).writerWithDefaultPrettyPrinter();
String result = jsonWriter.writeValueAsString(obj);

Processing JSON Response in JMeter

This is a simple and somewhat limited way to do this. You will be able to extract individual values pretty easily but if you want a comprehensive data model of the JSON data structure, this isn't the way to go. If the same property name is used in multiple objects within a JSON data structure, this won't work as well.

Basically this method uses Regular Expressions (using JMeter's Regular Express Extractor) to extract individual values that you're looking for specifically.

Link: http://alexandru-ersenie.com/2009/09/14/json-and-jmeter-extract-json-response/

For more complex requirements, someone has posted about using the BSF PostProcessor and Javascript.

Link: http://www.havecomputerwillcode.com/blog/?p=500

Tuesday, November 20, 2012

Article on Facebook and Corona

Link: http://gigaom.com/data/facebook-open-sources-corona-a-better-way-to-do-webscale-hadoop/

Corona is for scheduling and managing Hadoop jobs. Interesting part about the article is where it talks about the size and scale of the kind of data Facebook has to analyze and the infrastructure used to host it.

Friday, November 16, 2012

AWS S3: IAM Policy for Accessing S3 Bucket

In AWS S3, if you want to have a user account that is able to read/write to an S3 bucket and nothing else, use the following policy statements.

{
 "Statement": [
   {
     "Sid": "Stmtxxxxxxxxxxxxx",
     "Action": [
       "s3:ListAllMyBuckets"
     ],
     "Effect": "Allow",
     "Resource": [
       "arn:aws:s3:::*"
     ]
   },
   {
      "Sid": "Stmtxxxxxxxxxxxxx",
     "Action": [
       "s3:GetBucketLocation",
       "s3:ListBucket",
       "s3:ListMultipartUploadParts"
     ],
     "Effect": "Allow",
     "Resource": [
       "arn:aws:s3:::bucketname"
     ]
   },
   {
      "Sid": "Stmtxxxxxxxxxxxxx",
     "Action": [
       "s3:AbortMultipartUpload",
       "s3:DeleteObject",
       "s3:DeleteObjectVersion",
       "s3:GetObject",
       "s3:GetObjectAcl",
       "s3:GetObjectVersion",
       "s3:GetObjectVersionAcl",
       "s3:PutObject",
       "s3:PutObjectAcl",
       "s3:PutObjectVersionAcl"
     ],
     "Effect": "Allow",
     "Resource": [
       "arn:aws:s3:::bucketname/*"
     ]
   }
 ]
}
The ListAllMyBuckets permission isn't always needed. But some tools e.g. Cyberduck will have permission problems without it.

Friday, November 9, 2012

Article: Big data to be normal by 2020

Article Link: http://www.theregister.co.uk/2012/10/22/gartner_it_spending_big_data_projections/

Highlights:

  1. Big data to be as mainstream as ERP and supply chain management
  2. Social network and clickstream analysis will be the largest portion of big data spending this year
  3. Shortage of "data scientists" expected

Tuesday, November 6, 2012

iOS: String Format for Numbers With Leading Zeros

To obtain a formatted String with a fixed number or digits, and any shortfall padding by leading zeroes,   use the following function call


[NSString stringWithFormat:@"%04d", i];


This will return a String containing the integer "i" and will always be 4 digit long. If i is 1, then the String will be "0001". If it is 12, then the String will be "0012".

Friday, November 2, 2012

iOS: Differentiate Between iPhone and iPad

Use the function "UI_USER_INTERFACE_IDIOM()".

If what it returns is equals to "UIUserInterfaceIdiomPad", it's an iPad.

If what it returns is equals to "UIUserInterfaceIdiomPhone", it's an iPhone.

Reference: http://stackoverflow.com/questions/3905603/is-it-safe-to-check-for-ui-user-interface-idiom-to-determine-if-its-an-iphone

iOS Cocos2D Old Splash Screen Still Showing

Somehow, iOS simulators caches the loading image (e.g. Default.png), so even after you've deleted it, it still shows. In order to remove it, you'll need to do a clean operation in XCode, and also reset the simulator.

Reference: http://stackoverflow.com/questions/4768960/cant-get-rid-of-splash-screen-in-xcode

Friday, October 19, 2012

Java Obtain Thread Dump

In Java, a thread dump can be useful in giving you some clues when an application is hanging or consuming a lot of CPU resources (e.g. infinite loop).

Obtaining one is actually quite easy, via the "jstack" utility shipped with the JDK.

Just login to the server and issue the command "jstack <pid>".

Thursday, October 18, 2012

Linux Load Average

The "Load Average" metric that you see in Linux using a tool like "top" actually refers to the number of processes that are wanting to use CPU time at each point in time. One advantage of using this definition over just raw CPU utilization is that it takes into consideration situations where the system isn't able to work on processes due to waiting for IO etc. So it then becomes a good proxy for how quickly the system is likely to respond to new processes and tasks.

However, one gotcha with this is that it gives artificially low readouts for thread based programs such as Java. You can have a Java process with hundreds of threads, most of which waiting to use the CPU as the CPU is maxxed out, and still get a low load average.

References:

Monday, October 8, 2012

Javascript Thread Safety

Browser so far run Javascript single-threaded, even if the programming model often uses asynchronous events, unless "WebWorkers" is explicitly used.

So no need to worry about thread-safety.

References:

AngularJS $resource Service

AngularJS provides the $resources service to provide an easy way to access REST resources.

Creating services can be as simple as follows:

angular.module('myResourceService', [ 'ngResource' ])
.factory(
'Cat',
function($resource) {
return $resource('/ws/cat/:catId',
{}, {
// resource with no custom method
});
})
.factory(
'Dog',
function($resource) {
return $resource('/ws/user/:dog/dogId',
{}, {
update: {method: 'PUT'} // custom method
});
});


Once they have been created, getting something from the web service is as simple as e.g.

Cat.get({catId:’xxxxx’},function(data) { // callback function contents });


By default, the following methods are implicitly declared for each resource:

{ 'get':    {method:'GET'},
 'save':   {method:'POST'},
 'query':  {method:'GET', isArray:true},
 'remove': {method:'DELETE'},
 'delete': {method:'DELETE'}
};


Notice that PUT is not supported, which is why it has to be added as a custom method (see example on top).

References:

Sunday, October 7, 2012

AngularJS Select Input

In HTML template

<select ng-model="langId" ng-options="lang.id as lang.name for lang in languages">
</select>

In the controller

$scope.languages = [
   {id:'en', name:'English'},
   {id:'zh', name:'Chinese'}, etc....
   ];

Example fiddle: http://jsfiddle.net/2JWb2/5/

AngularJS API Reference for $watch

And also some other methods. They're hidden under the "scope" API and rather difficult to find.
http://docs.angularjs.org/api/ng.$rootScope.Scope#$watch

AngularJS "ng-include" Gotcha with Controllers

I had a page with many forms in an accordion style grouping, so I decided to have the individual forms in separate HTML documents which are pulled together using "ng-include". All these forms, however, were using the same Controller declared in the parent document.

This turned out to be problematic, as I was finding that the controller's scope variables were not being updated. After much troubleshooting, it seems that every HTML fragment needs its own controller. I'm still not exactly sure why but this seems to be the only way to make things work.

Wednesday, October 3, 2012

Tuesday, October 2, 2012

MySQL Change User Password

Done as follows:

SET PASSWORD FOR 'dbuser'@'%' = PASSWORD('xxxxxxxx');

Thursday, September 27, 2012

AngularJS: "element" in Directives

When developing Directives, it's quite common to encounter the "element" object that's passed into function callbacks for events. This is actually AngularJS's wrapper object for the DOM element object. List of supported methods can be found here: http://docs.angularjs.org/api/angular.element

AngularJS: Notification Callback on Blur Event

This is one of those things in AngularJS that is perhaps a bit more complicated than it really should be, as the only way I know to do this at the moment is via a Directive. AngularJS updates the model instantly when it changes. In the case of the text input field, it's after every character is typed or deleted. However, there are times where you want to be notified only on the "blur" event, such as when calling the server to validate the value.

   directive('input', function() {
       return {
           restrict: 'E',
           link: function(scope, element, attr) {

               if (attr.type === 'radio' || attr.type === 'checkbox') return;

               element.bind('blur', function() {
                   scope.$apply(function() {
                    scope.onBlur(element.attr("name"));
                   });
               });
           }
       }
   });

In this example, the Controller's "onBlur" callback is called with the element's name. This example returns immediately if the input is of type "radio" or "checkbox", because the "change" event is  more applicable for them.

Tuesday, September 25, 2012

Bootstrap Form Input Size

Changing the size attribute in Bootstrap does not seem to affect the width of the form field. Instead, the suggested way to do this is via pre-defined CSS classes such as "input-small", "input-large" etc.

Reference: http://stackoverflow.com/questions/9784990/bootstrap-wider-input-field

Tuesday, September 18, 2012

Git Use Different Name and Email for Repository

If you use Git for multiple projects and wish to use different identities for each project, you can specify a repository specific identity in the repository's config file.

Instructions here: http://stackoverflow.com/questions/4220416/can-i-specify-multiple-users-for-myself-in-gitconfig

Monday, September 10, 2012

Wicket Multiple Choice Select Box

The component to use for this is the ListMultipleChoice class.

Thursday, September 6, 2012

Jersey Client: Using Cookies

Example code for how it's done:
// contains the cookies for the session
private Map<String,Cookie> cookies;

public String get(WebResource.Builder webResource) {
   // setting cookie before sending request
   Set<String> cookieNames = cookies.keySet();
   for(String cookieName : cookieNames){
       webResource = webResource.cookie(cookies.get(cookieName));
   }

   // send the request
   ClientResponse response = webResource.get(ClientResponse.class);

   // retrieving cookie from server response
   List<NewCookie> newCookies = response.getCookies();
   for (NewCookie newCookie : newCookies) {
       // new cookie replaces existing cookies with the same name
       cookies.put(newCookie.getName(),newCookie);
   }

   // do something with response
}

MongoDB: Search Nested Value With Java API

Let's say we have an object with structure like this:
{
  "name" : John,
  "contactInformation" : {
        email : “john@gmail.com”,
        phone: "12341621"
   }
}

We can query for the e.g. email field which is a nested field as follows with the Java API:
BasicDBObject searchCriteria = new BasicDBObject();
searchCriteria.put("contactInformation.email", emailToSearchFor);
DBObject result = collection.findOne(searchCriteria);

MongoDB: Get ID of Inserted Document

After inserting, use the following:

DBObject dbObj = new BasicDBObject(valuesMap);
collection.insert(dbObj);
ObjectId id = (ObjectId)dbObj.get("_id");

Sunday, September 2, 2012

AngularJS: Using Services for Global State

In Javascript, global variables are sometimes needed to store state information that needs to be shared by multiple elements on a page. However, with global variables, you'll always run the chance of conflicting with another variable declared with the same name by another component, and obviously violates the principle of encapsulation.

With AngularJS, it's possible to use the services feature to achieve the same thing, but with encapsulation. This is because services are a singleton, meaning the same instance of an object can be shared across all AngularJS code in the same app.

Example:

angular.module('someModule', [ ]).factory(
'AppState',
function() {
function SomeClass(){
// what you want as global variables and functions to access them here
}
var instance = new SomeClass();
return instance;
});

AngularJS ng-include Gotcha

In AngularJS, ng-include processes the contents of "src" attribute as a Javascript expression, not as a file path.

What this means is that you can dynamically determine what to include by doing something like this:
<div ng-include src=”getAppropriateContent()”></div>
where the "getAppropriateContent()" Javascript function that you'll implement returns the path of the appropriate content to show for the situation.

However, when you want to hardcode the path to a HTML file, you'll have to remember it's a Javascript expression. You'll have to enclose it in quotes (single quotes in this case) or it won't work.
<div ng-include src=”’content.html’”></div>

Twitter Bootstrap Grid System

Makes layout out web pages easy: http://twitter.github.com/bootstrap/scaffolding.html#gridSystem

Saturday, September 1, 2012

CSS z-index Gotcha with Parent/Child Elements

In CSS, z-index is used to control which elements appear in front of or behind each other when they're overlapping on the screen.

However, there is one "gotcha" to note, that is if both a child and parent element has z-index defined, and you want the child to appear in front of something and the parent to appear behind, it won't work. Instead, both parent and child elements will appear behind, with the parent's z-index taking effect. This can happen for example if you have an overlay, and you want a modal window (the child) to appear on top of the overlay, while the parent element on the main page should be behind the overlay. If the parent has a z-index, then both parent and child will be behind the overlay, regardless of the z-index of the child.

Tuesday, August 28, 2012

POST vs PUT in REST

In designing REST APIs, it's often said to map POST to Create operations and PUT to update operations, but most people don't really explain why. Here's a good explanation I found:
http://jcalcote.wordpress.com/2008/10/16/put-or-post-the-rest-of-the-story/

In a nutshell:
  • Browsers treat PUTs as idempotent operations, and will not hesitate to call the server again with the same URL if the user hit the "back" button on the browser.
  • Browsers does not treat POSTs as idempotent operations, so when the user hits the "back" button on the browser, it asks the user if he wants to submit the data again.
Since it is not possible for the server to ensure idempotency when asked to create something new (i.e. it wouldn't know if the 2nd, 3rd call etc. are genuine calls to create more entries with the same data), POST is use for creating new entries.

Monday, August 27, 2012

Naming Convention for REST URLs

Separate words with camel case or dashes?

Not a very important issue but dashes wins it for me because URLs are mostly expected to be case insensitive.

Sunday, August 26, 2012

MongoDB Database Design: Large vs Small Documents

For relational databases, the approach is to have as many tables as you need to create the perfectly normalized database design. For MongoDB (and true to same or less extent for other NoSQL databases due to differing indexing capabilities), it seems the recommended approach is when in doubt, use less large documents (i.e. the embedding rather than linking approach).

Unlike other NoSQL databases, you don't have to create many small collections just because you have to query by with different fields as keys, as you can use indexing to solve this problem with MongoDB.  Furthermore, MongoDB allows indexes to be created on objects nested within the document hierarchy.

I can think of the following key benefits of using large documents:
  • Less joins, less follow up queries, write much less code
  • Operations within a single document are atomic, don't have to worry about writing to 3 separate documents and then what happens if one of the writes fail
The main downside to large documents is when you have to run queries that result in table-scans. You'll just have to make sure that you have indexes covering all possible queries you need to make.

References:

Sunday, August 19, 2012

Java Reflection: Access a Private Field

It is possible to access private fields in Java classes using the Reflection API (as long as the Security Manager isn't configured to prevent this).

This is done by adding "field.setAccessible(true);" before trying to obtain the value of the field.

Example code:


Field field = SomeClass.class.getDeclaredField(fieldName);
feld.setAccessible(true);
return field.get(obj);

JUnit Reference Equality Comparison

This can be done using the "assertSame" function.

Wednesday, August 15, 2012

Pentaho: MySQL Bulk Load

In MySQL, bulk load operations i.e. "LOAD DATA" has much faster performance than INSERT. In Pentaho's Data Integration module, it is possible to directly perform a bulk load operation into MySQL, using the "MySQL Bulk Loader" Step (in the "Bulk loading" folder).

However, one "gotcha" with it (version 4.3) is that it will crash on an empty stream. You'll either have to find a way to handle it, or use it only in situation where that either doesn't matter or never happens, or hope they fix this in future versions.

Thursday, August 9, 2012

Pentaho Data Integration 4.3 With MySQL

With version 4.3 of Pentaho Data Integration, the MySQL driver is not bundled because of "license compatibility issues". So if you need to connect to the MySQL database, you'll need to download the JDBC driver separately and copy it into the "libext/JDBC" folder.

Saturday, July 21, 2012

Dynamic Classes with AngularJS

Here's a solution someone posted: http://jsfiddle.net/rur_d/tNZAm/

Some say it's bad idea to have your controllers being aware of classes. Well it's a solution that works.

Document Ready Event When Using AngularJS With JQuery

When you are making a page out of multiple partials/fragments in AngularJS, the document ready event for JQuery seems to fire before the page is fully assembled.

The correct way to do something when the page is fully loaded in AngularJS is by using the '$viewContentLoaded' event listener, by putting the following code into your controller.
$scope.$on('$viewContentLoaded', function(){
// do something
});

Reference: http://www.aleaiactaest.ch/angular-js-and-dom-readyness-for-jquery/

AngularJS: Calling a Javascript Function in the Controller

This is done by using "ng-click".

Example assuming you already created a function in the controller called "doSomething":
<a href ng-click="doSomething()">Do It</a>

Friday, July 20, 2012

Jersey Exception Handling

Jersey offers centralized Exception handling with "ExceptionMappers". This means you can allow Exceptions to be thrown up to the framework and then you can define how to handle them. It also means you are able to "catch" and handle exceptions that occur before and after the code that you write is being run.

 Let's say you want to handle "MyWebServiceException", you can create an ExceptionMapper "MyWebServiceExceptionMapper" like this:
@Provider
public class MyWebServiceExceptionMapper implements ExceptionMapper<MyWebServiceException> {

@Override
public Response toResponse(Exception e) {
GenericEntity<String> entity = new GenericEntity<String>(
   “{\"statusCode\":\"ERR-100\",\"responseData\":\"Error Processing Web Service\"}” ){};
return Response.status(Status.OK).entity(entity).type(MediaType.APPLICATION_JSON).build();
}
}

In order for this to be registered with Jersey, you'll need to put it in a package that's being scanned by Jersey to be resources or providers, so in the web.xml, have something like this:
<init-param>
   <param-name>com.sun.jersey.config.property.packages</param-name>
   <param-value>com.myws.resource;com.myws.provider</param-value>
</init-param>

In this example, I separated the packages for resources and providers, providing 2 packages to be scanned.

To handle each exception differently, just create as many ExceptionMapper classes as you wish, and put them in the same package to be picked up and registered.

You can also use this to return a different HTTP status code for different errors, but as mentioned in the comments of an earlier POST, that's not going to work well with cross-domain Javascript REST requests.

Thursday, July 19, 2012

Jackson Polymorphism

You can handle polymorphism with Jackson using the following annotations at the class level:
j@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "accountType")
@JsonSubTypes({
   @Type(value = AdminAccount.class, name =”ADM”),
   @Type(value = NormalAccount.class, name =”NML”)
})

This will tell Jackson to map the object to the "AdminAccount" class when the "accountType" property is "ADM", and to the "NormalAccount" class when the "accountType" property is "NML".

Other options are available, such as directly using the class name.

One "gotcha" I discovered is that the "accountType" property must not be implemented in the POJO class. If there is an "accountType" property in the class, it will be null when it's time to work with it in Java. In Java-land, you'll have to use "instanceof" to know what object it is.

A article with more detailed examples: http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html

Wednesday, July 18, 2012

HTTP Status Codes for REST

For REST services, one common pattern is to use HTTP status codes as the status code for the request itself.

A good reference: http://restpatterns.org/HTTP_Status_Codes

ProGuard: Read Obfuscated Stack Traces

You'll need to run retrace.jar.
java -jar retrace.jar proguard.map stacktrace.txt
You'll also need proguard.jar in the same folder.
Link: http://proguard.sourceforge.net/index.html#manual/retrace/examples.html

Sunday, July 15, 2012

iOS: AudioQueue Get Audio Level

A very good example of this is found in the "SpeakHere" reference project provided by Apple:
Link: http://developer.apple.com/library/ios/#samplecode/SpeakHere/Introduction/Intro.html

Just some gotcha's and points to note:

You need to call AudioQueueSetProperty to enable the level metering feature in the first place:
UInt32 enableMetering = 1;
AudioQueueSetProperty(audioQueue, kAudioQueueProperty_EnableLevelMetering, &enableMetering, sizeof(UInt32));

The number returned by the AudioQueue will be a negative number with a maximum value of 0. To convert it to a number on a linear scale (i.e. gain level), use the following formula:
float level = pow(10., 0.05 * averagePower);

Where averagePower is the value returned by the AudioQueue for the audio level average power.

The rest should be pretty straight-forward from studying the example.

Links and References:

Mongo DB: Java API Get Object by ID

You'll get an error if you try to do something along the lines of "{_id: xxxxx}".

This is how it's done:
BasicDBObject searchCriteria = new BasicDBObject("_id", new ObjectId(id));
DBObject dbObj = collection.findOne(searchCriteria);

Jackson: Ignore Unrecognized Fields

By default, Jackson will throw an exception when a field in the JSON is not declared as a member variable in the class it is mapped to. To ignore these fields, add the following annotation to the POJO class:
@JsonIgnoreProperties(ignoreUnknown=true)

AngularJS: Batarang Debugging Tool

Recently, a debugging tool call Batarang was released for AngularJS. It runs as a Google Chrome extension.

Here's a blog about it:
http://blog.angularjs.org/2012/07/introducing-angularjs-batarang.html

Installation instructions:
https://github.com/angular/angularjs-batarang/blob/master/README.md

Things to note:
  1. It doesn't run on the stock Google Chrome. It runs on the "Canary" version which has experimental features for early adopters. You'll have to download, install, and run it as a separate program.
  2. Installing the extension the usual way won't work due to security restrictions. You'll have to drag the "crx" file into the extensions page (i.e. chrome://chrome/extensions/).

iOS: Making the Table Cell Background a Gradient

This is a good guide for doing it:

http://www.raywenderlich.com/2033/core-graphics-101-lines-rectangles-and-gradients

GUID Uniqueness

This is an article explaining how GUID can be almost certainly (if not totally certainly unique).

Link: http://blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx

This is done by including the following information in the GUID:
  1. Machine ID (network card Mac address)
  2. Timestamp
  3. Counter to differentiate entries generated within the same timestamp
  4. Algorithm version identifier
This is the "Version 1" algorithm for GUID generation. There are other versions which rely more on random number generators. I'm not sure if those are as reliable as version 1 in terms of guaranteeing uniqueness, and will be the topic of future research.

MongoDB: Scaling Approach

The first step in scaling is creating Replica sets (master/slave) where the slaves are allowed to service queries. This will be helpful for read-mostly workloads.

After that, the next step is sharding, where you'll need to define a partitioning mechanism. At a very large scale, the topology would be that of multiple shards, within which contain individual replica sets.

Link: http://www.mongodb.org/display/DOCS/Sharding+Introduction

Mongo DB Object ID

It is the unique identifier for each document in a collection. Compared to UUID, it is smaller (12 vs 16 bytes) but should still be workable because the requirement is just to have uniqueness within the DB cluster.

Uniqueness is guaranteed by including the machine ID, process ID, a timestamp and a counter for entries generated within the same second.

Link: http://www.mongodb.org/display/DOCS/Object+IDs

Saturday, July 14, 2012

Git: Conflict Resolution By Choosing A Copy

Often, it is as simple as choosing either the local copy in its entirety or the remote copy in its entirety.

In this case, use the following commands:
  1. Use local copy: git checkout --ours FILENAME
  2. Use remote copy: git checkout --theirs FILENAME
Reference: http://gitready.com/advanced/2009/02/25/keep-either-file-in-merge-conflicts.html

Thursday, July 12, 2012

iOS Activity Indicator

This is how it is done (example is using WebView)
Link: http://stackoverflow.com/questions/11334247/add-activity-indicator-to-web-view

I made some further changes so the indicator is more visible (by putting it inside an alert popup):

- (void)viewDidLoad
{
    [super viewDidLoad];    
    loadingAlert = [[UIAlertView alloc] initWithTitle:@"Loading..."
                                                      message:@"\n"
                                                     delegate:self
                                            cancelButtonTitle:nil
                                            otherButtonTitles:nil, nil];

    activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    [loadingAlert addSubview:activityIndicator];
}

- (void) showLoadingAlert
{
    [loadingAlert show];    
    activityIndicator.frame = CGRectMake((x,y,w,h);
    [activityIndicator startAnimating];
}
- (void) dismissLoadingAlert
{
    [activityIndicator stopAnimating];
    [loadingAlert dismissWithClickedButtonIndex:0 animated:NO];
}

Note that I set the frame after "show". This is because if I wanted to calculate x,y,w,h relative to the size of the loading alert frame, these values will only be non-zero after show.

NSTimer Gotchas With Threads/RunLoops

Sometimes when you notice that the NSTimer isn't working (i.e. the scheduled task doesn't fire), it can be caused by runloop issues.

By default, it runs in the current run loop from where it is scheduled. If you schedule it from the wrong loop, it might not fire as the loop could be blocked somewhere else.

Which method you use to initialize the timer also makes a difference. The "scheduledTimerWithTimeInterval" creates a timer that runs in the current loop. If the current loop is not suitable for the timer to run, the timer may not fire and you have no idea why.

If you have a problem with the above, you will have to use the "timerWithTimeInterval" methods. However, you have to remember to add the timer to the run loop that you want to add on.

For example, to schedule a timer on the main loop from another loop:

NSTimer *timer = [NSTimer timerWithTimeInterval:waiTime target:self selector:@selector(fireMethod:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]

The various behaviors are documented in the class reference.

Reference: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nstimer_Class/Reference/NSTimer.html

Wednesday, July 11, 2012

iOS: Positioning a View Relative to Parent

This is done via the "frame" property of the View, e.g.

viewObj.frame = CGRectMake(20,20,50,40);

Tuesday, July 10, 2012

MySQL: Dumping With Users and Privileges

A gotcha when trying to clone an entire MySQL DB is that the user privileges are not completely cloned.

The following command would have resulted in users and privileges being cloned (since the "mysql" database would have been dumped), but they do not take effect until a "FLUSH PRIVILEGES" command has been issued:

mysqldump --all-databases > db.sql

This means additional manual step of issuing the "FLUSH PRIVILEGES" command is needed before the DB is usable.

In order to ensure that the "FLUSH PRIVILEGES" command is run during DB restore (so no additional steps needed to get DB up and running), include the "--flush-privileges" option during the dump.

mysqldump --all-databases --flush-privileges > db.sql

Apache Wicket: AjaxSubmitLink No Response

What happens is when you click the AjaxSubmitLink, there is no response, no error messages, and you don't know why there is a problem.

This is potentially a gotcha caused by "setRequired(true)" in your form elements. The form will refuse to act (and won't tell you why) when you leave a required field blank.

Monday, July 9, 2012

MongoDB Connection Pooling

It seems the Java Driver handles this already and there is no need for any additional engineering for this:

Link: http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency

Jackson: From Object to JSON String and Back

This is how it's done:
ObjectMapper jsonMapper = new ObjectMapper();
String jsonStr = jsonMapper.writeValueAsString(jsonObj);

And the other way round:
ObjectMapper jsonMapper = new ObjectMapper();
UserAccount result = jsonMapper.readValue(userAccountJson,  UserAccount.class);

MongoDB: Save Raw JSON With Java API

In MongoDB's Java API, most of the functions relating to saving objects into the DB requires you to either provide a map or add each property one by one. In situations where you already have the JSON document (e.g. submitted via Javascript), you'd want to just directly save the JSON document.

To do this in MongoDB:
DBObject dbObject = (DBObject) JSON.parse(jsonStr);
Where the "JSON" class is "com.mongodb.util.JSON".

Reference: http://www.mkyong.com/mongodb/java-mongodb-convert-json-data-to-dbobject/

Sunday, July 8, 2012

Bootstrapping Jersey With POJO / JSON Mapping

Jersey is the JAX-RS reference implementation by Sun / Oracle. The bootstrapping process is relatively straightforward. It is done by declaring Servlet(s) to handle the Jersey requests.

The basic configuration (without POJO / JSON mapping) can be found here: http://www.mkyong.com/webservices/jax-rs/jersey-hello-world-example/

To add POJO / JSON mapping:
  • Ensure the following jar files are on classpath:
    • asm
    • jackson-core-asl
    • jackson-jaxrs
    • jackson-mapper-asl
    • jackson-xc
    • jersey-core
    • jersey-json
    • jersey-servlet
    • jersey-server
  • web.xml should look something like this:

<servlet>
<servlet-name>WsServlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>com.xxxxx.ws</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>WsServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>