Friday, December 19, 2008

iPhone Application Development: Memory Management - Part 2

Re read the earlier post about Memory Management. Lots of new stuff and new understanding has been added to the earlier post. It should really be an article in itself.

iPhone Application Development: Collections

Apple provides three basic collection classes: NSArray, NSSet, and NSDictionary. All three of these classes are non-mutable. i.e. once created, they cannot be changed. Their mutable equivalents are NSMutableArray, NSMutableSet, and NSMutableDictionary. All collections store objects only - primitive types can be wrapped in NSNumber and stored in collections.

NSArray is used to store lists of objects. An Ordered Collection. Primitive types can be wrapped in NSNumber. Common operations are supported: count, objectAtIndex, containsObject, etc. NSMutableArray contains additional operations: addObject, insertObject... atIndex, removeObject, removeObjectAtIndex, etc.

NSSet is a set of Objects. An Unordered Collection. An object might appear a maximum of one time. Operations supported are similar to NSArray.

NSDictionary: are equivalent to Map in Java. They store key, value pairs. Both keys and values are objects. Common supported operations: count, objectForKey, allKeys. NSMutableDictionary also supports editing operations such as setObject... forKey, removeObjectForKey.

NSDictionary supports saving to (writeToFile) and loading from (initWithContentsOfFile) files. These are usually called property lists or plists. The file created would be an XML file. Similarly, initWithContentsOfURL, writeToUrl are supported for URL operations.

Memory Management Reminder: Every collection retains an object when its added, and releases it when it is removed. Releasing a collection object releases all the objects stored in it as well.

iPhone Application Development: Using gdb

gdb is a command line debugger. In addition to XCode providing a graphical debugger, Apple includes the gdb debugger with XCode. Setting a breakpoint is as easy as double clicking in the left margin of XCode. This is similar to Eclipse. For those new to gdb, here are a few basic gdb commands to get you started.


print-object anObj
print-object [anObj description]
print-object [nsStr stringByAppendingString:@" yes"]
print (int) [@"John Galt" length]
print (char *) [nsStr UTF8String]

other commands:
call [exp]: Calls the function
set [var] = [exp]
whatis [variable]: print details about variable
help

iPhone Application Development: Objective-C / Cocoa: String Operations

Apple has provided a very nice implementation of the String class. Called NSString. Any string in Objective-C, written as @"Status" is represented in the code as an instance of NSString. Keep in mind that NSString objects are non-mutable. Just like Java String objects.

Go through NSString.h for many many more methods

NSString *nsStr = @"iPhone Development";
int len = [nsStr length]; //
Length of a string
NSString *result = [nsStr stringByAppendingString:anotherNsStr]; Combine 2 strings
NSRange range = [nsStr rangeOfString:@"iPhone"]; // range (not a pointer) would contain location and length of found string
NSString *str = [@"iPhone Application Development" substringFromIndex:7]; // -> Application Development
NSString *str = [@"iPhone Application Development" substringToIndex:6]; // -> iPhone
NSString *str = [@"iPhone Application Development" substringWithRange:NSMakeRange(7, 11)]; // -> Application

NSArray *arrayOfStrings = [@"iPhone Application Development" componentsSeparatedByString:@" "]; // split on space

// Converting between C Strings and NSStrings
NSString *nsStr = [[NSString alloc] initWithUTF8String:"iPhone"];
(const char *)cStr = [nsStr UTF8String];


Mutable Strings: If you need to make modifcations to NSString, use NSMutableString. Some of the valid messages to NSMutableString:


[msMuStr appendString:@" needs an iPhone"];
[msMuStr deleteCharactersInRange:NSMakeRange(7, 11)];
[msMuStr insertString:@" is a good application " atIndex:10];
[msMuStr replaceCharactersInRange:NSMakeRange(7, 11) withString:@" is a good application "];

Monday, December 15, 2008

iPhone Application Development: Memory Management with Objective-C / Cocoa

This discussion touches the basics of memory management within Objective-C / Cocoa. Hopefully, you have already ready my post about differences between C++ / Java and Objective-C.

Cocoa library (and thus Cocoa Touch for iPhone Development) defines NSObject, which is at the root of the entire class hierarchy of the Foundation framework. Every other framework, depends on the Foundation Framework. NSObject implements a semi-automated / reference counting version of garbage collection. Memory manager might be a more appropriate name.

Here is some sample code that helps illustrate how to use NSObject's garbage collection mechanism:

#import <Foundation/Foundation.h>

int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSObject *obj = [[NSObject alloc] init];
NSLog(@"Created object %@", obj);
[obj release];

[pool release];
return 0;
}
NSObject provides the following messages to manage objects via the memory-manager:
  • alloc: Create a new object. Allocates physical memory for the object. This message to be passed to the class. Alloc "retains" the object. i.e. Objects created by alloc have a reference count of 1. Be sure to release it when you are done.
  • init: initializes the object. It is considered best practice to always init the object by sending it the init message. Typical object creation looks like MyClass *obj = [[MyClass alloc] init]; - calls both alloc and init.
    • If you override init, it must always return itself (id). Sample code: if (self = [super init]) { /* my inits */ } return self;
  • dealloc: Free the memory obtained by alloc. Avoid calling dealloc. Always call release - let the memory manager perform dealloc, when appropriate.
  • retain: Signal to the garbage collector that we are intrested in this object. This increases the reference counter for this object by one.
  • release: Signal to the garbage collector that we are no longer interested in this object. This decreases the reference counter by one. When the reference counter reached 0, the object is deallocated. As a general rule, always "release" pointers holding memory. This will let the memory-manager do its job.
NOTE: If you do decide to over-ride any of these methods, be sure to call super's corresponding method at the appropriate time.

Creating an NSAutoReleasePool creates and inits the memory-management system. At the end of the program, the release message to the auto-release pool signals that we are no longer interested in it. The system then disposes off the auto-release pool, and sends release message to all the objects it contains. Any object that gets to a reference count of 0, is deallocated.

General Tips / Rules of thumb related to memory management
  • Classes should override dealloc, if they want to be notified of when the object is put out of its misery. This is an appropriate place for the object to release any memory that it may have allocated. Be sure to call parent's dealloc when you are done.
  • In setters, always retain the new object first, then release the old object. This will take care of cases when the same value is being set over and over again.
  • Maintain atleast one Auto release pool per thread
  • If you have to create an object and return it from a method. Make sure you pass the autorelease method to it. This will add the object to the autorelease pool.
  • This leads to: don't release objects that you receive from other messages. Assume that they have been added to the auto release pool by the creator. release them *only* if you retain them for some reason.
  • Write memory balanced code: total count of alloc, copy, mutableCopy should be equal to the total count of release, autorelease
  • Every collection retains an object when its added, and releases it when it is removed. Releasing a collection object releases all the objects stored in it as well.
  • NSString objects created using @"..." should be considered as constants. retain or release messages have no effect on them.

Objective-C for C++ / Java developers

Here I document the differences between Objective-C and another object oriented language like C++ / Java. The goal is to get someone, who has a fair grasp of object oriented concepts in either C++ or Java or (preferably) both, started with understanding / writing Objective-C code as soon as possible. The goal being effective iPhone Development. If you are reading this without any background, please read my previous post about objective-c "hello world" program structure, and creating a first basic class in objective-c.

This blog entry is a work in progress. I will keep updating this as I learn more about objective-c.

Differences between Objective C and C++ / Java.



















































ConceptC++ / JavaObjective-CDetails
File name extension.h / .c / .cpp / .java.h / .mDeclarations in .h file. Implementation in .m
Declaring a method / messageint add(int x, int y)- (int) add:(int)x with:(int)ytypes are always enclosed in brackets
Calling the method / sending a messageint result = obj.add(10, 12);int result = [obj add:10 with:12];message name and first parameter are same
Nesting method callsint r = obj.add(obj.getX(), obj.getY);int r = [obj add:[obj getX] with:[obj getY]];
FormattingAll printf formats (%s, %d etc)All C formats, and %@%@ prints and object's "description"
Calling methods in parent classsuper.init();[super init];
Refering to myself / current objectthis.add(10, 12);[self add:12 with:12];



Other things
  • Type (id) represents current class. No need to specify name of the class
  • NULL: the keyword "nil" represents a null value.
  • Message passing is nil safe. nil elements do not core dump / throw a NullPointerException. Data members are auto-initialized to nil
  • All method / message binding in Objective-C is dynamic. Classes maintain a list of messages that will be accepted at runtime. All other messages are passed on to parent. This processing happens at run time.
  • For Class level messages, replace the "-" with "+" as the first character of the message declaration and implementation

Objective-C: creating a basic class

Objective-C is an object oriented implementation added to C. Apart from objects, everything is C works in Objective-C. Here, I try to document what a class looks like, and what it all means. Bear in mind that I am just starting to learn objective-c myself, so, wouldn't recommend anyone using this class in a production environment :)

Objective-C separates a class into its declaration and implementation. It is not enforced, but is a best practice to put the declaration in a header (.h) file, and implementation in a .m file. See notes embedded in the source code below for details.

Geek.h (Class declaration)

#import <Foundation/Foundation.h>

// An Objective-C class is declared using the interface tag
// The parent of this class is declared after the ":"
// Best Practice tip: Always inherit from NSObject, when you don't have anything else to inherit from.

@interface Geek : NSObject{
// All data members go inside the braces
NSString *name;
int level;
}

/*
* All supported messages (functions) are declared before the @end tag
* Best-Practice tip: All messages that initialize the class should begin with "initWith".
* This provides the reader with good information.
* a.k.a. declared initializers
*
* You don't really have to declare messages that this class will override.
* It would be good idea to do so, in the interest of readability
*
* All data types are enclosed in brackets.
* id is a special type that means "myself". Any method that declares (id) as return type, must return "self"
*
* Methods don't really have a name. If you want, you could consider the first
* parameter as the name itself.
*/
- (id) initWithName:(NSString *)name level:(int)level;

// As a general rule of thumb, getters usually don't begin with "get"
- (NSString *)name;
- (int)level;
- (void) setName:(NSString *)name;
- (void) setLevel:(int)level;

@end // Marks the end of the interface tag


Geek.m (class definition)

#import "Geek.h"

// implementation of this class starts from here
@implementation Geek

// message definitions follow C rules
// overridden message (not declared, but defined)
- (id) init {
if (self = [super init]) {
level = 10; // set default level
}
}

- (id) initWithName:(NSString *)newName level:(int)newLevel {
[self init];
[self setName:newName];
[self setLevel:newLevel];

return self;
}

- (NSString *)name {
return name;
}

- (int)level {
return level;
}

- (void)setName:(NSString*)newName {
// See blog entry on memory management for retain / release notes.
[newName retain];
[name release];
name = newName;
}

- (void) setLevel:(int)newLevel {
level = newLevel;
}

// This is equivilant to Java's toString method.
- (NSString *)description {
NSString *desc = [NSString stringWithFormat:@"Name=%s level=%d", [name UTF8String], level];
return desc;
}

- (void)dealloc {
[name release];
[super dealloc];
}

@end // marks end of implementation of the class


Using the class above. Write a main.m file:


#import "Geek.h"

int main(int argc, char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

Geek *a = [[Geek alloc] init];
[a setName:@"Jack"];
NSLog(@"Hello. Geek: %@", a);
[a dealloc];

a = [[Geek alloc] initWithName:@"Jill" level:15];
NSLog(@"Hello. Geek: %@", a);
[a dealloc];

[pool release];
return 0;
}


Compiling and running the program:

$ gcc -framework Foundation Geek.m main.m
$ ./a.out
2008-12-15 19:24:47.043 a.out[7052:10b] Hello. Geek: Name=Jack level=10
2008-12-15 19:24:47.045 a.out[7052:10b] Hello. Geek: Name=Jill level=15


There you have it, a pretty useless class, but illustrates basic objective-c usage. Should be useful is getting started with iPhone development.

Linux: The "Terminator" reviewed

Terminator is a cross-platform GPL terminal emulator with advanced features not yet found elsewhere. (or so they claim).

I use terminals a LOT. Whenever something doesn't work the way I want it to, the first thing I do is open a terminal. My main computer is my Mac laptop, and I have a Ubuntu desktop. My preferred tool choice for networking between the two is ssh / scp. That's how much I use terminals.

I came across Terminator from the home page of CrunchBang Linux. Given my terminal usage, and hopes for finding something better, I decided to take The Terminator out for a spin. The web site made it sound the best thing since sliced bread, so I installed "Revision 1478 (2847)" on mac.

Used it for about 15 minutes, and here is what I think:
  • Wow! neat font. I like it. The color combination is also very pleasing. Colors holds up nicely while displaying output (eg. alias ll="ls -lhF --color")
  • Aw shucks! this thing doesn't remember its window size from when I last closed it. Found a setting to set an initial window size, but that's just not the same.
  • Terminator doesn't have a way to manage ssh connections. It won't remember my ssh connections, and per connection settings. I like to set different color combinations for different category of machines. (eg. prod machines are red). This will also be a problem on my (office) windows machine, where my ".ssh" directory is not in my $HOME. Putty manages this well.
  • Visual bell is annoying, but there is a way to turn it off. Good riddance.
  • No integration of "bell" with system audio.
  • Key combos for switching between tabs is easy to remember. Good to have key combos for organizing tabs.
Verdict: In addition to being multi-platform, the font/color combination seems to be the only thing working in favor of The Terminator. I didn't really see any feature(s) that would make my life easier or I couldn't find on Mac's Terminal or Gnome's Terminal or Putty.

I don't see myself replacing any of my existing Terminal apps with Terminator anytime soon. Its good to see the effort / progress being made. Perhaps in a few versions, things will get better.

I would like to start using Terminator, mostly because of the eye-candy, but having a remote / SSH connection manager would be a must. Something that remembers my settings on a per connection basis. A utility to import connections settings from Putty would be awesome.

Sunday, December 14, 2008

"Hello, World!", Objective C / Cocoa style

All iPhone development is done in objective-c, so I started to look into objective-c. Hello World!

The following program has been compiled on an Intel based Mac, using the command line:

$ cat hello.h

#import <Foundation/Foundation.h>

int main(int argc, char *argv[]) {
NSLog(@"Hello, World!");
}
compiling and running:

$ gcc -framework Foundation hello.m
$ ./a.out
2008-12-14 10:41:50.597 a.out[5452:10b] Hello, World!

Differences between objective-c and c++ / java in this example:

1. #import is just like #include. The only difference is that #import is intelligent enough to not include a file more than once.

2. Foundation/Foundation.h: Foundation is the base / core library of programming for iphone / mac. If you need to do anything with cocoa, you need the Foundation "framework". A framework can be thought of as a library. One of the good things Apple did is aggregate all the required headers of all classes in a framework, and made it accessible from one header file. Foundation.h is a huge list of import statements, that gives access to all the class definitions in the Foundation framework.

3. NSLog is the logging function for objective-c/Cocoa. Anything passed to NSLog will be "logged" to stdout.

4. "gcc -framework Foundation hello.m": -framework flag links the binary produced to the Foundation library.

And the rest, as they say, is history :)

Friday, December 12, 2008

Java: Apache Derby: dealing with CLOB errors

While using Apache Derby, I ran into this error:

"A truncation error was encountered trying to shrink CLOB..."

I google'd for the error, but wasn't able to find something that jumps right out, and helps me fix the issue. So, after mucking around for a few minutes, a bulb went over my head: I had let hibernate create / update the table schema as it saw fit. Sure enough, hibernate created a CLOB that was too small.

The default CLOB size assigned by hibernate was 255, which, IMHO, is WAY too small for a CLOB. I mean, why use a CLOB at all, if you are just going to store 255 bytes. A varchar would be a much better choice.

Anyway, so I deleted the table (manually), and re-created it with the default size of 2GB.

ij> describe report_description;
COLUMN_NAME |TYPE_NAME|DEC&|NUM&|COLUM&|COLUMN_DEF|CHAR_OCTE&|IS_NULL&
------------------------------------------------------------------------------
NAME |VARCHAR |NULL|NULL|255 |NULL |510 |NO
FIELDS |CLOB |NULL|NULL|255 |NULL |NULL |YES

2 rows selected

ij> drop table REPORT_DESCRIPTION;
0 rows inserted/updated/deleted

ij> create table REPORT_DESCRIPTION(name varchar(255), fields clob);
0 rows inserted/updated/deleted

ij> describe report_description;
COLUMN_NAME |TYPE_NAME|DEC&|NUM&|COLUM&|COLUMN_DEF|CHAR_OCTE&|IS_NULL&
------------------------------------------------------------------------------
NAME |VARCHAR |NULL|NULL|255 |NULL |510 |YES
FIELDS |CLOB |NULL|NULL|21474&|NULL |NULL |YES

2 rows selected

My app ran fine after that.

Note that Apache Derby does not care about the case of the table / field names.

iPhone Developer Program: Is it worth signing up?

I started looking into the iPhone development. Which led me to Apple's iPhone developer website. After a free, cursory sign-up, I was be able to download xcode (bundle of the chosen IDE for iPhone and Mac development, along with all the iPhone development libraries), and a whole bunch of getting started documents, along with iTunes video presentations... The whole shebang...

Of course, you do need an Intel-based Mac to do any "official" development work with the SDK.

I was pondering if I should sign up for the iPhone Developer Program and pay $99 for the privilege. Unfortunately, Apple's website provides no information about what does one gains from signing up for the program. So I did what any self respecting geek would do: google for info, post on mailing lists, and then blog about it, for the benefit of the general populous.

Without paying for the program, you:
  1. Can download the complete development environment, along with all the libraries, frameworks and other useful tools (xcode, interface builder, iPhone simulator, etc...)
  2. Can access all the available documentation, code samples, video presentations etc. at Apple's website.
  3. Can get started with building iPhone applications.
  4. Can run applications in the iPhone simulator.
  5. Cannot test your applications on an actual iPhone.
What you cannot do, and can be done only by paying members:
  1. You get a bunch of certificates that enable you to deploy, and test your applications on an actual iPhone or iPod touch device.
  2. You get on-device debugging capabilities.
  3. You get pre-release versions of the iPhone OS and API.
  4. You get access to Official Apple iPhone Developer Forums. The main benefit here is interacting with Apple employees, who hang out there. Sometimes, public service announcements are also made on these forums.
  5. And most important of all: Submit your applications to Apple.
If you just wat to get up to speed on the iPhone development SDK and see what its all about, you don't have to be a paying member of the program.

But, if you decide to get serious about it, you would need to become a paying member of the iPhone developer program.

Thursday, December 11, 2008

Posting copy-able code in a blog

I ran into a problem where I could not put code into blog entries. So, after much research, I found that:

1. Make sure the maximum number of characters without spaces is 80. Anything else will be wrapped and lost

2. To add code (Java / C++ / C# etc.) in your blob entry, "Edit Html", and enclose the code in:

<pre style="font-size: 90%;"><code>
--- PASTE CODE HERE ----
</code></pre>

3. To Embed / insert xml code into html / blog entry, you must get rid of all of these characters from XML and replace then with their equivalent HTML friendly format: '<', '>', '&'. For a pretty display, I also converted all tabs to 4 spaces. Here is Java code that helped me do just that:

import java.io.FileReader;

public class ConvertToHtml {

public static void main(String[] args) throws Exception {
if (args.length != 1) {
usage();
return;
}

FileReader fr = new FileReader(args[0]);
int c;
while ((c = fr.read()) != -1) {
if (c == '<') {
System.out.print("<");
}
else if (c == '>') {
System.out.print(">");
}
else if (c == '&') {
System.out.print("&");
}
else if (c == '\t') {
System.out.print(" "); // 4 spaces to a tab
}
else {
System.out.print((char) c);
}
}
fr.close();
}

private static void usage() {
System.out.println("This util converts input to html safe code");
System.out.println("Please pass one and only one argument: file that needs converting. Output will be sent to stdout");
}

}


Hope this helps. Please do post a comment, if you use some other way to make blog entries code friendly.

Java: Using Apache Derby with Hibernate

Today, I came across a need to have an extremely light database. The database is to be used to store report formats. Formats change very infrequently. Its an internal application, used by only 1 user. In the coming years, the user count may grow to 10. So, the load on the database would be negligible.

Big databases like Oracle and Sybase would be an overkill for this, so I started looking at small / light weight embeddable database. Being a Java Programmer, I stuck with Java database. The choice boiled down to 2 databases HSQLDB and Apache Derby. From the documentation, it seemed like some additional configuration would be required to make HSQLDB save contents to a file. Being a lazy developer, I started looking into Derby. Apache Derby has an interesting history. When I found out that Java 6 includes Derby, it kind of sealed the deal for me. So... Derby it is.

Started going through the documentation, I quickly wrote a small script that would allow me to access my database. A little elaborate, but gets the job done:

db.sh

export JAVA_HOME=/apps/jdk/1.6.0_05
export JAVA=${JAVA_HOME}/bin/java
export DERBY_HOME=$JAVA_HOME/db
export DB_OPTS="-Dderby.system.home=/apps/db/derby -Dij.database=jdbc:derby:FoundryReportsDB"
export CLASSPATH=$DERBY_HOME/lib/derby.jar:$DERBY_HOME/lib/derbytools.jar

$JAVA $DB_OPTS org.apache.derby.tools.ij

So far, so good. I created a database at the command prompt and tries it out. Pretty nifty.

Now, next challenge: How do I integrate derby with Java and Hibernate? I wasn't sure even if hibernate supported Derby. Given, Java's support, I had a feeling that it did. Google revealed that my feeling was right. Found information scattered all over on how one could use hibernate with derby, but no central HOWTO. So, here it is:

Create a hibernate.cfg.xml file. I chose to name mine hibernate-derby.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<!-- database connection settings -->
<property name="hibernate.dialect"> org.hibernate.dialect.DerbyDialect </property>
<property name="hibernate.connection.driver_class"> org.apache.derby.jdbc.EmbeddedDriver </property>
<property name="hibernate.connection.url"> jdbc:derby:FoundryReportsDB;create=true </property>
<property name="hibernate.connection.username"></property>
<property name="hibernate.connection.password"></property>

<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">5</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>

<!-- helper debug settings -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">false</property>

<mapping resource="com/blah/util/Nerd.hbm.xml"/>
</session-factory>
</hibernate-configuration>


After this, its pretty much straightforward Java / hibernate code:

Just for completeness sake, here are the rest of the files:

Nerd.java

package com.blah.util;

public class Nerd {
private String name;
private int level;

@Override
public String toString() {
return new StringBuffer(getClass().getSimpleName() + "[")
.append("name=").append(name)
.append(", level=").append(level)
.append("]").toString();
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
}

Nerd.hbml.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.blah.util.Nerd" table="nerd">
<id name="name"/>
<property name="level"/>
</class>
</hibernate-mapping>

Unit Test


import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class DerbyTest {
private static final Logger LOG = Logger.getLogger(DerbyTest.class);

@Test public void testDB() {
final Session session = initHibernate();
try {
Transaction tx = session.beginTransaction();
try {
create(session);
list(session);

tx.commit();
tx = null;
}
finally {
if (tx != null) {
tx.rollback();
tx = null;
}
}
}
finally {
if (session != null && session.isOpen()) {
session.close();
}
}
}

private void create(final Session session) {
Nerd n = new Nerd();
n.setName("Ajay");
n.setLevel(10);
session.save(n);

n = new Nerd();
n.setName("Arkadiy");
n.setLevel(100000);
session.save(n);

n = new Nerd();
n.setName("Ping");
n.setLevel(1);
session.save(n);
}

private void list(final Session session) {
Query q = session.createQuery("from " + Nerd.class.getName());
List list = q.list();
LOG.info("Query came back with " + list.size() + " results");
for (Object row : list) {
LOG.debug(row.toString());
}
}

public Session initHibernate() {
final Configuration configuration = new Configuration(). configure("gds/hibernate-derby.cfg.xml");
LOG.info("Connecting hibernate to URL=" + configuration.getProperty("hibernate.connection.url")
+ " as user=" + configuration.getProperty("hibernate.connection.username"));
return configuration.buildSessionFactory().getCurrentSession();
}
}