Tuesday, 16 October 2012

XMPP on Mobile Devices

As with anything, there are no hard and fast rules. If there were, they might look like these. First, for devices:
Transmit no data.
Transmitting costs significant power, and moreover raises the radio state. Not transmitting will allow it to maximize the time spent in the low-cost Idle state.
If you must transmit, then transmit only a small volume.
If there is only a small amount of data transmitted - less than 128 octets typically - the radio will only raise to FACH, which is significantly cheaper than DCH.
If you must transmit, then compress as hard as possible.
Since individual octets have an associate power - and often financial - cost, it's worth maximizing the compression algorithm, even if the volume of traffic will raise to DCH.
If you have transmit a lot, then do a lot
If the radio is raised to DCH anyway, then you may as well go fetch that avatar you were missing, since you're chewing through power anyway.
If you receive, then transmit
If your peer raises the radio state, you may as well use it.
And for servers, similar rules apply:
Send no data.
Sending data will cause the handset to be raised out of Idle. This immediately costs massively higher power.
If you must send, send tiny bits.
Sending small enough data maximizes the likelyhood that the devices radio will only be raised to FACH levels.
If you receive, then send anything you have.
Receiving data indicates that the radio is active - it'll stay active for some time, so sending data doesn't incur the overhead of raising the radio state, and won't increase power drain on the handset.
If you must send when not receiving, send plenty.
Sending data will raise the radio's state - unless you can tell this will only raise it to FACH, it's worth sending as much as possible.

XEP-0286: XMPP on Mobile Devices 
- GSMA: Smart Apps for Smarter Phone

Saturday, 29 September 2012

Move Windows 7 Library folder


  1. create the target Library folder, e.g. D:\music
  2. go to "properties" to make sure the folder is shared (so a network path is showed).
  3. go to "C:/User/xxx/My Music" -> "properties" -> "location", and point it to the target folder created
  4. when asked whether or not the move the folder and everything, confirm with "yes"
  5. now "C:/User/xxx/My Music" will no longer exist, because it's now at the new location; because the target folder is shared already, it can take the network name "My Music" while preserving it's real folder name "D:\music". 

Wednesday, 1 August 2012

REST, SOA

OMG, can't believe people are still debating this in the mid 2011! Move on and get things done, please!

Friday, 27 July 2012

Shiro 1.2 new PasswordService and PasswordMatcher

This becomes super simple and clean.

Here is the summary:

1. Signing-up code:
  // Using the new PasswordService instead
  PasswordService svc = new DefaultPasswordService();

  //e.g. during account signup or password reset:
  String encryptedPassword = svc.encryptPassword(password);
  logger.debug("encryptedPassword: " + encryptedPassword);

  // Salt is not needed to handel separately but encrypted all together within the "password"
  // Example password becomes $shiro1$SHA-256$500000$gTF/EC2mLKxlln2w1CMUAQ==$HvG+0Qe1RONAF41bUy11hjkgqdHrwwf/urEAXeYDt1w=
  User user = new User(username, encryptedPassword, null, email);
  userDao.createUser(user);

 2. INI configuration:
  passwordMatcher = org.apache.shiro.authc.credential.TempFixPasswordMatcher
  # since jdbcRealm is used, the stored password in String needs to be converted to char[]
  # algorithm related configuration comes in default
  passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
  passwordMatcher.passwordService = $passwordService

  realmDS = com.mysql.jdbc.jdbc2.optional.MysqlDataSource
  realmDS.serverName = localhost
  realmDS.user = root
  realmDS.databaseName = test

  jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
  jdbcRealm.credentialsMatcher = $passwordMatcher
  jdbcRealm.authenticationQuery = select password from user where username = ?
  jdbcRealm.dataSource = $realmDS

  securityManager.realm = $jdbcRealm

3. Matcher code
  public class TempFixPasswordMatcher extends PasswordMatcher {

      @Override
      protected Object getStoredPassword(AuthenticationInfo storedAccountInfo) {
          Object stored = super.getStoredPassword(storedAccountInfo);
          if (stored instanceof char[]) {
              return new String((char[])stored);
          }
          return stored;
      }
  }

  source1, source2


Tuesday, 24 July 2012

Shiro @RequiresPermissions not working

@RequiresPermission and other annotations do not work just yet like mentioned in the documentation.

This post gives the solution by explicit configuration of using AOP and cglib.

And don't forget to keep the configuration in the same Spring configuration where MVC annotation scanning is specified. 

Wednesday, 11 July 2012

What's new in Java 7



  • Improved Type Inference for Generic Instance Creation (Diamond)
  • Multi-catch
  • try-with-resources statement
  • Simplified Varargs Method Invocation
  • Strings in switch
  • Polymorphic Methods
  • Miscellaneous

--- source

Tuesday, 10 July 2012

JSON Padding explained

The following is effectively what will happen when using JSON padding in JavaScript.

 <script type="text/javascript">showPrice({symbol: 'IBM', price: 91.42});</script>

  • {...} is the useful JSON data (JavaScript Object formatted) provided by the remote server.
  •  showPrice is the callback function that will need to be defined in the calling script. The padding is also added by the remote server.
  •  In order to achieve all these, the whole lot highlighted will need to be dynamically inserted to the calling script by for example the following:
  <script type="text/javascript">
  // This is our function to be called with JSON data
  function showPrice(data) {
      alert("Symbol: " + data.symbol + ", Price: " + data.price);
  }
  var url = “http://server2.example.com/RetrievePrice?symbol=IBM&jsonp=showPrice”; // URL of the external script
  // this shows dynamic script insertion
  var script = document.createElement('script');
  script.setAttribute('src', url);
 
  // load the script
  document.getElementsByTagName('head')[0].appendChild(script);
  </script>
   
All this is, loosely, due to that JavaScript is not allowed to access foreign domain code, except from within. i.e. "... the domain of the requested URL must be the same as the domain of the current Web page ..." --- source