Thursday, May 12, 2011

Seam Forge -- Scaffolding and Metawidget

I spent a couple of hours going thru Keon Aers excellent posting about Seam Forge (http://community.jboss.org/en/tools/blog/2011/05/11/have-your-cake-and-eat-it-too-forge-tools).  Seam Forge is similar to Spring ROO in that it has a console in eclipse that helps you create mavenized projects that use JPA2 and allows scaffolding of different view technologies.  Forge uses MetaWidget (http://metawidget.sourceforge.net/index.php) which has out of the box scaffolding for JSF, GWT and Swing among others.

It took me a few extra minutes to sort out 64-bit windows problems with JBoss Tools.  I needed to download Indigo 32-bit to get JBoss Tools to install at all.  I have not figured out how to force eclipse to run in 32-bit jvn just yet (the -vm setting in eclipse.ini causes jdk 32-bit to crash), so for now I can't use the JBoss visual editor.

It would be nice to have/build a Wicket metawidget.  I am also interested to experiment with reverse engineering a project from an existing database and/or adding forge scaffolding to existing jpa2 entities (for example change my cabin finder as an android application).

Wednesday, May 11, 2011

Future Projects?

At last posting I had been working thru a Cabin Finder application that used GitHub, JEE6 (JPA2, CDI and Weld), JSF2 and Primefaces.  I run the application in Glassfish and had attempted to host it on Google AppEngine (varying degrees of success).  I used Arquillian container based testing and Apache Derby for the database (BigTable for GAE).

The application loads data (geo information and reviews) from Yahoo Local Search based on keywords and zipcode, and plots them on google maps with info bubbles to show more details.  Since I was primarily concerned with cabins in Hocking Hills Ohio, I loaded up ~150 cabins and lodges and then pulled amenities from a static html site.

I used the application to find a cabin for our Men's retreat this year and it worked out well.  Our target cabin was booked so I was able to find another in the same area with the desired amenities.  We booked the cabin and it was better than our original target cabin.  So that was good.

Now I need to forge ahead and work thru some other technologies and want to build on the cabin finder.  Here are a few ideas for future enhancements:


  1. Hook up gitHub, Arquillian and Hudson for CI which is sadly lacking from the app.
  2. Use JBoss7 (CDI 1.1 update).
  3. Use a no-sql database (either CouchDB or MongoDB).
  4. Create a different UI using Wicket, GWT or .NET
  5. Cloud based ??  EE7 spec updates for multi-tenancy and jax-rs.
  6. Use JBoss Seam 3 and Seam Forge and re-create the app.
  7. Mobile app (either Android or IPad iOS)
That's a lot of projects to investigate, I need some help narrowing down the list.  What do you find most interesting?  Using GitHub maybe we can learn together?

Vote on the poll to the right  ======>

Saturday, February 19, 2011

Setup Eclipse JEE6 Primefaces and Glassfish - Part IV

In the first three parts of this series we have gone over the IDE Setup, Arquillian Test configuration, and a basic design of a cabin finder application that I want to build.  Now it's time to get started with the cabin finder application development.

Since we'll be using Maven, deploy to Glassfish and use embedded Derby database, there's very few dependencies we need to add to our project pom.  I'll be using GitHub for the all project source, so you can find the pom at https://github.com/sbasinge/primetest/blob/master/pom.xml.  It has primefaces, derby, arquillian, weld and logging dependencies.

I'm a visual person, so I like to start with the page definitions and work my way thru the page beans to the persistent entities (let's call this top down versus bottom up where we design the entities first and the pages last).  Most often it takes several passes of top-down, then bottom-up, then top-down, etc. until I get everything the way I want.  This affords me the opportunity to refine and refactor as I go.  The downside of this pattern is that from a test first perspective, it is more difficult to write UI tests than application logic tests.  Perhaps a middle-out approach would be best, where you define the pagebeans first and work out to the pages and down to the entities.  That approach would allow for writing of application logic tests early, the definition of UI to Server contracts and division of work into separate teams.

Let's try the middle-out approach.  A quick review of our mock-up shows we need a search bean that can take in several search parameters and return a list of cabins that we will plot on google maps.  JSF development makes me think a little more server sided, so I don't think of passing parameters from a page post to the server, as much as I think of a backing bean that can hold cabin attributes that I want to base a search on.  I also like query by example based application, since it allows me to extend searching capability to whatever attributes are supported by the underlying entities/data.  So let's start by creating a CabinSearchBean that will hold a Cabin instance where we'll collect the input from the search page.  We'll need to have a search method that takes the collected data and searches for matching Cabins, but that's pretty easy with the JPA Criteria Queries.

I'll start be creating the com.examples.cabin package in my src/main/java and src/test/java folders.  Then I'll create a CabinSearchBean in main and a CabinSearchBeanTest in test.  Since I like to have an Abstract class for most every package, I'll create an AbstractPageBean class in com.examples.cabin and have CabinSearchBean extend it.  That way if I need to add some behavior for every page bean it'll already be setup and ready.  As for the CabinSearchBean I need to add the @ConversationScoped and @Named annotations so it will be usable.  Also I need to inject the JPA persistence context and CDI conversation using @Inject PersistenceContext em; and @Inject Conversation conversation; respectively.  I'll also want a Cabin attribute for query by example and a List<Cabin> to hold the search results.  With JSF, you need to be sure not to put logic in getters, i.e. always separate the search event handling from the getCabins method.  So I'll add a search() method that will perform the jpa query and store the results in the cabin list.  But wait a second.....  I don't have a Cabin class yet.  This is where our middle-out approach is going to branch into the entity layer for a bit.  If you have a hibernate/jpa expert around, this is where they'd get started.

Create a package for com.examples.cabin.entity and add an AbstractEntity class.  The AbstractEntity needs annotated with @MappedSuperClass so it can be used as a basis for all other entities.  Make it implement Serializable so your application is cluster ready.  Also, create the Id and Version attributes on it, since all of our entities will get an autocreated Id and optimistic locking version.

Then create a Cabin class that extends AbstractEntity.   The easiest form of a JPA entity is annotated with @Entity and some simple attributes with getters and setters.  Add the attributes for
  String name;
String url;
String imageUrl;
boolean hotTub;
boolean firePit;
boolean firePlace;
String phoneNumber;

and have eclipse generate the getters and setters.  Now we have a basic Cabin entity we can use for persistence, query by example and to store values to/from our pages.

Back to the CabinSearchBean.  Now we can have the Cabin and List<Cabin> attributes with no compiler failures.  Also, we can build a search method using the Criteria API to populate the list.

  public void search() {
log.warn("Searching cabins for {}", cabin);
List<Cabin> results = null;
results = buildAndRunQuery();
log.info("Results: {}", results.size());
setCabins(results);
}

and 
private List<Cabin> buildAndRunQuery() {
List<Cabin> retVal = null;
CriteriaBuilder builder = db.getCriteriaBuilder();
CriteriaQuery<Cabin> query = builder.createQuery(Cabin.class);
Root<Cabin> root = query.from(Cabin.class);

Predicate temp = builder.conjunction();;
if (cabin.isFirePit()) {
temp = builder.and(temp,builder.isTrue(root.get(Cabin_.firePit)));
}
if (cabin.isFirePlace()) {
temp = builder.and(temp,builder.isTrue(root.get(Cabin_.firePlace)));
}
if (cabin.isHotTub()) {
temp = builder.and(temp,builder.isTrue(root.get(Cabin_.hotTub)));
}
query.where(temp);
retVal = db.createQuery(query).getResultList();
return retVal;
}

You'll notice that the buildAndRunQuery makes reference to Cabin_.  That is a reference to static JPA metadata.  Setup eclipse to create the metadata by adding the JPA facet to the project under project/properties.  Also, goto the Java Persistence properties and set the Canonical Metamodel path to src/main/java.  Then as you make changes to the Cabin entity the metadata will be generated into the same folder and package as the entity and you'll have a Cabin_.java.

Ok, now we have the basic cabin entity, and search bean.  We need to flush out more of the entities per our class diagram.  We'll add additional entities for Address, GeoLocation, RentalTerms, Review and Bedroom.  We'll add @OneToOne and @OneToMany annotations on the Cabin entity for the attributes.

@OneToOne(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="ADDRESS_ID")
Address address;

@OneToOne(cascade = CascadeType.ALL)
RentalTerms rentalTerms;

@OneToMany(cascade = CascadeType.ALL)
List<Review> reviews;

@OneToMany(cascade = CascadeType.ALL)
List<Bedroom> bedrooms;

On the Address entity we'll embed a GeoLocation (means it will be stored in it's own table similar to OneToOne) and have a State enumeration.

@Enumerated(EnumType.STRING)
State state;
@Embedded
GeoLocation geoLocation;


With those in place we can add a little more to our search -- like a State search

if(cabin.getAddress().getState()!=null) {
Join<Cabin,Address> address = root.join( Cabin_.address );
temp = builder.and(temp,builder.equal(address.get(Address_.state),cabin.getAddress().getState()));
}


and a filter for average rating:
if (this.getRating() >= 1) {
List<Cabin> tempResult = new ArrayList<Cabin>();
for (Cabin cabin: retVal) {
if (cabin.getAverageRating()>= getRating()) {
tempResult.add(cabin);
}
}
retVal = tempResult;
}

Next time we'll move to the page design and hooking up to our CabinSearchBean using expression language. Sounds tough, but it looks like 
     <p:commandButton id="searchButton" action="#{cabinSearchBean.search}" value="Search"/>

Whew!  That was quite a bit of ground to cover.  We've now created a backing bean with QBE capabilities and supporting entity model.  Essentially the server side aspects of our Cabin Finder application.  We still have a ways to go.  We need to work on tests, creating test data and pages so we can see what this will all look like, but we made good progress!




Tuesday, February 8, 2011

Setup Eclipse JEE6 Primefaces and Glassfish - Part III

In the first 2 installments we setup eclipse, glassfish, maven, primefaces, JPA2 and arquillian for web application development. Now it's time to put it to practical use.

First, we need an application to exercise the JEE6 stack. We'll build a cabin finder which is a project I needed to build for a retreat I am planning. I want to evaluate cabins where we can stay. Several factors determine whether it's a place we may like -- location, amenities and cost. So what I am picturing is a search page with a left panel of search criteria and a content panel that will show matching results on google maps. We'll need a way to get cabins entered/loaded into the system. For that we'll use Yahoo local search to populate some basic data and then manual entry to add amenities, cost and the like. Here's an mock up I made using Gliffy (http://www.gliffy.com/publish/2461936/).  And here is a basic class diagram (http://www.gliffy.com/publish/2461999/)

I also picture menu navigation using primefaces dock component to get to maintenance pages to load data and maintain data.  So we'll need at least 4 pages to get started (search, load, list, edit).

One other thing I'd like to do.  I'd like to share the code between my home computer, work computer and this posting.  I'll try github for that. git://github.com/sbasinge/primetest.git.  Install the eGit plugin into eclipse from http://download.eclipse.org/egit/updates by adding it as an update site (help/install new software/Add).  Once installed use the eclipse import menu to import  "projects from git".  Clone the repository (this makes a copy of the repository to your local machine).

egit documentation: http://www.eclipse.org/egit/documentation/
   Search for "Working with Remote Repositories" to learn about cloning - step 1.
   Then go up to "Starting from existing Git Repositories" to setup the eclipse project.

Next time we'll take the entity model and create our JPA entities and associated tests.

Wednesday, January 26, 2011

JPA2 Criteria API

In the process of writing the cabin finder application, I wanted to have a search panel where you could enter amenities such as fireplace, hottub, firepit, price range, etc. and update content panel with a google maps view of the matching cabins.  First I started with the old JPAQL way of writing a entityManager.createQuery("select c from cabins c where .......").   Then I came across the new way of doing it.  The Critieria API.

What's so great about Critieria API?  Well 2 things for starters.  First, queries are strongly typed in that the don't return a List of untyped objects.  Now they return a List<Cabin> or whatever root object type you set.  Second, they query syntax used to be a String, now it is a set of builder commands that can be validated by the compiler with the use of MetaData.

Step 1 is to setup MetaData.  If you're using eclipse, this is pretty simple.  Goto project properties and set the project facet for JPA version 2.  The additional configuration options allow you to select the JPA provider and download a user library of the JPA provider jars.  I'm using eclipselink since it's native to Glassfish and helps keep my war file small (~5mb so far of which 4.2 are the db drivers for derby and mysql).  Once the user library and JPA provider are setup, eclipse will scan your project and create the JPA  metadata.  I put mine in the .apt_generated folder.  Once created you can review the metadata.  Mostly you'll see SingularAttribute or ListAttributs for simple and list types respectively.  Also note the class names are followed with and inderscore, so Cabin entity gets Cabin_ metadata created.

Step 2 is to start using the Criteria API.  The example to search for amenities such as fireplace, hottub and/or firepit is pretty straightforward.  First, get a CriteriaBuilder from the entityManager.  Then set the class type you are expecting the query to return.  The "where" part of the query is defined by Predicates so we'll initialize one and add each submitted criteria one at a time.  Then set the query's where to the predicate and get the results list.



 private List buildAndRunQuery() {
  List retVal = null;
  CriteriaBuilder builder = db.getCriteriaBuilder();
  CriteriaQuery query = builder.createQuery(Cabin.class);
  Root root = query.from(Cabin.class);

  Predicate temp = builder.conjunction();;
  if(cabin.getAddress().getState()!=null) {
   Join address = root.join( Cabin_.address );
   temp = builder.and(temp,builder.equal(address.get(Address_.state),cabin.getAddress().getState()));
  }
  if (cabin.isFirePit()) {
   temp = builder.and(temp,builder.isTrue(root.get(Cabin_.firePit)));
  }
  if (cabin.isFirePlace()) {
   temp = builder.and(temp,builder.isTrue(root.get(Cabin_.firePlace)));
  }
  if (cabin.isHotTub()) {
   temp = builder.and(temp,builder.isTrue(root.get(Cabin_.hotTub)));
  }
  query.where(temp);
  
  retVal = db.createQuery(query).getResultList();  
  return retVal;
 }

Here's a few references that I found to be helpful.
http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/querycriteria.html
http://wiki.eclipse.org/EclipseLink/Examples/JPA/JSF_Tutorial#Using_JPA_Queries
http://stackoverflow.com/questions/2510106/dynamic-jpa-2-0-query-using-criteria-api
and
http://stackoverflow.com/questions/2880209/jpa-findbyexample

The source code for the cabin finder is on GitHub at https://github.com/sbasinge/primetest.

So give the Criteria API a shot and have validated, type safe and fast queries!

Tuesday, January 25, 2011

On word

Gizmo was born in the back of a semi-truck, son a a runaway father and slightly irresponsible mother.  He didn't let the difficult upbringing affect him at all.  He learned quickly to befriend others.  My wife Judy first met Gizmo when he was very young and had been separated from his mother.  All the women in the office loved him immediately, but Judy was the one who Gizmo took to the most and it was not long until he became part of our family.

Let''s just say that his older brother Felix was not as easy to get along with.  For the first few weeks the two had to be separated for their safety and our sanity, but it was not long until the young Gizmo won the respect of his older (by 1 1/2 years) brother.  For the next 15 years the 2 were inseparable.  They played together, ate together and slept together.

As is often the case, the older siblings are the first to go.  As Felix suffered through a cancerous growth on his larynx, Gizmo was inconsolable, lost...  After a bit of time, Gizmo marched forward on his own.  As he had been since the beginning, undeterred by his surroundings, he sought out others, relished in his new role in the family and even became a social beacon for the rest of the family.

Sadly, this last Saturday Gizmo passed after a long bout with kidney disease.  He was a good friend, brother and family member.  At age 93 (19 in cat years) he lived a full and rewarding life. He will be missed, but someday my wife and I may adopt another cat, heck maybe even a dog.

Saturday, January 15, 2011

Google App Engine and JSF/Weld

I was planning to create another long blog about this topic but it turned out to be more work to get a sample application running.  Here's the basic premise.  In prior blogs about Glassfish and JSF we went thru the process of setting up an eclipse based development environment, mavenized project that illustrated JEE6 features like JSF, Facelets and JPA.  We also added Primefaces JSF tags for a little spice.

Now I'd like to turn that exercise into something more real so I imaged an application....  Call it cabin finder and what I want to build is a 4 panel layout -- with header, footer, left panel and content.  On the header I want to use primefaces Dock for site navigation.  The footer is adverstisements I guess.  The left panel is a search criteria builder where you could enter the location, amenities and price range of the vacation spot your looking for.  In the content panel we'll show google maps of the resulting cabins and a popup dialog for each with more details.

We'll also need a cabin entry page that should be secured -- so login required.  Also, just to get things up and going I want an admin page to load sample data.  I actually had the entities, search controller and pages built pretty quickly based on our previous work.

Then......

I decided it would be cool to host the whole thing on Google App Engine.  I've spent the past 2 days working on that part and finally have it going.  Take a look for yourself at http://mycabinshh.appspot.com.  Keep in mind I've spent more time futzing around with GAE than working on the application so there's no entry page, security, only the state searching is supported, the maps info popus aren't there, etc., etc.

Now .....

I'd like to move the source code to github.  Maybe I'll never get to the app.