As I am about to undertake this and I can't find instructions using the glassfish GUI admin, I might as well blog it:



Database
Create Database
I'm going to use the Derby/JavaDB database that came with Netbeans:

Click on the 'services' tab in Netbeans
Right click on JavaDB under Databases and select 'Create Database..'
Input details for the database, I used 'security' for database name , username and password (ironically).

Create Connection Pool for Database
Then in the Glassfish admin panel:
Resources->JDBC->Connection Pools, select 'New'
Name: security
Resource Type: javax.sql.DataSource
Database Vendor: JavaDB
<next>
Scroll down to additional properties:
DatabaseName: security
User: security
Password: security
ServerName: localhost

NB! Delete all other properties.

<save>
then try 'ping' it

make sure your database is up and running, compare properties to other loaded connection pools..

Create JDBC Resource
In the Glassfish admin panel:
Resources->JDBC->JDBC resources, select 'new'
JNDI Name: jdbc/security
Pool Name: security
<OK>

Create Tables
In Netbeans 'Services' tab:
Database->jdbc:derby://localhost:1527/security, right click and select 'Execute Command'

create table usertable (
        username varchar(128) NOT NULL CONSTRAINT USER_PK PRIMARY KEY ,
        password varchar(128) NOT NULL
);
and

create table grouptable(
        username varchar(128) NOT NULL,
        groupid  varchar(128) NOT NULL,
        CONSTRAINT GROUP_PK PRIMARY KEY(username, groupid),
        CONSTRAINT USER_FK FOREIGN KEY(username) REFERENCES usertable(username)
            ON DELETE CASCADE ON UPDATE RESTRICT
    );
and populate:

insert into usertable(username,password) values ('admin', '21232f297a57a5a743894a0e4a801fc3');
insert into grouptable(username,groupid) values ('admin', 'USER');
insert into grouptable(username,groupid) values ('admin', 'ADMIN');


scripts modified slightly from http://blogs.sun.com/foo/resource/createschema.sql from the article http://blogs.sun.com/foo/entry/mort_learns_jdbc_realm_authentication

Which is pretty much what I am doing..

Realm
Create New
In the Glassfish admin panel:
Configuration->Security->Realm, select <new>
Name: security
Class Name: the one with 'jdbc' in it

JAAS Context: jdbcRealm
JNDI: jdbc/security
User Table: usertable
User Name Column: username
Password Column: password
Group Table: grouptable
Group Name Column: groupid
Digest Algorithm: MD5
<OK>

time to test..

Web Config
Roll Mapping
In Netbeans in the projects tab:
<your war project>->Configuration Files->sun-web.xml and open it
click on <security>
<Add Security Role Mapping>
Security Role Name: USER
<Add Group>
Group Name: USER

and do the same for the admin role/group

web.xml
As I am using JEE 6, I have had no need for the web.xml file as yet, so now I need to create it:
right click on the war project
new->other->Web->Standard Deployment Descriptor

now edit it:
select the 'Security' button/tab
under 'Login Configuration' select Basic
Realm Name: security

then under Security Roles <Add..>
Role Name: USER
do the same for ADMIM role

Now <Add Security Constraint>
Display Name: Test Constraint

Web Resource Collection <Add..>
Resource Name: test
URL Pattern(s): /test/*
<OK>

tick 'Enable Authentication Constraint'
Role Name(s): USER

and save..

create a directory 'test' with a jsp file in it and try access it..

Worked for me, yay me!

The harddrive on my laptop is filling up and I have a client who's database runs into the gigs (per dataset). So I created a MySQL database on an external harddrive a while ago, but now need to do it again (the harddrive is flaky) and have forgotten how to do it. I seem to be looking in the wrong places, so maybe if I write this blog other people searching for the same thing will find it and be able to use it. I will be able to do it next time without searching too!


Well, its actually quite easy. I first tried to create a separate configuration file like I did the previous occasion, but this means not being able to store the config file on the disk: mysql requires that the config file not be world writeable, but by default the external hardrive is mounted with all files world read/writeable. So rather than mess about with the fstab and change the way it is mounted, I opted for specifying the options on the command line.

So this is what I had to do:


First I created I directory where the MySQL database would reside, all further commands are run from that directory.

I then created a data directory store the databases:

mkdir data

I the ran mysql_install_db to initialize the MySQL database tables:
mysql_install_db --ldata=data

Then I could start the database (remember to shutdown your other mysql database if it is running, else specify a different port for this databse to run on):

mysqld --pid-file=./mysqld.pid --socket=./mysqld.sock --datadir=./data

I put this into a 'start.sh' script.

The socket file will be created in the data directory (data/mysqld.sock.
You can then connect to the database like this:

mysql --user=root --socket=./data/mysqld.sock

If you want access to the MYSQL tables use --user=root, else create your own users etc. If you want to use the MySWL Administrator and MySQL Query Browser graphical front ends, make sure you specify the socket file:


Shutdown the database using the following command:

sudo mysqladmin shutdown -S ./data/mysqld.sock

It bothers me that I have to shut it down using sudo, I'll look for a work around when it starts to really irritate me.

Now to wait for the 8 Gig of data to load.

On a side note: I don't think Acid Mothers Temple is the best band to listen to while programming, my brother might disagree..

 <<Blog as memory>>

This is the first thing I do when giving a course on JEE: I open up Netbeans, create a JEE project, create a JavaDB database, create a JPA persistance unit, create an entity bean, create a session bean, create a servlet, create a JSP page and create a cutsom tag (all associated with the entity bean created).

This is a great help to the students as it gives them the overview of what we will be working with and shows them how quick and easy it is to create a JEE application in Netbeans - It takes the complexity fear out of them (to a certain extent).

I thought it would be a great help if this were available as a blog for others to follow. Comments will be most welcome, but not that this is pretty much off the cuff and bares no relevence to a real application.

I'll provide a time line to give you an idea of speed, my slow laptop and making it up as I go along should handicap my normal coding dexterity :)

10:51 - music selection, hmm, Black Keys, Brian Eno and David Byrne, Cake.

Ahh, Thickfreakness!


10:55 - Project creation
New Project -> Java EE -> Enterprise Application
I'm calling it BooksDemo
Using the defaults: Glassfish V2, Java EE 5, Create EJB Module, Create Web Application Module

This will create three projects - BooksDemo 'containing' BooksDemo-ejb and BooksDemo-war

11:02 - Create the Datastore

Under Databases in your 'services' tag, right click on 'Java DB' and select 'Create Database' and create a database called 'BooksDemo' with username and password set to 'books' (I've found it doesn't work so well to not have username and password - go figure).

The creation will also start the database, if you go back to the services tab, you will be able to open and view the database.

Back to the project tab: select 'BooksDemo-ejb', right click -> new -> other -> Persistance -> Persistence Unit - > Next
I use the default unit name (BooksDemo-ejbPU) and for datasource select 'New Data Source' at the bottom of the dropdown. Then select the BooksDemo database you created earlier and make the JNDI name 'jdbc/booksDemo', leave the rest as default and finish.

Now for the Entity Object:
Back to the project tab: select 'BooksDemo-ejb', right click -> new -> other -> Persistance -> Entity Class -> Next

Classname 'Book', package 'com.example.book.model' the rest default and finish.

In the Book class, create a new field 'name' as a String field: <alt>INSERT -> Add Property: make the name 'name' and select OK.

11:15 - Create the SessionBean

(Brian Eno is a genius)

In the project tab: select 'BooksDemo-ejb', right click -> new -> other ->Java EE -> Session Bean -> Next

Call it 'BookService', package 'com.example.book.service', the rest default.

Now we are going to create two 'business' methods: getAll and add for retrieving all books and add a book to the datastore.

<ALT>INSERT -> Add Business Method with name 'getAll' with return type 'List<Book>'

<ALT>INSERT -> Add Business Method with name 'add' and add a parameters called 'book' of type 'Book'.

Next fix the imports - <CTRL>-<SHIFT>-I (in the interface as well)


Next we need a handle on the persistance unit: Right click in the BookServiceBean -> Persistence -> Use Entity Manager

You will now have something like the diagram above.

Now we need to use the EntityManager to store and retrieve the books: for the getAll method:

return em.createQuery("select b from Book b").getResultList();

for the add method:

em.persist(book);

11:31 - The Web

We are going to edit the index.jsp ading a form to add a book and retrieve a list of books.

hmm, we need a Servlet to act as the action storing the book first:

On the 'BooksDemo-war' (note its 'war', dammit) right click -> new -> other -> Web -> Servlet -> Next

Class Name: 'BookAdd'
package: 'com.example.book.web.action'

the rest is default, click 'next' and 'finish' (note that the servlet will be called using '/BookAdd' in the URL.

Add the SessionBean by <ALT>-INSERT (in the servlet class) -> Call Enterprise Bean and select the BookServiceBean and OK.

Edit the 'processRequest' method, take everything out and replace it with the following:

Book book = new Book();
book.setName(request.getParameter("name"));
bookServiceBean.add(book);
response.sendRedirect("index.jsp");

We can see if we are on the right track so far: in the project tab, select the 'BooksDemo' projec, right click and 'Run'

This took me 1 min 6 sec..

You should see 'Hello World!' in your browser, this is the index.jsp we haven't edited yet.

Add 'BookAdd?name=test' to the URL in the browser navigation thingy, you should be redirected to the index page, so you will not see anything of value in the browser. this is good. if you see stack traces, bummer.

Go to the Services tab, select Database, select the BooksDemo database, Tables, Book -> right click -> View Data, you should see a record in the table with the name 'test', Hurrah!

11:50 - The index.jsp



Under 'Web Pages' in the 'BooksDemo-war' project you will find the index.jsp page, open it and add the following code after '<h1>Hello World!</h1>':

<form method="post" action="BookAdd">
<input name="name"/>
<button type="submit">add</button>
</form>

Save it, reload your browser and you should see a form with one input field and an 'add' button, enter a name for a new book and press 'add'. Check that you have a new record in the database.


Custom Tag

On the 'BooksDemo-war' right click -> new -> other -> Web -> Tag Library Descriptor -> next

TLD Name: books
default for the rest and click 'finish'
On the 'BooksDemo-war' right click -> new -> other -> Web ->Tag Handler -> Next

Class Name: BookTag
Package: com.example.book.web.tag
default for the rest and click 'Next'

TLD File: WEB-INF/tlds/books.tld (browse to it)
Tag Name: book
default for the rest and click 'finish'

In the BookTag class, <ALT>-INSERT -> Call Enterprise Bean and select BookServiceBean.

Next, remove everything from the 'doTag' method and add the following:

BookServiceLocal bookServiceBean = lookupBookServiceBean();
List<Book> books = bookServiceBean.getAll();
for(Book book: books){
getJspContext().setAttribute("book", book);
getJspBody().invoke(null);
}

You will also need to throw the IOException.

Back to index.jsp,at the top of the page add the following directive:

under the '<%@page' directive,
<%@taglib uri="/WEB-INF/tlds/books" prefix="b"%>

Note: you can <CTRL>-SPACE to auto complete the uri.

(sheep go to heaven, goats go to hell)

Then add the following under the form:

<hr/>
<table>
<tr>
<th>name</th>
</tr>
<b:book>
<tr>
<td>${book.name}</td>
</tr>
</b:book>
</table>


If you reload your browser you should have a list of your book under the form:
And at 12:09, thats a wrap.
At just under two hours, I don't think its that bad for getting a trivial application up and running (bear in mind I did not prepare for this, so some time was spent thinking each step through), if you had to do it by hand it would be more of a headache. Netbeans adds a lot of value to creating these applications.

The project seems to slow down once we reach the web side of things, but maybe one day we'll have a better way of creating web applications :)

OK, this is a very sketchy view of developing a first time application with GAEJ. It is a rewrite (not a port) of an application I wrote a while back in Java using Spring and JPA. The application is a timetracker recording time I spend on various client projects, I will publish the URL once I've cleaned up a few things and I want to add GWT to the front end.

This is my experience, warts and all, maybe it will help others. I'm using the eclipse plugin for development.

Persistance

In my previous hack, I used JDO to see what it was like, I didn't much like it and decided to move back to JPA. I found JDO quite verbouse to use and especially did not like the way you have to declsre parameters for queries.

The first step was to create the persistance.xml file, as the eclipse plugin only provides the jdo configuration as default. Its easy enough, put it in the same place as your jdoconfig.xml file (in the META-INF directory).

You will need to identify the Entity classes by specifying them in the persistenace.xml file using the <class> tag.

See Setting Up JPA in the docs. Hmm, the line
EntityManager em = EMF.get().getEntityManager();
should be changed to:
EntityManager em = EMF.get()createEntityManager();

Wow! Changed the JDO persisted class to a JPA entity class by changing the annotations and implementing Serializable and.. it work!!



Security

Edit the deployment descriptor (web.xml to you and me) and include the
security-constraint tag. There is an example in the docs called Security and Authentication.

See Google Accounts Java API Overview in the docs.

OK, then how does one access the user principal using EL in a JSP page?



Looking at the user principal I see it is implemented as: com.google.apphosting.utils.jetty.
AppEngineAuthentication$AppEnginePrincipal



UserServiceFactory.getUserService().getCurrentUser() which return a com.google.appengine.api.users.User object. There mus be some relationship to AppEnginePrincipal, but its not via inheritance.

Some digging around and I see AppEnginePrincipal holds an instance of User, so I can do this in JSP:

${pageContext.request.userPrincipal.user.email}
or
${pageContext.request.userPrincipal.user.nickname}
apart from:
${pageContext.request.userPrincipal.name}

(of course, once the user is logged in)

Any resources specified in a security-constraint will cause a redirect to the google login page. Any User specified as a developer on the application will have admin role, not sure what role everybody else gets or how to get more roles.

The Turn Around

Under the persistance section I mentioned moving from JDO to JPA, I really don't like JDO from a usablility point of few, the stench is too high - I don't want to be that aware of my datastore.

But now I find myself going back to JDO for a number of reasons:

  1. Not enough documentation on GAEJ about using JPA
  2. The JPA implementation is basically JDO under the hood and I get the feeling not everything translates well.
  3. JDO is simpler for storing objects outside your domain (the User object springs to mind)
  4. There is a general ".. I don't know, use JDO.." attitude on the mailing list
  5. I plan to use GWT in the project and there are serious issues regarding serializing Entities - GWT-RPC broken in GAE/J.
bugger, I really don't want to do this, humph.

The DataNucleus Enhancer is starting to T me off, keeps on popping up in the console after you save any class in your project, perhaps it should only be kicked off when saving persistant objects or not output unless on error.

Ah, got it: under your project properties -> google -> appengine -> ORM you can specify the specific file/ packages you want enhanced. Nice.

And we are back with JDO. The data hasn't changed, the same data was accessed by JDO, then JPA, then back to JDO without issue.

=================================
Then there is a gap where I modify my J2ME MIDlet, faf around with getting data from the phone and add a domain to my application and run out of bandwidth. This is not a happy period.
=================================

Implicit params in the JDO queries will be supported in the next release. Meh

The other 'Duh' drops

Spent a lot of time trying to figure out relationships and how to implement it with GAE. Did some more reading and recommend these articles: Re-thinking Object-Relational Mapping in a Distributed Key-Store world and How I Learned to Stop Worrying and Love Using a Lot of Disk Space to Scale. I've simplified my initial design dramatically and geared it towards my end goals and a (gasp!) de-normalized the design.

The thing that bothers me most is using JDO/JPA for something like this.I'm going to have a look at the lower level APIs and see if they make more sense (at some stage)

It would be nice to include a restart button for the local web host within eclipse.

Sessions

Session support is not enabled in appengine-web.xml by default. To enable sessions, put <sessions-enabled>true</sessions-enabled> in that file.

I've read somewhere that read only session attributes are supported out the box, I guess that is why you have access to the UserPrincipal.

And while I'm on session:: it seems objects stored in the session must be serializable, not obvious under the test server, but going live will throw  exceptions.

And you can view your applications sessions via the data viewer in the application administrator.


I finally understand why a lot of people are against pure servlet/JSP/taghandler development, they were probably using eclipse. A NetBeans GAEJ module would be nice.

Conclusion of Sorts

The major headache is around data access at the moment. Working with BigTable requires a mind change if your are used to relational databases.