Wednesday, February 29, 2012

Upgrading Postgres Database to 9.1 Format After Upgrading to Fedora 16

After upgrading from Fedora 15 to Fedora 16, I noticed Postgres was no longer running, so I tried to start it up:
sudo systemctl status postgresql.service
This printed the error "Job failed. See system logs and 'systemctl status' for details." Inspecting /var/log/messages revealed:
Feb 29 12:51:39 jetengine postgresql-check-db-dir[4912]: An old version of the database format was found.
Feb 29 12:51:39 jetengine postgresql-check-db-dir[4912]: Use "postgresql-setup upgrade" to upgrade to version 9.1.
Feb 29 12:51:39 jetengine postgresql-check-db-dir[4912]: See /usr/share/doc/postgresql-9.1.2/README.rpm-dist for more information.
Feb 29 12:51:39 jetengine systemd[1]: postgresql.service: control process exited, code=exited status=1
Feb 29 12:51:39 jetengine systemd[1]: Unit postgresql.service entered failed state.
So I needed to upgrade to the new 9.1 format. I used the following command to check the current version of my database:
sudo cat /var/lib/pgsql/data/PG_VERSION
This returned "9.0".

To upgrade the database, I first needed to install the postgresql-upgrade package:

sudo yum install -y postgresql-upgrade
I then ran the following command to update the database:
sudo postgresql-setup upgrade
This command took a minute or two to complete. Once it was done, the database at /var/lib/pgsql/data/ was in 9.1 format, and the old 9.0 format database was saved to /var/lib/pgsql/data-old/ However, the upgrade tool did not copy over my old pg_hba.conf, so I had to do that myself:
sudo mv /var/lib/pgsql/data-old/pg_hba.conf  /var/lib/pgsql/data/pg_hba.conf
Now I was able to successfully start up Postgres 9.1:
sudo systemctl start postgresql.service

Friday, May 27, 2011

Making Links Work Right in a SmartGWT App on IE

The GUI of RHQ 4.0 and later is built upon SmartGWT. In many places in the SmartGWT app, we embedded raw HTML to render fragment links (e.g. #Inventory/Servers) to other places in the app. We used raw HTML, rather than widgets, for a few reasons:

  1. SmartGWT does not provide a link widget. GWT provides the HyperLink and InlineHyperLink widgets, but we try to avoid using non-SmartGWT widgets when possible to prevent layout issues or CSS issues caused by straying from the SmartGWT framework. A SmartGWT Label or HTMLFlow can be extended to simulate a link using a ClickHandler but it will not be rendered as an 'a' tag and so will not inherit the CSS styles used for 'a' tags and will not display the link's URL in the browser status bar when the user hovers over the link.
  2. Many of our links are inside ListGrid cells. There is no straightforward reliable way to embed arbitrary widgets in ListGrid cells. I tried using the mechanism http://www.smartclient.com/smartgwt/showcase/#grid_cell_widgets described here and encountered overflow and wrapping issues, which I was unable to overcome. The CellFormatter interface only supports returning a String, but that String can include HTML, so that's what we ended up using for cells that need to contain a link.
  3. For FormItems that need to contain links, CanvasItem can be extended in order to embed GWT HyperLink widgets, but using a StaticTextItem with HTML embedded in its value is more straightforward.
Unfortunately, we noticed that clicking on any of our raw HTML fragment links in IE caused a full page refresh, which is not at all desirable in a GWT app, which is intended to be pure AJAX. Further investigation revealed that this is a longstanding quirk (aka bug) in IE; rather than simply generating a history event for the URL with the updated fragment, it sends an unnecessary request for the URL to the server. If you use the GWT HyperLink widget, GWT uses some JavaScript fanciness involving iframes to circumvent the IE bug and make fragment links work properly. However, since we were using raw HTML for all the links in the RHQ GUI, this magic was not there for us. Converting all our HTML links would be a ton of work and was simply not a viable option for links in ListGrid cells for the reasons described above, so we needed to find a way to execute GWT's magic when any of our raw HTML links were clicked. The answer ended up being to add a native preview event handler that intercepts browser click events and executes the magic if the click was on one of our 'a' tags. We did this by making our EntryPoint class implement the GWT Event.NativePreviewHandler interface as follows:
    public void onPreviewNativeEvent(Event.NativePreviewEvent event) {
        if (SC.isIE() && event.getTypeInt() == Event.ONCLICK) {
            NativeEvent nativeEvent = event.getNativeEvent();
            EventTarget target = nativeEvent.getEventTarget();
            if (Element.is(target)) {
                Element element = Element.as(target);
                if ("a".equalsIgnoreCase(element.getTagName())) {
                    // make sure it's not a hyperlink that GWT already
                    // handles
                    if (element.getPropertyString("__listener") == null) {
                        String url = element.getAttribute("href");
                        String historyToken = getHistoryToken(url);
                        if (historyToken != null) {
                            GWT.log("Forcing History.newItem(\"" +
                                historyToken + "\")...");
                            History.newItem(historyToken);
                            nativeEvent.preventDefault();
                        }
                    }
                }
            }
        }
    }

    private static String getHistoryToken(String url) {
        String token;
        if (url.startsWith("#")) {
            token = url.substring(1);
        } else if (url.startsWith("/#")) {
            token = url.substring(2);
        } else if (url.contains(Location.getHost()) && url.indexOf('#') > 0) {
            token = url.substring(url.indexOf('#') + 1);
        } else {
            token = null;
        }
        return token;
    }
We then add the native preview handler at app load time by adding the following line to our EntryPoint class:
Event.addNativePreviewHandler(this);
This solution is working great. However, we still might eventually go back and switch over to using GWT HyperLinks, rather than raw HTML, in places where it is feasible, such as FormItems, since it is generally better to use widgets rather than raw HTML to keep things object-oriented and leave the generation of HTML, CSS, and JavaScript to the framework.

Setting Up IntelliJ IDEA on Fedora

JetBrains does not provide rpm's for IDEA, so setting it up on Fedora requires a bit of extra work. Here are the steps that I do.

Unzip the Distribution
# cd /opt
# tar -xzvf /path/to/ideaIC-10.5.tar.gz

This will create the directory /opt/idea-IC-107.105.

Create Symbolic Links
# cd /opt
# ln -sf /opt/idea-IC-107.105 /opt/idea
# ln -s /opt/idea/bin/idea.sh /usr/local/bin/idea

I overwrite the /opt/idea symlink each time I install a new version of IDEA. Creating the /usr/local/bin/idea symlink effectively adds idea to the system PATH. You'll only need to create this one the very first time you install IDEA.

Set JDK Environment Variable

idea.sh checks the IDEA_JDK, JDK_HOME and JAVA_HOME environment variables, in that order of preference, to determine the JVM it will use to run IDEA. Make sure one of these points to a JDK 6 installation. I am currently using JRockit, but the Sun JDK or OpenJDK will also work.

Update idea.vmoptions

The projects I work on are usually quite large, and my box is pretty beefy, so I always pump up the JVM's heap size and permgen size.
# cd /opt/idea/bin
# mv idea.vmoptions idea.vmoptions.orig
# cp /path/to/my/idea.vmoptions .

For reference, here's my idea.vmoptions file, though you will probably not want to use it verbatim:
-Xms1500M
-Xmx3000M
-XX:MaxPermSize=500M

Create a GNOME .desktop File

This will add an application launcher to the GNOME Applications menu. As root, create a file named idea.desktop in /usr/share/applications with the following contents:
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Name=IntelliJ IDEA
GenericName=Java IDE
Comment=IntelliJ IDEA is a code-centric IDE focused on developer productivity. The editor deeply understands your code and knows its way around the codebase, makes great suggestions right when you need them, and is always ready to help you shape your code.
Exec=idea
Icon=/opt/idea/bin/idea_CE128.png
Terminal=false
Type=Application
Categories=Development;IDE

If you wish to tweak this file at all, the syntax for .desktop files can be found here.

Tuesday, January 26, 2010

JD-GUI on 64-bit Fedora 12

I just setup JD-GUI, a Java decompiler, on my 64-bit Fedora 12 box. I went with JD-GUI, because, unlike JAD, it supports Java 5 and 6 class files and is actively maintained.

A 32-bit Linux binary can be downloaded from the JD-GUI homepage. The tar.gz file just contains a single binary executable. I installed it as follows:
tar -xzvf jd-gui-0.3.3.linux.i686.tar.gz 
sudo mv jd-gui /usr/local/bin
Since my box is 64-bit, I was missing a handful of 32-bit libraries on which JD-GUI depended. Fortunately, these were all available from the default Fedora yum repos and can be installed using the following command:
sudo yum install libcanberra-gtk2.i686 PackageKit-gtk-module.i686 gtk2-engines.i686
These are the packages for Fedora 12 or later. If you're on Fedora 11, suffix the package names with .i586, rather than .i686. For Fedora 10, use .i386 as the suffix.

If you're using GNOME as your desktop environment, you may also want to associate .class files with JD-GUI. To do so, open File Browser and find a .class file. Right-click on the class file and select Properties. Select the Open With tab, click the Add button, select "Use a custom command", enter "/usr/local/bin/jd-gui", and finally click the Add button. Now when you double-click on a .class file from the File Browser, it will open that file using JD-GUI.

Tuesday, October 14, 2008

Embedded Jopr - An Open Source Admin Console for JBossAS

Embedded Jopr (pronounced "jopper") is an exciting new open source project that has just been released by JBoss. In a nutshell, it's a web application that can be dropped into the deploy directory of a JBossAS 4.2.x instance to provide a user-friendly front end for administering the app server. Version 1.0 includes support for:
  • monitoring metrics for the server itself and for webapps
  • monitoring metrics and editing configurations for datasources, connection factories, JMS topics and queues, and the host JVM
  • creating and deleting datasources, connection factories, and JMS topics and queues
  • executing scripts that reside within the JBossAS bin directory

Under the hood, Embedded Jopr is based on the Jopr project, which is in turn based on the RHQ project. RHQ is an open source enterprise management infrastructure framework, which includes a simple yet full-featured API for writing management plugins for managing just about anything under the sun. RHQ also bundles a set of plugins for managing popular open source products such PostgreSQL and Apache Web Server. The Jopr project consists of the RHQ platform, along with a set of additional plugins for managing JBossAS and other JBoss projects - Hibernate, JBossWeb, etc.

To understand how Embedded Jopr leverages RHQ and Jopr, let's first take a step back and look at the architecture of Jopr. It consists of a single Server with multiple Agents reporting into it. There is one Agent running on each machine that is hosting applications to be discovered and managed by Jopr. Each Agent contains a Plugin Container that in turn contains plugins for each of the supported managed products. The Agent essentially wraps the Plugin Container in a standalone process that can communicate with the remote Jopr Server. The Server stores all data reported by the Agents in a central database and provides a web-based GUI for viewing and updating that data.

The goals of Embedded Jopr were considerably less complex than those of its older sibling Jopr. Embedded Jopr sought only to manage a single JBossAS instance. Because we did not need to manage multiple products running in separate OS processes, and because the JBossAS instance being managed was a Java-based application server, we could embed the Jopr Plugin Container inside an application deployed to the JBossAS instance itself - no need for a separate Agent process.

As for what type of application in which to embed the Plugin Container, we had a couple requirements:
  1. provide a way to bootstrap the embedded Plugin Container when the JBossAS instance starts up
  2. provide a web-based interface to the management data collected by the Plugin Container - real-time monitoring only

Since we only needed to provide real-time monitoring, there was no need to persist any of the collected management data, which meant we didn't require a database or Hibernate, EJB, etc. The Servlet spec provided the necessary APIs for running our bootstrap code at webapp deployment time, and JSF (which is bundled with JBossAS 4.2 and later) provided a nice framework for building a GUI. So the most sensible type of application in which to embed the Plugin Container was a webapp. We were also able to leverage Facelets, Seam, and RichFaces - extensions to JSF that allowed us to create a robust and maintainable web application.

Jopr includes RHQ plugins for managing a number of different products - JBossAS, Apache Web Server, PostgreSQL, Oracle, etc. Embedded Jopr did not need to include all of these plugins - it only needed the plugins required to manage JBossAS, its deployed services, and its host JVM. This allowed us to keep Embedded Jopr relatively lean (about 9 MB).

With such powerful foundational technologies, Embedded Jopr promises to soon become one of the nicest administration consoles out there. We hope to see lots of participation from the community, since this is one project that will greatly benefit all JBossAS users. The main goal for Embedded Jopr 1.1 is to add support for JBossAS 5.