Monday, June 18, 2012

Javascript Closures and few other Javascript concepts

Similar to Java's inner classes, JavaScript has something called Closures.

Before going into the details, let me explain the issue I was facing and why Closure was the right fit.

In my Java code, I had a native method like:

public native JavaScriptObject drawSomething()/*-{
//'menu' is variable to which we can add menu items
menu.addItem('Menu Item 1', 'someimage1', function() {
// Here goes the code which handles the event when 
//user clicks this menu item
});
}-*/;

In the above code, the method body is enclosed between /*-{ and }-*/. This marks the code as JSNI. JSNI is essentially more or less JavaScript code.

I had to add menuItems to the menu. In the above code (menu.addItem('Menu Item 1', 'someimage1', function()), the first parameter is the text to be displayed on the menu item, second parameter is the icon/image to be displayed for the menu item. Third parameter is a function definition. When a user clicks on this menu item, this function will be invoked.

I can even call like this:
menu.addItem('Menu Item 1', 'someimage1', myfunction);
function myfunction(){
//some code
}
where myfunction is the name of a function. That is, method-name can be passed as a parameter and JavaScript will invoke the method with that name.

Now I want to pass parameters to this new function.
Can I do like this:

menu.addItem('Menu Item 1', 'someimage1', myfunction('someString'));
function myfunction(str){
//some code
}
NO.
What happens when the above code is executed?
the myfunction(str) is invoked when the JavaScript engine executes the menu.addItem() method itself.
That is, it does not wait for the user to click on the menu item.

So how to pass variables to such methods?
Use Java Closures!

Solution is:
Move the menu.addItem() to a new method:
function myfunction(menu, str){
     function newfunction() {
          //Use the str parameter here
     }
menu.addItem(str, 'someimage1', newfunction);
}

In the above code, I wrote a new function named newmethod inside the myfunction().
This newmethod will have access to the parameters passed to its parent function, that is, myfunction. Here we can use the str parameter. The value for the str parameter was the 'Menu Item 1'.
That is because, I wanted to invoke a Java method with a parameter with value as the menuItem that has been selected by the user.

This is how we sue JavaScript closures.

Thanks to my colleagues Ganesh and Raj for helping me out solve an issue in Javascript using this concept.

Before I close, I would also like to mention about 'Invoking Java methods from inside JSNI' briefly:

function myfunction(menu, str){
     function newfunction() {
          //Use the str parameter here
          thisClass.@com.sample.MyClass::menuItemSelected(Ljava/lang/String;)(menuitem);

     }
menu.addItem(str, 'someimage1', newfunction);
}

In the above code, I am passing the text of the menuItem selected by the user to a instance method inside a Java class named MyClass in the package com.sample.

The syntax for invoking a Java method from JSNI is:
classobject.@fully_qualified_classname::method_name(syntax_of_parameter[s])(actual_parameter[s]);

Let me know if you have any questions.

Thursday, May 31, 2012

Amazon Interview Questions

I gave an interview with Amazon in the start of the year. Here are the questions I faced:

First Round was a Written Test.
Q1) Reverse words in a sentence
Q2) Print 2D array in Spiral Order
Q3) Remove all nodes with the given value in a linked list:
       LinkList removeValues(LinkList Head, ValueObject value){
       }
 Q4) Find the first non-repeating character in a word.

Second round was a F2F technical discussion:
Given a Tree:














What is the order of nodes when you parse the tree as:

1) Breadth First:
Ans: 1 2 3 4 5 6 7 8 9
2) Reverse Breadth First
Ans: 7 8 9 4 5 6 2 3 1
3) Zig Zag
Ans: 7 8 9 6 5 4 2 3 1

He asked many followup questions on Tree Parsing, searching, Collections, LinkedLists etc.
Few of them were like:
While doing the above Breadth First, etc, How would you do it if you were to do  only using:
1) Only two Queues
2) Only 1 Queue and 1 Stack
3) Only 2 Stacks

Third Round:
He gave me pattern like:
Write a recursive program to print similar pattern shown below given any number:
Pattern 1:
number: 5

-----

-
--
-

---

-
--
-

----

-
--
-

---

-
--
-

-----

Pattern 2:

number: 4

----

-
--
-

---

-
--
-

----

Pattern 3:
number: 6

------

-
--
-

---

-
--
-

----

-
--
-

-----

-
--
-

----

-
--
-

---

-
--
-

------

If you observe the patterns,

given a number the first and last lines will have so many number of dashes.

the the common pattern occurs between dash lines:
-
--
-

Then after the first line, start with 3 dashes and go till (n-1) then go back till 3. 

Friday, March 9, 2012

Solution for the "Issue with Executable/Runnable Jar file"

I was facing an issue when running an Executable Jar file.:

I had a simple Java Project, in which I had a class named "Sample.java". I need to use log4j for logging statements. This project should be archived as an Executable Jar.

My Project has the following files:











The Sample.java looks like:
package com.dwij.sample;

import org.apache.log4j.Logger;

public class Sample {

 public static final Logger LOGGER = Logger.getLogger(Sample.class);

 public static void main(String[] args) {
  LOGGER.info("Simple usage of log4j");
 }
}


You can download the zip file of this project from here

In the Manifest.MF file, mention your Main class and classpath:
Manifest-Version: 1.0
Class-Path: lib/log4j.jar
Main-Class: com.dwij.sample.Sample



Now I go to command prompt and issue commands for:
  1. Compile sources: javac -sourcepath src -classpath classes;lib\log4j.jar src\com\dwij\sample\*.java -d classes
  2. Archive the project into a Jar file: jar -cvfm Sample.jar Manifest.MF -C lib . -C classes . .classpath .project
  3. Now run the jar file: java -jar Sample.jar. (Issue this command after placing the Sample.jar in a separate folder)
    • This fails with an error: NoClassDefFoundError for the org.apache.log4j.Logger class
Why is so?
That is because, When you have your main class inside a Jar file and if you need to refer to classes from the Jar files from this main class, which are again packaged inside the same Jar, YOU JUST CAN'T DO IT.
There is a thread which explains this issue: Executable JAR ClassPath problem

Solution 1:
You will be able to run this only when the Sample.jar is sitting beside a folder named "lib", which has the log4j.jar.

That is because, when you run the Executable Jar, the Manifest.MF is read for the classpath property. In our case, we mentioned lib\log4j.jar. So it looks for a "lib" folder at the same level where the jar resides.
But this is not an optimal solution, ideally, we would like to package our code in a single self-contained Jar file.

Solution2:
Here, the requirement is to package all the dependent jars also inside the Sample.jar.
For this, I used Eclipse's solution. When you export a Java Project from Eclipse, and mark it as Runnable Jar specifying your Main class, all the dependent Jar files will be packaged into the resultant Runnable Jar file and there are 5 classes that are added by Eclipse. Apart from these classes, Eclipse modifies the Manifest.MF file to add the following parameters:

Rsrc-Class-Path: ./ log4j.jar
Class-Path: .
Rsrc-Main-Class: com.dwij.sample.Sample
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader

Here, Eclipse is using the concept of URL Class loaders. This manifest file will be read and your actual Main class will be called after pointing the classpath to the Jars files mentioned in the "Rsrc-Class-Path" property.

I included these classes in my source project, compiled and archived.

That works like a charm!

Here are the steps:
  • Copy the following classes into your source project:
Now go to command prompt and issue commands for:
  • Compile sources: javac -sourcepath src -classpath classes;lib\log4j.jar src\com\dwij\sample\*.java src\org\eclipse\jdt\internal\jarinjarloader\*.java -d classes
    • Observe that we are compiling the new package as well.
  • Archive the project into a Jar file: jar -cvfm Sample.jar Manifest.MF -C lib . -C classes . .classpath .project
  • Now run the jar file: java -jar Sample.jar. (Issue this command after placing the Sample.jar in a separate folder)
  • Observe that the Jar runs fine! 

Happy executing-your-Runnable-Jar-files! :)

Thursday, March 8, 2012

Using Log4J

In this post, I will try to keep things as simple as possible and explain how to use log4j in Java.

1. Create a Java Project in Eclipse, say "Sample"
2. Create a java class with main() method, say Sample.java.
3. Download log4j.jar. I would recommend you to download the latest jar.
4. Have that log4j.jar in buildpath of the project.
5. In the Sample.java, write the following code to include Logging statements:
package com.dwij.sample;

import org.apache.log4j.Logger;

public class Sample {

 public static final Logger LOGGER = Logger.getLogger(Sample.class);

 public static void main(String[] args) {
  LOGGER.info("Simple usage of log4j");
 }
}

6. Run the Sample.java class. Yes, the error you see is expected.
log4j:WARN No appenders could be found for logger (com.dwij.sample.Sample).
log4j:WARN Please initialize the log4j system properly.

7. How to fix this "No appenders issue"?
  • Have a log4j.properties in classpath of the project:
    • Create a file with name "log4j.properties" and have the below content in it:
      • log4j.rootCategory=DEBUG, S
        log4j.appender.S = org.apache.log4j.ConsoleAppender
        log4j.appender.S.layout = org.apache.log4j.PatternLayout
        log4j.appender.S.layout.ConversionPattern = %c{1} [%p] %m%n
    • The logging level can be DEBUG, INFO, ERROR, FATAL
    • "S" in log4j.rootCategory can be any string you want; it is just that you need to give the same string in the other properties (log4j.appender.S, log4j.appender.S.layout, log4j.appender.S.layout.ConversionPattern)
    • I am using ConsoleAppender here because I just want to see the Log statements in the console.
    • ConversionPattern goes something like this:
      • %c{1}  prints the classname that is ran
      • [%p] prints the Log level
      • %m prints the message provided in the log statement in the code
      • %n prints a new line
  • Define your own appender and add it to the Logger instance:
package com.dwij.sample;

import org.apache.log4j.Appender;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;

public class Sample {
 
 static Appender myAppender;  
 public static final Logger LOGGER = Logger.getLogger(Sample.class);

 public static void main(String[] args) {
  // Define Appender     
  myAppender = new ConsoleAppender(new SimpleLayout());  
  
  LOGGER.addAppender(myAppender);  
  LOGGER.setLevel(Level.ALL); 
 
  LOGGER.info("Simple usage of log4j");
 }
}

8. Run the class, and you should see the below output:
INFO - Simple usage of log4j

In order to keep things simple, I have not included examples which include writing Log statements to Files, etc.

I will add more content, if requested.