Friday, March 4, 2011

I don't Git it!

I just don't! Now, maybe I'm just getting crotchety in my old age or something, but Git is all the rage. Maybe an old dog just can't learn new tricks. But I'm truly getting to the point that if I have to go to the command line for any reason, this just tells me the tooling just isn't mature yet.

Now, I've done my fair share of Linux/BSD development. I know csh and rsh and so on. I can hack with the best of them. But I also know that for the money I get for my time, I shouldn't be messing around with apt, much less yum. I shouldn't have to play 'locate' games or do find . -name '*' -exec grep -Hi 'find this in a file somewhere' \;. The tooling should be mature, and that means GUI.

Yes! I know! People may bash hit me for saying something so noob, but let's face it, if I truly understand what's going on under the scenes then what's wrong with being able to click twice instead of typing a few hundred lines shell commands? That's what I call productivity.

Secondly, if it doesn't play nice in Windows... all the more reason it just ain't going to fly.

Yes, I could install Ubuntu and do all my development on my laptop there. Or even in OS X on some 'so-light-it-by-all-rights-shouldn't-exist-in-Euclidian-space book'. And yes, I could have all my office tools running either virtually or not even us Microsoft products to handle email, documents, drawings... etc.

But why? I don't have time to mess, I don't have time to work around all the problems or install updates every few days, or find out why the update created incompatibilities in four other packages...

I want/need all my tools to Just Work! And I'm not going to spend my time and resources messing around on *nix just because it's cool, or all the hacker dudes are doing it. I'm NOT going to get an iMac just because it runs on BSD under the covers. I'm going to get the system, OS and tools that get the work done!

So, back to Git:

  • There are no good, complete tools for Windows with a GUI, period. 
  • In the *nix world, everyone uses the CLI for git. 
  • The most recommended client, for Windows, to do command line Git, is msysGit.
  • msysGit is a compilation of the git code using mingw.
  • The newest version is from 2004.
  • JGit is the back-end for the best Windows compatible GUI client that plugs into Eclipse, EGit. (eee-git!)
  • JGit does not come with batch files that support simple git syntax... it does come with .sh(ell) scripts if needed. Why?

So... I don't Git it. There's simply no point. What a waste.

Tuesday, July 6, 2010

Real Examples: OSGi Classloader Workaround

So, maybe my last post was a little too nebulous to get the gist. So I'm now going to give a solid example.

In this example we are going to use Substance Look And Feel within a JFrame that is also an OSGi component.

Here's the setup (again, I use iPojo for all my components/services within the Felix implementation of OSGi):

Here's a @Component JFrame. It's a little different than the standard main() created by Visual Editor within Eclipse or Jigloo. Instead of calling initialize() where I build all the visual components of my JFrame I call start() which is also the entry to building when I'm running within OSGi.


@Component
public class Example extends JFrame {
 public Example() {
  super();
 }

 public Example(BundleContext bundleContext) {
  super();
  context = bundleContext;
 }

 public static void main(String[] args) {

  SwingUtilities.invokeLater(new Runnable() {
   public void run() {
    Example thisClass = new Example();
    thisClass.start();
    thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    thisClass.setVisible(true);
   }
  });
 }
...

The start() method looks pretty standard now. I really don't want to shut down Felix or anything when this component is stopped, so I set the close operation appropriately. When the component is stopped I just want to get rid of the JFrame.


 public void start() {
  try {
   UIManager
     .setLookAndFeel( "org.jvnet.substance.skin.SubstanceMistAquaLookAndFeel");
   SwingUtilities.updateComponentTreeUI(this);
  } catch (Exception e) {
   System.out.println("Substance Mist Aqua failed to initialize...");
   e.printStackTrace();
  }
  initialize();
  setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  setVisible(true);
 }

 @Invalidate
 public void stop() {
  setVisible(false);
  dispose();
 }


Now for the secret sauce. This comes directly from my previous post. start() is now called from the @Validate function. Note that the method is called osgiValidate() instead of something like validate() as it is already used within java.awt.Container which JFrame inherits from four levels deep. We don't want to override that function.

The @Validate function gets the OsgiEnvironmentClassLoader and calls start().



 protected OsgiEnvironmentClassLoader getOsgiEnironmentClassLoader(
   BundleContext bundleContext) {
  return new OsgiEnvironmentClassLoader(bundleContext, Thread
    .currentThread().getContextClassLoader(), bundleContext
    .getBundle());
 }

 @Validate
 public void osgiValidate() {
  java.awt.EventQueue.invokeLater(new Runnable() {
   @Override
   public void run() {
    new ClassLoaderContext(getOsgiEnironmentClassLoader(context))
      .execute(new ClassLoaderContextCallback() {
       public void doAction() {
        start();
       }
      });
   }
  });

 }


In my case this produces something like this:


If you want the window decorated as well then you need to add a little static initializer:


 static {
  JFrame.setDefaultLookAndFeelDecorated(true);
  JDialog.setDefaultLookAndFeelDecorated(true);
 }

Then you get this:


As a little side note, if you wish to shutdown your entire OSGi instance from your swing UI you can use the BundleContext:


 Bundle bundle = context.getBundle(0);
 bundle.stop();

Some people may ask, "Why use this classloader work around instead of setting the org.osgi.framework.bootdelegation to include all the needed classes?" My answer... I'm not really sure that this way here is any more correct. They are both work-arounds for cases where 3rd party libraries are loading dependencies under the scenes... against what OSGi is trying to accomplish. I like this way because it feels better, not because it is better.

Tuesday, June 1, 2010

Cheating In OSGi

Note: Thanks to http://www.dynamicjava.org/ for making a whole slew of things OSGi ready, or at least OSGi usable.

From time to time I'm confronted with incompatibilities within OSGi with older libraries and methodologies. The classic example of this is using JDBC libraries directly. The standard method of loading a driver is through the class loader. This simply doesn't work within OSGi the way you think it does. Even if you use the Dynamic-ImportPackage header within your bundle description it's not unusual for your bundle not to be able to find the class.

Another example of this is with using 3rd party libraries like Oracle's optic and application client libraries against J2EE application servers. JaxB usage also has this issue.

So, here's a quick work around that I use. Note that I use the Felix OSGi implementation with iPOJO. However, this should work in any context.

First, get the BundleContext for your component. Within iPojo, it's as simple as creating a constructor where the BundleContext is passed in.


@Component
public class TestComponent {
protected BundleContext bundleContext;
  public TestComponent( BundleContext bundleContext) {
    this.bundleContext = bundleContext;
  }
}

Next I add a simple helper function.

 protected OsgiEnvironmentClassLoader getOsgiEnironmentClassLoader(BundleContext bundleContext) {
  return new OsgiEnvironmentClassLoader(
    bundleContext,
    Thread.currentThread().getContextClassLoader(),
    bundleContext.getBundle());
 }

Then, wherever I need to do something outside of the standard bundle's class loader:

new ClassLoaderContext(getOsgiEnironmentClassLoader(bundleContext)).execute(
  new ClassLoaderContextCallback() {
   public void doAction() {
    /* do something interesting here */
   }
 });