Archive for March, 2010

First Impressions, Google Wave

March 29, 2010

About two weeks ago I was excited to get a Google Wave preview account and wanted to give some thoughts on what’s good/bad etc. In case you haven’t heard of what Wave is all about take a look here. In a couple words though basically they are rethinking email now that we have all became such different users of the internet.

First off the good!

  • Wave Threads – Basically a ‘wave’ is analogous to an email but can do much more with a ‘wave’. They did a great job and have fixed near all issues with communicating via modern day email. You start it and address it to several users put an initial message attachment or even more. At this point nothing more than a normal email but where it leaves email in the dust is when people respond to your message. With a ‘wave’ you get a thread which allows you to inline reply, reply privately to just a single person, reply the sequence of replies, and again lots more. With a ‘wave’ you don’t have this long list of replies to topics in previous emails separated by email meta data which sometimes can make email’s almost un-followable.
  • Extensions – Wave provides interesting ability to leverage special in message extras such as ‘Yes/No/Maybe’ polling. This provides new abilities to exchange ideas like outlining a area on a map your interested in moving to via using the Google Maps extension. Because its pure now it seems like a great way to allow people to extend ‘wave’ quickly however I could see it turning into a new way to hack a computer.

The Bad

  • It’s slows down everything! Full disclosure on this one. I do most my computing on a ebook which isn’t the beefiest machine in the world but COME ON! If I run it with Chrome it can have a noticeable effect on my system. I do notice on other machines the effect isn’t bad (mainly multi core processors), however I hope its more about being a ‘preview’ still and not ready for prime time. From the presentations on wave I know they use GWT (Google Web Toolkit) which is infamous for creating more javascript then you thought was necessary, not sure if thats a function of that or what.
  • No integration with legacy email (yet). I would just think that the first thing out of the gate if you were serious about doing something made to be a peer to email and potentially a replacement would be to provide legacy email interaction functionality. Maybe though they don’t intend on integrating with email at all, I would guess not though. I know I’m probably just too early on this but its difficult to get a feel for how this would work out in real life with other people working on real email. I’m sure that email won’t just go away and the questions I have would be does one person using email with it ruin it or what?

From the quick look I have been able to do so far its a great idea and well executed overall so far. The big issue is performance to me and understanding how it fits in with current day email. All which are fixable. Keep an eye on Google Wave I think it has a way to go but could change how we communicate online.

OSGi Enabled War

March 25, 2010

If you have ever taken a look at OSGi and thought that it wasn’t going to fit into any of your web applications because of your application server, you may not be out of luck after all. Apache’s Felix project has made a relatively straight forward way of creating an OSGi enabled war file that fits within most applications servers. I’ll go over the basic process and point you to important examples on Felix’s site.

You’ll need to create two projects.

  1. A Bridge War project – this project will manage passing requests back to OSGi (Felix) via a ProxyServlet.
  2. OSGi bundle with Servlet registered – If you already have this skip it but we’ll hit way to register servlets with OSGi.

We’ll start with the Bridge war. You can see a working example on Felix’s site here.

Bridge Dependencies

<dependency>
     <groupId>javax.servlet</groupId>
     <artifactId>servlet-api</artifactId>
     <version>2.5</version>
     <scope>provided</scope>
</dependency>
<dependency>
     <groupId>org.osgi</groupId>
     <artifactId>org.osgi.compendium</artifactId>
     <version>4.0.0</version>
</dependency>
<dependency>
     <groupId>org.apache.felix</groupId>
     <artifactId>org.apache.felix.framework</artifactId>
     <version>1.8.1</version>
</dependency>
<dependency>
     <groupId>org.apache.felix</groupId>
     <artifactId>org.apache.felix.http.proxy</artifactId>
     <version>2.0.4</version>
</dependency>
<dependency>
     <groupId>org.apache.felix</groupId>
     <artifactId>org.apache.felix.http.bridge</artifactId>
     <version>2.0.4</version>
     <scope>provided</scope>
</dependency>
<dependency>
     <groupId>org.apache.felix</groupId>
     <artifactId>org.apache.felix.webconsole</artifactId>
     <version>1.2.8</version>
     <scope>provided</scope>
</dependency>

Special Dependency Handling

Two dependencies mentioned are actually OSGi bundles and need to get copied to the place you’ll load bundles from. Those two dependencies are…

  1. org.apache.felix.webconsole
  2. org.apache.felix.http.bridge

Here an sample of how the example how in maven2 you can get those dependencies copied to a special spot

<plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-dependency-plugin</artifactId>
     <executions>
          <execution>
               <id>copy-bundles</id>
               <goals>
                    <goal>copy-dependencies</goal>
               </goals>
               <configuration>
                    <includeArtifactIds>
                         org.apache.felix.http.bridge,org.apache.felix.webconsole
                    </includeArtifactIds>
                    <stripVersion>true</stripVersion>
                    <outputDirectory>
                         PLACE TO PACKAGE OR LOAD BUNDLES
                    </outputDirectory>
               </configuration>
          </execution>
     </executions>
</plugin>

Ok now that we have the dependencies out of the way here is the coding that needs to be done.

Step One – Create a start up hook to initialize Felix

The simplest place for this is a ServletContextListner.contextInitialized but it just needs to be a place which is guaranteed to be executed before your webapp tries to initialize the ProxyServlet which you’ll configure in step 3. Here is example code of how to initialize Felix.

Properties props = new Properties();
//Load a framework.properties from somewhere accessible to your application server.
//We'll just use the current threads context classloader as an example. Adjust to your situation.
props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("/framework.properties"));
HashMap<String, Object> map = new HashMap<String, Object>();
for (Object key : props.keySet()) {
map.put(key.toString(), props.get(key));
}
BundleActivator activator = ...//We will talk about this in the next step.
map.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, Arrays.asList(activator));
Felix container = new Felix(map);
//You will probably want to keep a reference to keep the container around to
//be able to stop. Depends on where you binding the lifecycle of Felix to.
container.start();

Step Two – Create a class to load your OSGi Bundles for the war

Here we’ll need to create something that implements BundleActivator for the bridge war. We want to create bundle activator that finds and installs bundles for the war file. I’ll provide one that simply looks on the file system at an external location for *.jar files and assumes they are all OSGi bundles. Check out Felix’s example to see how to load bundles internal to the war packaging.

public final class WebActivator
implements BundleActivator
{
public void start(BundleContext context)
throws Exception
{
ArrayList<Bundle> installed = new ArrayList<Bundle>();
File bundleDir = new File("/path/to/bundles");
File[] bundles = bundleDir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".jar");
}
});
for (File file : bundles) {
//Load the bundle. file.toURI().toURL()... can probably be done in an easier way not the  point here though.
Bundle bundle = context.installBundle(file.toURI().toURL().toExternalForm());
installed.add(bundle);
}
for (Bundle bundle : installed) {
bundle.start();
}
}
public void stop(BundleContext context)
throws Exception
{
//Nothing necessary
}
}

Step Three – Update your web.xml with ProxyServlet

Add the ProxyServlet mapping for the Felix bridge. Below is an example which forwards everything to the proxy servlet.

<servlet>
<servlet-name>proxy</servlet-name>
<servlet-class>org.apache.felix.http.proxy.ProxyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>proxy</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

Step Four – Create a bundle with a servlet in it.

Now you need to create an actual bundle project. I’ll assume you have created a bundle project before, if not check out Felix’s documentation and tutorials. I’ll just point out the basics of how to register your servlet in your new or existing BundleActivator to receive requests. Also I’ll provide the additional dependencies that are needed for you bundle.

Additional Dependencies for a bundle project

<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.http.api</artifactId>
<version>2.0.4</version>
</dependency>

Activator Example

public final class Activator
implements BundleActivator
{
private ServiceTracker tracker;
private CustonActionServlet servlet = new CustonActionServlet();
public void start(BundleContext context)
throws Exception
{
this.tracker = new ServiceTracker(context, ExtHttpService.class.getName(), null)
{
@Override
public Object addingService(ServiceReference ref)
{
Object service =  super.addingService(ref);
serviceAdded((ExtHttpService)service);
try {
//You can map the servlet to any context. This will actually map it to all requests.
((ExtHttpService)service).registerServlet("/", servlet, null, null);
} catch (Exception e) {
e.printStackTrace();
}
return service;
}
@Override
public void removedService(ServiceReference ref, Object service)
{
((ExtHttpService)service).unregisterServlet(servlet);
super.removedService(ref, service);
}
};
this.tracker.open();
}
public void stop(BundleContext context)
throws Exception
{
this.tracker.close();
}
}

If this isn’t making sense take a look Felix’s Example HTTP Servlet and Filter Bundle. This bundle shows also how Felix supports HTTP Filters as well.

Step Five: Build and Run!

Now you have everything in place you simply need to build your bundle then add it to the bundles location where your webapp will be looking for it. Then build your bridge webapp and run it with your favorite appserver.

Additional Notes and Thoughts

First off this is only useful for scenarios where using an application server that doesn’t provide some kind of OSGi integration out of the box. But if you are in a non-OSGi enabled application server you could use this pattern and start Felix in a central location available to all web applications and start integrating services across all applications which where the power in this would be. The trick to this is getting an entire legacy webapp tucked behind the servlet bridge which seems simple enough but there are lots of little issues here and there to work out. I’m working on a porting over several applications using different frameworks, I’ll put up updates if they turn out positive.

Trading Clicks for Keystrokes

March 22, 2010

There is a saying out there which goes something like ‘Reducing the amount of clicks to do an action is good’. I know that’s a gross paraphrase and I’m sure you could find exceptions to the rule, but generally I prescribe to this idea of reducing clicks. In many cases though there is only so much click reduction you can do. An alternative to think about though when you think you have reached your limit on reducing clicks is to explorer some non-standard browser functionality with hooking into keystroke events.

Providing short cuts to search functionality, help functionality, or maybe an ‘alt+tab’ type functionality to allow the user to shift through the previously visited pages, are all interesting ways to integrate keystroke events into a webapp. In then end most of the integrations of the keystrokes will GREATLY very from application to application. So I’ll show you a quick sample of hooking in with jQuery and then let your mind run free.

Here is an example of listening for a user who hits ‘Ctrl’ and ‘F’ at the same time (or in sequence) using jQuery. I wanted to make sure to provide something to used a two key combination because you probably don’t want a user to accidentally type ‘F’ and cause an action or interface to popup.

<script src=”http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js&#8221; type=”text/javascript”/>
<script>
var wasControlPressed = false;
$(document).ready(function(){
$(window).keydown(function (event) {
if(event.keyCode == 17) {
wasControlPressed = true;
} else {
if(event.keyCode == 70 && wasControlPressed) {
//Allow this path if ctrl was pressed.
alert(‘This sequence was met’);
} else {
//Reset because the sequence wasn’t met.
wasControlPressed = false;
}
}
});
});
</script>

I only tested this in Chrome and Firefox. I presume jQuery will take care of IE as well. Entirely probable that you’ll need to worry about ‘charCode’ there instead of ‘keyCode’ if jQuery doesn’t take care of it for you.  Here is a good site in case you need details on that http://www.quirksmode.org/js/keys.html.

Hello world!

March 20, 2010

Welcome! I’m sure most people would delete the default ‘Hello World’ WordPress post but the title fits too well for this blog so I made sure to keep it around.

This is my blog ‘The Heap Dump’ where I’ll be providing highlights about Software development, web development, and system admin stuff which I encounter daily.

The ‘I’ here is Chris Upton. I’m a IT Consultant who has worked in Software Development for years. Right now I focus specifically on web related software, so don’t be surprised to see that theme throughout.

I’ll leave you with a comical view of web tech, check out one of my favorite Strong Bad email’s from a long time ago -> Check it out