15 March 2010

Dumming Down the User Interface Again

One of my clients recently asked me to track changes they needed on their eCommerce website I've been maintaining over the last five years. Now, most of you will probably be going 'Hello? Brian has no issue tracking in place for his clients?', but let me defend myself: My client has a low tolerance for learning or being involved in anything that does not impact their business directly.

I know and understand the advantages of issue tracking and have used and installed a few over the years, almost all opens source (bugzilla, track, scarab et al) and I know the pain of working with any of these tools for the first time: its a big WTF with new terminology and lots of options. Its one of those areas where the domain is  simple, but everybody likes it slightly differently: how does an issue start out, is it 'open' is 'started' etc and is it 'high' priority, is it a bug, a feature etc..

What was ironic about the request is that I had set up issue tracking for them at least a year previously with a system I thought simple enough for them to just start using (they are completely tech literate), but they never used it (they did login though).

I went back to the old stand by: A shared Google Docs Spreadsheet: it is simple and it works and it is better than the 'spreadsheet in a shared folder' pattern, or the 'lets email the spreadsheet around' pattern. We've all been down there before and it is hell. The main problem with spreadsheets is maintaining them for any length of time. They work for month long projects, but anything longer can get chaotic.

I then spoke with a business friend of mine who is also using a spreadsheet to manage his workers and was complaining about it getting messy and out of state (it might have been a word document). I asked him why he was not using any tools to do this and he said he had tried, but that they were too limiting: he did not care who was updating the system and had no time for confirming tasks etc..

I was taken aback and forced to think about it, of course he is right. He should not have to adjust the way he works for a tool and the other thing that struck me was that what most of these tools try and enforce should be enforced by other processes rather. If you can't trust your workers to update and maintain a tracking system, you have bigger issues within your business.

Back to user-interfaces: We need to find some balance between the complex and the simple, between overwhelming the user with options and leaving him to do everything manually.

Mostly, application development is about automating things people don't want to do. No need complicate it any more than that.

The next irony in the story is that people love buying complexity! Using Gmail for the first time was a revelation: no complexity, simple interface - less stressful. The interface made me think about interface design in a different way: how can I remove options and how can I streamline the most important tasks.

19 January 2010

JEE6 with Netbeans 6.8 and Glassfish 3




I've been using JEE6 with Netbeans and Glassfish for a while and decided I should update my tutorial Creating a JEE application in Netbeans 6.5 to JEE6.


I'm following a similar loose format and creating a skeleton of an application to show case the various tiers (ORM, business objects and web) and give you an overview of what is possible.

I also want to demonstrate how easy developing EJB applications has become since the spec came out. I wouldn't be developing with it if it wasn't.

The musical background for today comes from The Willing Mind as a shameless plug ;). Find our music here: The Willing Mind on last.fm, The Willing Mind on Facebook

OK, I've got Netbeans 6.8 loaded, this is what I am running on:


Product Version: NetBeans IDE 6.8 (Build 200912041610)
Java: 1.6.0_16; Java HotSpot(TM) 64-Bit Server VM 14.2-b01
System: Linux version 2.6.28-17-generic running on amd64; UTF-8; en_ZA (nb)

I'm in my testing project group and turning the music on (Charls Riff).

15:00 - Create new Project

File -> New Project -> Java EE -> Enterprise Application -> 'Next'

Project Name: BooksDemo

'Next' again and keep the defaults (Glassfish v3 Domain, Java EE 6 etc)

'Finish'

Three projects will be created for you, the EJB project, the Web Project and the EE project references to EJB and Web project. In my case they were called BooksDemo, BooksDemo-ejb and BooksDemo-war

15:04 - Create the Datastore

The Database

In your 'Services' tag (Ctrl+5) under 'Databases' select Java DB, right click and 'Create Database':

Database Name: booksdemo
User Name: booksdemo
Password: booksdemo


'OK' and the new Java DB database will be created and start the server if not started.

Now the Persistance Unit

Back to your 'Projects' window (Ctrl+1), select the EJB project (BooksDemo-ejb), right click -> New -> Other -> Persistence -> Persistence Unit -> 'Next'

For the Data Source, in the drop down select 'New Data Source..'

JNDI Name: jdbc/booksdemo
Database Connection: <select the database you created earlier>


'OK'

Leave everything else as default and press 'Finish'.

The Entity class

In the projects window right click on the EJB project again and select 'New' -> 'Other' -> Persistence -> Entity Class -> 'Next'

Class Name: Book
Package: com.gamatam.tutorial.book.model

'Finish'

Now add a field to the Book class for the title:

Alt+Insert -> Add Property

Name: title

'OK'

Thats our data layer finished! (listening to 'Lick' by 'The Willing Mind' is it wrong to love your own music so much?)

15:23 - Create the Session Bean

In the projects window, select the EJB project and right click again -> New -> Other -> Java EE -> Session Bean -> 'Next'

EJB Name: BookService
Package: com.gamatam.tutorial.book.service

'Finish'

In the BookService class, right click -> Persistence -> User Entity Manager, this will add an instance variable for the entity manager.

Now we need the business methods, really easy: Alt+Insert -> Add Business Method

Name: getAll
Return Type: List<Book>

'OK'

Alt+Insert -> Add Business Method:


Name: add
(Parameters) 'Add'
Name: book
Type: Book


'OK'

Now to get rid of the squigly lines, or to fix the imports: Ctrl+Shift+i

Next we need to flesh out the methods a bit.


public List<Book> getAll() {
return em.createQuery("select b from Book b").getResultList();
}

public void add(Book book) {
em.persist(book);
}



OK, that was the business tier, please note there are no longer any interfaces created for the SessionBean!

15:36 - The Web

hmm, thinks a bit as to how to go forward this time..

Lets run the application here and do a sanity check: right click on the BooksDemo main project (probably highlighted) and select 'Run'.

32 seconds to build, browser coming up and we have 'Hello World!' staring at us, yay. We are looking at the default index.jsp page that was created by Netbeans when we created the project, there is no connection to the datastore or enterprise bean at this stage, but the database should have bean created.

Go to the Services window (Ctrl+5), under Databases select the database that we created at the begining of the tutorial, right click and 'Connect', then click to explore the node and select 'BOOKSDEMO', open it and open the 'Table' node.

You will see that the 'BOOK' table has been created for you and is made up of an 'ID' column and a 'TITLE' column to mach the properties in the Book entity class.

15:46 - Add Book Servlet

Back to the project window (Ctrl+1), select the war project (BooksDemo-war), right click -> New -> Other -> Web -> Servlet -> Next

Class Name: BookAdd
Package: com.gamatam.tutorial.book.web.action
'Next' and 'Finish'

Note the new 'Webservlet' attribute on the class, this means no more editing of the web.xml for serlvets!

Alt+Insert -> Call Enterprise Bean -> select the EJB project (BooksDemo-ejb) and select the BookService -> 'OK'

Remove everything from the 'processRequest' method and we will get the book name as a paramter, create a Book object and persist it using the SessionBean:

protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String title = request.getParameter("title");
Book book = new Book();
book.setTitle(title);
bookservice.add(book);
response.sendRedirect("index.jsp");
}



Once you save the servlet, Netbeans should deploy it, so you can test it by trying the following URL:

http://localhost:8080/BooksDemo-war/BookAdd?title=test

You will not see much as the servlet redirects back to the index page, but lets look in the database:

In the Services window (Ctrl+5), right click on the BOOK table and select 'View Data' - you will see a new row inserted with the title 'test'.

16:00 - Custom Tag

Now we will create a custom tag to view all the books:

Back to the project window (Ctrl+1) and right click on the war project -> New- > Other -> Web -> Tag Library Descriptor -> 'Next'


TLD Name: books


'Finish'

right click on the war project -> New- > Other -> Web -> Tag Handler -> 'Next'

Class Name: BookTag
Package: com.gamatam.tutorial.book.web.tag
'Next'
TLD File: WEB-INF/tlds/books.tld
Tag Name: book


'Finish'

Next we add a reference to the BookService EJB and modify the doTag method so that loops through all the books:

public class BookTag extends SimpleTagSupport {
@EJB
Bookservice bookservice;

@Override
public void doTag() throws JspException, IOException {
List<Book> books = bookservice.getAll();
for(Book book: books){
getJspContext().setAttribute("book", book);
getJspBody().invoke(null);
}
}
}



Next, in the index.jsp page we need to first declare the tag library and then use it:

Open the index.jsp page (war project, Web Pages, index.jsp) and add the following:

<%@taglib uri="/WEB-INF/tlds/books" prefix="b"%>

And in the page body:

<b:book>
${book.title}
</b:book>

If you reload the page in your browser, you will see a list of books added to the datastore.

And lastly, I will add a simple form for adding a book:

<form action="BookAdd"><input name="title"><input type="submit"></form>



And at 16:17, thats a wrap!


I'll leave it as an exercise for you to 'dolly' it up.