Wednesday, December 14, 2011

Store PDF Books on iPhone and iPad

I was searching for a way to manage my PDF books on my iOS device so I can read it anywhere.  And I found that there is a easy way of doing that without downloading any new apps.
To store your PDF books in iOS device is easy:
  1. Send PDF file to yourself as email attachment
  2. Open the PDF in your email on your iOS Device
  3. On the top right corner of the PDF view, there is a option button.  Touch that button and select "Open in iBook".  Now your PDF books will be stored in your iBook liberary.
The reading experience of iBook is way better than reading attachment in email.  Plus you can pick up where you left when you open the book next time.  Also, since your PDF is now in iBook it will be automatically sync to your PC over iTunes and to other iOS device over iCloud.  Cool!

The only limitation to this method is that the size of the book is limited by your email attachment size.
But it should be enough to cover many of your books.  Have fun reading your PDF on iPad and iPhone!

Wednesday, September 21, 2011

[SOLVED] jQuery Tablesorter Plug-in 'config.parsers' is null

I encountered an issue with jQuery Tablesorter Plug-in on Internet Exporer (IE) when the table is empty. Say, if you have a table looks like below:
<table id="myTable">
  <thead><tr><th>Col1</th><th>Col2</th></tr></thead>
  <tbody></tbody>
</table>
when you call $("#myTable").tablesorter(); You will get following error on IE saying:

'config.parsers' is null or not an object



If you are running Firefox (FF), you won't see this error but your javascript code on the page might be broken.
So, you should either remove the table element from you page or render empty row for the table if it's empty. Hope that helps you too.

Thursday, September 8, 2011

Connect in DB2 Control Center with Exclamation in password

If your password has exclamation (!) mark in it and you have trouble connect to DB2 in Control Center, you must be forgetting to wrap the password by double-quote (").


connect to #DBNAME# user #USERNAME# using "PASSWORD!"

Tuesday, July 19, 2011

Disable "Research" feature in MS Outlook

In Outlook 2003, when alt click on any words, it brings up a Research pane. This could be a better feature but it actually freeze the outlook for various amount of time and so it becomes very annoying.
For users who often use alt-tab combo, it becomes even more annoying....
There is no way to disable this feature in Outlook but it can be configured so it does not freeze the outlook.
The reason it freeze outlook is because the Outlook requires resources such as network connection, CPU cycles to bring up the research pane. This becomes much time consuming when Research Pane are configured to do many things. So naturally, the way to decrease the startup time of the pane is to reduce the options Research does. In other words, removing all options from Research equals virtually disabling this feature.

Here is how to do it:
  1. Bring up the Research pane by Alt + Left Click on a word
  2. Find and click "Research Option" at the bottom of the pane
  3. Uncheck options that is not required, all simply uncheck all
  4. Save the changes by clicking "Ok"

Hope that helps.

Monday, June 20, 2011

Java Float class valueOf method automatically rounds string

I encountered this problem when I try to do something like:

Float.valueOf("123456.123");

The result Float value is automatically rounded to 123456.00.
In order to preserve the precision, I need to use Double.

Double.valueOf("123456.123");

BTW, my jdk version is 1.6.

Friday, May 20, 2011

Struts 2 Interceptors - before, between and after

Struts 2 Interceptors is one of the greatest features of Struts 2 to handle regular routing logic and special logic at special occassion on demand the AOP way.
In most cases, you want to intercept the running application before action invocation, between action invocation and result generation and after view rendered.

I found a great tutorial on how to handle the above 3 senario at Benjamin J. McCann's blog post.

Below is quick summary:

To create a Struts 2 interceptor, you need to implement Interceptor interface or extend one of the build-in interceptor class. E.g. AbstractInterceptor

Intercept Before Action

public class MyInterceptor extends AbstractInterceptor {
  private static final long serialVersionUID = 5065298925572763728L;
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
      // do something before invoke
      try{
        if(o instanceof MyAction){
          ((MyAction) o).someLogicBeforeAction();
        }
      }catch(Exception e){
        return "error";
      } 

      // invocation continue    
      return invocation.invoke();
    }
  }
}

Intercept Between Action and Result

(after action is executed but before result is rendered)

Register a PreResultListener to the invocation instance. Sample code as below:
public class MyInterceptor extends AbstractInterceptor {
  private static final long serialVersionUID = 5065298925572763728L;
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
      // Register a PreResultListener and implement the beforeReslut method
      invocation.addPreResultListener(new PreResultListener() { 
        @Override
        public void beforeResult(ActionInvocation invocation, String resultCode) {
          Object o = invocation.getAction();
          try{
            if(o instanceof MyAction){
              ((MyAction) o).someLogicAfterActionBeforeView();
            }
          }catch(Exception e){
            invocation.setResultCode("error");
          }
        }
      });
      
      // Invocation Continue
      return invocation.invoke();
    }
  }
}

Intercept After View Rendered


public class MyInterceptor extends AbstractInterceptor {
  private static final long serialVersionUID = 5065298925572763728L;
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
      // do something before invoke
      try{
        // invocation continue    
        return invocation.invoke();
      }catch(Exception e){
        // You cannot change the result code here though, such as:
        // return "errorr"; 
        // This line will not work because view is already generated  
        // You can do something like database cleanup or logging at this point
        doSomeLogicAfterView();
      } 
    }
  }
}

Sunday, April 24, 2011

Proxy Error (502) caused by Tomcat Http Proxy Setting When Using Struts2

In Tomcat (my version is 5.5 +), the default http port is 8080. In your server.xml connector setting, you may have the following line:

The default Catalina connetor setting for HTTP proxy is pointing to port 80.
By doing so, the HttpRequest Object resides in your session will contain two port values:
  • port=8080
  • proxy port = 80
. This may cause problem when Struts2 is in use. If you use Struts2 UrlHelper to generate the current request URL (which you may save the url as last saved location) the url generated will not contain the 8080 port because proxy port is 80 and Struts use the HttpServletRequest.getServerPort() method to get the request port. So if your url was
http://mydomain.com:8080/some.action
The generated url is actually
http://mydomain.com/some.action
If you didn't setup your web server right or you don't have one, the request is going to failed for a 502 (bad gateway) error.
So double check your sever.xml connector setting in Tomcat if you are getting a 502 error.
The simple solution here is to change proxyPort to 8080 (same as your application port).


Monday, April 18, 2011

Spring Parent Class Member Not Injected When Loading Child Class

If Class B extends Class A where B calls a method in parent A that will access propertyOfA, the assumption is that when B is loaded all property of parent A will be injected automatically because B extends A.
However, that' s not the case.  If you do not inject A's property in child class B, they will not be injected and you will get NullPointerException...
Thus, you should always inject parent's member if you are going to access them either directly or indirectly.... that sounds awkward.  Am I missing something here?
[July 27, 2011 Thanks to Luca for the correction] 
In fact, in order to have the inheritance happen in Spring bean declaration, you must explicitly declare the parent class in the bean definition.

Example: Class B extends Class A, in order to access A's property, B must inject in its definition as well.

// Parent Class
public class ClazzA {
  private Clazz propertyOfA;

  protected void methodOfA(){
    propertyOfA.invokeSomething();
  }
  public Clazz getPropertyOfA(){
    return this.propertyOfA;
  }
  public void setPropertyOfA(Clazz propertyOfA){
    this.propertyOfA = propertyOfA;
}

// ClazzB is sub-class of ClazzA
public class ClazzB extends ClazzA{
  protected void methodOfB(){
    methodOfA();
  }
}

// Member property type for ClazzA
public class Clazz{
  public void invokeSomething(){
    System.out.println("Invoke Clazz to do something!");
  }
}


In order for B to access parent A's property, B must declare parent="classA" in its definition.


 




Note that:

This line must be injected.

Please correct me if I'm missing something basic. It seems strange that Spring does not automatically inject parent's properties....

Thursday, April 7, 2011

Modify iFrame Content Using JavaScript - Not Possible

It is not possible to modify the data loaded using iFrame. This is a security protection mechanism that disallow the user to do cross site scripting (XSS).
Imagine that if you are able to load a bank login page and then alter the form action to point to your own server? You cannot do that.
I saw some comments online said that it is possible to alter the content loaded by iFrame from the same domain. I tried today and it's not possible neither. Maybe someone can correct me and show me how.

What I did is I added a button to show the iFrame's innerHTML when clicked using jQuery. The theory is if I can retrieve the content of the iframe, I will be able to modify the content shown to the user.

<script language="JavaScript" type="text/javascript">
  $(document).ready(function(){ 
    $("#btn_show").click(function(event){
      event.preventDefault();
      alert($("#iframe_window")[0].innerHTML);
    });
  });
</script>
<input type="button" id="btn_show" value="show me"/>
<div class="ContentDetail" id="biIFrame" style="float: left; width: 100%;">
<iframe src="EXTERNAL_URL" height="800" id="iframe_window" width="100%">
  Content before loading the iframe
</iframe>
</div>

After the iFrame is completely loaded, I clicked the "show me" link and the alert box shows "Content before loading the iframe". Doesn't matter the 'EXTERNAL_URL' is from same domain or not, the iframe content retrieved by javascript is always the initial value. This demo shows that javascript engine is preventing user modifying the iFrame content. Sorry guys, it is just not safe to allow it.

Friday, March 4, 2011

jQuery offset function not working in IE - top is a IE keyword

The following piece of code is working fine in FF, Chrome, Opera but not in IE.  The error I got in IE says line 2 is 'Not Implemented'

left = $("#myElement").offset().left - 120;
top = $("#myElement").offset().top;     

It turns out that 'top' is a IE keyword. By saying top = ***, it implies set top position to ***, and this = operation is not implemented in IE.
So changed top to something else solved the problem.

This code is working in all browser:


rLeft = $("#myElement").offset().left - 120;
rTop = $("#myElement").offset().top;            

Thursday, February 10, 2011

Unable to read TLD "META-INF/tld/tiles-jsp.tld" from JAR file

I got this strange error saying:


org.apache.jasper.JasperException: Unable to read TLD "META-INF/tld/tiles-jsp.tld" from JAR file "file:/C:/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/MY_APP/WEB-INF/lib/tiles-jsp-2.0.4.jar": org.apache.jasper.JasperException: Failed to load or instantiate TagExtraInfo class: org.apache.tiles.jsp.taglib.UseAttributeTag$Tei
    at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:51)
    at org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:409)
    at org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:181)
    at org.apache.jasper.compiler.TagLibraryInfoImpl.(TagLibraryInfoImpl.java:182)
    at org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:386)
    .........



It turns out that I have both jsp-api.jar and tiles-jsp-2.*.jar in WEB-INF/lib together in my deployment folder.  They don't seem to like each other in the same place.  By removing jsp-api.jar, the problem is gone. 
Normally, jsp-api.jar should not be bundled in the war because all application server should have jsp-api.jar in their common library.  So this jar should not exists in application WEB-INF/lib folder.  The reason I had it in my project is because a bug currently exists in Eclipse Maven (m2e) plugin that includes jar files even they are set to provided scope.  In my project pom.xml I set the jsp-api to have the 'provided' scope.  However, the plugin still push the jar into my maven dependencies which are then port over to my tomcat deploy folder.  This is a known issue in Maven plugin.  If you have the same issue with me and has to use maven and tomcat together, you need to delete the file manually after server synchronization.  I wrote a simple batch file on my desktop as a short cut to delete the file.  Until the bug is fixed, this is the only workaround....

Eclipse version: Helio build 20100917-0705
M2E plugin version: 1.0.100.20110804-1717

Wednesday, February 9, 2011

Unit Testing JSP Custom Tag Using Spring

In order to unit test your JSP tag, you need to mock up ServletContext and PageContext.  This would be a difficult task without the help from 3rd party library.  Spring 2.5 provides a mock up liberary bundled in spring-test-2.5.x.jar.  This greatly speed up the construction of the test code.

Now I'm going to show an example on testing a custom tag using Spring test library:

Assuming we have a custom tag as below:

public class DataInquiryTag extends TagSupport {

 private String name;  // attribute parameter name
 private String size;  // HTML element size 
 
 @Override
 public int doStartTag() throws JspException {
  String msg = "Hello "+name+"";
  pageContext.getOut().write(msg);
  return super.doStartTag();
 } 
}

We test our tag using JUnit 4.
Before every test invocation, we need to mock ServletContext and PageContext. To do that we setup @Before method as below:

@Before
 public void setup(){
  // mock ServletContext
  mockServletContext = new MockServletContext();
  // mock PageContext
  mockPageContext = new MockPageContext(mockServletContext);  
  tag = new MyTag();
  tag.setPageContext(mockPageContext);  
 }
The @Before method will use spring mock library to mock ServletContext and PageContext. The is good enough for simple pojo tag that does not rely on any application context.
What if out tag is depending on application context? An example would be a class referenced in the test implements InitializingBean interface. The use of the class is to load properties and initialize values. This requires spring context to be loaded.
To load Spring Application Context, such as WebApplicationContext, we need to add following lines in @Before method:

String configLocations = "/WEB-INF/applicationContext.xml,/WEB-INF/applicationContext-mock.xml";
 mockServletContext.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, configLocations);
 ContextLoader loader = new ContextLoader();  
 loader.initWebApplicationContext(mockServletContext);
We first set the location of applicationContext file. Note that we add a applicationContext-mock.xml file to override beans defined in default context. This is handy because some beans may require external resource such as data source in order to be loaded correctly. We can override these beans to local pojo bean for the sake of unit testing.

Usually, application context is common to all tests so we only need to load spring context once before executing all tests. We can do so by adding these lines in @BeforeClass method. So our final setup looks like below:

@BeforeClass
 public static void init(){
  // mock ServletContext
  mockServletContext = new MockServletContext();
  //Add the following lines if your test depends on spring context to be loaded
  //For example, you have a referenced class that implements   
  org.springframework.beans.factory.InitializingBean interface
  String configLocations = "/WEB-INF/applicationContext.xml,/WEB-INF/applicationContext-mock.xml";
  mockServletContext.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, configLocations);
  ContextLoader loader = new ContextLoader();  
  loader.initWebApplicationContext(mockServletContext);
 }
 
 @Before
 public void setup(){
  // mock PageContext
  mockPageContext = new MockPageContext(mockServletContext);  
  tag = new MyTag();
  tag.setPageContext(mockPageContext);  
 }
The test setup as above to load application context at the beginning of all test run. Then every test will create its own PageContext to hold the request and response as well as a new tag instance.

After setting up the test environment, it's time to write our test:
@Test
 public void testDoStartTag() throws Exception{  
 try{
  tag.setName("John");
  tag.doStartTag();
  String output = ((MockHttpServletResponse)mockPageContext.getResponse()).getContentAsString(); 
  assert("Hello John
".equals(output)); }catch(JspException je){ assert(false); } }
The output string contains the actual http response (e.g. generated html code) of the tag when calling doStartTag method. So you can right specific assertion logic against the output of the tag.


The complete test class source is shown below:

public class TestDataInquiryTag {  
 @BeforeClass
 public static void init(){
  // mock ServletContext
  mockServletContext = new MockServletContext();
  //Add the following lines if your test depends on spring context to be loaded
  //For example, you have a referenced class that implements 
  //org.springframework.beans.factory.InitializingBean interface
  String configLocations = "/WEB-INF/applicationContext.xml,/WEB-INF/applicationContext-mock.xml";
  mockServletContext.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, configLocations);
  ContextLoader loader = new ContextLoader();  
  loader.initWebApplicationContext(mockServletContext);
 }
 
 @Before
 public void setup(){
  // mock PageContext
  mockPageContext = new MockPageContext(mockServletContext);  
  tag = new MyTag();
  tag.setPageContext(mockPageContext);  
 }

 @Test
 public void testDoStartTag() throws Exception{  
  try{
   tag.setName("John");
   tag.doStartTag();
   String output = ((MockHttpServletResponse)mockPageContext.getResponse()).getContentAsString(); 
   assert("Hello John
".equals(output)); }catch(JspException je){ assert(false); } } }

Tuesday, January 25, 2011

JMeter Notes

HTTP Proxy Server URL Patterns RegEx:
.*\.action          ====> all actions that ends with .action
.*\.action\?*     ====> all actions that contain parameters
.*\uri_name      ====> specific uri
.*\uri_name\?.* ====> specific uri with parameter

JMeter Variables
1. Global variable is created at Test Plan level
2. Global variables can be referenced using ${VARIABLE} in element level
3. JMeter context variable can be referenced using ${__VARIABLE} at element level. e.g. ${__threadNum}
4. Element level 'value' field cannot perform arithmetical calculation such as + - * / or string concatenation
5. PreProcessor can be used to handle variable calculation and algorithem in familiar scripting language
6. BSF Processor is the standard implemenation of JSR223 Processor

Useful Links
JMeter - User's Manual: Component Reference
JMeter - User's Manual: Functions and Variables

Friday, January 21, 2011

db2admin lost administrators rights after password reset on Windows

After I reset my db2admin password on Windows today, I found it lost its admin rights such as create table, grant permissions...
To fix this:
1. Go to computer management > user and group > select db2admin and remove Administrators group from it
2. Apply and then add the Administrators group back to db2admin
3. Apply and then restart all DB2 windows services (or restart windows)

I experienced this problem on Windows only as DB2 is using windows credential as login authentication and authorization.

Wednesday, January 19, 2011

[SOLVED] P6DriverNotFoundError: Error registering factory

ERROR

Caused by: com.p6spy.engine.spy.P6DriverNotFoundError:
Error registering factory [com.p6spy.engine.logging.P6LogFactory]
Caused By: java.lang.ClassCastException: com.p6spy.engine.logging.P6LogFactory
cannot be cast to com.p6spy.engine.spy.P6Factory
at com.p6spy.engine.spy.P6SpyDriverCore.initMethod(P6SpyDriverCore.java:289)
at com.p6spy.engine.spy.P6SpyDriver.initMethod(P6SpyDriver.java:78)
at com.p6spy.engine.spy.P6SpyDriver.(P6SpyDriver.java:74)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory
(BasicDataSource.java:1415)



SOLUTION

This problem is caused when I have multiple copies of p6spy.jar (one in my WAR file and the other one in Tomcat Lib folder). There should be only one copy of the jar per class loader. By removing p6spy.jar from either the war file or tomcat lib, problem is gone.

Sunday, January 16, 2011

Install MySql on Mac OSX

Extracted from this article

1. Download MySql dmg from official site

2. Install all packages

3. In system preference, make sure the mysql is up and running

4. Change root password => mysqladmin -u root -p’OLDPASSWORD’ password NEWPASSWORD

5. Set up command line and manual pages:

echo 'export PATH=/usr/local/mysql/bin:$PATH' >> ~/.profile

echo 'export MANPATH=/usr/local/mysql/man:$MANPATH' >> ~/.profile

(For Rails Developers:)
6. If you are migrated from Leopard to Snow Leopard, you need to reinstall snow leopard version XCode to get rid of gem update errors (caused by missing ruby.h header file)