Deploying Your Rails Application on OpenShift From a Windows Box

Install OpenShift Express Under Windows

Watch this great hands-on guide by gshipley21 and read on for a few gotchas/tips.

Tip #1 -- You will not need to install components that are already installed directly under Windows. If you get errors such as Error: ruby.exe: No such file or directory — /cygdrive/c/Ruby192/bin/gem, you will have to alias the binary to make the commands work in Cygwin. For example, to alias the ‘gem’ binary, use alias gem='C:/Ruby192/bin/gem'.

Tip #2 -- If you get errors, such as the one below while trying to create your OpenShift domain, you probably don’t have an .ssh folder in your Cygwin home directory -- you will have to manually create it.

Generating OpenShift Express ssh key to C:/Users/USER/.ssh/libra_id_rsa
C:/Ruby192/lib/ruby/gems/1.9.1/gems/rhc-0.79.5/bin/rhc-create-domain:140:in `initialize': No such file or directory - C:/Users/USER/.ssh/libra_id_rsa.pub (Errno::ENOENT)

Tip #3 -- I already mentioned this in my first tip, but if you get an error like the one below, create an alias for rhc-create-domain with alias rhc-create-domain='C:/Ruby192/bin/rhc-create-domain'.

C:\Ruby192\bin\ruby.exe: No such file or directory -- /cygdrive/c/Ruby192/bin/rhc-create-domain (LoadError)

Create Your App Domain

Tip #3 -- I already mentioned this in my first tip, but if you get an error like the one below, create an alias for rhc-create-domain with alias rhc-create-domain='C:/Ruby192/bin/rhc-create-domain'.

C:\Ruby192\bin\ruby.exe: No such file or directory -- /cygdrive/c/Ruby192/bin/rhc-create-domain (LoadError)

Create Your App

Tip #4 -- I am going to repeat this one more time in case you haven’t read the sections above -- if you get an error like C:\Ruby192\bin\ruby.exe: No such file or directory -- /cygdrive/c/Ruby192/bin/rhs-create-app (LoadError), you will have to create a command alias with alias rhs-create-app='C:/Ruby192/bin/rhs-create-app'.

Tip #5 -- You can use rhs-create-app -h to obtain more information for the available types of applications (the -t parameter).

Tip #6 -- I got the error below and upon inspecting my .ssh/config file, I found that there was a bad line that read ‘Enter new date (mm-dd-yy)’. I ended up removing it and my application was properly added.

Tip #7 -- You can create a new application using your OpenShift control panel’s web interface.

Tip #8 -- If you get e warning such as the one below, you will need to update the permissions on you key file with chmod 700 libra_id_rsa.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0755 for '/home/USER/.ssh/libra_id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
bad permissions: ignore key: /home/USER/.ssh/libra_id_rsa
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
fatal: The remote end hung up unexpectedly

VN:F [1.9.11_1134]
Rating: 0.0/5 (0 votes cast)
Posted in Cloud, Rails at October 19th, 2011. No Comments.

jsTree – Part 1: Introduction

I recently used jsTree in a Google extension to visualize a multi-level hierarchy, where each level contained different entities. For those of you familiar with the agile development process and VersionOne, it is the teams/iterations/stories/tasks hierarchy that looks like this:

Introduction

After reviewing a few free components out there, I decided to go with jsTree, which is a JavaScript-based component in the form of a jQuery plugin. Here are some of the reasons that influenced my decision, in no particular order:

  • Very easy to use
  • Highly configurable
  • Lots of functionality (including checkboxes, if needed)
  • Easy to inject into a page from a Google Chrome extension
  • Broadly used
  • Open source

To get an overview of the supported functionality and see the component in action, or download it, go to http://www.jstree.com/. I will attempt to go over the core functionality here, and dive into some of the more advanced topics, including things that are not officially supported but can be achieved through html/css trickery, in later posts.

For my use case, I ended up with the HTML data source, but it also supports JSON and XML. All I needed was a few nested HTML unordered list, looking similar to this:

<div id="selector">
  <ul>
    <li><a>Team A's Projects</a>
      <ul>
	<li><a>Iteration 1</a>
          <ul>
            <li><a>Story A</a></li>
            <li><a>Story B</a></li>
            <li><a>Story C</a></li>
          </ul>
        </li>
	<li><a>Iteration 2</a>
          <ul>
	    <li><a>Story D</a></li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</div>

All it takes is a single line of code to bring your tree to life!

$("#selector").jstree();

Here is the result:

The result is a fully-functional tree where you can expand nodes to reveal their children. It features some nice sliding effects and is pretty smooth overall.

Customizing your tree

Now let’s look at customizing it a little bit. We can start by changing the images for the team and iteration nodes. jsTree allows you to initialize it with settings supplied in the JSON format.

First, we’ll need to define some rel attributes for the team and iteration li nodes, like so:

...
  <ul>
    <li rel="team"><a>Team A's Projects</a>
      <ul>
	<li rel="iteration"><a>Iteration 1</a>
...

Now we can use the values from the rel attributes to associate images to those types.

$("#selector").jstree({
        "types" : {
            "types" : {
                "team" : {
                    "icon" : {
                        "image" : "../resources/icons/team.png"
                    }
                }, 

                "iteration" : {
                    "icon" : {
                        "image" : "../resources/icons/iteration.png"
                    }
                }
            }
        },
        "plugins" : [ "html_data", "types", "themes" ]
});

Notice the plugins definition at the bottom. jsTree includes a set of plugins that provide functionality and can be activated, if needed. By default, only the core is enabled, but you can enable additional plugins, by listing them in the plugins configuration option. In our case above, the types functionality is enabled by including the types plugins, and the themes plugin enhances the appearance of our tree. To see a list of the plugins that are available, go to the jsTree documentation page.

After adding the configurations above, our tree will display the custom icons for the team and iteration nodes.

Sliding animations

You can control the sliding animations by specifying a duration in the core block of the configuration like so:

"core" : {
    "animation" : 0
}

The number is in milliseconds, and 0 means no animations.

Selection in the tree

You can allow elements to be selected in your trees by including the ui plugin. There are a few ui configurations that are worth mentioning here.

You can limit the number of items that can be selected in your tree, by specifying a select_limit. The default is -1, which means no limit.

"ui" : {
    "select_limit" : 2
}

Or you can specify nodes that should default to selected by identifying them in your HTML code and adding them to the initially_selected list. Their parents will default to expanded to reveal them.

...
      <ul>
	<li><a>Iteration 1</a>
          <ul>
            <li><a>Story A</a></li>
            ...
          </ul>
        </li>
	<li><a>Iteration 2</a>
          <ul>
	    <li><a>Story D</a></li>
          </ul>
        </li>
      </ul>
...

And the configuration:

"ui" : {
    "initially_select" : [ "iteration1", "iteration2" ]
}

By using disable_selecting_children, you can prevent selecting children whose parents have already been selected. This only prevents selecting a child AND its parent, you can still select the child if you deselect its parent. The default is false

"ui" : {
    "disable_selecting_children" : "true"
}

You can specify what happens when a parent is collapsed while one or more of its children are selected with selected_parent_close. The default is “select_parent”, but you can also use “false”, which means do nothing, or select_parent, which will cause the parent to become selected.

Perform actions on the tree

Now that we’ve gone over some of the basic configurations that have to do with the selection in your tree, let’s switch gears and look at how to programatically select items, deselect items, etc. I will add a button at the bottom of my tree and wire it with a click event to demonstrate how to interact with the tree.

<div id="selector">...</div>

<button id="actionButton">Do it!</button>

To select an item, we can add the following code:

$("#actionButton").click(function() {
    $("#selector").jstree("select_node", $("#iteration1"), true);
});

The first argument can be a DOM node, a jQuery node, or a jQuery selector to an element in your tree. The second argument allows you to enforce the selection limit you may have set in your configuration, by setting it to true. It’s worth mentioning that if the parent of the node you are selecting is collapsed, it will be expanded to reveal your selection.

Deselecting items is just as easy. To deselect a specific node, add:

$("#actionButton").click(function() {
    $("#storySelector").jstree("deselect_node", $("#iteration1"));
});

You can deselect all nodes with this:

$("#actionButton").click(function() {
    $("#storySelector").jstree("deselect_all");
});

You can specify a context when calling the deselect_all method in order to limit its scope to a subset of nodes in your tree:

$("#actionButton").click(function() {
    $("#storySelector").jstree("deselect_all", $("#iteration1"));
});

So, if we had stories selected under both Iteration 1 and Iteration 2, the code above would cause only the one under Iteration 1 to become deselected.

In order to iterate over the selected nodes you can use the following snippet:

$("#actionButton").click(function() {
    $.each($("#selector").jstree("get_selected"), function(index, element) {
        alert("Index " + index + ": " + $(element).find("a:first").text());
    });
});

Similar to the deselect_all method, you can limit the scope of the get_selected by specifying a context as a second argument.

You can also test whether a specific node is selected:

$("#actionButton").click(function() {
    alert($("#storySelector").jstree("is_selected", $("#iteration1")));
});

Events

I can’t wrap up the first part of the tutorial if I don’t touch upon event handling. You can listen for events by using bind. Events live in the jstree namespace and are named after the function that triggered them. Note that for some events you will need to bind before creating the instance.

Here is an example that displays a dialog when an item is selected in the tree:

$("#storySelector").bind("select_node.jstree", function(event, data) {
    alert($(data.args[0]).text());
}).jstree({
    ...
});

Conclusion

As you can see from the examples above, jsTree is pretty easy to use and configure. We have only scratched the surface with this tutorial, and there is much more to it than the basic operations I’ve covered here, but this should get you off to a good start. I would suggest reading the documentation AND reading up on forums and blogs, as I have found the documentation to be pretty stale. Let me know if there is any particular functionality you want me to cover next and I’ll do my best to do so in future parts to this guide. Until next time!

VN:F [1.9.11_1134]
Rating: 4.8/5 (61 votes cast)
Posted in jsTree at May 3rd, 2011. 22 Comments.

Clear a Google Chrome Extension’s HTML5 localStorage Data

I’ve been pretty busy lately both at work and in my personal life, so it’s been a while since I last blogged, but I am planning to write an article or two on the topic of writing extension for Google Chrome. In the meantime, here’s a quick tip to feed your appetite.

I recently had to wipe out the localStorage for one of the Chrome extensions I was working on. It turned out it’s quite easy, and you can do that for any extension you have installed or uninstalled: go to the settings menu > Tools > Extensions and look up the ID of the extension you want to clear the data for:

Close all Chrome windows, go to your Chrome installation directory > User Data > Default > Local Storage, locate the corresponding .localstorage file and delete it.

That’s it! FYI, there was an issue logged for that, here, but it’s marked as WontFix for the time being.

VN:F [1.9.11_1134]
Rating: 0.0/5 (0 votes cast)
Posted in Chrome Extensions at April 20th, 2011. 2 Comments.

Computer Vision – Face Detection in Java with OpenCV using JavaCV

I stumbled upon a few libraries that enable us to put some artificial intelligence goodness right into our Java applications. One such library is OpenCV. While I’ve read about it in a few occasions I had not really explored it myself – until about a week ago. OpenCV stands for Open Source Computer Vision and has a catalog of functions that incorporate over 500 algorithms for real time computer vision and image processing. It was originally started by Intel back in the late 90s and is currently released under the open source BSD license. While it is mainly written in C, it has been ported on Python, Java, and other languages which has allowed it to gain more ground. In Java, it is available through JavaCV, which is a wrapper that calls the native functions.

Let’s switch gears and look at a simple example… But first we have to set up a few prerequisites. I am running it under Windows 7, but it is also available under Mac and Linux. Here is what we’ll need to get it up and running:

1. Install the OpenCV distribution (I installed the 2.1 binary distribution for Windows).
2. Make sure that the OpenCV installation folder is in your PATH.
3. Download the Java Native Access library (JNA), which allows JavaCV to call the native functions.
4. Put JNA and JavaCV in your classpath.
5. Try the following code:

import static name.audet.samuel.javacv.jna.cv.CV_BGR2GRAY;
import static name.audet.samuel.javacv.jna.cv.cvCvtColor;
import static name.audet.samuel.javacv.jna.cv.cvHaarDetectObjects;
import static name.audet.samuel.javacv.jna.cxcore.CV_AA;
import static name.audet.samuel.javacv.jna.cxcore.IPL_DEPTH_8U;
import static name.audet.samuel.javacv.jna.cxcore.cvGetSeqElem;
import static name.audet.samuel.javacv.jna.cxcore.cvLoad;
import static name.audet.samuel.javacv.jna.cxcore.cvPoint;
import static name.audet.samuel.javacv.jna.cxcore.cvRectangle;
import static name.audet.samuel.javacv.jna.highgui.cvLoadImage;
import static name.audet.samuel.javacv.jna.highgui.cvSaveImage;
import name.audet.samuel.javacv.JavaCvErrorCallback;
import name.audet.samuel.javacv.jna.cv.CvHaarClassifierCascade;
import name.audet.samuel.javacv.jna.cxcore.CvMemStorage;
import name.audet.samuel.javacv.jna.cxcore.CvRect;
import name.audet.samuel.javacv.jna.cxcore.CvScalar;
import name.audet.samuel.javacv.jna.cxcore.CvSeq;
import name.audet.samuel.javacv.jna.cxcore.IplImage;

public class FaceDetection {

  // The cascade definition to be used for detection.
  private static final String CASCADE_FILE = "haarcascade_frontalface_alt.xml";

  public static void main(String[] args) throws Exception {
    // This will redirect the OpenCV errors to the Java console to give you
    // feedback about any problems that may occur.
    new JavaCvErrorCallback().redirectError();

    // Load the original image.
    IplImage originalImage = cvLoadImage(args[0], 1);

    // We need a grayscale image in order to do the recognition, so we
    // create a new image of the same size as the original one.
    IplImage grayImage = IplImage.create(originalImage.width,
    originalImage.height, IPL_DEPTH_8U, 1);

    // We convert the original image to grayscale.
    cvCvtColor(originalImage, grayImage, CV_BGR2GRAY);

    CvMemStorage storage = CvMemStorage.create();

    // We instantiate a classifier cascade to be used for detection, using the cascade definition.
    CvHaarClassifierCascade cascade = new CvHaarClassifierCascade(
    cvLoad(CASCADE_FILE));

    // We detect the faces.
    CvSeq faces = cvHaarDetectObjects(grayImage, cascade, storage, 1.1, 1, 0);

    //We iterate over the discovered faces and draw yellow rectangles around them.
    for (int i = 0; i < faces.total; i++) {
      CvRect r = new CvRect(cvGetSeqElem(faces, i));
      cvRectangle(originalImage, cvPoint(r.x, r.y),
      cvPoint(r.x + r.width, r.y + r.height), CvScalar.YELLOW, 1, CV_AA, 0);
    }

    // Save the image to a new file.
    cvSaveImage(args[1], originalImage);
  }
}

A few things to note… The cascade files are located in /data/haarcascades in your OpenCV installation folder. If you get OpenCV errors that cause it to crash, you may have to compile OpenCV without SSE, per the following note by Samuel, the creator of JavaCV:

“OpenCV might crash if it has been compiled with SSE instructions. This is known to occur on 32-bit x86 CPUs when the SSE calling conventions of the compiler used to build the Java implementation differ from the one used to compile OpenCV. The AMD64 architecture appears unaffected. A workaround may be included in a future version of JNA, but for the moment, please be advised.”

I was able to use 2.1, but 2.0 had to be recompiled.

And here are the results:

The original image

The image with the detected faces

As you can see, it recognized almost all faces. You can probably get it to recognize all if you tweak the code a little, notably the cvHaarDetectObjects function call. I’ve tried it with other pictures too, and it performs really well! There is an OpenCV reference here. It is for C++, but it should be pretty clear to understand and apply to JavaCV. Also make sure to check the project’s site for more examples and open issues.

As always, all questions or comments are welcome!

VN:F [1.9.11_1134]
Rating: 4.8/5 (12 votes cast)
Posted in Artificial Intelligence at September 23rd, 2010. 19 Comments.

7 New Features in Eclipse Helios (3.6) That Will Save You Time

I recently upgraded to Eclipse Helios (3.6) from Galileo (3.5). I was reluctant to upgrade at first as the new features introduced in the Java development tools and the PDE did not catch my attention as something major or groundbreaking. However, now that I have used Helios for a month or so, there are a few things that I like and that save me time, so I thought I’d share those with you:

1. Breakpoints: The breakpoints view now includes the breakpoint configurations, so you no longer have to right-click, select Properties to define things like hit count, mark the breakpoint as conditional or add breakpoint conditions. Now it’s all available right at the bottom of the view!

2. Improved quickfix: You can now fix several occurences of the same problem in the problem hover. This saves you from scrolling through the code editor to fix all instances of the same problem.

3. Easily import missing dependencies: The quickfix hover now offers to search repositories for a missing imported package, and have the dependency that is supplying it added to your target platform!

4. Search repositories for a dependency: You can now search repositories for dependenies and automatically add them to your current target platform. To access this feature, hit Ctrl+Shift+Alt+A and start typing the name of a bundle, feature, or package.

5. Export the target platform: You can now export the contents of your current target platform, which will copy all features and plug-ins that are part of it to a directory specified by you. To access this wizard, go to File -> Export -> Plug-in Development -> Target definition.

6. Improved Java search maintenance: Java search operations are now much easier to keep in sync with your target platform. If you go to Window -> Preferences ->Plug-in Development, and check the “Include all plug-ins from target in Java search” option, you will no longer need to manually add all plug-ins to your target every time something changes, or maintain a project with all plug-ins from your target to make searching possible. All of that is taken care of by Eclipse behind the scenes.

7. View host OSGi console: You can now view the running Eclipse instance’s console by selecting “Host OSGi Console” in your Console view. No more restarting Eclipse with -console flag. The option is readily available to you whenever you need it!

These are some of the features that I really like in Helios. While they are not ground breaking by any means, they are likely to save you time, so give them a try. If you have anything to add, please do so in the comments section.

To download Eclipse, go to the Eclipse download center.
To learn more about the Helios release, see demos and more, go to the Helios welcome page.
To see the web help that includes an overview of all new features in the Helios release, go to the Helios help center.

VN:F [1.9.11_1134]
Rating: 5.0/5 (1 vote cast)
Posted in Eclipse at September 17th, 2010. 1 Comment.

Writing Microsoft Word Documents in Java With Apache POI (Part 2 – Creating Tables)

Make sure to check part one of this series for a general overview of Apache POI and to learn how to write a new document, add paragraphs to it, and apply styling to their contents. In this part I will show you how to create tables.

Tables

Creating tables with Apache POI is really easy and intuitive, so I will jump right into an example. One thing to keep in mind is that when a new XWPFTable is added to a XWPFDocument, it is initialized with one column and one row.

public class CreateTablesWithPOI {

    public static void main(String[] args) {
        XWPFDocument document = new XWPFDocument();

        // New 2x2 table
        XWPFTable tableOne = document.createTable();
        XWPFTableRow tableOneRowOne = tableOne.getRow(0);
        tableOneRowOne.getCell(0).setText("Hello");
        tableOneRowOne.addNewTableCell().setText("World");

        XWPFTableRow tableOneRowTwo = tableOne.createRow();
        tableOneRowTwo.getCell(0).setText("This is");
        tableOneRowTwo.getCell(1).setText("a table");

        //Add a break between the tables
        document.createParagraph().createRun().addBreak();

        // New 3x3 table
        XWPFTable tableTwo = document.createTable();
        XWPFTableRow tableTwoRowOne = tableTwo.getRow(0);
        tableTwoRowOne.getCell(0).setText("col one, row one");
        tableTwoRowOne.addNewTableCell().setText("col two, row one");
        tableTwoRowOne.addNewTableCell().setText("col three, row one");

        XWPFTableRow tableTwoRowTwo = tableTwo.createRow();
        tableTwoRowTwo.getCell(0).setText("col one, row two");
        tableTwoRowTwo.getCell(1).setText("col two, row two");
        tableTwoRowTwo.getCell(2).setText("col three, row two");

        XWPFTableRow tableTwoRowThree = tableTwo.createRow();
        tableTwoRowThree.getCell(0).setText("col one, row three");
        tableTwoRowThree.getCell(1).setText("col two, row three");
        tableTwoRowThree.getCell(2).setText("col three, row three");

        FileOutputStream outStream = null;
        try {
            outStream = new FileOutputStream(args[0]);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        try {
            document.write(outStream);
            outStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

The result:

As you can see from this example, creating tables with POI is a simple task. If you have questions, post them in the comments section.

VN:F [1.9.11_1134]
Rating: 4.6/5 (18 votes cast)
Posted in Apache POI at September 2nd, 2010. 32 Comments.

Writing Microsoft Word Documents in Java With Apache POI (Part 1 – Writing Paragraphs)

Apache POI and OOXML

Apache POI (which stands for “Poor Obfuscation Implementation”) is a collection of APIs for manipulating various file types in Java, most notably those based on the Open Office standards (OOXML) and the old MS OLE2 ones  – doc, xls, ppt, etc). Keep in mind that while POI offers functionality for most (simpler) use cases, it may be lacking advanced functionality, especially when it comes to editing documents. I successfully used it for a small side project at work that involved implementing a simple application that generates docx files from a template. I found that the latest stable release at the time – 3.6 – was lacking the functionality I needed, so I ended up using 3.7-beta2 and implementing some of the functionality by manipulating the underlying XML myself. While there are some examples out there, I couldn’t find a lot on reading and editing Word documents and had to rely on the documentation that is also far from perfect. I am planning to dedicate several blog posts to POI and go over some of the goodies it offers and come up with simple examples that will hopefully demystify it a little bit.

I will focus on the Open Office file types rather than the old OLE2. It is worth mentioning that I had problems opening OLE2 Word documents with MS Word 2010, that were generated by POI 3.6, so I resorted to writing docx files. OOXML is an open file standard developed by Microsoft. It stores data in XML files that are zipped up in a package. Microsoft started using OOXML as the default format in MS Office 2007. You can take verify by renaming a docx file (or any OOXML-based file, for that matter) and changing its extension to zip. If you want to learn more about Apache POI, visit the project website. To learn more about OOXML, just Google it.

Writing a Word file using Apache POI

Let’s shift gears and start with Word files. This is definitely not the strongest side of POI, but will probably be suitable for most basic needs. What became clear to me through my experience with POI, which is rather limited, is that it’s better at reading these files and is limited when it comes to writing them. After all, POI is an open source project, so if you need something that is missing, you can implement it and submit a patch, or log a request for it to be added.

Lets take a look at a very simple example that writes out a simple docx file:

public class CreateDocumentFromScratch {

    public static void main(String[] args) {
        XWPFDocument document = new XWPFDocument();

        XWPFParagraph paragraphOne = document.createParagraph();
        XWPFRun paragraphOneRunOne = paragraphOne.createRun();
        paragraphOneRunOne.setText("Hello world! This is paragraph one!");
        XWPFRun paragraphOneRunTwo = paragraphOne.createRun();
        paragraphOneRunTwo.setText(" More text in paragraph one...");

        XWPFParagraph paragraphTwo = document.createParagraph();
        XWPFRun paragraphTwoRunOne = paragraphTwo.createRun();
        paragraphTwoRunOne.setText("And this is paragraph two.");

        FileOutputStream outStream = null;
        try {
            outStream = new FileOutputStream(args[0]);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        try {
            document.write(outStream);
            outStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

From our simple example above you will notice that we are creating a document, which contains paragraphs, which contain “text runs”. As you may have guessed by now, text runs are blocks of text that shares similar features, such a font, style, etc.

Let’s explore styling in a little more details:

public class CreateDocumentFromScratch {

    public static void main(String[] args) {
        XWPFDocument document = new XWPFDocument();

        XWPFParagraph paragraphOne = document.createParagraph();
        paragraphOne.setAlignment(ParagraphAlignment.CENTER);
        paragraphOne.setBorderBottom(Borders.SINGLE);
        paragraphOne.setBorderTop(Borders.SINGLE);
        paragraphOne.setBorderRight(Borders.SINGLE);
        paragraphOne.setBorderLeft(Borders.SINGLE);
        paragraphOne.setBorderBetween(Borders.SINGLE);

        XWPFRun paragraphOneRunOne = paragraphOne.createRun();
        paragraphOneRunOne.setBold(true);
        paragraphOneRunOne.setItalic(true);
        paragraphOneRunOne.setText("Hello world! This is paragraph one!");
        paragraphOneRunOne.addBreak();

        XWPFRun paragraphOneRunTwo = paragraphOne.createRun();
        paragraphOneRunTwo.setText("Run two!");
        paragraphOneRunTwo.setTextPosition(100);

        XWPFRun paragraphOneRunThree = paragraphOne.createRun();
        paragraphOneRunThree.setStrike(true);
        paragraphOneRunThree.setFontSize(20);
        paragraphOneRunThree.setSubscript(VerticalAlign.SUBSCRIPT);
        paragraphOneRunThree.setText(" More text in paragraph one...");

        XWPFParagraph paragraphTwo = document.createParagraph();
        paragraphTwo.setAlignment(ParagraphAlignment.DISTRIBUTE);
        paragraphTwo.setIndentationRight(200);
        XWPFRun paragraphTwoRunOne = paragraphTwo.createRun();
        paragraphTwoRunOne.setText("And this is paragraph two.");

        FileOutputStream outStream = null;
        try {
            outStream = new FileOutputStream(args[0]);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        try {
            document.write(outStream);
            outStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

The result:

The code is self-explanatory, so I will not go into a lot of details on what each line is doing, but it should give you a good idea about what POI is capable of. You can explore the methods on XWPFParagraph and XWPFRun to learn more.

This should be a good start. In part two of this series, I will show you how to create tables in a Word document next time. Until then, post questions in the comments section.

VN:F [1.9.11_1134]
Rating: 5.0/5 (29 votes cast)
Posted in Apache POI at August 26th, 2010. 21 Comments.

More WordPress Plug-ins!

There are two more plug-ins that are worth mentioning here:

  • Google XML Sitemaps – This one helps search engines better index your blog. Pretty important stuff nowadays!
  • WP-DBManager – Awesome plug-in that helps managing the WordPress database. Allows you to optimize, repair, backup, restore your database , drop/empty tables and run selected queries. Probably the coolest feature is the automatic scheduling of backing up and optimizing of database, plus you get your whole database e-mailed to you every so often. One of my favorites for sure!
Google XML Sitemaps

VN:F [1.9.11_1134]
Rating: 0.0/5 (0 votes cast)
Posted in Wordpress at August 4th, 2010. No Comments.

WordPress

OK, so I’ve been obsessed with WordPress lately… I messed with it for the first time about 3 weeks ago. I must say it’s pretty easy to install, configure, and extend. Kudos to the community. There are some pretty cool plug-ins that are worth taking a look at:

  • Fixed Social Buttons – Those are the cool buttons at the top that let you post to your facebook, twitter, digg, etc.
  • Syntax Highlighter and Code Prettifier Plugin – I installed this one because I intend to post some code here… I’ll let you know if I’m impress when I give it a try.
  • WPtouch iPhone Theme – This one recognizes when my blog is being viewed on a phone screen and formats it to fit better. I’m not exactly sure why there’s an iPhone in its name, it looks pretty good on my Android phone. I guess they’re catering to the Apple fanboys…
  • NextGEN Gallery – This looks like a promising photo gallery. I haven’t tried it myself yet, but it’s pretty fancy from what I’ve seen on other blogs.

I will likely post some more in the next few days as I continue my WordPress exploration… What plug-ins would you suggest?

VN:F [1.9.11_1134]
Rating: 0.0/5 (0 votes cast)
Posted in Wordpress at July 21st, 2010. 4 Comments.

Welcome

Welcome to my blog! I’m not sure how much time I can dedicate here, but I will try to write new tutorial/article on various technical topics every once in a while. Most of these will be geared toward beginners or will build upon material covered in previous posts. If you have any suggestions or requests, please share them here.

VN:F [1.9.11_1134]
Rating: 5.0/5 (2 votes cast)
Posted in Uncategorized at July 20th, 2010. No Comments.

Rss Feed Tweeter button Facebook button Digg button Stumbleupon button