Really irritated with Netbeans 6.8 Beta: suddenly there are plugins missing (SOA, XML Schema Editor and WSDL) and if you are not careful to uninstall existing instances of Glassfish V3 then NB throws exceptions when you activate the Java EE and Web module.  Worse, NB then hangs. 

On the missing plugins, you can get access to the missing XML Schema Editor plugin by adding a new update center:
- Name: NetBeans Dev
- URL: http://updates.netbeans.org/netbeans/updates/6.8/uc/m1/dev/catalog.xml.gz
But when I tried to install it from here, I got this error:

ScreenHunter_01 Oct. 30 23.11

So this might be the reason they left it out of 6.8, but it would have been good to be warned and even better if a fix had been promised.  My cynical side wonders whether this is some sort of stealthy de-scoping of ‘enterprise’ features, coinciding eerily with progress on the Oracle/Sun deal and a less then fulsome commitment from Oracle on the future of Netbeans.  I do hope I’m wrong, but other folk clearly think that Oracle’s view of NB is ambivalent at best.

Meanwhile, back to more practical things Netbeans-related.  Have you recently updated your JDK installation (to JDK 6 Update 17)?  What happened when you next ran Netbeans?  Did you see a dialog telling you NB couldn’t find the JDK?

Annoyingly, when Netbeans installs itself, it creates an entry in the netbeans.conf file (in C:\Program Files\NetBeans 6.7\etc or the equivalent path in your installation) containing the explicit JDK path, e.g.

  # Default location of JDK, can be overridden by using –jdkhome <dir>:
  netbeans_jdkhome="C:\Program Files\Java\jdk1.6.0_17"

It’s seems a small thing, but forcing a user to fix this by locating and manually editing a configuration file is desperately poor.  As NB makes this check as it starts up, it should make more of an effort to detect alternative JDK installations, present the user with what it finds and offer to adjust the configuration for you.  It wouldn’t be hard.

Technorati Tags:
,

Why does Oracle’s purchase of Sun make me feel slightly sad?  Silly, sentimental reaction, isn’t it?  I should know better. After all, today’s Sun isn’t the super-confident (some would say arrogant) innovator and market leader I grew up with: arguably, today’s Sun needs rescuing from itself, needs a sharper focus on what it does best, and to sell more of fewer things.

But I have a soft spot for Sun. My first proper programming job involved writing C/C++ (and using Cfront – remember that?) on a Sun-3 workstation, and various versions were part of my working life for some time. I loved the solid feel of these machines. Remember the optical mouse that only worked on those special, shiny metal mats?

Between then and now, my only links to Sun have been through OpenOffice and Java. I played with Java quite early on, abandoned it in favour of Microsoft .NET, but have recently (and happily) returned to it. For the last couple of years I’ve been an enthusiastic user of NetBeans – I do hope Oracle recognizes just how good NetBeans is.  I have also tried OpenSolaris: ZFS is simply awe-inspiring, and very nearly enough on its own to make me run OpenSolaris, though truthfully I don’t think I need ZFS, and Windows remains simply more convenient and usable for everyday.

I’ve used OpenOffice for a long, long time.  I know Writer pretty well, warts and all. You need to ignore some of the cosmetic shortcomings, persevere with it and appreciate its fundamental strengths; things which I think make Writer better than Word. Occasionally I use OOo Writer to help colleagues debug and rescue Word documents which have evolved uncontrollable formatting: it amuses me to be using a free tool to clean-up after a rather expensive one.  I really hope Oracle will resource and manage the OpenOffice program properly. With the right additional effort, they have a potential Office-beater.

But the crown-jewels are Java itself, and the NetBeans IDE.  Everyone is trying to second-guess what Oracle will do with Java: I don’t have anything to add.  But I really want to add my voice to those hoping Oracle will recognize just how good NetBeans has become, not just as the best Java IDE out there, but also a first-class platform for building rich-clients.

Technorati Tags: ,,,,

Thanks to the folks who commented on yesterday’s post I have managed to overcome the assign problem and of course the answer was very simple: I had an inconsistent set of components installed in NetBeans and GlassFish.  I was using NB 6.5 together with components downloaded from the OpenESB site. 

The best solution is simply to download the complete NetBeans/GlassFish/OpenESB combination from the OpenESB downloads page and work with that. On the download page the top section contains the GA (stable) GlassFish ESB / NetBeans combination, and the nightly build of the latest (unstable) additional components (i.e. binding components, service engines etc.) which match this GA release.

The next major section on the page contains the GlassFish ESB v2.1 downloads (milestone 1 at the time of writing), which are not yet considered stable. I grabbed the 2.1 release, plus the HL7 BC (and NB design-time modules) from here.  Installation was completely pain-free.  I particularly liked the way the additional components are packaged as a jar-based installer – very nicely done. 

Because the main package is a GlassFish ESB bundle, it installs by default to a non-standard path: C:\GlassFishESB. Everything is installed under this directory, including the configuration files for NetBeans, which would normally be placed in your home directory (under .netbeans). Presumably this is done to allow parallel installation with a stable NetBeans/GF without either interfering with the other. What this means, of course, is that all your preferences (editor settings etc.) are not transferred. This is easily fixed, manually, by copying over the stuff from: C:\Documents and Settings\<user>\.netbeans\6.5\config\Editors to C:\GlassFishESB\.netbeans\glassfishesb\config\Editors

Anyway, back to the BPEL issue.  A clean rebuild of everything was sufficient: the CA deployed to GF, and it ran fine.  I used Hermes JMS and watched the test messages arrive on the queue. Now I can push ahead and explore more of OpenESB and BPEL.

Technorati Tags: ,,,

After far too many cycles staring at code, building, deploying, debugging and undeploying a pretty simple composite application, the damn BPEL assign activity still causes selectionFailure at runtime.

The BPEL is trivial, and the BPEL copy elements for optional elements in the source schema are marked with the ignoreMissingFromData attribute.  I have rebuilt everything from scratch.  I know the redeployments are successful because the error reports points to the correct line following an edit and I can use the BPEL debugger to step through the assign, eventually failing on the optional element.

I was given the hint about the ignoreMissingFromData attribute by Michael Czapski, in a blog comment.  Googling around for more help, I came across a few other postings, and discovered that the attribute could be placed at the process level or at the individual copy activity level. Jeff Sexton also has a nice post on the assign issue.

In Michael’s tutorial he does in fact place the attribute at the process level (see p.95 of the PDF document which accompanies his tutorial). Placing it at the process level is not very attractive because it will mask the absence of mandatory fields.

When placed at the copy element level, it seems to fail. Here’s the error I see, as output in the GlassFish console window:

BPCOR-6151:The process instance has been terminated because a fault was not handled; Fault Name is {http://docs.oasis-open.org/wsbpel/2.0/process/executable}selectionFailure; Fault Data is null
com.sun.jbi.engine.bpel.core.bpel.exception.StandardException: I18N: BPCOR-3023: Selection Failure occurred in BPEL({http://enterprise.netbeans.org/bpel/HL7Processor/bpHL7Processor}bpHL7Processor) at line 28!
BPCOR-6129:Line Number is 26
BPCOR-6130:Activity Name is Assign1

Note the line numbers in the above report: the first of these (line 28) is where the selection failure actually occurred, line 26 is the opening tag of the enclosing assign activity element.  Here’s a shot of the source so you can see the corresponding line numbers. I placed all the optional elements together at the start of the assign:

image

So why doesn’t this work? Is this a bug? Perhaps I’ve run into something which only works in the JavaCAPS product and not in OpenESB?  Shame.

Another unfortunate discovery is that the OpenESB UI in NetBeans 6.5 doesn’t seem to support adding the ignoreMissingFromData at the process level.  In Michael’s PDF he selects the top-level BPEL process scope and uses the property panel to set this attribute.  It doesn’t appear to exist in NB 6.5. In the shot below I’ve tried to capture the same UI as in Michael’s tutorial:

image

Note there’s nothing below the ‘Documentation’ entry: presumably this is additional UI support which you get in the commercial JCAPS product. I’m not that concerned with the missing UI, as long as I can add the attribute in the XML source.  So I edited the BPEL XML, using Michael’s tutorial source as a guide. It’s easy to add the process-level attribute; only the namespace prefix had to be changed:

<?xml version="1.0" encoding="UTF-8"?>
<process
    name="bpHL7Processor"
    xmlns:ns3="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension"
    ns3:ignoreMissingFromData="yes"
    targetNamespace="http://enterprise.netbeans.org/bpel/HL7Processor/bpHL7Processor"
    xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/executable"

So another clean/build/deploy and … it still didn’t work. So now I’m stuck, and I hate being stuck. It’s almost enough to put me off the product.

The impression I get is that BPEL is great for very simple maps and transforms, but anything complex quickly becomes awkward. I haven’t gone beyond ‘simple’ so far, so I’m getting a little concerned. The pretty visual tools and NetBeans integration are cool, but the complexity overhead seems high. It reminds me of Microsoft’s BizTalk product from a few years back – a lot of fiddly config, and not being able to ‘see the wood for the trees’. 

But I want to persevere with OpenESB: something about this product suggests that you need to reach a certain level of enlightenment, after which everything becomes clear and the benefits outweigh the overheads. I’m just not there yet.

Technorati Tags: ,,
Technorati Tags: ,,,

As well as looking at Apache Camel for healthcare integration, I have also been spending time with Sun’s OpenESB product.  OpenESB is the open-source counterpart of the Java CAPS product, a mature and well-supported Enterprise Service Bus (ESB) built on the Java Business Integration (JBI) standard.

OpenESB is delivered along with the GlassFish application server (v2) when you install the SOA extensions to the NetBeans IDE.

Michael Czapski of Sun is an excellent source of information on healthcare-related application of the CAPS / OpenESB product line. He has created a really substantial demonstration project based on a healthcare integration scenario. His blog entry and the associated downloads (and screencast) are well worth getting hold of.  The screencast and writeup are based on Java CAPS, the commercial product which provides a few nice UI improvements and I believe some additional tools which the OpenESB product does not have.

I decided to go through Michael’s complete tutorial, using NetBeans 6.5 and the bundled OpenESB / GlassFish combination, building the solution and making notes as I went along. I’ll put the source code for the NetBeans (6.5) and OpenESB project group up on a publically available Assembla Subversion space (URL to follow), in the hope they may be useful to others who want to use OpenESB to do a similar thing.

As already mentioned, the differences between Java CAPS and OpenESB are superficially small, so if you are already familiar with one or other product you probably only need Michael’s notes and material. However, if you’re relatively new to OpenESB (as I am), there are a few places where the absence of JavaCAPS tooling means you need to know what you’re doing to patch-up the OpenESB solution.

Getting Started

My first big lesson was getting a correct / compatible set of NB plugins and libraries installed. The zip archive provided by Michael appears to contain everything you need, including the XSDs, NB plugins and encoder libraries. As the article was published very recently, I assumed these were the latest versions so tried to configure my NB 6.5 instance using these.

I followed the instructions for installing the encoder library (first uninstalling the existing one), then installing the NB plugins. However, the plugin installation just wouldn’t go ahead:

image

I tried various combinations but in the end had to uninstall GlassFish v2 and run the NB installer again to reinstall GF plus the OpenESB bits. Fortunately, this is actually quite a quick process, and puts everything back as it was.

I won’t go through all my subsequent false-starts, but simply tell you to download a matched set of the latest versions from this location:

http://download.java.net/jbi/binaries/open-esb-full-install/nbm/latest/

The components here should all be compatible. It really is best that you download and install these yourself, so I won’t put them in the Assembla SVN space.

Doing without the Java CAPS Wizards

The most obvious differences when watching the screencast are the degree to which the commercial product contains wizard steps and conveniences for generating all the configuration items. Reasonable enough I think, and so far I have been able to complete every step using OpenESB and NetBeans 6.5.

When creating the concrete WSDL definitions with the HL7 bindings, the wizards in the Java CAPS product (seen in Michael’s screencast) do make the whole process slightly simpler. But if you take a little time to understand what these wizards are actually doing in the generated WSDL, it’s not too hard to complete the steps manually.  That’s easy to say now, but I should ‘fess-up and admit that it took me a little while to spot what I hadn’t done, a couple of times.

For example, once I’d completed the HL7Consumer_CA_A01_A03Delim_HL7In WSDL (sorry Michael, I’m not a big fan of your naming convention!), I simply couldn’t add it to the Composite Application design surface: the tutorial document instructions didn’t appear to work. I could see the WSDL in the list of available WSDLs and select it – but could not add it to the canvas, and couldn’t see any error message to tell me why.

After a cup of tea and a biscuit and a bit of careful thought, I realised why. The HL7 protocol properties were completely missing from the port declaration in the Services section.  It’s easy to fix this, using the context menu commands:

image

Then edit the properties in the property grids. Of course, in the JavaCAPS product the wizards prompt you for these properties and create the related WSDL bits behind the scenes.  I don’t like depending on wizards. Fortunately the NetBeans tooling gives you just enough convenient UI to hide the underlying cruft, but also lets you work at the XML / source level and see what’s going on down there.

That’s probably enough for this post.  There’s so much more to write but I need to knock it into shape before I publish.

I’ve been spending some time with Apache Camel and ActiveMQ, with a view to using Camel in a healthcare integration project.  Camel has support for HL7 both at the message structure level (wrapping access to the HAPI libraries) and at the protocol level (via the Apache Mina extensions for HL7 MLLP).

As anyone who’s looked at Camel (or IONA’s FUSE Mediation Router) will know, Camel implements a rather nice Java DSL for building routes.  This lets you write things like:
from(“hl7listener”)
            .unmarshal(hl7Format)
            .choice()
              .when( header(“hl7.msh.messageType”).isEqualTo(“ORM”) )
                    .beanRef(“hl7handler”, “handleORM”)
              .otherwise()
                    .beanRef(“hl7handler”, “badMessage”)
              // end choice block- marshal the ACK/NAK back to the TCP endpoint
            .end()
            .marshal(hl7Format);
Very readable, but as you might expect, it hides quite a bit of complexity.  This is no bad thing, but you do need to understand what’s going on behind the DSL. 
Camel exploits Spring, and in the above fragment “hl7listener” and “hl7handler” are bean names. The unmarshal and marshal methods allow DataFormat objects to convert between byte-streams and more convenient objects, such as HAPI messages.  The choice/when/otherwise operators allow predicates to control routing.

It’s taking a while for me to grok Camel; here is a couple of things I’m not yet clear about:

  • Knowing how to get an intermediate stage in a route to return an ACK or NAK to the originator, without subsequent (or parallel) stages in the route from doing so. 
  • Creating compound boolean expressions in predicates. For instance, if I want a conjunction inside a when(), I can’t have it. There don’t appear to be combinators for expressions.  
In the fragment above for example, how can I express a conjunction/disjunction in the when( … ) expression?  It only seems to be able to handle a single condition: I haven’t found a way to combine predicates e.g. I can’t do this:
when ( header(“hl7.msh.messageType”).isEqualTo(“ORM”) &&
             header(“hl7.msh.triggerEvent”).isEqualTo(“O01″) ).    // etc.
I have tried alternatives, e.g. nesting the when clauses:
from(“hl7listener”)
            .unmarshal(hl7Format)
            .choice()
              .when( header(“hl7.msh.messageType”).isEqualTo(“ORM”) )
                  .choice()
                    .when( header(“hl7.msh.triggerEvent”).isEqualTo(“O01″) )
                        .beanRef(“hl7handler”, “handleORM”)
                    .otherwise()
                        .beanRef(“hl7handler”, “badMessage”)
              .otherwise()
                  .beanRef(“hl7handler”, “badMessage”)
            // end choice block- marshal the ACK/NAK back to the TCP endpoint
            .end()
            .marshal(hl7Format);
But this doesn’t work either.  I’m just starting out with Camel, so I expect I simply haven’t read the right bit of the documentation (which even the creators admit is one of Camel’s weak points).
Another problem is controlling which component in the route returns a response to the originating endpoint (the MLLP sender, in the HL7 case).  I may have solved this one, but it’s worth setting out the problem and my approach, in case it helps someone else.
My requirements are for the pipeline to log the inbound message (i.e. whatever is actually received on the HL7 socket), unmarshal the message to HL7 (HAPI), then validate the HL7 message type: at this stage in the pipeline I want to return a NAK to the sender (on the HL7 MLLP connection) if the message is not of the expected type, otherwise I want to write the message to a JMS queue for further processing and return an ACK.
The following route appears to work (note that I have omitted the message-logger stage):
        // We need the specific HL7 DataFormat object for unmarshalling HL7 ER7 from the
        // inbound MLLP link.
        DataFormat hl7Format = new HL7DataFormat();
        // Inbound HL7 comes from MLLP endpoint. 
        // Timestamp message, log receipt, unmarshal and perform initial
        // handling, which just determines if its the right kind of HL7
        // message.
        // If so, return ACK to originator and push message to JMS queue.
        // If not, return NAK to originator and end.
        //
        from(“hl7listener”)
            .unmarshal(hl7Format)
            .choice()
              .when( header(“hl7.msh.messageType”).isEqualTo(“ORM”) )
                    .marshal().hl7().to(“jms:queue:orderMessage.queue”)
              .otherwise()
                    .beanRef(“hl7handler”, “badMessage”)
            .end()
            .marshal(hl7Format);
        
        // The order message processor – pulls message from JMS queue and sends to
        // the processor bean, which creates and returns an ACK to the hl7 channel
        // if the message is of the expected type.
        //
        from(“jms:queue:orderMessage.queue”)
            .unmarshal().hl7().beanRef(“hl7handler”, “handleORM”); 
All of this routing can be expressed in XML instead of using the Java DSL. Once I’m comfortable with Camel I may try writing a NetBeans plugin or RCP application to create visuals tools for Camel routes.
It’s probably not necessary to start this article with a mini-lecture on why logging, like unit-testing, is a Good Thing, so all I will say is logging is important not only during development but also invaluable in diagnosing runtime problems, once a solution is delivered and running. From here on I’m going to assume you’re convinced.

So, you know you should be logging, but how? And which of the many logging frameworks should you use? This article sets out to answer the first question, showing you how to get started logging in Java, using the NetBeans IDE, and offers an opinion on the answer to the second question.

There are several well-established ways to do logging in Java but the best approach I have come across so far is to use slf4j (the Simple Logging Facade for Java) for all logging statements in source code. The slf4j facade interfaces are completely independent of any specific logging implementation. The binding between the slf4j facade interfaces and a concrete logger implementation is done statically when the application jar is compiled: there is no runtime trickery involved (e.g. using class-loaders).

This approach allows you to replace one logging implementation with another without altering any of your logging code, just by binding to a different concrete logger (i.e. referencing a different logger implementation jar).

Splitting the logging job into two in this way means you need two references in your Java project, in order to use slf4j:

  1. a reference to the slf4j API itself, which provides the interfaces you will use exclusively in your logging code.
  2. a reference to a concrete logging implementation, which your logging code will call via the slf4j facade.

As the slf4j interfaces must be bound to a concrete logger implementation, you need to choose which logger to use. I have chosen Logback, which appears to be an improved version of log4j, one of the more efficient Java logging solutions.

This article describes what you need to do to start logging using this combination. I’m going to assume that you understand the value of logging, and know a little about log statements and logging levels: these are common to all modern logging frameworks, so I won’t cover them in detail.
Logger Libraries

Download slf4j and logback. Extract the distribution archives to wherever you keep your libraries. Then, in NetBeans, create libraries (via Tools/Libraries) for both distributions.

  • For slf4j, include the slf4j-api.jar. The precise name of the jar file will depend on the version you download: mine is slf4j-api-1.5.0.jar
  • For logback, you need logback-core.jar and logback-classic.jar. Again, precise file name depends on version e.g. logback-core-0.9.9.jar

You could create a combined library as a convenience for simple projects, if you know that you will frequently want to use the same concrete logger with the facade. However, bear in mind that for projects which build libraries or components used in other projects, you should only reference the slf4j library: the logger implementation binding should be done by the application which uses your component.

The source code for this tutorial assumes two NetBeans libraries, one for slf4j and the other for logback.

Adding Logging To Your Code

In your NetBeans application project, add references to the slf4j and logback libraries. To start logging from your code, you need to do the following things:

  1. Initialise a logger reference in every class you wish to log from.
  2. Add Import statements for the required slf4j types
  3. Add logging statements to your code.

Refer to the source code with this article. Look first at the Main class: the first declaration in the class is for the logger:

private static final Logger _log = LoggerFactory.getLogger(Main.class);

Notice that this logger is declared static: this is because Main houses the static main() application method, so the logger must be static for it to be referenced from the main method. Above, in the imports section, you will see the two imports necessary to use slf4j:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Now open the slf4j-sample-lib project, a trivial sample library which the main application references. Look at the StringReverser class, and notice that the logger is declared slightly differently:

private final Logger _log = LoggerFactory.getLogger(this.getClass().getName());

This is a non-static declaration: only non-static methods will have access to this logger. If you look carefully at the declaration, you’ll spot that this one is portable: it doesn’t contain the class name explicitly. This declaration can therefore be pasted without modification into any class, but remember that this is non-static, so will not be usable from any static methods in the class.

As the static logger is usable from everywhere (non-static and static contexts), wouldn’t it be convenient to have that declaration added automatically in every new class you create? Perfectly possible, in NetBeans. To include the logger declaration in your NetBeans source code template, go to Tools / Templates, open the Java branch and select Java class and click Open in Editor. You’ll see the Java class template source, complete with template parameters for the class name and some other stuff I’ll ignore here. All we need to do is add a single line to the class skeleton:

public class ${name}
{
private static final Logger _log = LoggerFactory.getLogger(${name}.class);

}

If you save the changes to your template and create a new class in NetBeans, you’ll see the logger declaration with the correct class name parameter value has been added to the source. You could even add the necessary import statements to the template.

But the overhead of including the logger declaration is low (just one simple line), and NetBeans will take care of the imports for you (use Fix Imports with Ctrl-Shift-I), so you may decide it’s not worth adding these lines to your templates.

Static versus Non-static Loggers

There’s one more difference between static and non-static loggers which you should at least be aware of. If you declare the logger static, there will be exactly one instance of the logger retrieved for the class, shared across all instances. As the logger reference is shared, memory is allocated just once and the logger is initialised just once, rather than once per object. This is not usually a problem, but you should be aware that the same logger reference will be shared across every instance of the class.

When declared non-static, every instance of your class will incur the memory and initialisation cost for the logger reference variable. For the vast majority of classes this will not be a significant overhead, but again you should be aware of the tradeoff. Note that within the same application, retrieving a logger by a given name will always return the same logger object: using a non-static logger reference does not mean that every instance of a class gets a new logger object of its own.

For a complete account of this issue, you should consult the slf4j documentation which covers this. Read this section of the online documentation.

Logging Statements

As I said in the introduction, I’m assuming you are somewhat familiar with logging. If not, go back and read the material on the slf4 and logback sites, and follow-up the references there.

Use the logger method appropriate to the level you wish to log at, for example:

_log.info(“‘{}’ reversed is ‘{}’”, instance.getValue(), instance.reverseValue());

Possibly the most important piece of advise I can give here is to consider the cost of logging carefully, especially debug-level logging. The actual call to the logger object is not usually the dominant cost in debug logging: you are likely to be constructing moderately large strings to output, and the cost of preparing these may be where you incur the biggest cost. Consider a line such as this:

_log.debug(“Debugging string: “ + ExpensiveGetter());

The runtime cost of constructing the string argument to this logging statement will always be incurred, whether the log-level is set to debug or to some other (less-detailed) level. Clearly that’s an undesirable, and fortunately there is a very simple coding idiom we can use to avoid this cost:

if (_log.isDebugEnabled())
{
_log.debug(“Debugging string: “ + ExpensiveGetter());
}

Simply guard the debug log statements with a test for the current (runtime) level of the logger. This does add a little source code; it is possible to reduce simple statements like the one above to a one-liner but I generally avoid this, valuing clarity over concision.

The cost of the debug statement will now be reduced to a simple boolean test, which is much more acceptable.

Configuring Logback

If you build and run the sample project accompanying this piece, you’ll see the log statements are written to the console. This is the default behaviour for most logging solutions, logback included. In most production situations you will probably want to direct your log messages somewhere else, to a file for example.

In common with other logger implementations (such as log4j) the logback subsystem can be controlled through an XML configuration file. For a complete treatment of the options and syntax, you’ll need to refer to the logback documentation and in this article I’ll give a superficial account of a simple but usable configuration.

Here is the configuration file:

<?xml version=”1.0″ encoding=”UTF-8″?>
<!–
Document : logback.xml
Created on : 25 February 2008, 22:40
Author : Roger
Description:
Configuration for logback logging framework.
For this file to be read by logback at runtime, it must be placed
on the classpath.
–>
<configuration>
<appender class=”ch.qos.logback.core.rolling.RollingFileAppender” name=”RootFileAppender”>
<file>application-log.txt</file>
<append>true</append>
<filter class=”ch.qos.logback.classic.filter.ThresholdFilter”>
<level>debug</level>
</filter>
<rollingPolicy class=”ch.qos.logback.core.rolling.FixedWindowRollingPolicy”>
<fileNamePattern>application-log.%i</fileNamePattern>
<maxIndex>2</maxIndex>
</rollingPolicy>
<triggeringPolicy class=”ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy”>
<maxFileSize>100000</maxFileSize>
</triggeringPolicy>
<layout class=”ch.qos.logback.classic.PatternLayout”>
<pattern>%d{yyyy-MM-dd HH:mm:ss},%p,%c,%F,%L,%C{1},%M %m%n</pattern>
</layout>
</appender>
<root>
<level value=”debug”/>
<appender-ref ref=”RootFileAppender”/>
</root>
</configuration>

Although this is quite a simple configuration file, there’s a lot of information in there and to understand it all fully you will need to study the logback documentation. I’ll skim over the most important bits here and leave the rest to you.

Appenders are the part of the logging engine which actually write the log messages somewhere. You can choose from many different appenders – my favourite is the RollingFileAppender which writes to a text file and ‘rolls-over’ to a new file once the existing file passes a certain size, declared in the triggeringPolicy element. The file element declares the filename, and the rollingPolicy/fileNamePattern declares the filename pattern to use for old log files, as the file rolls-over.

Layouts define the format of the messages written to the log appender. I’ve gone with a standard pattern which appears in the logback documentation: please consult the logback documentation on format strings to discover all the options here. Essentially, every log statement will include the date and time, and the origin of the log message, including the line number.

So the net effect of this configuration is that logback will write all log activity out to the file application-log.txt in the working directory, rolling the file when it reaches the size limit I have set (roughly 100k).

Logback and the Classpath

As explained in the logback documentation, if you want to configure logback with an XML file then the file must be present on the classpath of the application, otherwise logback will not find it and will fall-back to console logging.

If you examine the source code accompanying this piece you’ll see that I have placed the logback.xml file in the root of the source folder (src). In the NetBeans project, this is the ‘default package’: the name of anything placed here will have no namespace prefix. When NetBeans builds a Java application, it will compile any Java sources it finds in src and all its subdirectories, and will also by default include everything it finds in the root folder in the jar file. To prove this to yourself, go into the src folder, create an arbitrary file, say ‘fred.txt’, and rebuild the project. Now open the NetBeans Files view (Ctrl-2 will open this if it’s not already visible), locate the ‘dist’ folder and open the tree until you locate the slf4j-sample.jar file. The NetBeans file view allows you to browse the jar file contents – just open the tree to the next level:

And there are the two files, logback.xml and fred.txt, packed into the root of the jar. We don’t need fred, so delete the file and rebuild the jar.

So the source hierarchy in NetBeans contributes to the runtime classpath, and the ‘dist’ folder is where NetBeans writes out all artifacts resulting from a build. As the NetBeans documentation (and the generated readme) tells you, you can distribute your application by zipping-up and publishing the contents of the dist folder.

Let’s run the application. Open a terminal window in the dist folder and type:

java -jar slf4j-sample.jar

The program should run, but nothing should be written out to the console. Instead, an application-log.txt file should appear in the dist directory. Open that file and you will see the result of the logging statements. Logback has obviously located the configuration file and applied the settings.

If you’re thinking ‘job done’ at this point, not so fast! Just consider how logback has located and loaded the XML file. The logback XML file is packed into the (executable) jar file which is the main artifact generated by the build. When the Java runtime runs this jar it first examines the jar’s manifest (the MANIFEST.MF file in the META-INF folder inside the jar), which looks like this (from the sample application jar):

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 11.0-b15 (Sun Microsystems Inc.)
Main-Class: slf4jsample.Main
Class-Path: lib/logback-classic-0.9.9.jar lib/logback-core-0.9.9.jar l
ib/slf4j-api-1.5.0.jar lib/slf4j-sample-lib.jar
X-COMMENT: Main-Class will be added automatically by build

The runtime looks for the entry point of the program (the qualified name of the class containing the main method) and initialises the classpath from the Class-Path setting. Implicitly, ‘.’ (the root of the jar structure) is also on the runtime classpath.

What this means is that when the logback system goes looking for logback.xml it will find the copy in the jar file. Consider the function of the logback.xml file: the users of the application will almost certainly want to configure the log behaviour themselves rather than accept the settings you have baked-in to the copy of logback.xml inside the jar file.

So, we want to distribute our default logback.xml file but not have it baked-in to the jar file: what to do? Having it in the source classpath is convenient because it appears in the NetBeans project view so we can view and edit it from inside the IDE. However, we don’t want it packed into the jar, but we do want it on the runtime classpath. How can we satisfy all of these constraints?

We can achieve this with two simple steps:

  1. To prevent NetBeans including the XML file from the jar file, we exclude logback.xml from the list of source artifacts that NetBeans considers as jar contents.
  2. Add a step to the build process which copies logback.xml into the dist folder, placing it next to the jar file.

For step (1), open the NetBeans project properties dialog and navigate to the Packaging subsection, below Build. Add “logback.xml” to the list of Excluded files:

If you rebuild the application, then use a zip tool or archive manager to open the resulting jar file, you’ll see that the logback.xml file is no longer included. There is more help on excluding content from your jar in this page of the NetBeans documentation.

For step (2) we need to arrange for the logback.xml file to be copied into the dist folder during the build process. To do this, we will add a very simple custom build-step to the NetBeans build process. As you probably know, NetBeans uses Apache Ant as the build engine, and the IDE generates the Ant script automatically. I’m not going to go into much detail concerning what you can do with custom build steps – I suggest you read the well-commented Ant scripts, and look at this section of the NetBeans documentation.

There are standard stages in the build process where we can add tasks (‘targets’ in Ant-speak) to the NetBeans build. The build.xml file (in the project root) contains a comment describing these. All we want NetBeans to do is copy the logback.xml file into the dist folder after it has finished building the jar file, so we will add a -post-jar target to copy the file:

<target name=”-post-jar” >
<copy file=”${src.dir}/logback.xml” todir=”${dist.dir}”/>
</target>

Add this target at the end of build.xml, just before the close-tag for . Now rebuild the project, and take a look in the dist directory: you should see that logback.xml has been copied there. Now you’re ready to zip the dist folder and distribute your solution.

That’s the end of this little piece. You should know enough now to add straightforward, high-performance logging to your own projects. But there’s a lot more to learn: to go further, study the slf4j and logback documentation, follow the examples, and experiment.

While looking around for Java dependency tools I came across KirkK’s site, and his JarAnalyzer.  As usual, I wanted to know a little more about the person behind the software, so looked up his blog and found an article from 2007 there which really resonated with me: .Net : Software & Technology @kirkk.com

Kirk and I have travelled in opposite directions: he crossed the tracks to work on a .NET project, whilst I’ve recently shifted my attention almost completely from .NET and the Microsoft environment (where I have spent the last 10 or so years) to the world of Java.  What’s interesting is that he so quickly formed the same view of the Microsoft development that motivated my move to Java.

Microsoft’s greedy behaviour has done so much damage to its reputation and the level of goodwill amongst independent developers. Kirk cites the example of TestDriven.Net, but there are examples of other ‘alt.net’ type projects (NAnt and NDoc, for example) which Microsoft has effectively (though not directly) either killed or marginalised, not with licensing terms but by introducing proprietary (and arguably weaker) competing technologies.  I’m sure that part of the reason for that, with the N-prefixed projects at least, was that they couldn’t bear the prospect of absorbing something with what they would see as alien DNA into their product line.

This piece by Mike Hofer describes the NDoc demise and nicely summarises the twin underlying problems: the nature of the development community surrounding the Microsoft platform, and Microsoft’s inability (or unpreparedness) to work with it. Mike’s article, and the linked post by Charles Chen containing the email from NDoc’s founder, make for quite depressing reading. Perhaps the emergence of a mean-spirited, mean-minded community is to be expected, when the centre of its universe is an avaricious commercial juggernaut?

I feel these things especially keenly, now that I’m looking over the wall from the Java community side.  The contrast really couldn’t be more stark, more impressive and more compelling.  Even the large companies operating in this space, notably Sun Micrososystems, appear intelligent, enlightened and innovative; there’s a very healthy culture here. (A quick and revealing experiment: take Microsoft and Sun – now try to find the corresponding CEO’s blog. Top hit in Google for Steve Ballmer when I tried was a send-up site; top hit in Google for Jonathan Schwartz was Jonathan Schwartz’s blog. And it’s worth reading).

Coming back to the issue of building a healthy community around a technology, Sun’s Java is surely the shining example of how to embrace the great work done by independent developers and build on it, rather than trying to crush it. Just look at NetBeans: this is an enterprise-quality IDE, easily the equal of Visual Studio, but not only is it open-source (and free to download) it also employs established open-source tools instead of imposing inferior alternatives: For unit testing, JUnit is completely integrated; NetBeans uses Apache Ant as its underlying build-system; it can work seamlessly with Maven through the excellent plugin. And you choose the version-control system you prefer (e.g. Mercurial, Subversion) and NetBeans will allow you to make full use of it, right inside the IDE.

Lastly, you are free to extend NetBeans by writing whatever plugins (modules) you please, without running the risk of getting into litigious exchanges like the TestDriven.Net debacle described here, which seems to me to plumb the very depths of time-wasting pointlessness.

I never intended to write all that: it was originally just a reaction to a (rather old) blog entry. But as I revisited the world of the Microsoft monoculture through the tale of those N-projects, it just tumbled out.


I’ve been using LinuxMint 5 for some weeks now, and a very fine distro it is, too. I’ve noticed that NetBeans 6.1 starts and runs a great deal faster on Mint than on Windows XP – the difference is quite significant. I’ve been wondering why that is, given that this is Java and therefore presumably only the low-level loaders and file-system interactions differ across platforms. That’s just a passing observation and not the point of this post.

I found one annoying thing happening occasionally (but often enough to be irritating): NetBeans dialog boxes would appear completely empty. Take a look at the screenshot:

There didn’t seem to be any pattern to this behaviour; it wasn’t always the same dialog, and if you closed the dialog and opened it again it would appear normally. Not good.

Well, it turns out this is known problem when using the Compiz window manager on Linux – a quick search revealed a good post on the NetBeans forums about this subject. The answer is to use the latest JRE / JDK build as it addresses this compatibility issue. I decided to download and install JDK 6u10 RC and give it a try.

To get NetBeans to use the newer JDK, you can do one of two things:

  1. Edit the NetBeans configuration file (in <installationFolder>/etc/netbeans.conf) and change the path pointed to by netbeans_jdkhome
  2. Change your system default Java installation.

Not very keen on (1) – feels like I’m hiding a workaround in just one application’s config, but the problem exists for any Java application I run on this system.

So I decided to do (2). It worked perfectly, so thought I’d share the steps I used to do it. First, where is Java actually installed on the filesystem? If you do ‘which java’ in a console, it will report /usr/bin/java. But if you look closely, this is just the first step in an indirection; the ls tool reveals:

$ ls -l /usr/bin/java
lrwxrwxrwx 1 root root 22 2008-10-01 06:55 /usr/bin/java -> /etc/alternatives/java

And /etc/alternatives/java is another step:

$ ls -l /etc/alternatives/java
lrwxrwxrwx 1 root root 36 2008-10-01 06:55 /etc/alternatives/java -> /usr/lib/jvm/java-6-sun/jre/bin/java

And the /usr/lib/jvm/java-6-sun file is actually a symbolic link to the actual Java installation folder, which is in the same folder. That’s a lot of indirection, and I am quite sure there are good reasons for all of it, but I haven’t time to learn all of them. There is a very detailed post by Anthony Richardson which patiently explains how to create a proper DEB package from the JDK download; this is almost certainly a good idea.

I chose to exploit the fact that the last step in the indirection chain is that symbolic link file. By unpacking the JDK directory into /usr/lib/jvm and getting the java-6-sun link to point to the new JDK folder, I decided I could replace 6u6 with 6u10, system-wide.

However, there is another file in this folder: the .java-6-sun.jinfo file (this is a ‘.’ file – you’ll only be able to see those if you use the a switch with ls (e.g. ls -al) or View / Show Hidden Files in Nautilus). Looking inside it, only the first line appears to contain version-specific stuff – everything below uses paths which use the symbolic link:

name=java-6-sun-1.6.0.06
alias=java-6-sun
priority=63
section=non-free

jre ControlPanel /usr/lib/jvm/java-6-sun/jre/bin/ControlPanel
jre java /usr/lib/jvm/java-6-sun/jre/bin/java
jre java_vm /usr/lib/jvm/java-6-sun/jre/bin/java_vm
jre javaws /usr/lib/jvm/java-6-sun/jre/bin/javaws
jre jcontrol /usr/lib/jvm/java-6-sun/jre/bin/jcontrol
<snip>

I decided to leave this as-is for now, and edit it later if required. So, in summary here is what I did:

  1. Copied the JDK 6u10 contents into /usr/lib/jvm.
  2. Went to the directory /usr/lib/jvm and opened a gnome-terminal as root (you need to be root or use sudo, to make changes here).
  3. Completely unnecessarily, I backed-up the old symbolic link file, just in case. The easiest way is to use mv (by default mv doesn’t follow sym-links), but if you’d prefer to make a copy of a symlink (rather than the object to which it points) you need to use the -P switch, e.g.
    cp -P java-6-sun java-6-sun_OLD.
  4. Made a copy of the jinfo file:
    cp .java-6-sun.jinfo .java-6-sun.jinfo_ORIGINAL_1.6.0.06
  5. Made java-6-sun symbolic link point to the new JDK directory:
    ln -s jdk1.6.0_10/ java-6-sun

And it does seem to work. NetBeans reports that it’s using 6u10, and I haven’t seen any empty dialogs yet! Better yet, NetBeans seems to start and run faster, too. (I haven’t timed it – this may be placebo effect…)

Hope this may help out other folk using LinuxMint or Ubuntu, facing the same problem. Of course, remember that you can easily disable Compiz (set Visual Effects to None in the Appearances Preferences), and you can get some simple effects back using Gnome Compositing, available via the Mint Desktop tool in Control Center.

I recently installed NetBeans 6.5 Beta on both OSs on my laptop (Acer 2GHz dual-core, 2GB, dual-booting Win XP and LinuxMint) and I almost immediately uninstalled it. What is going on? Some of the UI appears to be broken: controls not lining up correctly, some dialogs displaying completely blank contents, some the wrong size (e.g. far too big). Sometimes the last two could be fixed by closing/re-opening, but not every time. It also felt a lot slower than 6.1.

Seems other people have been having the same experience. A lot of what Casper wrote in his piece resonated with me, as I also come from the Visual Studio / C# background. I do hope the NetBeans team pays attention because this is an important product which is already good, and deserves to be better. I really don’t want to use Eclipse, and I’d prefer not to pay for IntelliJ. Come on Sun!