Simple startup profiling of OSGi applications

October 18, 2013

Prompted by a colleague’s question about profiling the startup time of Apache Sling systems, I vaguely remembered writing something a while ago, but couldn’t find it immediately.

Funny how one’s memory works – it took me a while to find it again, but I did indeed write an OSGi events recorder + timeline utility in SLING-1109.

That utility has since moved to the Apache Felix webconsole events plugin bundle, which is included in the Sling launchpad and thus was right here under my eyes.

Here’s how you can use that webconsole plugin to get a simple timeline of an OSGi system’s startup:

  1. Install the org.apache.felix.webconsole.plugins.event bundle in an OSGi app where the Apache Felix Webconsole is active.
  2. Set that bundle to a low start level, say 1 or 2, so that it’s activated early and captures as much startup events as possible.
  3. Configure the events recorder at /system/console/configMgr/org.apache.felix.webconsole.plugins.event.internal.PluginServlet, setting the number of events to capture high enough to record your app’s startup.
  4. Start your app.
  5. Look at the startup timeline at /system/console/events

This provides a simple graphical timeline, as shown on the screenshot below, that’s especially useful in detecting outlier bundles or services that take a long time to start up.

Webconsole Events plugin screenshot


MANIFEST.MF must be the first resource in a jar file – here’s how to fix broken jars

November 15, 2011

Some tools, like the Sling OSGi Installer, require the MANIFEST.MF to be the first file in a jar file, or they won’t find it.

This happens when using the java.util.jar.JarInputStream class to read a jar’s manifest, for example.

The manifest is where OSGi bundle headers are found, for example, so not having it in the right place makes the jar unusuable as a bundle.

I won’t discuss here whether this requirement is part of the jar file spec (it would make sense, as this makes sure you can read it quickly even from a huge jar file), but anyway there are many cases where this is required.

To fix a jar where this is not the case, you need to unpack the jar and recreate it, as in this example, starting from a broken.jar in the current directory:

$ mkdir foo
$ cd foo
$ jar xvf ../broken.jar
$ mv META-INF/MANIFEST.MF /tmp/mymanifest
$ jar cvfm fixed.jar /tmp/mymanifest .

That’s it – creating the new jar with the jar utility puts the MANIFEST.MF in the right place.


Transforming Maven POM properties with Groovy

February 11, 2011

We’re moving to fragment bundles in Sling instead of using system properties, for example to export packages from the JVM’s classpath.

If you have no idea what I’m talking about, bear with me – this is just about a simple Maven trick to transform POM properties using bits of Groovy script.

Basically, an OSGi fragment bundle is a jar file that contains just metadata under META-INF, especially META-INF/MANIFEST.MF that contains the OSGi bundle headers.

One of these headers is Bundle-Version, which does not support values like 5.4.2-SNAPSHOT which are common in Maven. The dash is invalid in an OSGi bundle version number, that value needs to be converted to 5.4.2.SNAPSHOT

To avoid having a separate bundle.version property in your POM, which if you’re like me you’ll forget to update before a release, here’s how to transform the value using a bit of Groovy scripting:

<plugin>
  <groupId>org.codehaus.groovy.maven</groupId>
  <artifactId>gmaven-plugin</artifactId>
  <version>1.0</version>
  <executions>
    <execution>
      <phase>generate-resources</phase>
        <goals>
          <goal>execute</goal>
      </goals>
      <configuration>
      <properties>
        <rawVersion>${pom.version}</rawVersion>
      </properties>
      <source>
        // Convert POM version to valid OSGi version identifier
        project.properties['osgi.version'] = 
          (project.properties['rawVersion'] =~ /-/).replaceAll('.')
      </source>
    </configuration>
  </execution>
 </executions>
</plugin>  

As usual in Maven POMs (though I think Maven 3.x can improve on that, feedback welcome) that’s a bit verbose to write, the actual Groovy code is just

project.properties['osgi.version'] = 
  (project.properties['rawVersion'] =~ /-/).replaceAll('.')

But even with the verbosity it’s cool to be able to do that without having to write a plugin. You can then use the ${osgi.version} property for the Bundle-Version header.

For the sake of completeness, here’s the other interesting part of that pom, which sets the required OSGi headers to create a fragment bundle. com.example,whatever is the package that we need to be exported by the system bundle.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <configuration>
    <archive>
      <index>true</index>
      <manifest>
        <addClasspath>false</addClasspath>
      </manifest>
      <manifestEntries>
        <Bundle-Version>${osgi.version}</Bundle-Version>
        <Bundle-Description>${project.description}</Bundle-Description>
        <Bundle-Name>${project.name}</Bundle-Name>
        <Bundle-DocURL>http://www.example.com/</Bundle-DocURL>
        <Bundle-ManifestVersion>2</Bundle-ManifestVersion>
        <Bundle-Vendor>YourCompanyAG</Bundle-Vendor>
        <Fragment-Host>system.bundle;extension:=framework</Fragment-Host>
        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
        <Export-Package>
          com.example,whatever;version=1.0,
      </Export-Package>
    </manifestEntries>
  </archive>
 </configuration>
</plugin>

Update: a complete sample pom is available at http://svn.apache.org/repos/asf/sling/trunk/samples/framework-fragment/pom.xml


So Java is more complex than Scala? You must be kidding

August 26, 2010

My esteemed colleague Michael Duerig posts about Scala code being simpler than java.

His Scala example is beautiful, no question about it:

object ScalaMain {
  case class Person(name: String, age: Int)

  val persons = List(
    Person("Boris", 40),
    Person("Betty", 32),
    Person("Bambi", 17))

  val (minors, majors) = persons.partition(_.age <= 18) 

  def main(args: Array[String]) = {
    println (minors.mkString(", "))
    println (majors.mkString(", "))
  }
}

Though I wonder how many Scala programmers are actually able to come up with such concise and elegant code.

Michi’s corresponding java example, however, is…let’s say horrible. Like making things as complex and bloated as they can be.

Here’s my (slightly) more elegant Java version:

import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;

public class Person extends HashMap<String, Object> {
    
    public Person(String name, int age) {
        put("name", name);
        put("age", age);
    }
    
    public static void main(String args[]) {
        final Person [] persons = {
            new Person("Boris", 40),
            new Person("Betty", 32),
            new Person("Bambi", 17),
        };
        
        List<Person> minors = new ArrayList<Person>();
        List<Person> majors = new ArrayList<Person>();
        
        for(Person p : persons) {
            if( (Integer)p.get("age") <= 18 ) {
                minors.add(p);
            } else {
                majors.add(p);
            }
        }
        
        System.out.println(minors);
        System.out.println(majors);
        
        // Output:
        // [{age=17, name=Bambi}]
        // [{age=40, name=Boris}, {age=32, name=Betty}]
    }
}

Not bad hey? 37 lines all included, and although Java does require more boilerplate code, it’s not too bad.

All this is kinda tongue in cheek, ok? We could start all sorts of flame wars about type safety, generics and dynamic programming – my point is just that elegant and ugly code can be written in any language.

Scala definitely helps with conciseness, but in my opinion Java does not require things to be as bloated as some of those language wars examples show.

I’m on my way to Michi’s office to sort this out face to face as well ;-)

Update: face to face discussion went well, we agreed to not start religious wars…and in the meantime, here are two additional (and more serious) posts on the subject:


Dear Oracle, can we have our nice javadoc URLs back?

July 21, 2010

If you support this request, please vote for it in the comments below and/or on twitter using the #E17476 hashtag!

Update (2010/07/24): it looks like the old java.sun.com URLs are back, thanks Oracle and especially @mreinhold!

Update (2010/07/27): see also Good Feedback and Happy Endings – The Ugly URLs.

Dear Oracle,

A while ago you bought Sun, and IIRC promised to do good things for Java. Or at least indicated you would. Or something like that.

Now, a bad thing happened a few days ago. Not a bad bad bad thing, just a tiny annoying change in the cool URLs that Sun used to publish the JDK’s javadocs. Not annoying annoying annoying but not nice.

Even Google remembers: today if I search for IndexOutOfBoundsException on Google it returns the following URL:

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/IndexOutOfBoundsException.html

Which is a cool URL that shouldn’t change.

Now, requesting this URL today causes a redirect to:

http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/api/java/lang/IndexOutOfBoundsException.html

Which is also somewhat cool, but not as much. Factor 10 down in coolness. It makes me assume that you’re serving javadocs from a CD, and that CD’s identifier is E17476_01. That’s useful info if you’re the filesystem driver who’s reading the CD, but I doubt filesystem drivers are searching for javadocs on Google. Also, I’m not looking at downloading anything. Just browsing, okay?

Cool URLs shouldn’t change.

Can we have the old one back? Ok, maybe with java.oracle.com instead of java.sun.com – you bought them anyway. But please please please, let the poor CD filesystem driver alone!

Thanks.

P.S. we’re having a little vote on Twitter about this, check it out at http://search.twitter.com/search?q=%23E17476


Talking at Jazoon, Zürich, next week

June 17, 2008

jazoon.jpgI’ll be talking as a co-speaker with David Nuescheler at Jazoon next thursday, on the revenge of the weblog in 15 minutes. The talk description still mentions microjax, but that’s dead, it’s the Sling client library now. No conceptual changes though, that’s mostly a renaming.

I’m working on the Sling JST templates this week, as the code that this template engine generated was way too ugly to be shown in public. That’s getting better.


The Java Service Provider spec and sun.misc.Service

October 31, 2007

Looking for a lightweight plugin mechanism for microsling, I found the jar service provider spec to be good enough.

But wait…although the spec dates back from JDK 1.3, there’s no implementation in the JDK before 1.6? And what’s the mysterious Service class in the spec’s example?

Actually there are some implementations, well hidden in obscure JDK packages. Jackrabbit for example uses javax.imageio.spi.ServiceRegistry, which looks completely out of place in that package but is otherwise well specified. And apparently it is safe to use javax packages in any VM.

For now, the final word of this story is Sun’s bug 4640520 – looks like sun.misc.Service should have moved to the JDK public API long ago, but for some reason it didn’t.

Thanks to the sling-dev and advanced-java folks for their help in putting this info together. Sounds like a trivial problem, and it should be, but I bet many people have lost hours on this already.

Update: Jeremias indicates that the xmlgraphics commons include such a Service class – Batik and FOP have been using that for years.


mv SUNW JAVA

August 24, 2007

So, according to Jonathan Schwartz (who should know), Sun has decided to change its stock ticker symbol from SUNW to JAVA.

The comments on that blog post are mostly in the huh? category, and I tend too agree…like the one that says this is sillier than if Apple were to change its ticker to IPOD.

I’m not sure if JAVA is a good choice as a ticker symbol. MSWY would have sounded better to me. May the Schwartz be With You.


Java gems: Throwable.initCause()

May 21, 2007

Gem might be a bit of an overstatement, but as Jukka shows, initCause() can save your day, or at least your stack trace.


Java one-liner: XML text escapes

May 15, 2007

It never occured to me before today but

str.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;");

is good enough for quick and dirty escaping of XML text.

And escaping it manually to write it here is also fun ;-)


Follow

Get every new post delivered to your Inbox.

Join 29 other followers