2014-04-08

Quick Start to Logging with SLF4J and Logback for a Maven-based Project

I followed this informative but slightly out -of-date article, How to setup SLF4J and LOGBack in a web app - fast, to get started with logging in my Vaadin web app. Here is my description of the same steps using NetBeans 8 with Java 8 hooked up to Tomcat 8 on a Mac mini running Mavericks.

First create your Maven-based project. In my case, I'm using version 1.1.1 of the Vaadin Plugin for NetBeans  to create a new Vaadin 7.1 project.

Add the logging façade library, SLF4J.
  1. In the NetBeans project navigator pane, context-click on the Dependencies item.
  2. Choose Add Dependency.
  3. Type: slf4j-api
  4. Open the org.slf4j : slf4j-api item to choose the latest version.
I find that repository listing in NetBeans is consistently inconsistent, in other words, psycho-crazy. Close that dialog, repeat the same steps,  and get a different list of version numbers. Sometimes you see later versions, sometimes you see only earlier versions. So check the web site for the desired dependency (SLF4J in this case) to determine the true latest version. Repeat that dialog a few times until it randomly decides to show you a version number close to the true latest. Choose that item. Later you can edit your "pom.xml" to the true latest.

In a fashion similar to SLF4J, let's add Logback. Logback is a direct implementation of that SLF4J façade. You can use nearly any other Java-based logging frameworks in conjunction with an adapter. Logback needs no adapter. Logback is the successor to Log4J, both of which were created by the same man.

We need two jars for LogBack, "classic" and "core". However, adding a dependency for "classic" will automatically get us "core".
  1. In the NetBeans project navigator pane, context-click on the Dependencies item.
  2. Choose Add Dependency.
  3. Type: logback-classic
  4. Open the ch.qos.logback : logback-classic item.
  5. Choose the latest version offered.
Again, you'll probably get a not-quite-right list of versions. Take the latest offered, and update later.

Save all your files, and do a clean-and-build of your project (Hammer & Broom icon) to get Maven to do its duty. You should find in the project navigator pane a new item Other Sources. Expand that item to find a src/main/resources item.
  1. Context-click the src/main/resources item to create a new XML file.
  2. Name the new XML file: logback.xml
  3. Into that file, past the following XML text seen below.
  4. Change the XML text, replacing "com.example" with your own project’s top package.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
 
    <logger name="com.example" level="TRACE"/>

    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>
   
</configuration>


This XML is different than that older article, having replaced the deprecated layout with an encoder. This XML configures Logback to send your logging messages to the NetBeans console. You'll need to make alterations for use when deployed to production, but this should get you started in development.

Now try it out. In your Vaadin app, locate the MyVaadinUI.java file that drives your app.
  1. Add an import: import org.slf4j.*;
  2. At the top of your class definition, add the line:
    static final Logger LOG = LoggerFactory.getLogger(MyVaadinUI.class);
  3. In the init method of this class, add the following code to see if logging works.
        LOG.trace("Yogi - Logging Test - Trace");
        LOG.debug("Yogi - Logging Test - Debug");
        LOG.info("Yogi - Logging Test - Info");
        LOG.warn("Yogi - Logging Test - Warn");
        LOG.error("Yogi - Logging Test - Error");

      
Run your Vaadin app. You may need to do a clean-and-build (Hammer & Broom icon). On one of the tabs in the NetBeans "Output" console pane you should see your messages.

To update the version numbers of SLF4J and Logback, look in the NetBeans project navigator pane. Expand the Project Files item to locate and open "pom.xml" file. Search for "slf4j" and "logback" and update each one’s version tag with the number you know to be current. Saving the XML file may cause Maven to do its duty. If not, try a clean-and-build.

Caveat: I am a Maven and SLF4J and Logback triple newbie. The above steps worked for me, but I cannot say that I understand them fully. Follow these steps at your own risk. Backup your project first.

2014-02-02

Simple Vaadin Charts Example

While watching this video demo, on this Vaadin blog post, about the new Vaadin plugin 1.1.x for NetBeans 7 IDE, I noticed this very simple example being done with Vaadin Charts 1.1.x. Just 3 lines of code.

Vaadin Charts can be a bit overwhelming to approach because of its huge power and flexibility. So I was glad to see, and try, this little "Hello World" example.

NOTE: Vaadin Charts is a commercial product, requiring a paid license. A 30-day free trial is available.

Code…

// Chart
Chart chart = new Chart();
chart.getConfiguration().addSeries( new ListSeries( 1, 2, 3 ) );
layout.addComponent( chart );

You can simply add that code to the default app created by the Vaadin Plugin, and run.

See this YouTube video for another demo of Vaadin Charts, from their webinar.

2014-01-29

Getting To Know "Blocks" in Objective-C

Blocks, also known as closures, are a programming/compiler trick to treat a chunk of code as on object. That chunk of code can be passed around, stored in collections, and executed now or later.

Apple has added full support for Blocks in recent releases of both Xcode versions 4 and 5. Apparently support for blocks was a major motivation for Apple to switch from the old GCC compiler technology to the modern LLVM/Clang world.

Blocks bring a new funky syntax. While truly grokking blocks may strain your brain, simply using them is not so difficult. Basically they replace some uses of Delegation and other callback techniques.

A new introduction and tutorial, Introduction to Objective-C Blocks, just appeared. This is the best written into on this topic that I've seen. The Wikipedia page on Blocks is also worth a look, as is the sibling page on Closure. Yet another good source of info is Part 2 of How to Use Blocks in iOS 5 Tutorial on the RayWenderlich.com site.

2013-10-08

Lowercase UUIDs

The UUID spec requires that hex strings be generated in lowercase, while tolerating uppercase for input.

6.5.4 Software generating the hexadecimal representation of a UUID shall not use upper case letters. NOTE – It is recommended that the hexadecimal representation used in all human-readable formats be restricted to lower-case letters. Software processing this representation is, however, required to accept both upper and lower case letters as specified in 6.5.2.
 Unfortunately, the 'uuidgen' command in Mac OS X is out of compliance with the spec, outputting uppercase. Example:

…$ uuidgen
54B09346-2176-4EF5-AB36-5E8A70D0BC9F


Also, Microsoft utilities in the past have output mixed case, oddly enough (a programing boo-boo according to legend).

This blog post  shares a line of bash code to convert the Mac's hex string to lowercase.
uuidgen | tr [:upper:] [:lower:]

Example:
$ uuidgen | tr [:upper:] [:lower:]
a03959cb-cf12-4de5-89d2-3a3be7963e1c


2013-08-23

Nil Out Views in iOS

Before iOS 6, iOS would take the liberty of deleting any view controller’s view not currently on screen upon a low memory situation. As of iOS 6, Apple decided it would remove the memory-intensive backing stores of the graphical display, and thereby free up some memory, without bothering the app developer. So from the app developer’s point of view, the view remains intact. In actuality, iOS recreates the graphical backing stores when the affected view re-appears. Now iOS 6 no longer invokes either method you may have implemented: viewWillUnload & viewDidUnload.

You can recreate the old behavior. As always, your view controller receives a message about low memory by having its didReceiveMemoryWarning method invoked. You may nil out the controller's view. Be sure to check first that the view is not currently on screen. As always, the  didReceiveMemoryWarning invocation is an opportunity for you to clear unnecessary collections and to close other memory-intensive resources, all in an effort to free up memory.

When the view returns to the screen, you must of course recreate the view and restore the needed resources. Do so in your implementations of the loadView or viewDidLoad methods.

Example code:
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // While off-screen, dispose of the controller's view as well as any memory-intensive variables, collections, and resources that can be recreated. 

    NSLog(@"TRACE - %s:%d someObject=%@", __func__, __LINE__, self);  // If you want to log this for educational purposes.
    if( [self.view window] == nil ) { // Verify view is not on-screen.
        [myCollection removeAllObjects]; // Clear a collection.
        self.myImageView = nil; // Clear a resource.
        self.view = nil; // Re-creating pre-iOS 6 behavior to clear view.
    }
} 

2013-08-20

Poor Yahoo!

I just spent a couple hours trying to explain and fix this error:
<Error>: CGAffineTransformInvert: singular matrix.
…reported in my app's log while I was testing my use of the WebKit widget (UIWebView class) to display HTML.

The "CG" means CoreGraphics, Apple's intense pixel-bending technology. One fellow on the internets says the issue is related to matrix math:
Probably you tried to use singular transformation matrix somewhere in your code. You should check your transformation matrices and avoid matrices like:
0 0 0
0 0 0
0 0 1
and others - check out Google how to tell singular 3x3 matrix (hint: it has determinant = 0).
Blah, blah, blah… All I did was try to load a web page. I'm not doing any graphics work.

I tried all kind of folk remedies related to my use of the UIWebView widget, but nothing worked.

Long story, short…

For this testing, I had randomly picked "http://www.Yahoo.com/" out of thin air as an arbitrary page. This error occurred repeatedly on every run. Eventually I switched to Google.com, no problem. Reuters.com, no problem. SeattleTimes.com, no problem. Go back to Yahoo.com, problem. And problem happens repeatedly while scrolling.

I'm guessing that Yahoo is doing some kind of screwy HTML or JavaScript, probably manipulating images or the page itself graphically, and thereby invoking CoreGraphics and generating the error.

Poor Yahoo can't seem to get anything right anymore.