@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(); } |
My online tech scrapbook where I keep my notes in case I need to look them up later
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:
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
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.
Note that this is for the query cache, not the second-level cache, the latter which is used for "get" operations.
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.
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
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.
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.
The ListAllMyBuckets permission isn't always needed. But some tools e.g. Cyberduck will have permission problems without it.
{ "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/*" ] } ] } |
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:
Highlights:
- Big data to be as mainstream as ERP and supply chain management
- Social network and clickstream analysis will be the largest portion of big data spending this year
- 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
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".
[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".
Saturday, November 3, 2012
iOS: Singletons
Recommended way as described in following links, if thread safety is a potential issue:
iOS Dev: Files to Ignore For Version Control
This article provides an example .gitignore file:
http://www.makebetterthings.com/iphone/gitignore-for-ios-projects/
http://www.makebetterthings.com/iphone/gitignore-for-ios-projects/
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
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
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>".
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:
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:
Wednesday, October 17, 2012
Linux Understanding "top" output
As explained in these links:
- http://unix.stackexchange.com/questions/18918/in-linux-top-command-what-are-us-sy-ni-id-wa-hi-si-and-st-for-cpu-usage
- http://www.linuxquestions.org/questions/linux-general-1/top-command-details-599224/
Explanations can also be found in:
- man vmstat
- man mpstat
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:
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:
Once they have been created, getting something from the web service is as simple as e.g.
By default, the following methods are implicitly declared for each resource:
Notice that PUT is not supported, which is why it has to be added as a custom method (see example on top).
References:
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
In the controller
Example fiddle: http://jsfiddle.net/2JWb2/5/
<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
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.
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
Route53 Update DNS Entry Gotcha
This summary is not available. Please
click here to view the post.
Tuesday, October 2, 2012
MySQL Change User Password
Done as follows:
SET PASSWORD FOR 'dbuser'@'%' = PASSWORD('xxxxxxxx');
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.
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.
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
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
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:
We can query for the e.g. email field which is a nested field as follows with the Java API:
{ "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:
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.
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:
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.
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:
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.
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.
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.
Reference: http://www.aleaiactaest.ch/angular-js-and-dom-readyness-for-jquery/
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":
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:
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:
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.
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:
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
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
A good reference: http://restpatterns.org/HTTP_Status_Codes
ProGuard: Read Obfuscated Stack Traces
You'll need to run retrace.jar.
You'll also need proguard.jar in the same folder.
Link: http://proguard.sourceforge.net/index.html#manual/retrace/examples.html
java -jar retrace.jar proguard.map stacktrace.txt |
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:
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:
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:
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:
- http://stackoverflow.com/questions/1149092/how-do-i-attenuate-a-wav-file-by-a-given-decibel-value
- http://stackoverflow.com/questions/1281494/how-to-obtain-accurate-decibel-leve-with-cocoa
- http://stackoverflow.com/questions/9403094/ios-audioqueue-kaudioqueueerr-invalidpropertyvalue-for-property-kaudioqueueprop
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:
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:
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:
- 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.
- 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
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:
Link: http://blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx
This is done by including the following information in the GUID:
- Machine ID (network card Mac address)
- Timestamp
- Counter to differentiate entries generated within the same timestamp
- Algorithm version identifier
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
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
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:
In this case, use the following commands:
- Use local copy: git checkout --ours FILENAME
- Use remote copy: git checkout --theirs FILENAME
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):
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.
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:
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
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:
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.
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.
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
Link: http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency
Jackson: From Object to JSON String and Back
This is how it's done:
And the other way round:
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:
Where the "JSON" class is "com.mongodb.util.JSON".
Reference: http://www.mkyong.com/mongodb/java-mongodb-convert-json-data-to-dbobject/
To do this in MongoDB:
DBObject dbObject = (DBObject) JSON.parse(jsonStr); |
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:
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> |
Subscribe to:
Posts (Atom)