Friday, September 28, 2012

Turbo-charge your Android emulator for faster development


I came across an article, which claims to boost the Android emulator's performance using Intel's Hardware Accelerated Execution Manager (HAXM) driver. It got me excited and I decided to verify this claim. This blog entry is my story.

My tools:

  • Android SDK r20.0.3
  • Intellij Community Edition 11.1.3


Basically, the special 'enhancement' provided by Intel is a special x86 Atom system image which utilizes the HAXM driver that enables better emulator performance. I'll not repeat the technical details here, you can access the links below for more info.

Caveat: This trick only works on Intel hardware and with the Virtualization Technology for Directed I/O (VT-d) enabled (usually via BIOS).

Also, Intel x86 system images are currently (as of this blog posting) available for Android versions 2.3.3 (Gingerbread), 4.0.3 (ICD), and 4.1 (Jelly Bean) only.

To avoid headaches, set the environment variable ANDROID_SDK_HOME to point to your Android SDK root folder before proceeding.

High-level steps:
1. Download & install relevant packages via Android SDK Manager
2. Create Android Virtual Devices (AVD)
3. Create an Android Module project in IntelliJ CE
4. Test launching the Android application using the AVDs

1. Download relevant packages via Android SDK Manager

Launch the SDK Manager and ensure the following is installed:

  • Intel x86 Atom System Images (shown below is for Android 2.3.3)
  • Intel x86 Emulator Accelerator (HAXM)



Next, you'll need to install the HAXM driver manually. Go to the Android SDK root folder and navigate to extras\intel\Hardware_Accelerated_Execution_Manager. Execute file IntelHaxm.exe to install.

2. Create Android Virtual Devices (AVD)

Launch the AVD Manager and create 2 AVDs with the same options but different Target:

  • DefaultAVD233 - Android 2.3.3 - API Level 10
  • IntelAVD233 - Intel Atom x86 System Image (Intel Corporation) - API Level 10




3. Create an Android Module project in IntelliJ CE

In IntelliJ, create a new project of type "Android Module", as shown:



Under "Android SDK", select the appropriate Android platform. You'll need to point to your Android SDK root folder in order to choose the appropriate build target. As shown below, "Android 2.3.3" is chosen:



Ensure that the "Target Device" option is set to Emulator, then click "Finish" to complete the project creation.

4. Test launching the Android application using the AVDs

Ok, we'll test using the default Android 2.3.3 AVD first.

At the IntelliJ menubar, select "Run" > "Edit Configurations...". Go to the "Target Device" section. At the "Prefer Android Virtual Device" option, select "DefaultAVD233". Then Run the Android application. After a while, you should see the emulator window with the "Hello World" message.

To run with the Intel AVD, choose the "IntelAVD233" instead.

What's most exciting is the speed of the emulator launch (timed from clicking 'Run' in IntelliJ up to the 'Hello World' message is shown in the emulator). The rough timings recorded using my notebook (Intel i3 380M, 3GB RAM):

  • DefaultAVD233 - 1m 7s
  • IntelAVD233 - 35s


Wow, that's fast (~50% faster), without tuning other parameters to speed things up even further.

References:
http://www.developer.com/ws/android/development-tools/supercharge-your-android-emulator-speed-with-intel-emulation-technologies.html
http://software.intel.com/en-us/articles/installing-the-intel-atom-x86-system-image-for-android-emulator-add-on-from-the-android-sdk
http://stackoverflow.com/questions/1554099/slow-android-emulator
http://developer.android.com/sdk/index.html
http://www.jetbrains.com/idea/download/

Thursday, September 27, 2012

Embedding HSQLDB server instance in Spring

I was using XAMPP happily for development until I had to host it somewhere accessible via the Internet for the client to test and use. I have a VPS that only has 384 RAM, and needing to find a way fast, I decided to install XAMPP into the VPS. Because of the low RAM, when MySQL was running, Tomcat failed to start, even though the initial Java heap size was set to 64m. I managed to host the site temporarily in Jelastic, before moving to OpenShift.

I toyed with the idea of combining the database and application server instances in 1 JVM, to reduce RAM usage (compared to running MySQL + Tomcat). After searching the Internet, I came across several articles on running HSQL server instances together with Tomcat. No doubt I have to update my site to be compatible with HSQL first, but as a POC (proof-of-concept) attempt, I decided to explore the feasibility of running the HSQL server instance in a Spring container.

There are several reasons to run the HSQL server just like a bean in Spring:
1. All-in-one configuration. Everything that is needed to be configured is done in Spring. There are examples in the Net to run the HSQL instance alongside Tomcat, but this requires adding stuff to Tomcat (see links below).
2. Application server independence. 'Theoretically' (in quotes as I successfully tested this in Tomcat only), since everything is done in Spring, there's no or little that needs to be configured in the appserver.

The HSQL server 'bean' is also meant to launch an instance in network mode (not in-process e.g. mem or file). Some reasons for this:
1. 'mem' in-process access is the fastest, but is not persistent. There are other means to initiate a 'mem' data source using Spring's spring-jdbc tags, which is a better approach.
2. 'file' in-process access is persistent, but like 'mem', it can only be accessed within the Java process.
3. Network mode (hsql) is both persistent and accessible using external JDBC client tools. This is useful for troubleshooting and verification.

After reading HSQLDB's documentation, here's the code that does the HSQL server instance bean lifecycle management:

package org.gizmo.hsql.spring;

import java.io.IOException;
import java.util.Properties;

import org.hsqldb.Server;
import org.hsqldb.persist.HsqlProperties;
import org.hsqldb.server.ServerAcl.AclFormatException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.SmartLifecycle;

public class HyperSqlDbServer implements SmartLifecycle
{
 private final Logger logger = LoggerFactory.getLogger(HyperSqlDbServer.class);
 private HsqlProperties properties;
 private Server server;
 private boolean running = false;
 
 public HyperSqlDbServer(Properties props)
 {
  properties = new HsqlProperties(props);
 }
 
 @Override
 public boolean isRunning()
 {
  if(server != null)
   server.checkRunning(running);
  return running;
 }

 @Override
 public void start()
 {
  if(server == null)
  {
   logger.info("Starting HSQL server...");
   server = new Server();
   try
   {
    server.setProperties(properties);
    server.start();
    running = true;
   }
   catch(AclFormatException afe)
   {
    logger.error("Error starting HSQL server.", afe);
   }
   catch (IOException e)
   {
    logger.error("Error starting HSQL server.", e);
   }
  }
 }

 @Override
 public void stop()
 {
  logger.info("Stopping HSQL server...");
  if(server != null)
  {
   server.stop();
   running = false;
  }
 }

 @Override
 public int getPhase()
 {
  return 0;
 }

 @Override
 public boolean isAutoStartup()
 {
  return true;
 }

 @Override
 public void stop(Runnable runnable)
 {
  stop();
  runnable.run();
 }
}

The abridged Spring configuration:


<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

 <bean class="org.gizmo.hsql.spring.HyperSqlDbServer" id="hsqldb" init-method="start">
  <constructor-arg>
   <value>
    server.database.0=file:d:/hsqldb/demobase
    server.dbname.0=demobase
    server.remote_open=true
    hsqldb.reconfig_logging=false
   </value>
  </constructor-arg>
 </bean>
</beans>



Sample output when starting Spring in Tomcat:
[Server@1e893ae]: [Thread[pool-2-thread-1,5,main]]: checkRunning(false) entered
[Server@1e893ae]: [Thread[pool-2-thread-1,5,main]]: checkRunning(false) exited
[Server@1e893ae]: Initiating startup sequence...
[Server@1e893ae]: Server socket opened successfully in 7 ms.
Sep 27, 2012 9:26:23 AM org.hsqldb.persist.Logger logInfoEvent
INFO: checkpointClose start
Sep 27, 2012 9:26:23 AM org.hsqldb.persist.Logger logInfoEvent
INFO: checkpointClose end
[Server@1e893ae]: Database [index=0, id=0, db=file:d:/hsqldb/demo
base, alias=demobase] opened sucessfully in 442 ms.
[Server@1e893ae]: Startup sequence completed in 451 ms.
[Server@1e893ae]: 2012-09-27 09:26:23.395 HSQLDB server 2.2.8 is online on port 9001
[Server@1e893ae]: To close normally, connect and execute SHUTDOWN SQL
[Server@1e893ae]: From command line, use [Ctrl]+[C] to abort abruptly


References:

  • http://hsqldb.org/doc/2.0/guide/index.html
  • http://dkuntze.wordpress.com/2009/01/28/hsql-on-tomcat/
  • http://www.ibm.com/developerworks/data/library/techarticle/dm-0508bader/


Tuesday, September 18, 2012

Accessing Git Repositories using SSH behind HTTP proxy (Corkscrew, OpenSSH)


OpenShift uses SSH for its Git repositories. But at my workplace, where I need to use a HTTP proxy to access the Internet, getting TortoiseGit to connect to the Git repository seemed impossible. Out of the box, SSH can't be accessed via HTTP proxies. After vigorous searching using Google, I came across Corkscrew (http://www.agroman.net/corkscrew/README). Corkscrew enables tunnelling of TCP connections through HTTP/S proxy servers.

Since I am using Windows, and happen to use Cygwin (was required by OpenShift) and TortoiseGit, here's what I did to make it work:
1. Fire up Cygwin setup, searched for 'corkscrew', download packages
2. In my Cygwin home folder (default folder for SSH settings), open file ~\.ssh\config
3. Add/modify the ProxyCommand line (replace with your proxy IP and port) as shown in the example below:

Host *.rhcloud.com
  IdentityFile ~/.ssh/libra_id_rsa
  VerifyHostKeyDNS yes
  StrictHostKeyChecking no
  UserKnownHostsFile ~/.ssh/libra_known_hosts
  ProxyCommand /bin/corkscrew localhost 8118 %h %p

4. Open TortoiseGit's Settings window, go to Network. Check the 'Enable Proxy Server' option, and add the proxy IP and port values.
5. In the SSH client textbox, enter the path to the ssh.exe file e.g. C:\cygwin\bin\ssh.exe. This assumes that you are using OpenSSH in Cygwin. Click OK.

That's it, now you can access your Git repository via SSH behind a HTTP proxy!

Spring 3.1 - Loading Properties For XML Configuration From Database

Spring makes it easy to inject values obtained from properties files via its PropertyPlaceholderConfigurer and (pre-Spring 3.1) PropertySourcesPlaceholderConfigurer (Spring 3.1). These classes implement the BeanFactoryPostProcessor interface, which enables them to manipulate the values within the Spring XML configuration file before the beans are initialized. So if you specify ${jdbc.driverClassName} to be set to the property 'driverClassName', this variable will be replaced/swapped with the value with the key 'jdbc.driverClassName' in a properties file.

Apart from properties files, the database table can also be a place to get key-value pairs. Great, so just extend the PropertySourcesPlaceholderConfigurer, and have it read a table containing the key-value pairs, populate them and we're done!

However, there's a slight problem. If the DataSource bean also relies on values obtained from a properties file (e.g. JDBC URL, username, password), and being good Springers, inject this bean to the bean class extending PropertySourcesPlaceholderConfigurer, the bean container will fail to startup properly, because the 'jdbc.driverClassName' variable cannot be resolved. Strange, but true.

The reason for this is that any bean injected into a BeanFactoryPostProcessor class will trigger bean initialization BEFORE the BeanFactoryPostProcessor classes are run. You know, dependency injection...all depending beans have to be ready before being injected into the consumer. So this creates a cyclic-dependency kind of thing. All dependencies in the XML configuration are resolved first before the BeanFactoryPostProcessor classes are run.

So, how to go about this? Well, there's a trick you can employ. A BeanFactoryPostProcessor class has access to the ConfigurableListableBeanFactory object via the 'postProcessBeanFactory' method. From this object, you can do a 'getBean' and get a reference of any bean with an id. And guess what, you can get the vaunted DataSource bean without triggering premature bean initialization.

Let's say there's a table 'sys_param' with the following data:

 PARAM_CD        PARAM_VALUE  
 --------------  --------------
 service.charge  1.5          
 rebate.amount   15.99        
 smtp.ip         173.194.79.16

The DbPropertySourcesPlaceholderConfigurer is shown here:


package org.gizmo.labs.utils.spring;

import javax.sql.DataSource;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

public class DbPropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer
{
 @Override
 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
 {
  DataSource dataSource = beanFactory.getBean(DataSource.class);
  DbProperties dbProps = new DbProperties(dataSource);
  
  setProperties(dbProps);
  super.postProcessBeanFactory(beanFactory);
 }
}



The DbProperties class will make use of the DataSource reference and queries the database to get the key-value pairs:


package org.gizmo.labs.utils.spring;

import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

public class DbProperties extends Properties
{
 private final Logger logger = LoggerFactory.getLogger(DbProperties.class);
 private static final long serialVersionUID = 1L;

 public DbProperties(DataSource dataSource)
 {
  super();
  JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); 
  List> l = jdbcTemplate.queryForList("select param_cd, param_value from sys_param");
  
  for(Map m: l)
  {
   logger.debug("Loading from DB: [{}:{}]", m.get("PARAM_CD"), m.get("PARAM_VALUE"));
   setProperty((m.get("PARAM_CD")).toString(), (m.get("PARAM_VALUE")).toString());
  }
 }
}



To demonstrate that the values from the table are properly injected, here's the class which acts as the consumer:


package org.gizmo.labs.utils.spring;

import java.math.BigDecimal;

import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;

public class DbPropConsumer implements InitializingBean
{
 private final Logger logger = LoggerFactory.getLogger(DbPropConsumer.class);

 private BigDecimal serviceCharge;
 private double rebateAmount;
 private String smtpIp;
 
 @Override
 public void afterPropertiesSet() throws Exception
 {
  logger.debug("I have consumed: {}", this);
 }

 public String toString()
 {
  return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
 } 
 
 public BigDecimal getServiceCharge() {
  return serviceCharge;
 }

 public void setServiceCharge(BigDecimal serviceCharge) {
  this.serviceCharge = serviceCharge;
 }

 public double getRebateAmount() {
  return rebateAmount;
 }

 public void setRebateAmount(double rebateAmount) {
  this.rebateAmount = rebateAmount;
 }

 public String getSmtpIp() {
  return smtpIp;
 }

 public void setSmtpIp(String smtpIp) {
  this.smtpIp = smtpIp;
 }

}


Last but not least, the Spring configuration (DataSource bean not shown, simplified for clarity):



<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

 <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
     <property name="order" value="1">
     <property name="locations">
      <list>
       <value>classpath:system.properties</value>
      </list>
     </property>
 </property></bean>

 <bean class="org.gizmo.labs.utils.spring.DbPropertySourcesPlaceholderConfigurer">
  <property name="order" value="2">
     <property name="placeholderPrefix" value="%{">
     <property name="placeholderSuffix" value="}">
 </property></property></property></bean>

 <bean class="org.gizmo.labs.utils.spring.DbPropConsumer" lazy-init="false">
  <property name="serviceCharge" value="%{service.charge}">
  <property name="rebateAmount" value="%{rebate.amount}">
  <property name="smtpIp" value="%{smtp.ip}">
 </property></property></property></bean>
</beans>



The first 2 bean definitions are the BeanFactoryPostProcessor classes, and to ensure the first one is run first, the 'order' property is set (lower means higher precedence).

For the DbPropertySourcesPlaceholderConfigurer, a different placeholder prefix and suffix is used for clarity (notice the placeholders for DbPropConsumer).

So, upon Spring container startup, you should be able to view a similar output as below:
2012-09-18 00:03:14, DEBUG, org.gizmo.labs.utils.spring.DbProperties, Loading from DB: [service.charge:1.5]
2012-09-18 00:03:14, DEBUG, org.gizmo.labs.utils.spring.DbProperties, Loading from DB: [rebate.amount:15.99]
2012-09-18 00:03:14, DEBUG, org.gizmo.labs.utils.spring.DbProperties, Loading from DB: [smtp.ip:173.194.79.16]

2012-09-18 00:03:14, DEBUG, org.gizmo.labs.utils.spring.DbPropConsumer, I have consumed: org.gizmo.labs.utils.spring.DbPropConsumer@189b939[
  logger=Logger[org.gizmo.labs.utils.spring.DbPropConsumer]
  serviceCharge=1.5
  rebateAmount=15.99
  smtpIp=173.194.79.16
]

Monday, September 17, 2012

MySQL 5.1 - Default Time Zone

This is the easiest way to set the default timezone in MySQL, after looking through the manual (http://dev.mysql.com/doc/refman/5.1/en/time-zone-support.html). I happen to use phpMyAdmin, an easy-to-use web UI to administer MySQL, and currently wildly popular with cloud database providers e.g. OpenShift, Jelastic and XeRound.

At the 'Home' of phpMyAdmin (I'm using version 3.5.2.2), select 'More' > 'Variables' from the top menu bar. You will be intimidated by the massive list of MySQL variables. Just type 'time' to filter the list and you should be able to find the time_zone variable (http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_time_zone) as shown:

Click 'Edit' and enter the desired timezone offset from UTC e.g. for Malaysia (MYT) is +8:00. By default, this time_zone variable is set to SYSTEM which means MySQL will take the timezone settings from the OS.

Changes to the time_zone variable is effective immediately. To test, just run a simple query e.g. SELECT NOW() FROM SOMETABLE


Sunday, September 16, 2012

Spring 3.1 Bean Profiles

One of the most exciting new features (to me) introduced in Spring 3.1 is the bean definition profiles (http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/). Bean definition profiles are simply bean configurations that are 'activated' based on an the existence of an indicator or marker.

A lot of examples of bean definition profiles uses the JDBC DataSource bean to illustrate its usefulness. Usually for unit testing, a DriverManagerDataSource class is sufficient, as shown below:



<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
 <property name="driverClassName" value="${jdbc.driverClassName}">
 <property name="url" value="${jdbc.url}">
 <property name="username" value="${jdbc.username}">
 <property name="password" value="${jdbc.password}">
</property></property></property></property></bean>


In order to deploy the application (typically a webapp) for active use or production, the DataSource bean is usually configured to get from a JNDI lookup, as shown:


 


The JNDI lookup way also requires configuring the DataSource connection pool at the application server.

Before Spring 3.1, in order to make one of the bean definitions 'active', the desired bean definition will need to be loaded last, to override the earlier appearing bean definition e.g. the 'dataSource' bean using DriverManagerDataSource will need to be in a Spring XML file that is loaded last. One of the ways to achieve this is to specify the XML file as the last file in a comma-separated value of the context-param 'contextConfigLocation' in web.xml. An Ant task may be invoked to automate a 'deletion' of this file entry so that when deployed to production, the 'dataSource' bean using JNDI lookup will be the 'active' bean. Or, just comment out the undesired bean :). It was clumsy and led to different builds for different environments.

So, how does Spring 3.1 solve this problem? Spring 3.1 allows the incorporation of the 2 different bean definitions with the same id in the same XML file, by having nested 'beans' XML elements, as shown (simplified for clarify):



<beans xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

 <!-- Generic bean definitions ABOVE -->
  
 <beans profile="openshift,default">
  <bean class="org.springframework.jndi.JndiObjectFactoryBean" id="dataSource">
         <property name="jndiName" value="${jndi.datasource}">
     </property></bean>
 </beans>
 
 <beans profile="testing">
     <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
         <property name="driverClassName" value="${jdbc.driverClassName}">
         <property name="url" value="${jdbc.url}">
         <property name="username" value="${jdbc.username}">
         <property name="password" value="${jdbc.password}">
     </property></property></property></property></bean>
 </beans>
</beans>


A few things to note:
- The nested beans XML elements must be placed at the end of the configuration XML file
- Ensure that the Spring 3.1 Beans XSD file is used (earlier versions won't work).
- It is recommended to have one bean profile to be the default profile.

To 'activate' a bean profile, one of the ways is to pass in a system property 'spring.profiles.active'. For my testing environment, I use Tomcat, so I placed this property in setEnv.bat (not in Tomcat by default, just create it under ${TOMCAT_HOME}/bin folder, and the file will be processed by Tomcat when starting up). So for testing, the value to pass is: -Dspring.profiles.active=testing

If the 'spring.profiles.active' value is not specified, then the default profile will be the active profile.

To check or test whether which profile is active, you can get the Environment object from an ApplicationContext, as shown:

Environment env = ctx.getEnvironment();
String[] activeProfiles = env.getActiveProfiles();


In my example above, it seems that only 1 profile can be active at a time, but the Spring API allows activation of multiple profiles. Just comma-separate the profiles when specifying the value of 'spring.profiles.active'. But proceed with caution as too many profiles may lead to confusion.

Friday, September 14, 2012

Default transformations for AES, DES, DESede (Triple DES) in Java


I posted on StackOverflow regarding the default transformation used for AES in Java (http://stackoverflow.com/questions/6258047/java-default-crypto-aes-behavior/10084030). Initially I couldn't find any mention of it in the JDK documentation, but I recently stumbled upon it (http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#trans).

I was working with a vendor who was using .NET to emulate the AES encryption on a sensitive value that my Java web service is requiring as input. He kept asking about things like what mode e.g. ECB, CBC and what padding to use e.g. no padding or PKCS. I checked the Java code used to encrypt, and the only input needed is "AES":

Cipher cipher = Cipher.getInstance("AES");

So I dug deeper into the JDK documentation and found out that to pass the mode and padding, you can pass it in one string e.g. AES/CBC/NoPadding. From the documentation, I took the recommended transformations (http://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html) and wrote a JUnit test to compare the cipher texts of the various transformation options against the default plain-vanilla "AES".

I've extended it further to include DES and DESede (Triple DES). Running it on Oracle JDK 7 yielded the following output (the transformation that produced the same cipher text value as the default transformation is in bold):

AES/ECB/PKCS5Padding: true
AES/ECB/NoPadding: Input length not multiple of 16 bytes
AES/CBC/NoPadding: Input length not multiple of 16 bytes
AES/CBC/PKCS5Padding: false
==========================================================
DES/CBC/NoPadding: Input length not multiple of 8 bytes
DES/CBC/PKCS5Padding: false
DES/ECB/NoPadding: Input length not multiple of 8 bytes
DES/ECB/PKCS5Padding: true
==========================================================
DESede/CBC/NoPadding: Input length not multiple of 8 bytes
DESede/CBC/PKCS5Padding: false
DESede/ECB/NoPadding: Input length not multiple of 8 bytes
DESede/ECB/PKCS5Padding: true
==========================================================

The JUnit test for reference:

package org.gizmo.crypto;

import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
import java.util.List;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

import org.apache.commons.codec.binary.Hex;
import org.junit.Before;
import org.junit.Test;

public class DefaultEncryptionAlgoTests
{
 private List<MyCipher> myCiphers = new ArrayList<MyCipher>();
 
 private String plainText = "Sticks and stones may break my bones but coding makes me joyous";

 private class MyCipher
 {
  public String cipherName;
  public String[] algorithms;
  public SecretKey secretKey;
 }
 
 @Before
 public void generateKeys() throws Exception
 {
  //AES
  MyCipher c = new MyCipher();
  c.cipherName = "AES";
  c.algorithms = new String[] {"AES/ECB/PKCS5Padding", "AES/ECB/NoPadding", "AES/CBC/NoPadding", "AES/CBC/PKCS5Padding"};
  KeyGenerator kgen = KeyGenerator.getInstance(c.cipherName);
  kgen.init(128);
  c.secretKey = kgen.generateKey();
  myCiphers.add(c);
  
  //DES
  c = new MyCipher();
  c.cipherName = "DES";
  c.algorithms = new String[] {"DES/CBC/NoPadding", "DES/CBC/PKCS5Padding", "DES/ECB/NoPadding", "DES/ECB/PKCS5Padding"};
  kgen = KeyGenerator.getInstance(c.cipherName);
  kgen.init(56);
  c.secretKey = kgen.generateKey();
  myCiphers.add(c);
  
  //DESede (or Triple DES)
  c = new MyCipher();
  c.cipherName = "DESede";
  c.algorithms = new String[] {"DESede/CBC/NoPadding", "DESede/CBC/PKCS5Padding", "DESede/ECB/NoPadding", "DESede/ECB/PKCS5Padding"};
  kgen = KeyGenerator.getInstance(c.cipherName);
  kgen.init(168);
  c.secretKey = kgen.generateKey();
  myCiphers.add(c);
 }

 @Test
 public void testSecurityProvider() throws Exception
 {
  for (Provider provider: Security.getProviders())
  {
   System.out.println(provider.getName());
   for (String key: provider.stringPropertyNames())
   {
    System.out.println("\t" + key + "\t" + provider.getProperty(key));
   }
  }
 }
 
 @Test
 public void testAlgorithms() throws Exception
 {
  for(MyCipher c :  myCiphers)
  {
   //Default algorithm
   Cipher cipher = Cipher.getInstance(c.cipherName);
   cipher.init(Cipher.ENCRYPT_MODE, c.secretKey);
         byte[] cipherText = cipher.doFinal(plainText.getBytes());
         String defaultAlgoEncryptedHex = Hex.encodeHexString(cipherText);
   
   //Possible algorithms
   for(String a : c.algorithms)
   {
    try
    {
     cipher = Cipher.getInstance(a);
     cipher.init(Cipher.ENCRYPT_MODE, c.secretKey);
     cipherText = cipher.doFinal(plainText.getBytes());
     
           String encryptedHex = Hex.encodeHexString(cipherText);
           
           System.out.println(a + ": " + defaultAlgoEncryptedHex.equals(encryptedHex));
    }
    catch (Exception e)
    {
     System.out.println(a + ": " + e.getMessage());
    }
   }   
   System.out.println("==========================================================");
  }
 }
}


Anyway, to make things clear in your program, it's best to specify the full string rather than relying on default transformations in Java.

Thursday, September 13, 2012

Lazy-initializing beans in Spring: Exceptions


Lazy-initializing beans in a Spring container is generally desirable to allow for faster startup times, especially if there are lots of beans involved. However, there are some beans that must be loaded up or initialized when the application starts e.g. a background Quartz scheduler running jobs, or just doing 1st-level diagnostics or health check that writes results to a log file.

By default, all beans with scope="singleton" are initialized during container startup, but this behaviour can be changed by adding default-lazy-init="true" at the 'beans' top-level element, as shown (simplified for clarity):





To ensure a Spring-managed bean is initialized during container startup regardless of the attribute default-lazy-init="true" at the 'beans' top-level element in Spring configuration XML (or in Java code), you can one of the following:

  • Configure your bean definition to force initialization by adding attribute lazy-init="false", as shown in the example below:
    
    
  • Have your class implement the interface org.springframework.context.SmartLifecycle. This will guarantee the class will be initialized as long as isAutoStartup() is implemented to return 'true'. See the class Javadoc (http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/SmartLifecycle.html) for more info.


Thursday, September 06, 2012

Logback NT Event Log Appender

I've been searching the Net for a logback-based Windows event log appender, but couldn't find any. Log4j has a built-in NTEventLogAppender, as stated in http://stackoverflow.com/questions/8945187/logback-and-windows-event-system-integration, but I came across a nice alternative in the form of log4jna (https://github.com/dblock/log4jna), which doesn't require placing native DLLs in a system directory.

So I based my logback Windows event log appender on org.apache.log4jna.nt.Win32EventLogAppender, to speed things up. After some trial and error, I concluded that it is better to manually create the Windows registry keys and setup some values to ensure the implementation works instead of relying on the current user's administrative rights and having the registry keys created during the appender's initialization. So the code is 'simplified'. More info @ http://code.dblock.org/log4jna-log4jerror-could-not-register-event-source-access-is-denied

By default, the log records will be placed under the Application log, which will contain records from other sources/systems. Viewing the records specific to your application will then require great perception or the use of filters. Since I am using Windows 7 (development) and Windows 2008 Standard (testing/production), there can be a dedicated menu item under 'Applications and Services Logs', as shown below:


To create it, just add the following using regedit: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\${Custom_Log_Name}\${Custom_Source} 

Replace
  •  ${Custom_Log_Name} with the value that will be shown under 'Applications and Services Logs'. In my example, is 'MCI-CA'
  • ${Custom_Source} with the source value that you'll need to set and specify in the logback.xml configuration file. In my example, is 'mci' 
Note: The 'source' value of the appender needs to be unique (system-wide).

Next, configure the appender in logback.xml:


    
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n%throwable
        
    

    
     mci
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n%throwable
        
    

 
        
    
    
    
        
    



Whack in the JARs to classpath: jna.jar, platform.jar (both from log4jna zip package), logback-core-1.0.5.jar, logback-classic-1.0.5.jar, slf4j-api-1.6.4.jar

Also, copy Win32EventLogAppender.dll (log4jna) to Window's system32 folder (e.g. C:\Windows\System32) and add a registry value (refer to .reg file in the zip file link at bottom). You can refer to http://code.dblock.org/log4jna-the-description-for-event-id-4096-from-source-log4jna-cannot-be-found for more details.

Then just get the logger instance and start logging away! I've furnished a simple JUnit test as a sample (link below). I used the system property to load a specific logback.xml file e.g. -Dlogback.configurationFile=D:\eclipse-workspaces\indigo-workspace\Sandbox\src\logback.xml

Caveat: The logback appender can be coded to cater for logback 'classic' and 'access', but I only implemented it for 'classic'. See http://logback.qos.ch/manual/appenders.html for more details.

Accompanying files can be accessed here: http://dl.dropbox.com/u/103052906/blog/tech/nt-logback/logback-ntappender.zip