Friday, December 2, 2011

Mobile Applications with HTML5 and CSS3

The pendulum swings:  it seems like web application development has been a square peg in a round hole for a while now.  We want highly interactive, user responsive web applications that feel like desktop applications.  We want separation of business logic from presentation tier.  We use JSP, ASP or JSF to act as the intermediary between the client and business tiers (take in html, process and emit html).  The HTML spec was written in a request/response paradigm which is hardly interactive and responsive.  So we add on Javascript to give web sites some interactivity.  And from here the worm begins to turn......

Javascript evolved from a tool marketers could use to add some sizzle to a web site, into a full fledged framework for control of the browser.  With CSS3, you can take advantage of local hardware to perform faster renderings than the browser could do alone.  All this makes me wonder if the JSP, ASP or JSF paradigms work in mobile phone development since they are both server side templating and emission of HTML.  With more advanced HTML and Javascript specs, could the browser really BE the templating and emission of HTML tool?  Could you just use the server to accept, emit and validate data via JSON/XML or whatever?  Would that allow the browser to store the data in local cache for later use, like when you get off the airplane or finish a phone call?  If this approach is good for the phone, then why not the desktop user?  Could web applications be written using HTML/JavaScript and JSON -- with a Spring, JEE or .NET stateless service handling get/post requests?

I don't know the answer.  It seems to me that the HTML spec may be missing some necessary templating rules to make that happen, i.e it would be nice to have a site format with top/left nav and footer applied to all pages.  Wait!  isn't that CSS' job.  What about large data, like images or content from a CMS?  The browser does a good job of caching these things locally already.

As browsers advance in efficiency and capability, and W3C has finally started to move the HTML/CSS specs forward, Maybe it's time to rethink the paradigm.

Wednesday, November 2, 2011

MySQL Database on OpenShift

I've been working on an application for my golf club that will allow us to arrange tee times, sign up and play, and report our scores.  I want to build the application with JEE6 technologies like CDI/Weld, JSF2 and JPA2. I started using JavaDB as a database.  Then I found OpenShift from RedHat as a hosting alternative.  It allows me to build the application locally on JBoss AS7 and then publish it to my OpenShift account using Git.  OpenShift also allowed me to change the DB over to MySQL by simply installing MySQL into my account using rhc-ctl-app -a "fw" -e add-mysql-5.1.  You can also add phpAdmin to make administration of your DB easier.  Here's a good blog on setting up OpenShift, MySQL, phpAdmin and Redmine: https://www.redhat.com/openshift/blogs/phpmyadmin-your-way-into-openshift-express-database-management-bliss

 You can see the application running at http://golfplus-basinc.rhcloud.com/.  I am now working to get Google Analytics and WebMaster tools hooked up to the application.  Once that's done, I can focus on the android cell phone component.  I will be reviewing phoneGap, Sencha and Tiggr as alternatives to straight up Android SDK.

Monday, August 15, 2011

JBossAS7 and Primefaces on OpenShift

This weekend I began experimenting with OpenShift, the JBoss platform as a service (PaaS) available at https://openshift.redhat.com/app/.  I run from Windows so a Cygwin and Ruby install is required to get started.  The installation of cygwin and required modules took me about 1 hour to complete.  After that, I was up and running on OpenShift in a jiffy.   There's a good blog on using CDI/Weld on Openshift at https://www.redhat.com/openshift/blogs/seeing-cdi-working-in-openshift.

In order to get Primefaces to deploy correctly on JBossAS7 I had to upgrade to primefaces 3.0.M2.  Then there are a few markup differences between 3x and 2.2 that I need to resolve.  For instance, the theme selector needed changed in order to get any pages to work.  Also, the gmapInfo panel has some difference requirements, so I have disabled it for now.  Lastly, the dataTable instant selection is different.  It used to have a onrowselectlistener attribute, but now wants a nested p:ajax tag.  I haven't figured out how to get those to work yet either.

You can see the current JSF/Primefaces/Weld/CDI/JPA application at http://cabins-basinc.rhcloud.com/primetest/cabins/search.jsf

Wednesday, August 10, 2011

Using JAXRS and CDI

The following helped me out a lot when setting up jaxrs over existing managed beans.

http://download.oracle.com/javaee/6/tutorial/doc/gkncy.html

Essentially the managed bean is now stateless ejb with jaxrs annotation:

@Stateless
@Named
@Path(value = "/cabins")

the method is also annotated:

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path(value = "/list")

The entity is annotated so it can be marshalled:

@XmlRootElement
public class Cabin extends AbstractEntity {

And a JaxApplication loader class was added:

package com.examples.service;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/rest")
public class JaxApplicationPath extends Application {
}

With these things in place I can reuse the CabinSearchBean from the web page site as a bean for jaxrs (json or xml) and access via Android.



Thursday, July 28, 2011

EE Server versus Tomcat/Jetty

First off, I like Tomcat.  It starts fast, is a solid JSP/Servlet container and, when coupled with Spring, gives a well rounded application development framework.  However, I also like Weblogic, Glassfish and JBoss.  EE6 containers with EJB3, CDI/Weld and JSF/Facelets also gives a solid application development framework.  So what's the difference, and why or when should you use one over the other?


  1. Connection Pooling vs C3PO
  2. JTA vs Atomikos
  3. JMS vs ActiveMQ/RabbitMQ
  4. JAX-RS/WS vs Metro or CXF
  5. EE Security (5 specs) vs JSecurity or Spring Security
  6. EE Interceptors vs Spring Events


So it appears as though you can add in each of the EE stack specs into Tomcat as needed.  The real question becomes what is as needed and do you design your application around what's missing as much as what's there?

Lightweight
Tomcat/Jetty/Resin will all start using less memory than Glassfish/JBoss.  If however, you need connection to a database(s) (issues 1 and 2 above), asynchronous processing (issue 3), restful web services (issue 4), security (5) and loose coupling (6) then you'll need to add Spring to your web app on Tomcat/Jetty/Resin and then the startup times and memory footprint begins to look similar.

Vendor Independence
Tomcat with Spring gives you lots of configuration options.  Different implementations of JCA, JMS, Web Services, Security, Persistence can all be wired in to the environment.  This is a great advantage when dealing with existing application infrastructure where synergy to other applications is required.  As much as JEE vendors purport that the EE spec isolates you from vendor lockin, it's more difficult to perform than the color glossy brochure would have you believe.  The ability to deploy a war on multiple JEE servers does exist, so there is that level of independence, but it's generally much easier to use the vendor's chosen implementations of security, persistence, jms, etc.

Testing
Spring has a great test framework to allow testing from junit or testng without a container.  Since Spring is independent of container provided services, you can pretty easily spin up a Spring configuration in the JVM.  JEE testing requires a container.  With frameworks like arquillian, it's easier to spin up a embedded container for testing, but Spring has a definite advantage here.

Free
What a misnomer.  Often we think that because we can download a product and use it without paying, that it is free.  Well, I guess if we already knew everything we needed to know to use the product -- it would be free.  But, when you try to use the software you just download for the first time, there's usually some learning curve.  Documentation, community involvement, support and professional services can all come into play in order to get you up and running.  My opinion is that the Spring documentation is pretty good here.  The JEE documentation (link below) is good also, but note quite as polished as Spring's.  The issue with Spring, is that the variety of implementations for any of the basic services, means you will be dependent on additional vendor documentation, unless you simply use what Spring recommends.  So the vendor independence advantage may be a little diluted.

Why Use JEE
If you have a clean slate to start with, i.e. very few mandates to use a particular implementation of Security, WebService engine, etc.  Also, if you really don't care who provides your connection pooling, JMS, JCA, JTA, etc. then a JEE server will provide all of those basic services.   You have development and deployment hardware capable of supporting a reasonably large memory footprint.

Why Use Spring
You want customize and tailor the configuration of the basic application infrastructure.  You want to learn technology that is widely spread.  You want to learn technology that can be used in a variety application ecosystems.  You are severely limited in the development or deployment hardware.


references:
EE Doc: http://download.oracle.com/javaee/6/tutorial/doc/gfirp.html
Spring Doc: http://static.springsource.org/spring/docs/3.1.0.M2/spring-framework-reference/html/

Thursday, July 21, 2011

Think Objectively

What does ORM stand for?  Object Relational Mapping.

What is an Object?  Data and behavior.

What is a DAO?  Data access object.

If an Object is data and behavior, why is there such a thing as a "data" access object?  Why not an Object access Object?  Does a DAO have any place in an object oriented architecture?

Good questions.  I don't pretend to have the answers, but I have a few observations.

First, if you use DAO layer, then something has to reassemble your object model from the "data" you just accessed.  Now you have a DAO, a DTO and an assembler just to get data from a database into a usable object model.  Seems like a lot of work.  Also sort of inflexible to change as we are prone to omit details from the model that we are not currently interested in, and leave it up to the next person.

Second, hibernate is a good ORM but it has a steep learning curve and a few limitations.  There is no cure for having to learn things and I get that, but it's pretty weird that the ORM market is still evolving some 35 years after OO design and development began.  It seems pretty fundamental to software development to be able to get  and store data.  JPA is a "standardized" version of Hibernate, but eclipseLink and Hibernate implementations of JPA are not simply swappable.  Don't kid yourself, Oracle wants you to use EclipseLink and Redhat wants you to use Hibernate for a reason $$$$.  They aren't going to make it super easy to change things and cut them out of the loop.

Lastly, I personally would like to think the DAO is dead (DOA).  Spring ROO manual has a section dedicated to the demise of the DAO.  JPA gives a much cleaner transition from data storage to Object model.  It's not perfect, but far better than having three or four architectural layers dedicated to getting data.  Also, I have seen applications where Object classifcation/subclassing is left out altogether in the DAO layers just because it's difficult to implement in that way.  This leads to the visitor pattern to implement object specific behavior.  Now, maybe I'm wrong but doesn't it seem like a bad idea to have a travelling section of business logic that is seperate from the actual object model?  I guess I'd like to see the visitor pattern go the way of the DOA DAO.

l8r

Friday, July 15, 2011

Many To Many Problems

This week I've been struggling with a many to many mapping where the join table has extra columns and the lower side of the many to many should be deleted once all the top side holders are removed.  First the model..

(Gliffy account expired so no pictures.)
  • Folder
    • Message
      • Contents
The basic premise is that a folder can contain many messages.  Messages contain 1 content, but 1 content can be referenced by many messages.  A message represents content in a user's folder.

The test case is to send a message to five people's inbox folder.  So each folder will have a Message and each message will reference the same Content.  So I would expect 5 folders, 5 messages and 1 content in the database.  If the first 4 users delete the message I would expect the 5 folders, 1 message and 1 content remaining.  When the last of the messages are deleted, the content should be deleted too.

We started by mapping the Folder's set of messages as ManyToOne.

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "folder", orphanRemoval=true)
private Set messages = new HashSet();

The orphanRemoval is the equivalent of hibernate's cascade type DELETE_ORPHAN. Then we map the Message class back to the Folder as a many to one.

@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "FOLDER_ID", nullable = false)
private Folder folder;

@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "CONTENT_ID", nullable = false)
private Content content;


Lastly we map the Contents to Message as a OneToMany and we effectively have a ManyToMany with extra attributes on the Message join table.

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "content", orphanRemoval=true)
private Set messages = new HashSet();


Now we add a few convenience methods to update both sides of the one to many relationships.  When we have mappedBy in the mapping it is equivalent to inverse=true which means the Message is the owning side of the relationships.  Therefore, when we add to the folder.messages collection, we also need to set the message.folder.  Likewise on the content.messages and message.content.

public void addMesage(Message message) {
this.messages.add(message);
message.setFolder(this);
}



Everything worked pretty well when adding although the Content didn't seem to persist automatically and we would get a transient entity error.  The create mesage looks like this

public void createMessaage(List to, Content content) {
for (Folder folder : to) {
Message message = new Message();
folder.addMessage(message);
content.addMessage(message);
}
save();
}


Delete works pretty straightforward also.  Simply remove the message from the folder and the content.   Unfortunately what we encountered were a lot of re-saved entity issues and content either being removed prematurely (the entire graph deleted on first message delete) or never at all (content not deleted after last message reference removed).

My solution has been to make the delete return a boolean as to whether the Content needs removed and then issue session.delete(content) on it.  I don't like it, but it works.

Wednesday, July 13, 2011

Google AppEngine and JPA/DataNucleus

JPA is provided on Google AppEngine (GAE) via DataNucleus.  DataNucleus data store used on GAE is BigTable.  The solution has a few rough edges.  See the references below for some of the docs from Google.

References
http://code.google.com/appengine/docs/java/overview.html
http://code.google.com/appengine/docs/java/datastore/overview.html
http://code.google.com/appengine/docs/java/datastore/jpa/overview.html

Troubled Dog?

I have this song running thru my head..... there's a line in it "Worry, worry, worry".  It's used on a Travlerers Insurance company commercial where a dog hides his bone in the backyard.  Then frets over it, digs it up and takes it to the bank.  Then the dog worries about it even more.  He goes to the bank and takes out the bone and keeps it in his sight at all times.  Man that dog is troubled!  The song is "Trouble" by Ray LaMontagne. You tube video here.

So my bone these days is software development and why are things so hard.  Recently I've spent a day or two getting a many to many hibernate/jpa mapping to update correctly.  I began to think I had more than just a simple problem, but many to many problems.  That's where Ray LaMontagne comes in. I have a few ideas of things to discuss in upcoming posts such as:

  • My Many To Many Problems
    • Is ORM the vietnam of software development? 
  • Think Objectively - rich entities lead to ORM
    • where O = Object which is data and behavior.
    • not anemic.
  • EE Server versus Tomcat/Jetty/etc.
    • Is lightweight lightweight when you have to wire everything together in app config?
    • How will this work with ESB?  Every app has it's own def?
    • What about change?  Does every app change?
  • Ding Dong the DAO is dead
  • STS 2.7 Review
    • Vendor lock in?
  • ORM Testing
    • How to verify persistence is mapped correctly
    • Spring Testing versus Arquillian
  • There's Chocolate in my Peanut Butter
    • Are DBAs development or operational?
    • The impact DBAs have on ORM mappings
  • A dog needs a bone.  Don't worry be happy.


I'll try and get one of these topics out each week for the next 7 weeks.  In the meantime, I'll spend less time worrying and more time listening to Ray.

Sunday, July 10, 2011

Seam3 Project Archetype

The jboss-javaee6-webapp archetype from org.jboss.spec.archetypes has a lot of goodies in it.  There is 

  1. JSF 2.0
  2. Restful Services
  3. CDI 1.x
  4. EJB 3.1
  5. JPA 2.0
  6. Bean Validation
  7. Arquillian Tests
I created a project from the archetype in eclipse 3.7 with jboss tools 3.3, built and deployed to jboss 7 in under 15 minutes.  With JBoss tools you get code insight when editing the ui pages.  So when you type #{ in an xhtml, the annotated beans are reviewed for matching candidates. Once you select a bean, the available methods are displayed.   Just like working with the java code.  

Some of the other JEE features sprinkled thruout the example are event fire and observe techniques.  Also @Producers (think factory) and @Named beans.  And bean validators, which is just plain cool to me.  Think of it, the same validation that you use on the entities can be used directly by the UI.  One set of rules....  very dry.

So if you're interested in fast approach to java web development, try out eclipse, jboss tools and this archetype and I think you'll be up and running in no time.


Thursday, June 23, 2011

Prodigal Change

One of the things you hear often in Agile transformations (and maybe IT in general) is to embrace change.  Overall, I have witnessed a good deal of acceptance of change throughout IT.  As a matter of fact, change is the reason I went into IT some 30 years ago.  However, when folks refer to embracing change, I believe they have a vision of  prodigal embrace.  If you're not familiar with the parable of the prodigal son and the embrace he receives from his father, here goes....

A man has 2 sons who ask him for their inheritance well before he is to die.  He divides much of his wealth between his two young sons.  The first son stays with him and helps run the farm.  The second son moves away from home and takes up partying as a serious hobby.  Soon he has spent his entire inheritance and has to take up work feeding someone's pigs.  He finally sucks it up and decides to go home and beg his father for mercy.  As his father sees him coming towards the house, he joyously runs out to greet him, says they will have a great party celebrating his return and gives him a huge hug.  You can read more about this at http://christianity.about.com/od/biblestorysummaries/p/prodigalson.htm.

So my parallel to the parable is that management often thinks of embracing change as this prodigal embrace...  We will be joyous, overlooking any past issues, and ready to welcome the new change in with open arms.  The parable about the prodigal son is meant to represent how an all loving God will welcome us if we turn to Him, no matter what things we've done in the past.  I am positive that management does not think of us as an all loving God, so I'm pretty sure the prodigal embrace of change is not meant to be applied to us.  We are humans, we are suspicious, unforgiving, territorial, and changes gives us the heeby jeebies.

We embrace change differently.  While we may take the messed up son back into the house, we will certainly keep an eye on him.  Heck, we may even lay down some ground rules before welcoming them back in the first place.  That doesn't mean we don't welcome the son back, it's just not a prodigal embrace.  If we all keep our expectations realistic, then we will be ready for change (it's coming whether we're ready or not).  Management should expect change to be welcomed in when it has met some of the basic ground rules and it won't be a trusted member of the household until it has proven itself.  i.e. change does not happen overnight.

Friday, May 27, 2011

The Javascript Bigot

Why am I a Javascript bigot?  Good question and my introspection my adversity led to an evaluation of coding practices and frameworks......

Javascript in and of itself is not bad, but I see a lot of web applications where Javascript has gone way beyond simply adding a rich feel to web applications.  When Javascript is used to control and orchestrate application behavior that's where things go off the tracks.  A lot of this is due to marshalling frameworks.  For example, you have the Order and Order Item data relationship.

I have seen lots of examples where the data is "flattened" to send it back to the client.  Initially this was done to save bandwidth (think old dial up days).  So instead of sending every order item along with the order, you may have sent an order item id and let the client ask for the order item by id later.  The reduction of the payload leads the client to have an intimate understanding of the data relationships and their implementation on the server side.  The client must orchestrate the requests for data in a way that makes sense to the server.  This leads to a distributed set of logic, multiple maintenance points, fragility and difficult testing.

Examples of this are sending data over XML where data relationships that exist on the server are not represented in the data sent to the client.  I've seen similar with JSON payloads.  DTOs used in Swing applications, Smalltalk models, Spring Beans and JSF backing beans.  If you look at web applications as basically taking data from a database and formatting it so it is pretty for the user, allows them to view and interact with the data, and save their changes -- then the closer the client model is to the persistence model, the less confusion and rework there is.   Keeping client and server models as 2 separate things leads to duplicate maintenance and ultimately multiple sets of logic and orchestration.  One of the reasons I really liked JSF and Seam is the close relationship of the server persistence model to the client model.  It leads to bean validation where the client can use the server validation rules.  It leads to expression language use of the server model within the page rendering engine.  It leads to a client that simply formats data, allows the user to interact with it and save their changes.  Perfect.

So maybe I'm not a Javascript bigot after all.

ASP .NET MVC 3

I've recently been going thru the FREE .NET training from pluralSight available at http://www.asp.net/mvc.

The training shows you how to download free versions of Visual Web Developer, IIS and SQL Server for development purposes.  There are 10 classes, each about 45 minutes long and they take you thru basic tool setup, simple web application development, the MVC framework, Unit Testing with NUnit and .NET Entity Framework (Code First model).

I am struck by the similarity between .NET MVC 3 and Spring framework 3.

Request Routing
Both frameworks route requests based on the URL.  For example a url with /Home/Search will route to the HomeController (*Controller added by convention) and the Search method within the controller.  Methods can be annotated to determine different variations for http get versus post.

Parameter Marshalling
Parameters required by the method (e.g. Search( String term)) will be gleaned from the post body or the url parameters and automatically marshalled into the method.   Even complex types like Customer will be automatically marshalled.  This is nearly identical between .NET and Spring.

Model Validation
Spring uses the @Valid annotation on method parameters to automatically invoke model validation or it can be programmatically initiated.  .NET allows programmatic initiation.  Model errors are added to the ModelState and the form redisplayed via return View();  The delivered javascript libraries from Spring and .NET (both JQuery based) display the errors on the correct place on the form.  Spring also has jsp tags to process the model errors which is better I think, as it is less javascript on the client.  Similarly, .NET allows client side validation to be turned off and let the Razor engine put model validation errors where they belong.

Model Composition
Once inside the controller, persistence processing (add/update/delete/select) can be done and a new Model can be built for use by the next view.  The model and view are combined and returned as a result of the controller method.  For example -- return View(model); or return JSONView(model);  The page template is selected from the origianl URL, for example /Home/Search will route to the HomeController.Search method and return the /home/search.cshtml page with the model injected.  The cshtml uses the Razor engine to take the model and put it's attributes on the form, much like Spring's JSP binding.

Entity Framework
Spring will use JPA/Hibernate whereas .NET can use the EntityFramework.  Both have annotated mappings of entity attributes and relationships that are very similar.  Both have the notion of an entity manager that will take care of persisting data changes without the programmer needing to be worried about connection pools and the like.  Both allow validation annotations such as required, regex matching, min/max, etc.  Both allow extension to provide your own validation rules.  Searching is performed via LINQ in .NET and JPA Criteria API in Spring.  Both use a similar idea of creating a Query using a QueryBuilder that you add .From, .Where, .And, .OrderBy clauses and the like.  The entity framework takes care of translating the query to the particular database dialect you are using and issues the query, gets the result/s and marshalls them into the appropriate entity classes.

Overall, I have really been amazed by how similar the two frameworks are.  I've long been a JSF developer and feel that JSF kicks JSPs butt.  However, if I want to be skilled in a way that allows me to develop for .NET and Java, the Spring and .NET MVC frameworks really position me to do just that with a marginal amount of re-training.

Sunday, May 15, 2011

Potential Project

One potential project may be to take the cabin finder application and port it to run on MongoDB with JBoss 7 as a container.  Then run in on Amazon EC2.  Then hook up an android UI.

To get started we could use Seam forge with the already built JPA entities for the cabin finder application.  Forge can create a JSF UI for us and a deployment to JBoss AS7.  We could tweak the UI to use primefaces and google maps widgets.  JBoss Tools 3.3 will help us with cloud deployment.  Then we could dive into MetaWidget a little bit to get an Android UI to work with it.

So while it may seem like a circuitous route to get there, I think a bit more diving into Seam Forge and Metawidget is the first order of business.  If we can accomplish our goals thru them with as little code as possible, then maybe we're on the right track.

To get started I'll download AS7, Eclipse Indigo and JBoss Tools 3.3.

JBoss Tools: Install thru eclipse add new site: http://download.jboss.org/jbosstools/updates/nightly/trunk/

Unzip Indigo and JBoss AS7.  Fire up eclipse and setup the JBoss 7 server.

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.

Saturday, January 8, 2011

Setup Eclipse JEE6 Primefaces and Glassfish - Part II

In the first installment we setup a basic web application with JEE6, JSF2, Primefaces running on Glassfish using Eclipse for the IDE.  We'll continue here to add testing with Arquillian and Persistence with EclipseLink/JPA2.  Once again we're simply tweaking Nicklas Karlsson's examples except we're making it a little less JBoss specific.


We'll build upon the primetest project, which you can download from here.  Simply extract the zip into your workspace and use import existing maven projects to get you caught up.


The first thing we'll do is add some dependencies for Arquillian and a Profile for Glassfish Embedded.  Arquillian allows you to run tests with JUnit or TestNG.  It facilitates in-container testing, which means all the CDI injections take place, you don't have to hand-wire together test objects.  Let's add a few properties to the pom for our dependencies:
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <arquillian.version>1.0.0.Alpha4</arquillian.version>
    <glassfish.embedded.version>3.1-b04</glassfish.embedded.version>
    <junit.version>4.8.1</junit.version>
    <slf4j.version>1.5.9.RC1</slf4j.version>
</properties>

and the dependencies themselves:
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-junit</artifactId>
<version>${arquillian.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
We'll also add a dependency management section like so:

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

and lastly, the profile for Glassfish embedded:

<profile>
<id>glassfish-embedded-3</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-glassfish-embedded-3</artifactId>
<version>${arquillian.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>${glassfish.embedded.version}</version>
</dependency>
</dependencies>
</profile>
Notice the activeByDefault flag.  We'll toggle the flag between true for testing and false for runtime.  A bit problematic, but the best way I've found to have a profile for testing only.

ok, now we're all setup for testing, we just need to write a test......
First we'll create a simply class named TemperatureConverter in the com.examples.test package like so:

package com.examples.temp;
public class TemperatureConverter {
public double convertToCelsius(double f) {
return ((f - 32) * 5 / 9);
}
public double convertToFarenheit(double c) {
return ((c * 9 / 5) + 32);
}
}


and then a test case in src/test/com.examples.temp like this:


package com.examples.temp;
import javax.inject.Inject;
import junit.framework.Assert;
import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import static org.junit.Assert.assertEquals;
@RunWith(Arquillian.class)
public class TemperatureConverterTest {
@Inject
private TemperatureConverter converter;
@Deployment
public static JavaArchive createTestArchive() {
return ShrinkWrap.create(JavaArchive.class, "test.jar")
.addClasses(TemperatureConverter.class)
.addManifestResource(
EmptyAsset.INSTANCE,
ArchivePaths.create("beans.xml"));
}
@Test
public void testConvertToCelsius() {
Assert.assertEquals(converter.convertToCelsius(32d), 0d);
Assert.assertEquals(converter.convertToCelsius(212d), 100d);
}
@Test
public void testConvertToFarenheit() {
Assert.assertEquals(converter.convertToFarenheit(0d), 32d);
Assert.assertEquals(converter.convertToFarenheit(100d), 212d);
}
}

A breif description of what's happening here.  The @Deployment annotation designates the container setup for the test.  We will create a temporary jar (test.jar) to put in the glassfish embedded container and add an empty beans.xml for CDI.  With that done, the container will properly inject the TemeratureConverter class that we'll use in the 2 test cases.


I tried several ways of getting the maven integration to work for this, including setting the default profile in the project's maven properties, setting the default profile in the pom and creating a special run config for the tests.  All had issues, so what I've settled on is changing the activeByDefault flag in the pom, and then perform mvn test (or run as/maven test in eclipse).  Try that and see the test results... 
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0


Not much in the way of logging is happening, so add a log4j.xml file in your src/test/resources:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
   <!-- ============================== -->
   <!-- Append messages to the console -->
   <!-- ============================== -->
   <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
      <param name="Target" value="System.out"/>
      <param name="Threshold" value="ALL"/>
      <layout class="org.apache.log4j.PatternLayout">
         <!-- The default pattern: Date Priority [Category] Message\n -->
         <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
      </layout>
   </appender>
   <!-- ================ -->
   <!-- Limit categories -->
   <!-- ================ -->
   <category name="com.examples">
     <priority value="ALL" />
   </category>
   <root>
     <appender-ref ref="CONSOLE"/>
   </root>
</log4j:configuration>


Ok, now we have some running tests for our simple web app.  If you downloaded the zip file, you'll notice a few extra beans and additions to the greetings.xhtml to add a few more primefaces widgets (autocomplete and date picker).  

Now let's add some persistence for our greetings.  We'll use an Apache Derby database since it's simple to setup and comes with Glassfish.  So we first need to define a dataSource in Glassfish.  For that we use the sun-resources.xml file.  Create/register the jdbc/primetest jndi resource by adding sun-resources.xml in the src/main/resources folder like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Resource Definitions //EN"
   "http://www.sun.com/software/appserver/dtds/sun-resources_1_4.dtd">
<resources>
   <jdbc-resource pool-name="EmbeddedDerbyPool"
      jndi-name="jdbc/primetest"/>
   <jdbc-connection-pool name="EmbeddedDerbyPool"
      res-type="javax.sql.DataSource"
      datasource-classname="org.apache.derby.jdbc.EmbeddedDataSource"
      is-isolation-level-guaranteed="false">
      <property name="databaseName" value="/tmp/databases/derby"/>
      <property name="createDatabase" value="create"/>
   </jdbc-connection-pool>
</resources>

Then we'll add the JPA persistence file in the src/main/resources/META-INF/persistence.xml like this:


<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="test">
      <!--
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      -->
      <jta-data-source>jdbc/primetest</jta-data-source>
      <properties>
         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
         <property name="hibernate.show_sql" value="true"/>
         <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
         <property name="eclipselink.logging.level" value="FINE"/>
      </properties>
   </persistence-unit>
</persistence>

Now we have our JPA setup and ready to go, let's create a Greeting entity that we can persist.  Create Greeting.java in the com.examples.greeting package:

package com.examples.greeting;
import static javax.persistence.TemporalType.TIMESTAMP;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Temporal;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Entity
public class Greeting
{
   @Id
   @GeneratedValue
   int id;
   String text;
   
   @Temporal(TIMESTAMP)
   Date created = new Date();
   public Greeting(String greet) {
   text = greet;
   }
   public Greeting() {
   }
   public int getId()
   {
      return id;
   }
   public void setId(int id)
   {
      this.id = id;
   }
   public String getText()
   {
      return text;
   }
   public void setText(String text)
   {
      this.text = text;
   }
}

We are going to raise an event when a Greeting is added, so we'll create an Interface named Added and put it in the com.examples.greeting package.

package com.examples.greeting;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
@Qualifier
@Retention(RUNTIME)
@Target( { METHOD, FIELD, PARAMETER, TYPE })
public @interface Added
{
}

Now we need to create something to get and save Greetings.  We'll call it GreetingArchiver and put it in the com.examples.greeting package too.


package com.examples.greeting;
import java.util.List;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.UserTransaction;
@ApplicationScoped
public class GreetingArchiver
{
   @PersistenceContext
   EntityManager db;
   @Inject
   UserTransaction userTransaction;
   public void saveGreeting(@Observes @Added Greeting greeting)
   {
      try
      {
         userTransaction.begin();
         db.joinTransaction();
         db.persist(greeting);
         db.flush();
         userTransaction.commit();
      }
      catch (Exception e)
      {
         e.printStackTrace();
         // The recommended way of dealing with exceptions, right?
      }
   }
   public List<Greeting> loadGreetings()
   {
      return db.createQuery("select g from Greeting g").getResultList();
   }
}
Lastly, we need to update GreetingBean to use all this new persistence setup.


package com.examples.greeting;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.inject.Named;
@ApplicationScoped
@Named
public class GreetingBean implements Serializable
{
   Greeting greeting = new Greeting();
   List<Greeting> greetings = new ArrayList<Greeting>();
   @Inject
   @Added
   Event<Greeting> greetingAddedEvent;
   @Inject
   GreetingArchiver greetingArchiver;
   
   @PostConstruct
   public void init()
   {
      greetings = greetingArchiver.loadGreetings();
   }
   public void addGreeting()
   {
      greetings.add(greeting);
      greetingAddedEvent.fire(greeting);
      greeting = new Greeting();
   }
   public Greeting getGreeting()
   {
      return greeting;
   }
   public void setGreeting(Greeting greeting)
   {
      this.greeting = greeting;
   }
   public List<Greeting> getGreetings()
   {
      return greetings;
   }
   public void setGreetings(List<Greeting> greetings)
   {
      this.greetings = greetings;
   }
}
Notice that the greeting attribute is used as a template to hold information from the page.  Also note the postConstruct is used to load greetings upon initialization.  Lastly notice the greetingAddedEvent and that it is fired in the addGreeting method.  This is what triggers the saveGreeting method in GreetingArchiver because it is listening for Added Greetings.

A few tweaks are required to our page to enter and list the greetings and we'll be ready to run the application.  First, set the activeByDefault flag to false in the pom.  Then update the greetings.xhtml to look like this:


<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
<title>Greetings</title>
</h:head>
<h:body>
<h:form>
<p:ajaxStatus>
<f:facet name="start">
<h:outputText value="Loading..." />
</f:facet>
<f:facet name="complete">
<h:outputText value="Done!" />
</f:facet>
</p:ajaxStatus>
<p:accordionPanel id="mainPanel">
<p:tab title="Greetings" id="firstTab">
<p:dataTable id="myTable" value="#{greetingBean.greetings}" var="greeting">
<f:facet name="header"><h:outputText value="Greeting"/></f:facet>
<p:column>
<h:outputText value="#{greeting.text}"/>
</p:column>
</p:dataTable>
<h:inputText value="#{greetingBean.greeting.text}"/>
<p:commandButton value="Add" action="#{greetingBean.addGreeting}" update="mainPanel"/>
</p:tab>
<p:tab title="Date Picker">
<h:outputText value="Ipsum" />
<p:calendar value="#{dateBean.date}" />
</p:tab>
<p:tab title="Auto Complete">
<p:autoComplete value="#{autoCompleteBean.text}"
completeMethod="#{autoCompleteBean.complete}" />
</p:tab>
</p:accordionPanel>
<h:outputText value="#{greetingBean.greeting.text}" />
</h:form>
</h:body>
</html>

Notice that we named the main accordian panel "mainPanel" and that the Add button refreshes the "MainPanel".  This is all you have to do to have a partial page refresh using primefaces!  Pretty sweet.


Start your server and refresh the goto http://localhost:8080/primetest/greetings.jsf and you should get a page like this.



In order to setup our test environment for JPA we need to do a few things.  First add a src/test/resources-glassfish-embeded to hold our configuration files for the embedded test environment.  We'll need a persistence.xml and sun-resources.xml.  They'll look similar to the ones we created for the webapp so just copy them.  Rename the persistence.xml to test-persistence.xml.  Then add an arquillian.xml to the src/test/resources folder.


<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.com/arquillian"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:glassfish-embedded="urn:arq:org.jboss.arquillian.container.glassfish.embedded_3">
   <!-- Uncomment to have test archives exported to the file system for inspection -->
   <!--
   <engine>
      <deploymentExportPath>target/</deploymentExportPath>
   </engine>
   -->
   <glassfish-embedded:container>
      <glassfish-embedded:sunResourcesXml>src/test/resources-glassfish-embedded/sun-resources.xml</glassfish-embedded:sunResourcesXml>
   </glassfish-embedded:container>  
</arquillian>

Add the src/test/resources-glassfish-embedded to the build path.  With that we're all ready to test.  We just need to write the test in src/test/com.examples.greeting:

package com.examples.temp;
import static org.junit.Assert.assertEquals;
import java.io.PrintStream;
import java.util.List;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.transaction.UserTransaction;
import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.examples.greeting.Greeting;
@RunWith(Arquillian.class)
public class GreetingPersistenceTest {
private static Logger log = LoggerFactory.getLogger(GreetingPersistenceTest.class);
   @PersistenceContext
   EntityManager em;
   
   @Inject
   UserTransaction utx;
   @Deployment
   public static Archive<?> createDeployment()
   {
      return ShrinkWrap.create(WebArchive.class, "test.war")
            .addPackage(Greeting.class.getPackage())
            .addManifestResource("test-persistence.xml", "persistence.xml")
            .addWebResource(EmptyAsset.INSTANCE, "beans.xml");
   }
   private static final String[] GREETING_TEXT =
   {
      "Super Mario Brothers",
      "Mario Kart",
      "F-Zero"
   };
   public void insertSampleRecords() throws Exception
   {
      utx.begin();
      em.joinTransaction();
    
      log.info("Clearing the database...");
      em.createQuery("delete from Greeting").executeUpdate();
    
      log.info("Inserting records...");
      for (String title : GREETING_TEXT)
      {
         Greeting greet = new Greeting(title);
         em.persist(greet);
      }
    
      utx.commit();
   }
   @Test
   public void should_be_able_to_select_games_using_jpql() throws Exception
   {
      insertSampleRecords();
      
      utx.begin();
      em.joinTransaction();
    
      log.info("Selecting (using JPQL)...");
      List<Greeting> greetings =
         em.createQuery("select g from Greeting g order by g.id", Greeting.class)
         .getResultList();
      log.info("Found {} greetings (using JPQL)",greetings.size());
      assertEquals(GREETING_TEXT.length, greetings.size());
    
      for (int i = 0; i < GREETING_TEXT.length; i++) {
         assertEquals(GREETING_TEXT[i], greetings.get(i).getText());
         log.info("{}",greetings.get(i).getText());
      }
      
      utx.commit();
   }
   
   @Test
   public void should_be_able_to_select_games_using_criteria_api() throws Exception
   {
      insertSampleRecords();
      
      utx.begin();
      em.joinTransaction();
    
      CriteriaBuilder builder = em.getCriteriaBuilder();
      CriteriaQuery<Greeting> criteria = builder.createQuery(Greeting.class);
      // FROM clause
      Root<Greeting> greeting = criteria.from(Greeting.class);
      // SELECT clause
      criteria.select(greeting);
      // ORDER BY clause
      criteria.orderBy(builder.asc(greeting.get("id")));
      // No WHERE clause, select all
    
      log.info("Selecting (using Criteria)...");
      List<Greeting> greetings = em.createQuery(criteria).getResultList();
      log.info("Found " + greetings.size() + " greetings (using Criteria)");
      assertEquals(GREETING_TEXT.length, greetings.size());
    
      for (int i = 0; i < GREETING_TEXT.length; i++) {
         assertEquals(GREETING_TEXT[i], greetings.get(i).getText());
         log.info("{}",greetings.get(i).getText());
      }
    
      utx.commit();
   }
}


Set the activeByDefault flag to true in the pom and run/as maven test.

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0


Awesome!  Till next time, keep learning!


Here's a link to the finished project.