A Better HTML Autofocus Implementation

6 November 2018

So you have this login form with a username and password field. Typically you want the username to be pre-filled and the password to be empty for a password manager to fill or to type in. It would be nice if the password field receives the focus so you can start typing away and press to submit the login form.

But often the username field is also empty. And if that is the case, you want the userfield to have the focus.

Your first pick is to add the autofocus attribute to both fields:

<label for="username">Username:</label>
<input id="username" type="text" name="username" autofocus>

<label for="password">Password:</label>
<input id="password" type="password" name="password" autofocus>

But in some browsers this focuses the username field regardless of its contents, and in other browsers the password field is focussed, even though the username field is not filled.

It appears that the behavior of two fields with autofocus is not specified.

In one of my applications I solved this problem with a little JavaScript snippet that runs when the DOM is ready.


This requires JQuery to be in your page, but if you want the Vanilla JS version, the line below will do the same:

document.querySelector('input[value=""]:enabled:not([style*="display: none"]):not([style*="display:none"]):first-child').focus()

This will filter the disabled, invisible, empty fields and select the first field to put the focus on.

If you are an Apache Wicket user, you can easily add this to your page using a header item, in particular the OnDomReadyHeaderItem, in the renderHead() method of your page.

Enjoy the best autofocus behavior you could wish for.

Generate a User Manual - With Your Tests

6 July 2017

This article was published in Java Magazine, 4th edition of 2017 in Dutch. This is a augmented Google Translate version of that article.

“Do we have a manual for the users already?” Asks the product owner. As your teammates dive under their desks, you stammer something about no time, varying priorities and the endless backlog. Without success of course, so you are the volunteer to provide the 96-page Word document with 149 screenshots. Four sprints later, the application no longer looks like the screenshots and you can start all over again.

But it can be different! After all, we stepped into this field to automate time-consuming human activities, to have time left to do fun, valuable things. We also like to write software and solve complex problems.

If I tell you that you can take screenshots automatically with the right development tools, you can integrate them into a nicely formatted manual in HTML and PDF format, and you can test your application at the same time, will I have your attention?

In this article I will show you how to generate an always up-to-date manual with AsciiDoctor, Graphene, Arquillian and aShot. It solves an actual problem, it consists of a lot of programming work, it can become as complex as you want and is also fun. To illustrate this, I use a simple project: an online cheese shop.

The Cheesr Online Cheese Shop

The cheese shop ‘Cheesr’ was invented in 2005 for the book Wicket in Action, because my co-author Eelco really missed the cheese shop “De Brink” in Deventer when he emigrated to the US. Cheesr is a standard web application with two screens: selecting cheeses and placing an order. In figure 1 you see a number of pages of the manual.

Figure 1: Cheesr Manual Figure 1. Some example pages from the Cheesr Manual

The cheese shop uses Apache Maven to connect the various components of the building process. Figure 2 illustrates the steps that are taken to get from the source code to a web application, containing the manual bundled together.

Figure 2: The build process Figure 2. The phases and files that play a role in building the cheese shop and the manual

After the source code has been compiled, the tests are run. Arquillian ensures that the web application is started and controls the browser with WebDriver . Thanks to Graphene , we can describe HTML pages as Java objects and use them to perform the tests. The library aShot makes the screenshots and puts these files in the folder target / screenshots. You will learn more about these technologies later on.

In the “pre-package” phase of the construction process, just before the web application is assembled by Maven, AsciiDoctor converts the manual from AsciiDoc to HTML and PDF. Ultimately, the web application is ready and there is also the manual as a PDF and as an HTML file.

As an example, the code in Listing 1 tests that the checkout button is not available, if you do not have an item in your shopping cart yet. In addition, the test also makes the first screenshots immediately.

Listing 1. The first test of the cheese shop

public class IndexTest {
    @Deployment (testable = false)
    public static WebArchive createDeployment () {
        return CheesrDeployment.createWar ();

    private WebDriver browser;

    public void step1EmptyCart (@InitialPage GIndex index) {
        Camera.takeScreenshot (browser, "cheesr-1-home.png");
        Camera.takeScreenshot (browser, "cheesr-1-home-navigator.png", By.id ("navigator"));

        // nothing was selected, so the checkout should not be present
        assertFalse (index.checkoutPresent ());

The annotation @RunWith(Arquillian.class) indicates that this test case should be run with Arquillian. With Arquillian you can perform integration tests, start and stop servers and deploy your application code. You can also use Arquillian to run your tests against an already running remote server, so you do not have to set it up entirely from your tests.

The createDeployment method with the @Deployment annotation tells Arquillian what needs to be deployed to the server: a WAR in our case, containing our application code.

The @Drone WebDriver browser field is an instruction for Arquillian to inject an instance of WebDriver in the test case, in order to control the browser.

The @InitialPage GIndex index parameter of the test method indicates that this test should start with the GIndex page. GIndex is a representation of the interaction possibilities of the Cheesr homepage: an implementation of the Page Object Pattern. This class includes the location (URL) to which the browser should be sent. Graphene ensures that the GIndex instance is created correctly and that the browser loads the page just before the test has started. You can immediately interact with that page, such as taking screenshots, clicking on links and asking if certain elements are present.

For now it is useful to see how the screenshots of this test are used in the text of the manual. A piece of AsciiDoc from Listing 2 is an example of this.

Listing 2. A piece of AsciiDoc from the cheese shop manual.

== Buying Cheese

When you point your browser to our store front using the URL _http://example.com_.
This will show you the page from <<cheesr-home>>.

[[cheesr-home, figure 1]]
.The home page of the Cheesr store.

You can browse the cheeses using the navigator at the bottom of the page (<<cheesr-navigator>>).

[[cheesr-navigator, figure 2]]
.The navigator to discover even more cheese!

When you have found the cheese of your liking, you can add it to your shopping cart using the _add_ link.
This will add the cheese to the cart, as shown in <<cheesr-cart>>.

The test case from Listing 1 generates screenshots with names such as “cheesr-1-home.png”. The AsciiDoc of Listing 2 picks it up in image elements such as image::cheesr-1-home.png[]. Finally the result will look like the manual of Figure 1.

AsciiDoc and AsciiDoctor

AsciiDoc is a text format for writing documents. AsciiDoc is very similar to the widely used Markdown, but offers more options: includes, table of contents, automatic numbering of sections, warnings, annotations on code samples and much more.

AsciiDoctor is a project that can process AsciiDoc files and convert into PDF, HTML, EPub and DocBook. There is a commandline tool, which you can call directly, but also plug-ins for Maven and Jekyll (a static website generator). AsciiDoctor also integrates with chart tools such as PlantUML and GraphViz. This allows you to describe UML diagrams in plain text.

AsciiDoc is an ideal format for storing in a Git repository, because it is a plain text format. You can keep your your documentation up-to-date together with the code of your project, and even include it in code reviews (did you update the manual?)

The AsciiDoc content of the sample project (in which this article is also written) looks like this:

├── artikel.adoc
├── cheesr.adoc
└── images
    ├── build-process.png
    ├── cheesr-cover.jpg
    ├── cheesr-manual.jpg
    └── pageobjects.png

With these documents AsciiDoctor can generate the manual and include the screenshots (from target/screenshots) in the manual. The screenshots are taken during the execution of the application tests. This has been set up using Arquillian, WebDriver and Graphene.

WebDriver and Graphene

WebDriver is a technology for controlling and reading browsers. This can produce fragile code if you are not paying attention: changes in the structure of the HTML in the browser can easily make your tests fail. Graphene is a shell around WebDriver to describe your application at a higher level of abstraction by encapsulating the (interaction with) HTML by enabling the Page Object pattern.

Instead of looking for a link in the HTML document to add a cheese to the shopping cart, you call the addCheese method on your page object. Of course behind the scenes, the search in the HTML goes to the link in question, but that is hidden from your tests. Figure 3 shows the difference between working directly with the WebDriver API (and with it the HTML) and working with a Page Objects API.

WebDriver API vs Page Objects Figure 3. The difference between the WebDriver API and Page Objects

The use of page objects makes your tests much easier to read. The code in Listing 3 gives an example of the difference between the WebDriver API and the use of Page Objects.

Listing 3. Example of working with the WebDriver API and Page Objects

// WebDriver code:

List <WebElement> addLinks = browser

addLinks.stream ()
    .filter(e -> e.getAttribute("id").contains("edam"))


// page objects code:


Assert.assertTrue(index.checkoutIsPresent ());

In the example of the page objects code the intention of the test is immediately clear, while that in the WebDriver code is hidden in pitting the HTML structure. Of course this is simply moving the WebDriver logic to a façade, but that is precisely the essence of the Page Object pattern.

The code in Listing 4 shows the implementation of the GIndex page object.

Listing 4. A Page Object for the Cheesr homepage

public class GIndex {
    private List <GrapheneElement> addLinks;

    private GrapheneElement checkout;

    public void addCheese(String cheese) {
        addLinks.stream ()
            .filter(a -> a.getAttribute ("id").contains(safeCheeseId(cheese)))
            .orElseThrow(() -> new NoSuchElementException("Add" + cheese + "link"))

    public boolean checkoutPresent() {
        return checkout.isPresent();

    public By byCart() {
        return By.cssSelector("div[id=cart], input[type=button]");

The code starts with @Location to tell where the page is located in the application: "" means the root. From there all the links are collected, which can add a cheese to the shopping cart. Finally, the addCheese method offers the possibility to add a cheese based on the name by clicking on the corresponding link.

Thanks to Graphene, you can easily apply the Page Objects pattern to create a model of your application, so that your tests remain readable and maintainable. Now we still have to actually make the screenshots. The library aShot is made to make screenshots with WebDriver.

Screenshots with aShot

aShot has a fairly simple but powerful API. You only have to provide aShot with the WebDriver and the element you want to make the screenshot of. aShot will give you the picture. You can do some extra things and so it is useful to wrap it in a function that you can call from your tests.

You can also specify more web elements, of which a picture has to be taken. In addition, it is also possible to add extra space to the elements and you can release filters on the surrounding area, such as black-white or blur (blur) of the edge. The code in Listing 5 shows how you can achieve this with aShot.

Listing 5. Takes a screenshot of specific elements in the page

public static void takeScreenshot(WebDriver browser, String name, By crop) {
    IndentCropper cropper = new IndentCropper(25)
        .addIndentFilter(new MonochromeFilter());

    BufferedImage screenshot = new AShot()
        .takeScreenshot(browser, browser.findElements(crop))

    saveScreenshot(name, screenshot);

Making a screenshot has become very simple with this function. Now we can save screenshots during testing and use them in our manual (see Listing 6).

Listing 6. A test that uses the page object GIndex and takes screenshots

public void step2AddToEmptyCart(@InitialPage GIndex index) {
    Camera.takeScreenshot(browser, "cheesr-2-cart-0-empty.png", index.byCart());
    index.addCheese ("edam");
    Camera.takeScreenshot (browser, "cheesr-2-cart-1-edam.png", index.byCart());

    // assert that the checkout button is present

An example of the screenshots taken in this test is shown in Figure 4. ! Screenshots of listing 6 Figure 5. Two screenshots of the shopping cart

This completes the article. We can now test the application, take screenshots and generate a manual.


We have one integrated whole, because the documentation lives together with the code in AsciiDoc format. We test our application via the browser, thanks to Arquillian and Graphene. During the execution of the tests we make screenshots and focus on exactly those parts that are important with aShot. Maven combines all these steps into one smooth process, which ultimately incorporates our up-to-date manual into our application.

With this setup you can also create internationalized screenshots for multilingual manuals: put your application in another language and perform the tests again. Now only someone willing to translate that 96 pages of text to translate …

View all code on Github

The source code is available on Github: https://github.com/dashorst/nljug-article-2017. It is a Maven project, so you can import it directly into your favorite IDE. The README.md contains instructions for building and running the project. In this article I do not dwell on the specific versions and configuration of plug-ins and dependencies. You can find this in the project.

Is Blendle the Savior of Traditional Media?

3 May 2015

Ever since we invited Alexander Klöpping to our company’s conference as a keynote speaker I have been following his endeavors. He’s a busy fellow and does some amazing stuff. He’s created the University of the Netherlands, a televised series of lectures rich in media by renowned professors. And he created a startup that is shaking up old media.


Blendle strives to revolutionize the way you consume news using micropayments in a sensible way. Blendle has contracted with several traditional newspapers and magazines (mostly in the Netherlands and Belgium), and is now increasing its reach across the atlantic ocean with content from the Wall Street Journal and the New York Times.

The idea is that you can read an article for a small amount of money–a micro-payment. So one article could set you back €0.19 and another €0.59. The price depends on the publisher, the content and demand.

Curated content combined with technology

The site features a lot of curated content and automated trending content. Of course any article you read is accompanied by a list of related articles.

Blendle’s setup wizard lets you create your own curated list of publications. The publications you have selected will be featured in a section called “My Blendle” and will list the most popular articles. You can also select categories that will form the top menu bar and the site will select the trending and popular articles for each category:

Blendle top menu bar showing categories

For example I picked “Tech”, “Big Interviews”, “Foreign”, “Science”, “Media” and “Education” as my categories, as shown in the prior image.

When you want “Share on the Interwebs” Blendle has you covered, allowing you to share links to articles through social media (Twitter, Facebook and LinkedIn), the platform itself or through email.

Engage more with the daily newsletters

You’ll recieve a curated list of articles of all morning editions in your inbox. You’ll also receive a message when a new issue of a magazine is published, and one message at the end of the week with an overview of the most important and popular articles.

Blende daily newsletter

Of course you can opt out of these messages with a familiar “Recieve too much mail from us? Click here to unsubscribe of this daily newsletter”. The preferences page on their site has several options for customizing your need to stay informed.

Each daily message ends with a nice “Psst, this is also noteworthy” suggestion for some tongue in cheek content, making the newsletter bit more entertaining. For example:

Pssssssst! Eva had an affair with a co-worker just after getting married. The affair stopped and her marriage was saved, but then Eva ran into her co-worker by chance

Of course this is click bait, but the Blende team appears to use it as a form of satire rather than a monetization strategy.

Readers can have their cake and eat it too

The platform is thought through very well: when you are already a subscriber to a participating newspaper you get all their articles for free on blendle–you already paid for them. You still get access to all other articles from other publishers, and there’s no risk of paying for an article twice.

Buy an issue or use an existing subscription with Blendle

When you read an article you can get the whole issue where it appeared in (e.g. the saturday newspaper) at a discount: the amount you already spent on the articles of that issue. While I haven’t tried it, it wouldn’t surprise me that when you buy enough articles to offset the cost of the complete issue, it unlocks the issue automatically.

Satisfaction guarantee or your money back

When you read an article but don’t like it, or the price doesn’t fit the article in your opinion, Blendle will gladly refund you. You’re only asked a simple question: why you want your money back. Blendle provides you with a list of prepared answers, or provide your own feedback for the author and publisher.

Satisfaction Guarantee or your money back

The ease of getting a refund makes it risk free for clicking on articles. The price of newspaper articles is low enough to ignore the cost and are pretty much on par what you’d want to pay. Articles from magazines (looking at you Viva) are often priced too high in my short experience with the platform.

Blendle also released an app for mobile called “Blendle Trending”. It currently only shows the curated list of trending articles, and your reading list. It was launched as a single day public beta on the App Store for iOS. The app works, but is very limited in its use when compared to the web site. I expect the app to become the major interaction vector for Blendle really soon.

Awesome design

The design of the website (and app) is gorgeous. The articles look good, are nicely typesetted using good readable fonts not unlike the original publication’s type face. In fact the website loads about 45 different type faces in multiple weights.

The gorgeous design of Blendle

The user experience is great too. The tone of voice is familiar, friendly. It might be a bit too familiar for some folks, but it didn’t bother me. As the site is aimed at the 20 something crowd I think they hit the sweet spot.


The Blendle team has created a really interesting platform for the future of publications, enticing youngsters to read background articles that were previously hidden inside old media. Who has time to read magazines, news papers and other publications in our age of 140 character snippets? Who even has time to read 140 character snippets when a couple of 😜🎓✈️ will do?

Blendle has crafted a great experience to entice not only the youngsters but also the old media. Springer and the New York Times are on board as investors and have their publications available through the site. The team has grown from 3 to 40 in a very short time and is one of the Netherlands’ most successful start ups.

I’m just a recent user of Blendle, but I’ll keep checking their site and application for more interesting news every day, consuming it a micropayment at a time.

How to keep YouTube working on your first gen iPad

26 April 2015

YouTube is shutting down version 2 of its API, effecitvely killing the support for devices that have YouTube apps that haven’t been updated to use the newer version. This includes many ‘Smart’ TVs, and of course the first iPad.

The YouTube API is used to search for, and serve videos to your devices. The version 2 of the API provided limited ad support to YouTube, which makes the site run. That combined with a declining number of users of the old API version, made YouTube decide to shut down the old version. This saves on a lot of maintenance on their part.

This decision leaves many parents without a working YouTube app on their old, passed down iPad 1s. The first iPad is stuck at iOS 5.1 and starting from iOS 6 Apple no longer provides their own YouTube app, nor will Apple update the old YouTube app to use the newer version of the YouTube API.

YouTube suggests using the mobile version of their website, but considering that the Safari browser on the first iPad is also no longer maintained and has many unfixed security issues, this is not a good path to take.

Fortunately there seems to be a workaround to install an older version of the official YouTube app on your iPad 1:

  1. purchase the official YouTube app on a supported device
  2. on your iPad 1 go to App Store » Purchased
  3. search for YouTube
  4. click the download button

Your iPad will ask you to download an older version of the app, because the current version requires iOS 6.

  1. Confirm the download of the older version
  2. $$$ profit

This will install a new YouTube app on your iPad with an updated (but older) YouTube icon (white shield with black “You” and a red button with white “Tube”).

Enjoy while it lasts!

Improve Error Reporting in Java EE

9 March 2015

While I am a great advocate of adopting standards and have come to dislike ducttaped together solutions of the years, I still have some qualms with Java (EE) in general and WildFly in particular.

My number one dislike is the error reporting during deployment. These are inscrutable, unsolvable, unhelpful messages that are complete and utter gibberish. If there should be one fricking standard that should be adopted for Java EE 8 it should be better, standardized error reporting.

Exhibit A:

14:47:37,980 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-15) MSC000001: Failed to start service jboss.deployment.subunit."eduarte-deliverable-dev-ear.ear"."eduarte-common-dao-2.42-SNAPSHOT.jar".PARSE: org.jboss.msc.service.StartException in service jboss.deployment.subunit."eduarte-deliverable-dev-ear.ear"."eduarte-common-dao-2.42-SNAPSHOT.jar".PARSE: JBAS018733: Failed to process phase PARSE of subdeployment "eduarte-common-dao-2.42-SNAPSHOT.jar" of deployment "eduarte-deliverable-dev-ear.ear"
	at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:166) [wildfly-server-8.1.0.Final.jar:8.1.0.Final]
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1948) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1881) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [jrebel-bootstrap-a53fd962a83484078782af30d2cabc06.jar:1.8.0_31]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [jrebel-bootstrap-a53fd962a83484078782af30d2cabc06.jar:1.8.0_31]
	at java.lang.Thread.run(Thread.java:745) [jrebel-bootstrap-a53fd962a83484078782af30d2cabc06.jar:]
Caused by: org.jboss.msc.service.ServiceNotFoundException: Service service jboss.ejb.default-resource-adapter-name-service not found
	at org.jboss.msc.service.ServiceContainerImpl.getRequiredService(ServiceContainerImpl.java:668) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
	at org.jboss.as.ejb3.deployment.processors.MessageDrivenComponentDescriptionFactory.getDefaultResourceAdapterName(MessageDrivenComponentDescriptionFactory.java:278)
	at org.jboss.as.ejb3.deployment.processors.MessageDrivenComponentDescriptionFactory.processMessageBeans(MessageDrivenComponentDescriptionFactory.java:155)
	at org.jboss.as.ejb3.deployment.processors.MessageDrivenComponentDescriptionFactory.processAnnotations(MessageDrivenComponentDescriptionFactory.java:82)
	at org.jboss.as.ejb3.deployment.processors.AnnotatedEJBComponentDescriptionDeploymentUnitProcessor.processAnnotations(AnnotatedEJBComponentDescriptionDeploymentUnitProcessor.java:58)
	at org.jboss.as.ejb3.deployment.processors.AbstractDeploymentUnitProcessor.deploy(AbstractDeploymentUnitProcessor.java:81)
	at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:159) [wildfly-server-8.1.0.Final.jar:8.1.0.Final]
	... 5 more

And a couple of hundred lines below:

14:47:42,608 ERROR [org.jboss.as.controller.management-operation] (Controller Boot Thread) JBAS014613: Operation ("deploy") failed - address: ([("deployment" => "eduarte-deliverable-dev-ear.ear")]) - failure description: {"JBAS014671: Failed services" => {"jboss.deployment.subunit.\"eduarte-deliverable-dev-ear.ear\".\"eduarte-common-dao-2.42-SNAPSHOT.jar\".PARSE" => "org.jboss.msc.service.StartException in service jboss.deployment.subunit.\"eduarte-deliverable-dev-ear.ear\".\"eduarte-common-dao-2.42-SNAPSHOT.jar\".PARSE: JBAS018733: Failed to process phase PARSE of subdeployment \"eduarte-common-dao-2.42-SNAPSHOT.jar\" of deployment \"eduarte-deliverable-dev-ear.ear\"
    Caused by: org.jboss.msc.service.ServiceNotFoundException: Service service jboss.ejb.default-resource-adapter-name-service not found"}}
14:47:42,642 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "eduarte-portal-eo-student.war" (runtime-name : "eduarte-portal-eo-student.war")
14:47:42,642 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "eduarte-portal-eo-ouder.war" (runtime-name : "eduarte-portal-eo-ouder.war")
14:47:42,642 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "eduarte-portal-eo-docent.war" (runtime-name : "eduarte-portal-eo-docent.war")
14:47:42,642 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "eduarte-portal-eo-bedrijf.war" (runtime-name : "eduarte-portal-eo-bedrijf.war")
14:47:42,643 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "eduarte-portal-eo-authenticator.war" (runtime-name : "eduarte-portal-eo-authenticator.war")
14:47:42,643 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 28) JBAS018559: Deployed "eduarte-deliverable-dev-ear.ear" (runtime-name : "eduarte-deliverable-dev-ear.ear")
14:47:42,644 INFO  [org.jboss.as.controller] (Controller Boot Thread) JBAS014774: Service status report
JBAS014777:   Services which failed to start:      service jboss.deployment.subunit."eduarte-deliverable-dev-ear.ear"."eduarte-common-dao-2.42-SNAPSHOT.jar".PARSE: org.jboss.msc.service.StartException in service jboss.deployment.subunit."eduarte-deliverable-dev-ear.ear"."eduarte-common-dao-2.42-SNAPSHOT.jar".PARSE: JBAS018733: Failed to process phase PARSE of subdeployment "eduarte-common-dao-2.42-SNAPSHOT.jar" of deployment "eduarte-deliverable-dev-ear.ear"

14:47:42,653 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on
14:47:42,653 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on
14:47:42,654 ERROR [org.jboss.as] (Controller Boot Thread) JBAS015875: WildFly 8.1.0.Final "Kenny" started (with errors) in 22967ms - Started 1208 of 1315 services (4 services failed or missing dependencies, 225 services are lazy, passive or on-demand)
14:47:42,936 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-13) JBAS015974: Stopped subdeployment (runtime-name: eduarte-common-dao-2.42-SNAPSHOT.jar) in 38ms
14:47:42,942 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015974: Stopped subdeployment (runtime-name: eduarte-ws-eo-rest-2.42-SNAPSHOT.war) in 44ms
14:47:43,054 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-6) JBAS015974: Stopped subdeployment (runtime-name: eduarte-sis-web-main.war) in 156ms
14:47:43,088 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-9) JBAS015877: Stopped deployment eduarte-deliverable-dev-ear.ear (runtime-name: eduarte-deliverable-dev-ear.ear) in 195ms
14:47:43,136 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018558: Undeployed "eduarte-deliverable-dev-ear.ear" (runtime-name: "eduarte-deliverable-dev-ear.ear")
14:47:43,137 INFO  [org.jboss.as.controller] (DeploymentScanner-threads - 2) JBAS014774: Service status report
JBAS014777:   Services which failed to start:      service jboss.deployment.subunit."eduarte-deliverable-dev-ear.ear"."eduarte-common-dao-2.42-SNAPSHOT.jar".PARSE

14:47:47,715 WARN  [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 2) JBAS015002: Deployment of 'eduarte-web-main.war' requested, but the deployment is not present
14:47:47,715 INFO  [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 2) JBAS015003: Found eduarte-deliverable-dev-ear.ear in deployment directory. To trigger deployment create a file called eduarte-deliverable-dev-ear.ear.dodeploy

Apparently something is missing, but the stack traces don’t contain any code that is under my purview, and the error message is really clear and helpful in identifying what is missing:

MSC000001: Failed to start service jboss.deployment.subunit.”eduarte-deliverable-dev-ear.ear”.”eduarte-common-dao-2.42-SNAPSHOT.jar”. PARSE: org.jboss.msc.service.StartException in service jboss.deployment.subunit.”eduarte-deliverable-dev-ear.ear”.”eduarte-common-dao-2.42-SNAPSHOT.jar”. PARSE: JBAS018733: Failed to process phase PARSE of subdeployment “eduarte-common-dao-2.42-SNAPSHOT.jar” of deployment “eduarte-deliverable-dev-ear.ear”

Which is caused by:

org.jboss.msc.service.ServiceNotFoundException: Service service jboss.ejb.default-resource-adapter-name-service not found

What the hell is Wildfly trying to tell me?

The solution (of course) is to run the configuration script that is external to our application, in order to tell Wildfly that a new message queue should be added:

15:03:30,952 WARN  [org.jboss.messaging] (management-handler-thread - 2) JBAS011618: There is no resource matching the expiry-address jms.queue.ExpiryQueue for the address-settings #, expired messages from destinations matching this address-setting will be lost!
15:03:30,952 WARN  [org.jboss.messaging] (management-handler-thread - 2) JBAS011619: There is no resource matching the dead-letter-address jms.queue.DLQ for the address-settings #, undelivered messages from destinations matching this address-setting will be lost!
15:03:31,033 WARN  [org.jboss.as.messaging] (MSC service thread 1-16) JBAS011600: AIO wasn't located on this platform, it will fall back to using pure Java NIO. If your platform is Linux, install LibAIO to enable the AIO journal
15:03:31,149 INFO  [org.hornetq.core.server] (ServerService Thread Pool -- 72) HQ221000: live server is starting with configuration HornetQ Configuration (clustered=false,backup=false,sharedStore=true,journalDirectory=/Users/dashorst/Workspaces/luna/wildfly-8.1.0.Final/standalone/data/messagingjournal,bindingsDirectory=/Users/dashorst/Workspaces/luna/wildfly-8.1.0.Final/standalone/data/messagingbindings,largeMessagesDirectory=/Users/dashorst/Workspaces/luna/wildfly-8.1.0.Final/standalone/data/messaginglargemessages,pagingDirectory=/Users/dashorst/Workspaces/luna/wildfly-8.1.0.Final/standalone/data/messagingpaging)
15:03:31,151 INFO  [org.hornetq.core.server] (ServerService Thread Pool -- 72) HQ221006: Waiting to obtain live lock
15:03:31,222 INFO  [org.hornetq.core.server] (ServerService Thread Pool -- 72) HQ221013: Using NIO Journal
15:03:31,288 INFO  [io.netty.util.internal.PlatformDependent] (ServerService Thread Pool -- 72) Your platform does not provide complete low-level API for accessing direct buffers reliably. Unless explicitly requested, heap buffer will always be preferred to avoid potential system unstability.
15:03:31,359 INFO  [org.hornetq.core.server] (ServerService Thread Pool -- 72) HQ221043: Adding protocol support CORE
15:03:31,372 INFO  [org.hornetq.core.server] (ServerService Thread Pool -- 72) HQ221043: Adding protocol support AMQP
15:03:31,380 INFO  [org.hornetq.core.server] (ServerService Thread Pool -- 72) HQ221043: Adding protocol support STOMP
15:03:31,427 INFO  [org.hornetq.core.server] (ServerService Thread Pool -- 72) HQ221034: Waiting to obtain live lock
15:03:31,428 INFO  [org.hornetq.core.server] (ServerService Thread Pool -- 72) HQ221035: Live Server Obtained live lock
15:03:31,610 INFO  [org.hornetq.core.server] (ServerService Thread Pool -- 72) HQ221007: Server is now live
15:03:31,610 INFO  [org.hornetq.core.server] (ServerService Thread Pool -- 72) HQ221001: HornetQ Server version 2.4.1.Final (Fast Hornet, 124) [1141831d-c665-11e4-86db-0ffb92fb33f7] 
15:03:31,666 INFO  [org.jboss.as.messaging] (ServerService Thread Pool -- 72) JBAS011601: Bound messaging object to jndi name java:/messaging/ConnectionFactory
15:03:31,672 INFO  [org.hornetq.core.server] (ServerService Thread Pool -- 73) HQ221003: trying to deploy queue jms.queue.eventQueue
15:03:31,785 INFO  [org.jboss.as.messaging] (ServerService Thread Pool -- 73) JBAS011601: Bound messaging object to jndi name queue/eventQueue
15:03:31,820 INFO  [org.jboss.as.connector.deployment] (MSC service thread 1-10) JBAS010406: Registered connection factory java:/messaging/JmsXA
15:03:31,908 INFO  [org.hornetq.ra] (MSC service thread 1-10) HornetQ resource adaptor started
15:03:31,908 INFO  [org.jboss.as.connector.services.resourceadapters.ResourceAdapterActivatorService$ResourceAdapterActivator] (MSC service thread 1-10) IJ020002: Deployed: file://RaActivatorhornetq-ra
15:03:31,910 INFO  [org.jboss.as.connector.deployment] (MSC service thread 1-5) JBAS010401: Bound JCA ConnectionFactory [java:/messaging/JmsXA]
15:03:31,910 INFO  [org.jboss.as.messaging] (MSC service thread 1-16) JBAS011601: Bound messaging object to jndi name java:jboss/DefaultJMSConnectionFactory

Unfortunately the original error message did not provide any useful insights as to what was missing.


20 February 2015

A list of all active space probe missions including mission details.

New Horizons Rosetta
The New Horizons and Rosetta missions

Via @kottke

Brianna Wu Risking Life versus Gamergate

20 February 2015

Unreal what happens to Brianna Wu. I admire her will to continue to fight the good fight and I hope she’ll be safe. Nobody deserves what she has to go through. This is from 9 days ago:

This weekend, a man wearing a skull mask posted a video on YouTube outlining his plans to murder me. I know his real name. I documented it and sent it to law enforcement, praying something is finally done. I have received these death threats and 43 others in the last five months.

Read the whole article and be appalled at the threats and vitriol she recieves for being a woman in tech.

IBM Design Language

10 February 2015

Who’d thought: IBM talking design.

“Living Language – A shared vocabulary for design”

Via Daring Fireball

Designing a Backend for a Famous Backend

10 February 2015

When Kim Kardashian and Paper magazine set out to break the internet, it was the task of one engineer to make sure that Paper’s backend systems wouldn’t crumble under the weight of Kim’s backend.

Hosting that butt is an impressive feat. You can’t just put Kim Kardashian nudes on the Internet and walk away —that would be like putting up a tent in the middle of a hurricane. Your web server would melt. You need to plan.

And the understatement of the year:

“We may get a lot of traffic.”

Rather interesting read how to scale a system with mostly static content, but that will get hammered by millions within a few hours.

I'm an Anti-Braker

10 February 2015

A brilliant piece by Robert Moore:

A few weeks ago I saw a car accident - two people went through an intersection at the same time. Both slammed on their brakes at the same time and collided. Fortunately no one was seriously injured.

But then it occurred to me - if they had just gone through the intersection, they wouldn’t have collided. The brakes CAUSED the accident!

Maven incremental builds

6 February 2015

One of the issues we have at our company is that build times for our major products take a long time to complete, hindering adoption of non-incremental build IDEs such as Netbeans.

A possible way out is to adopt takari’s incremental build features. This is certainly something we are going to try out in the coming week(s).

From the Takari Lifecycle as a replacement for Maven’s default lifecycle page:

TEAM includes an optimized replacement for the Maven default lifecycle. The Takari Lifecycle Plugin provides you access to a number of significant advantages:

  1. One plugin with a small set of dependencies provides equivalent functionality to five plugins with a large set of transitive dependencies. This reduces the download times to retrieve the needed components as well as the storage space requirements in your repositories.

  2. The configuration for a number of aspects for your build is centralized to one plugin and simplified.

  3. The reduced complexity of the plugins involved in the build, results in higher build performance on the command line and in the IDE.

  4. The build is fully incremental, not only for your source code, but also for your resources, which in turn again speeds up development cycle and build times.

  5. Dedicated IDE support brings the advantages of the lifecyle to your daily development work.

The AI Revolution: The Road to Superintelligence

6 February 2015

In the category of interesting things to read when you have some time, this first part of a series by Tim Urban should be on your list:

It’s most intuitive for us to think linearly, when we should be thinking exponentially. If someone is being more clever about it, they might predict the advances of the next 30 years not by looking at the previous 30 years, but by taking the current rate of progress and judging based on that.


And everything we just mentioned is still only taking in stagnant information and processing it. To be human-level intelligent, a computer would have to understand things like the difference between subtle facial expressions, the distinction between being pleased, relieved, content, satisfied, and glad, and why Braveheart was great but The Patriot was terrible.

Read it all. Part 2 is also available.

Missing the Point of Server-Side Rendered JavaScript Apps

6 February 2015

The death of server-side rendering has been greatly exaggerated. Ember.js developer Tom Dale:

Say what you will about server-rendered apps, the performance of your server is much more predictable, and more easily upgraded, than the many, many different device configurations of your users. Server-rendering is important to ensure that users who are not on the latest-and-greatest can see your content immediately when they click a link.

Interesting things brewing in the Ember.js space.

Eclipse: confidence lost

7 October 2014

Today I lost about 2 hours of time trying to figure out why my modified code didn’t end up in my running application server, even while I use JRebel to reload classes.

It was caused by having the “Build automatically” flag turned off.

Upfront this is clearly a PEBCAK failure on my part.

What frightens me is my complete and utter distrust of Eclipse’s plugin system that made me go on a yak shaving mission in trying to find which plugin failed to work this time, instead of remembering the obvious, glaring setting that enables/disables builds.

Eclipse has failed so many times to work properly that I have lost the confidence in its ability to help me be a better developer.

And no: this is not a plight for alternative IDEs: I’ve tried them all and still think Eclipse is a better fit for me. YMMV.

iPhoto Considered Harmful

25 August 2014

Screenshot of iPhoto repairing my library

I collect my precious photos in iPhoto. iPhoto is Apple’s photo management application for families–or so I thought. Unfortunately while designing the application Apple in all its wisdom thought that the personal computer would be the ‘Digital Hub’, without taking into account that people would own multiple PC’s to access that Digital Hub–in our case our photo library.

The last few weeks I have been repairing, rebuilding and restarting my iPhoto library to no avail. iPhoto is completely and utterly unsuited as a photo library management application. It looses track of your photos, it looses metadata, EXIF information and worst of all denies you access to the precious photos of your family on a regular basis.

iPhoto’s library is not just a folder structure with your photos neatly distributed around it such as normal users would structure a photo library, but it is a structure that encompasses a database. I should give the Apple engineers credit for not putting the actual photos into said database–if you open the libary you can see the originals sitting comfortably in a folder called Masters, organized by the date of import.

To accomodate the following usecases we keep our iPhoto libraries on a NAS:

  • accessibility from multiple computers in our home network
  • redundancy in hardware through a RAID-1 setup, which uses two drives to store all data twice, also called mirrorring
  • automatic backups of our memories through autobackup tools supplied by the NAS vendor

For the last 4 weeks since I uploaded my vacation photos to my iPhoto library I cross my fingers in idle hope every time I start iPhoto that the gods that be will allow unhampered access to my photos.

I have memorized the startup key sequence necessary to coerce iPhoto to do its magic on the database:

I have started all options in vain. I had to create a new, empty iPhoto library and import all photos from my broken beyond help original library. This removed all metadata, all event information and even modified EXIF data.

Screenshot of iPhoto updating my library

With this new library in place it took two nights of work to recategorize all photos and movies into the vacations we have had over the years. We did loose all metadata associated with the photos: the detailed location information added because our 2005 camera didn’t have a GPS for example.

Insanity is repeating the same mistakes and expecting different results.

And yet when we were selecting the photos of our last vacation to put into a photoalbum, iPhoto randomly corrupted the database again. This with a clean library only 2 weeks old. I had to do the restart machine, repair permissions, rebuild library and repair database rain dance all over again. I was this close to raiding the freezer of a chicken and waving it in front of my MacBook.

I desperately await the day Apple pulls the plug on iPhoto. I hope the new Photos platform will be of this day and age and won’t force me to start using Google’s Picasa–they already read all my email and search queries, I don’t want them to own my photos too.

Can I fault the developers at Apple for this? I’d like to but I guess a multi-user design for the underlying system didn’t make the drawing board as that doesn’t demo well enough. I blame the internal system at Apple that is responsible for such design decisions for this monstrocity of an application.

After last couple of weeks’ experience I consider iPhoto harmful, and so should you.

Maven Release plugin: a lesson in pain, failure and depression

22 August 2014

When trying to release Wicket using the maven-release-plugin I’m often presented with a failed build because Maven couldn’t upload to Apache’s Nexus instance (remote closed the connection). Of course that shouldn’t happen but I’m not holding my breath for a solution anytime soon.

The failed build causes me to have to restart the release from scratch. Now folks have told me previously that I need to run

  • cd target/checkout
  • mvn -rf module deploy

instead of using the release plugin. However, this is not very pragmatic when you have to provide all parameters configured in the build script at the command line, and it goes against all my principles of having an automated build.

So I figured to configure the maven-deploy-plugin to retry uploads, and only upload at the end so I first get test failures and not a half filled staging repository when something goes awry:


Lo and behold, this doesn’t work, because the Maven Deploy Plugin no longer uploads anything during “release:perform”.

So you think: no problem I just run mvn deploy from the checkout and be done with it… Nope. Maven:

  • starts building the artefacts again and
  • testing them again (for the 3rd time) and
  • packaging them again
  • and …

How anyone can actually use this contraption effectively is beyond me. And it appears I’m not the only one.

What now?

M2E Eclipse Settings Plugin

15 July 2014

At work (Topicus) we just released a M2E plugin for Eclipse that enables you to manage your workspace settings for your team from your Maven POM file.

The M2E Settings plugin allows you to specify your Eclipse settings once, and have them delivered across your team with ease.

If you are still using the maven-eclipse-plugin to generate your project files and use its configuration jar setup you can now switch to using M2E because our plugin will maintain these settings for you.

You could configure the maven-eclipse-plugin in your project’s POM like so:


So previously you had to manually apply the settings using the maven-eclipse-plugin. This would copy all the configured files to their locations, and configure Eclipse (a restart of the workspace is typically required):

$ mvn eclipse:eclipse

And with the right configuration this would create, amongst other things for each of your projects a .settings folder with your configuration files:

$ ls -l .settings/
total 160
-rw-r--r--  1 dashorst  staff     85 Nov 29  2013 edu.umd.cs.findbugs.plugin.eclipse.prefs
-rw-r--r--  1 dashorst  staff     88 Nov 29  2013 org.eclipse.core.resources.prefs
-rw-r--r--  1 dashorst  staff    206 Nov 29  2013 org.eclipse.jdt.apt.core.prefs
-rw-r--r--  1 dashorst  staff  29892 Nov 29  2013 org.eclipse.jdt.core.prefs
-rw-r--r--  1 dashorst  staff  11754 Nov 29  2013 org.eclipse.jdt.ui.prefs
-rw-r--r--  1 dashorst  staff     86 Apr  5  2013 org.eclipse.m2e.core.prefs
-rw-r--r--  1 dashorst  staff    575 Nov  7  2013 org.eclipse.wst.common.component
-rw-r--r--  1 dashorst  staff    167 Apr 19  2013 org.eclipse.wst.common.project.facet.core.xml
-rw-r--r--  1 dashorst  staff    403 Nov 29  2013 org.eclipse.wst.validation.prefs
-rw-r--r--  1 dashorst  staff     77 Aug 25  2013 org.hibernate.eclipse.console.prefs
-rw-r--r--  1 dashorst  staff    262 Nov 29  2013 org.maven.ide.eclipse.prefs

Unfortunately with the advent of Eclipse 4.3 and its M2E integration, the maven-eclipse-plugin can no longer be used. But we still want the settings to be applied to all our projects.

In comes an Eclipse plugin that hooks up M2E and the maven-eclipse-plugin to use the same configuration and instructs M2E to fulfill the role of the maven-eclipse-plugin.

The M2E Settings plugin piggybacks on the configuration you already had in place for the maven-eclipse-plugin. This makes it easier to migrate your team members without forcing everyone to start using M2E.

For more information about the M2E Settings plugin, take a look at the project on Github and try it out. It should be added to the Eclipse Marketplace somewhere tomorrow, making it easier to find and install.

This plugin was made possible by Olivier Nouguier, so many thanks for his initial work.

Go check out the M2E Settings Plugin and have fun!

Fix wrong iPhoto upload

10 July 2014

When you select the wrong iPhoto library–say a backup copy of your iPhoto library–and upload your son’s birthday pictures, and then erase your memory card to take more pictures, you find yourself in a pile of hurt.

It is unclear if an rsync between both libraries will work: will the extra photos appear in the library or not. Will they have an event attached, etc. Your main library with over 5 years of photos of your child is not something to experiment with.

So I figured that you need to find out the files that are present in one library and not in the other, and copy them to an outside location. From that point on, you can just import the photos using the standard iPhoto tooling into the correct library.

Now my NAS (a Synology) creates additional files and folders, and OS X is also notorious for adding hidden folders. I particularly wanted to exclude those files and folders as they were not instrumental in re-importing the missing photographs.

Fortunately rsync has an option to compare two folders and synchronize the missing or updated files to a third location. The command below will copy over the missing or updated files in my master iPhoto library from my backup iPhoto library to an external folder.

Note the exclusion of the “CR2” files–I exclude the RAW versions of my photographs because I didn’t want to have to edit 250 RAW pictures. The JPGs will be good enough for this birthday party. If you care about your RAWs then remove that line.

rsync --verbose --exclude=".AppleDouble" --exclude="*Syno*" \
      --exclude="@eaDir" \
      --exclude="*.CR2"  \
      -h  \
      --archive  \
      --ignore-existing  \
      /volume2/backup/iPhoto.photolibrary/Masters/2014/ \
      --compare-dest=/volume1/Photos/Liam.photolibrary/Masters/2014 \

I can then import these photos from the /volume1/Photos/2014 folder into my master iPhoto library.

Of course note that this is provided as is and you should check if this works for your usecase before running the script on your own photo libraries. Use at your own risk!

Create your own Custom Eclipse Luna

7 July 2014

Ever dreamed of a lean mean Eclipse machine? So did we–and we think we are now living the dream!

At work we have about 30-35 developers working with Eclipse. Each developer has to download their own Eclipse bundle, and ask their co-workers which version they should get:

  • Eclipse for Java Developers
  • Eclipse for JavaEE Developers
  • Eclipse Platform SDK

Neither of these bundles are perfectly alligned with our daily needs.

We are Java developers but use Github for our code repositories. We use Maven (and have migrated our projects to utilize M2E). We have migrated from Subversion to Git a while ago. The Eclipse for Java Developers is bundled with Subversion support, Mylyn support (who uses that?) and some other plugins we don’t use. So while a good starting point it already comes with bagage.

Low-cost airlines motto for development environments: extra bagage costs more.

We are in the transition moving away from our custom monolithic platform (tomcat/spring/hibernate/wicket/cxf) on towards a more commonly accepted platform based on JavaEE 7, where we can skip direct dependencies in favor of a pre-packaged, pre-integrated container.

This migration towards JavaEE would suggest that the Eclipse for JavaEE (EJEE for short) developers would be ideal for us. But it isn’t, far from it! EJEE is slow, enables too many non-essential validations, checks and other tripe that keeps your workspace rebuilding for the next couple of months.

This means that folks would probably download the EJEE edition, and get bogged down in plugins that you need to suspend (with a low success rate), or have to go on a treasure hunt to find the right plugins.

A typical fresh and clean Eclipse installation would take about 2 hours of work to get up and running with the proper tooling and plugins installed. With Eclipse Luna now available, our company was looking for a serious productivity dip while developers are installing the latest and greatest.

Enter yoxos

In our friday “innovation day” project we discovered yoxos: a way to craft and distribute your own custom Eclipse builds and profiles. This was exactly what the doctor ordered!

We were able to craft our own custom Eclipse profile with proper initial settings (like use native polling/hooks to monitor file system changes), nice plugins (like qwickie), and without unnecessary baggage such as a JPA-validator that can’t cope with 800 entities.

All our developers can have a working custom JavaEE Eclipse setup in about 10 minutes. With yoxos we can distribute updates to our setup without any issue. And best of all: our developers can still customize their setup if they choose.

It is also possible to create custom profiles for varying projects that need a particular plugin installed (for example an Android project).

There are some (minor) issues with yoxos though:

  • the yoxos advanced launcher doesn’t work on ubuntu
  • yoxos doesn’t have a way to provision M2E connectors
  • there is no way to add your own profile to the launcher making it more easy to start your custom Eclipse
  • checking out source code for your workspace from the profile doesn’t work (as well) when using private github repositories

We’d also like to be able to provision a wildfly local server and launch configuration using yoxos, but alas that is still something we need to do manually.


Yoxos is highly recommended for crafting your own custom Eclipse distribution inside your company (or university).

Our previous setup model:

  1. download a Eclipse distribution
  2. start Eclipse
  3. wait for eclipse “rebuild workspace” to complete
  4. go to marketplace
  5. select, accept and install plugins
  6. restart
  7. wait for eclipse “rebuild workspace” to complete
  8. add update sites to eclipse to add more plugins
  9. add more plugins
  10. accept licenses and wait for downloads
  11. restart eclipse
  12. wait for eclipse “rebuild workspace” to complete
  13. remember which checkmarks you need to set to make Eclipse workable
  14. wait for eclipse “rebuild workspace” to complete
  15. try to disable a random plugin to get rid of idiotic webservice validations
  16. give up

Our new model:

  1. download Yoxos launcher
  2. start Yoxos launcher
  3. log in
  4. Download our profile
  5. Launch our eclipse profile
  6. Accept licenses and wait for downloads
  7. Wait for eclipse “rebuild workspace” to complete
  8. Start coding
  9. Profit!

Eclipse Console Wish List

3 July 2014

There are a lot of things I like about working with Eclipse. This is not a post about those things. Here I’d like to vent small frustrations I have with Eclipse that would make it feel more like a thoughtful product than something incidental.

This instance I’ll rip on Eclipse’s Run/Debug Console.

Eclipse’s debug/run console is really barebones. It’s my guess that a MS DOS 2.0 prompt gives more formatting possibilities. So here’s my wish list for Eclipse’s console:

  • default infinite scroll buffer (bugzilla)
  • ANSI escape character support (bugzilla)
  • smart scroll lock behavior (bugzilla)

There are more gripes to be had with the console, but for now let’s look at these three.

Default infinite scroll buffer

Vi, less, more, and all other utilities are capable of displaying gigabytes of log files, yet Eclipse’s console seems stuck in the Notepad era. With each new installation and workspace I have to instruct the console to use a infinite scroll buffer. Should Eclipse actually support an infinite scroll buffer, without memory overhead, why not make it the default?

ANSI escape character support

Granted most of the times I’m looking at a long list of log lines produced by SLF4J or some similar logging framework. But even in those circumstances it would be beneficial to have color coded lines (e.g. red colored lines for error level messages)

Sometimes though I have a commandline utility where I’d like to show a progress using a percentage (overwriting the previous state). ANSI control characters would allow that (and is properly supported in most terminals).

Unfortunately someone closed the feature request in Eclipse’s bugzilla instance with no option to reopen it.

Smart scroll lock behavior

Currently the scroll behavior of the console is abysmal. When you scroll back in the log to see if something went awry during startup, any logging activity will put your view back to the end of the log. You can of course lock the scroll position, but then no update will ever be visible because the position is locked. You then have to manually scroll to the end to see the action.

In my opinion scroll behavior could be quite a bit smarter when implemented as follows:

  • When I look at the end of the buffer, scroll lock should be disabled and updates should scroll before my eyes keeping the most recent update in view.

  • Whenever I scroll back, scroll lock should be enabled immediately. There is no use in moving back to the end of the buffer when something new arrives while I am looking at a stack trace.

  • Whenever I scroll forward and reach the end of the buffer, scroll lock should be disabled and updates should scroll before my eyes, keeping the most recent update in view.

I really would like to see these implemented and I think numbers 1 and 3 should not be too hard to implement.