Wednesday, October 31, 2012

Ant Tutorial: Our First Project with Apache Ant!

The prerequisites for this project can be found here.

The aim of this tutorial is to build a simple project that prints "Hello World" using eclipse. We will use Ant to compile the source code in the src folder and create the binaries in the dst folder. At the end of this project we will have a SayHello.class file in the dst folder that can be executed using $java SayHello

  1. Create a project called  ANT_HelloWorld
  2. Create The Java Class to be executed:
    Next, create a java class SayHello in the package com.abhi.tutorials. Lets just have a simple static main method that prints the magic words "Hello World!". The file now looks like this..

    Ant:Hello World
    Ant:Hello World

  3. The Build.xml file:
    Pretty Easy! Huh! Now the ant file build.xml .What's build.xml? Its just the file that the ant command looks for when ant command is called from the prompt.
    Create a build.xml file under the ANT_HelloWorld folder. Right click on the build.xml file and open it with Ant Editor. The following screen shots should help you out!

    Ant: Open With Ant Editor-1
    Ant: Open With Ant Editor-1


    Ant: Open With Ant Editor-2
    Ant: Open With Ant Editor-2

  4. Writing The Ant Script:
    Type
    the following ant script in the build.xml . You can ignore the first line since it will be auto generated by eclipse for you.
    <?xml version="1.0" encoding="UTF-8"?>
    <project name="SayHello" default="compile" basedir=".">
     <target name="compile">
      <javac srcdir="./src" destdir="./dst" /> 
     </target>
    </project>
    

    Don't worry if you don't understand what each line means! We'll see them one by one in the coming sections. Don't copy-paste the code but type them. It'll force your brain to register each and every token you type.

  5. Executing the Ant Script:
    Done Typing? Now open a command prompt and go to the directory ANT_HelloWorld. Check out this post for a handy short cut. And type ant and Enter. You must see the following output.

      
    1:  C:\abtutorials\ANT_HelloWorld>ant  
    2:  Buildfile: C:\abtutorials\ANT_HelloWorld\build.xml  
    3:  compile:  
    4:  BUILD FAILED  
    5:  C:\abtutorials\ANT_HelloWorld\build.xml:4: destination directory "C:\abtutorials\ANT_HelloWorld\dst"  
    6:   does not exist or is not a directory  
    7:  Total time: 0 seconds  
    

    Hmmm....Lets see what happened here line by line...
    Line 1: The ant command typed. Nothing much here...
    Line 2: Its saying the build file is build.xml in our project direrctory.
    Line 3: The word compile with a colon Hey! That's familiar . We had that in the target tag in our build.xml
    Line 4: Whoops! It says the build failed. But Why??
    Line 5 and Line 6: It says the destination directory "C:\abtutorials\ANT_HelloWorld\dst" does not exist! Its also having a :4 printed after the build.xml. That number, my friend is the line number in build.xml where this error is occurring. 
    Line 7: Total time taken to run the script is 0 seconds...

  6. Anatomy of the Ant Script:
    Now's the time we'll analyze the build.xml script indepth. By this time you would have figured out some stuff going on behind the scene. Also we'll fix the problem that occurred in the previous step.
    Here's the build script again!
    <?xml version="1.0" encoding="UTF-8"?>
    <project name="SayHello" default="compile" basedir=".">
     <target name="compile">
      <javac srcdir="./src" destdir="./dst" /> 
     </target>
    </project> 
    
    
    
    Line 1:  That's an xml declaration. We wont be discussing about it much. As of now just have it in your mind that all XML files have this declaration as the first line.

    Line2: That's the project tag. Each build.xml file should have one and only one of this.
    This tag has these attributes :
    name: I have decided to name this project as "SayHello". You can name it anything you want.
    default: This attribute specifies the default target that needs to be executed when we type ant in the command prompt. What's a target? Its a bundle of logical operations or tasks that we use to build our project.
    basedir: Any guesses, what this is? Yes, this is the base directory. It acts as a starting point for referring to other directories, something I have used in the coming lines in this file.See that "./src" and "./dst"? What is the base directory in our case? Its the single dot, "." meaning the current folder, in our case its the ANT_HelloWorld folder.

    Line 3: The target tag. I'll repeat it again for you.. Its a bundle of logical operations or tasks that we use to build our project.In our example, we have a single attribute - name.  We can have a number of targets under the project tag. Also, there a few other attributes and one of the most used attributes after name is called the depends attribute which we will discuss shortly.

    Line 4: The javac tag with attributes srcdir and destdir. Pretty easy to figure out... Here javac
    is called a task in ant terminology. What is a task? Coming straight from the Apache Ant User manual, the definition goes like this:
    Task : A task is a piece of code that can be executed.
    There are many other tasks which ant has to make our lives easier. We'll see some of them later.
    Coming back to the javac task at hand, we have 2 attributes:
    srcdir: The source directory where the java files are present. We have it as "./src" which is nothing but the folder ANT_HelloWorld/src , the place where our SayHello.java resides.
    destdir: Yep, the destination directory. In our case its ANT_HelloWorld/dst.

    But!Hey!  Where's that directory? It doesn't exist!
    That's the reason ant complained "destination directory "C:\abtutorials\ANT_HelloWorld\dst"  does not exist or is not a directory"  Thats the root of our problem...
    We'll correct this in the next step..
    The rest of the lines are just ending tags of target and project.
  7. Correct the Ant Script:
    Lets solve the build error. For this we will create another target and name it as clean. The clean target will perform two tasks for us.
    A. The first task is to remove the directory "./dst" which will clear the old class files. For this we'll use the  delete task. No, it wont throw any error if the directory to be deleted doesn't exist.
    B.
    Next is to create the directory "./dst" itself. We'll use the mkdir task for this.
    The build file after adding the clean target looks like this....

    <?xml version="1.0" encoding="UTF-8"?>
    <project name="SayHello" default="compile" basedir=".">
     <target name="clean">
      <delete dir="./dst" />
      <mkdir dir="./dst" />
     </target>
     <target name="compile" >
      <javac srcdir="./src" destdir="./dst" />
     </target>
    </project>
    


    Now wait up! We aren't finished yet..
    We need to link up the two targets compile and clean. The so that the clean target executes before the compile. 
    We now add the depends attribute to the compile target with its value set to clean. What does this mean?
    It means , the compile target should execute after the clean target is executed. The execution chain will be clean --> compile even when compile is the default target.
    The complete build file without any errors is below:

    <?xml version="1.0" encoding="UTF-8"?>
    <project name="SayHello" default="compile" basedir=".">
     <target name="clean">
      <delete dir="./dst" />
      <mkdir dir="./dst" />
     </target>
     <target name="compile" depends="clean">
      <javac srcdir="./src" destdir="./dst" />
     </target>
    </project>
    



  8. Rebuild:
    Now we'll run the build file as we did before.Go to the folder ANT_HelloWorld and type ant. You will see the following output as in the screenshot below.

    Ant execution after Correction
    Ant execution after Correction

    Note that the delete task is not being called. That's because there's no directory named dst as yet to be deleted. If you run the same ant command again the delete task will show up.

    Now go ahead and run the class SayHello by going to the dst directory. The sample run is shown below.....


    Sample Run
    Sample Run


  9. Calling the target in the ant command :
    Before we end this tutorial. I would like to show one more thing... We can call a desired target from the ant command itself. In the following screen we call the
    clean target directly..

    Notice that the only clean target gets executed.

Hope this tutorial helped you in getting a kick start in your ant learning!

Ant Tutorial : Learn it Today with examples!


  1. What the heck is Ant??!!
  2. Prerequisites for learning Ant.
  3. Our first project Java Project with Ant.


  1. What the heck is Ant?

    The name's Ant, Apache Ant! That's the official name that differentiates the creepy one from the tool you actually use. Ant was created by James Duncan Davidson for building Tomcat, the webserver. Ant stands for "Another Neat Tool", aptly named!

    So much for history. What does it exactly do? It builds projects. What's building a project? Its a fancy way of saying compiling all the code in your java project.

    Compiling all your java code using the javac is only manageable when you have three to four files. You may say, "Eclipse handles compiling and the build path for me!". Yes it does! That's the reason I love eclipse too! But what happens when you have thousands of files controlled by different teams to be compiled together? Eclipse goes only as far for a small team. In a production environment however, a build tool like Ant/Maven helps you.
  2. Prerequisites for Learning Ant

    The prerequisites listed here are the prerequisites required for this tutorial. We will be coding all along this tutorial with less of rambling.

    So get your Ant gear in place! 
    • Some Basic Java Knowledge  
    • Installed JDK of 1.6+
    • Eclipse : For the lazy, I have the link right here. Download the one which suits your OS and processor(32 bit or 64 bit). I assume you already know how to install eclipse.
    • Apache Ant :
      * Download the zip here.
      * Unzip it and you will find the folder apache-ant-1.8.4.
      * Place it under under the C:\ directory.
         A screenshot placed below will help you to understand the folder structure.
      Apache Ant Folder structure
      Apache Ant Folder Structure


      * Add C:\apache-ant-1.8.4\bin to your Path environment variable.
      *
      Test it out by typing the ant command in a random location with no build.xml .
         When you type ant command in the command prompt you will see something like
         this...
    • Some knowledge of basic XML. Even if you dont know what's XML ,its fine... The language is so simple you'll learn it in 30 seconds.
  3. Our First Project with Apache Ant!

    Time to get our hands dirty! Since this is a big section in itself.Click here to start off! 

Thursday, October 25, 2012

Eclipse Plugin Development Notes

Some notes I am writing for myself and all the developers who are thinking  "There must be a utility for this, Where the !@#$ is it?!".

Some of the classes here are belong to the internal package which will give a "Discouraged Access" warning. You might want to recreate the code for those methods in your class itself. Its better you read this article

  1. How to know the current OS on which eclipse is running?
    Ans: Use org.eclipse.core.runtime.Platform.getOS()
  2. How do I check if my current OS is Windows (or something else) ?
    Ans: Platform.getOS.equals(Platform.OS_WIN32)
  3. How do I log some error in my eclipse plugin?
    Ans: Activator.getDefault().getLog().log(new Status(ERROR,Activator.PLUGIN_ID,e1.getMessage()));

     
  4. How do I get the current workspace?
    Ans: ResourcesPlugin.getWorkspace()
  5. I want to copy contents into a clipboard. Which class gives me clipboard utilities?
    Ans: org.eclipse.swt.dnd.Clipboard
  6. I want to add my own UI elements into my plugin How do I do it?
    Ans: Use org.eclipse.swt and org.eclipse.jface classes. In short learn SWT and JFace
  7. I want to validate a package name. How the heck do I do it !?
    Ans: JavaConventions.validatePackageName(nameOfPackage, JavaCore.VERSION_1_3, JavaCore.VERSION_1_3);
  8. Now I want to validate a package name in a project! How ??
    Ans: JavaConventionsUtil.validatePackageName(text, project)
  9. Where can I find the java files related "Open Resource" dialog?
    Ans:  org.eclipse.ui.ide.jar
      --> org.eclipse.ui.internal.ide.dialogs.OpenResourceDialog 
  10. Who calls OpenResourcesDialog?
    Ans: org.eclipse.ui.OpenWorkspaceFile(this is an action) -->org.eclipse.ui.internal.ide.handlers.OpenResourceHandler -->
    org.eclipse.ui.internal.ide.dialogs.OpenResourceDialog. Go to plugin.xml of org.eclipse.ui.ide --> Extensions subtab --> type in 'Open' in the search field.
    The command associated with this dialog is org.eclipse.ui.navigate.openResource
  11. Give me a screenshot of  org.eclipse.jdt.debug.ui plugin.
    Ans: OK
    org.eclipse.jdt.debug.ui
    org.eclipse.jdt.debug.ui
  12. Who implements the Ctrl+1 action?
    Ans:
    Plugin : org.eclipse.ui.ide_3.8.100.v20120917-171812.jar
    CommandID: org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals
  13. Where can I get the ID of the Package Explorer View and other Views?
    Ans:See the org.eclipse.jdt.ui.JavaUI class.

How To Write A Junit Test When A Method Returns Multiple Values

So you have a class like this :

public class PersonUtils {
 static List<Person>  persons = new ArrayList<Person>();

 static List<Person> getPersonList(){
  Person p1 = new Person();
  p1.setId(0);
  p1.setName("Batman");
  
  Person p2 = new Person();
  p2.setId(1);
  p2.setName(null); //bad!! we want person to have a name!

  persons.add(p1);
  persons.add(p2);
  
  return persons;
 }
 
}

class Person{
 private String name;//cannot be null - must check in JUnit !!!
 private int id;
 
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getId() {
  return id;
 }
 public void setId(int id) {
  this.id = id;
 }
}

And then your boss asks you to write unit tests to test Person name because a lot of them are having their names as null!

And now you ponder! "Hmmm.. Writing a JUnit Test which loops through and tests each person attributes is bad! I need to come up with something more clean"

Thankfully JUnit  provides you with........(drum rollllllll).......
Parameterized Tests

Now how the heck do we write a parameterized Test case ? It looks like .......

@RunWith(value= Parameterized.class)
public class PersonListTest {

 Person person ;
 
 @Parameters
 public static Collection<Object[]> data(){
  List<Person> persons = PersonUtils.getPersonList();
  Object[][] data = new Object[persons.size()][1];
  
  for (int i = 0; i < data.length; i++) {
   data[i][0] = persons.get(i);
  }
  
  return Arrays.asList(data);
 }
 
 public PersonListTest(Person p) {
  this.person = p;
 }

 @Test
 public void testPersonNameNotNull() {
  assertNotNull("Person name cannot be null!" + person.getName(),
    person.getName());
 }
 
 //other tests go here
 
}

  1. The data() method does all the dirty work.
  2. This data() prepares a 2d array which is then fed one by one to the Test as a whole.
  3. See that PersonListTest(Person) constructor? That's where its fed.
  4. After that, each of the @Test methods in this class are run..
One last note.. You may have to take the appropriate jar version of junit for Parameterized class to be present

And in case you are wondering how I formatted this code , I did it using this.

Wednesday, October 24, 2012

Eclipse Plugin Development: Discouraged Access

Many times if you use an existing plugin class when developing a plugin you might get some warning something like:
Discouraged access: The type ArchiveFileManipulations is not accessible due to restriction on required library C:\eclipse\plugins\org.eclipse.ui.ide_3.8.100.v20120917-171812.jar

Discouraged access: The method isTarFile(String) from the type ArchiveFileManipulations is not accessible due to restriction on required library C:\eclipse\plugins

 After a lot of searching I finally found out the answers here

Here's the summary:

  1. The class you are accessing mostly belongs to some package that has internal in its name.In my case its org.eclipse.ui.internal.wizards.datatransfer.ArchiveFileManipulations.
     
  2. This warning means you are using an internal method not an API. It means your plugin may not work in a different version in the future because that method may be removed/changed.

  3. Advice: Avoid using it altogether! If you want that functionality its better off you implement it yourself.

Hope this post helps people who wander a lot to get the right answer!

Saturday, October 6, 2012

Pextools : Eclipse Plugin For Package Explorer

Hiya all!

I created a new eclipse plugin Pextools that adds some menu items to the Package explorer.

After this plugin is installed,the right click menu on any item in the Package Explorer should have a submenu "PexTools" that extends into three three extra menu options
  • Open Command Window Here Opens the Shell/Command Prompt with the current working directory set to the file's parent directory or the folder's path.
  • Open Folder Opens a file explorer window with the directory chosen or the file's parent directory
  • Copy Path To Clipboard Copies the absolute path of the file or folder into clipboard

Screen Shot

pextools
PexTools


If you liked it please let me know! ;)

Please click on the link below to favourite this plugin in eclipse market place!