Please check out...
http://www.jroller.com/RickHigh/entry/crank_crud_intro
Crank is a framework for doing CRUD based applications very quickly. It is a
nascent framework, but it has made some recent progress. Crank is based on
ideas we explored with Presto and a much earlier framework that I worked on at
eBlox .
Scott Fauerbach, Chris Mathias and many others worked on Presto. Scott
Fauerbach and many others worked on the original framework (which I believe we
called CRUD which was Struts/EJB2 based circa 2001). Currently Paul Tabor,
Chris Mathias, and many others are working on Crank.
The major improvements from Presto and Crank is that Crank is geared towards
annotation driven development, Generics with less AOP than Presto (but still
some). There are 20 to 40 application launched on top of Presto and a fulltime
ArcMind guy maintaining it.
Out of the box with Crank you can easily create CRUD listings. For example the
following code would produce a CRUD listing that allows all columns to be
sorted and filtered:
<h:form id="expListForm" rendered="#{controllerBean.showListing}">
<crank:listing paginator="${paginators['Employee']}"
jsfCrudAdapter="${cruds['Employee']}"
propertyNames="firstName,lastName,active,dob,age,phone,email,department.name,description"
pageTitle="Employees"
parentForm="expListForm"
reRender="${reRender}"
crud="${cruds['Employee'].controller}"/>
</h:form>The above produces the following listing (from the example crud app,
which you can download or get from SVN or read more about and try out).
The listing has pagination, each column is filterable (dates, strings,
booleans, relationships). By filterable, I mean you can click the inspection
icon (magnifying glass) and enter in filters for that column. You can apply as
many filters and sorts (order bys) as you need. You can clear filters and sorts
as well. You can sort more than one field.
There is no code you need to write. Underneath the covers, the listing using
our own Criteria API which has a translator that translates that to JPA QL then
uses are GenericDAO to retrieve the results from the database. This is done
without writing any additional code. The idea is that if you have a model with
JPA annotations that works, then you should be able to easily create a listing.
The forms management is nice in that it will automatically render the right
kind of input field. It will render file upload, date input, one to many
relationship selection (list box), booleans (check box), strings (text input),
large strings (text areas) and more.
Let's say for example that you have an Employee object with JPA annotations as
follows:
@Entity
public class Employee implements Serializable {
@Id
@GeneratedValue( strategy = GenerationType.AUTO )
private Long id;
@Column( nullable = false, length = 32 )
private String firstName;
private String lastName;
@Column( length = 150 )
private String description;
private boolean active;
private int age;
private String email;
private String phone;
private Integer numberOfPromotions;
private EmployeeStatus status;
private Integer rank;
private Date dob;
@OneToMany( cascade = CascadeType.ALL )
private Set<Task> tasks;
@ManyToOne( )
private Department department;
private PersistedFile file;
public PersistedFile getFile() {
return file;
}
public void setFile( PersistedFile file ) {
this.file = file;
}
public void addTask( Task task ) {
this.tasks.add( task );
}
public void removeTask( Task task ) {
this.tasks.remove( task );
}
public Long getId() {
return id;
}
public void setId( Long id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
@Required
@ProperNoun
@Length( min = 2, max = 35 )
public void setFirstName( String firstName ) {
this.firstName = firstName;
}
public Department getDepartment() {
return department;
}
public void setDepartment( Department department ) {
System.out.println( "SET DEPARTMENT " + department );
this.department = department;
}
public boolean isActive() {
return active;
}
public void setActive( boolean active ) {
this.active = active;
}
public int getAge() {
return age;
}
@Required
@LongRange( min = 18L, max = 135L )
public void setAge( int age ) {
this.age = age;
}
public Integer getNumberOfPromotions() {
return numberOfPromotions;
}
public void setNumberOfPromotions( Integer numberOfPromotions ) {
this.numberOfPromotions = numberOfPromotions;
}
public String getLastName() {
return lastName;
}
@Required
@ProperNoun
@Length( min = 2, max = 35 )
public void setLastName( String lastName ) {
this.lastName = lastName;
}
public EmployeeStatus getStatus() {
return status;
}
public void setStatus( EmployeeStatus status ) {
this.status = status;
}
public Integer getRank() {
return rank;
}
public void setRank( Integer rank ) {
this.rank = rank;
}
public Date getDob() {
return dob;
}
public void setDob( Date dob ) {
this.dob = dob;
}
public Set<Task> getTasks() {
return tasks;
}
public void setTasks( Set<Task> tasks ) {
this.tasks = tasks;
}
public String getDescription() {
return description;
}
public void setDescription( String description ) {
this.description = description;
}
public String getEmail() {
return email;
}
@Email
public void setEmail( String email ) {
this.email = email;
}
public String getPhone() {
return phone;
}
@Phone
public void setPhone( String phone ) {
this.phone = phone;
}
}We can easily render the above object in a form without writng a lot of code.
We can allow editing of the OneToMany relationship (Employee->Tasks) and the
ManyToOne relationship (Employee->Department) without much effort and
practically no code. The idea behind Crank Crud is reasonable behavior. Also we
read and process the meta-data stored in the JPA annotations, Java types, and
validation annotations to render the right kind of input fields and validation.
Here is the page that renders a form to edit the Employee object and its
relationship.
<h:form id="pagForm" prependId="false" enctype="multipart/form-data">
<crank:form crud="${cruds['Employee'].controller}"
propertyNames="firstName,lastName,active,dob,age,phone,email,department,description,file">
<c:set var="taskDetailController"
value="${employeeCrud.controller.children.tasks}" />
<crank:detailListing detailController="${taskDetailController}"
propertyNames="name,startDate,endDate,complete"
relationshipCollection="#{taskDetailController.model}"/>
</crank:form>
</h:form>The above renders this form:
There is quite a bit going on. The above allows you to edit first name, last
name, active, and dob (date of birth) using text input, checkboxes and calendar
widget with no effort. More amazingly, you are able to change department which
is a ManyToOne relationship with no additonal code. Also a file input field is
rendered for the file property. Even more amazingly the above allows you to
easily render a master detail within the form (Employee has Tasks). I have
hoped I piqued your interests.
In addtion, to provide validation you can use validation. Notice that the email
and phone (as well as others properties) are annotated with validation rules
which get processed as runtime:
@Required
@ProperNoun
@Length( min = 2, max = 35 )
public void setLastName( String lastName ) {
this.lastName = lastName;
}
@Email
public void setEmail( String email ) {
this.email = email;
}
@Phone
public void setPhone( String phone ) {
this.phone = phone;
}Here is an example of runtime processing (the example needs some CSS
love... sorry):
A couple of parting shots, Crank is a tiered framework much of the code has
nothing to do with JSF and can work easily with other frameworks namely Spring
MVC. We are using quite a bit of Crank with a Spring MVC application. There is
an example of integating Crank Validation with Spring MVC and a Crank Crud
Spring MVC example is in the works (Chris Mathias).
The example Crank Crud is based on JSF, Ajax4JSF, Facelets, Spring, and JPA
(Hibernate based). The listings are Ajax enabled thanks to Ajax4JSF.
So why am I writing this. Bragging? No... Well maybe. Do I want feedback? Not
really... although suggestions are welcome. Mainly I am writing this becuase I
am looking for help. Are there other people out there who must use JSF or want
to use JSF and also need to create CRUD listings? Then please use Crank or
better yet help us improve it. I'd love to get a few more solid commiters. In
addition, I'd love to see Crank ported to other web frameworks (Struts 2,
better Spring MVC support) and GUI frameworks (Swing, GWT). I am meeting
tomorrow with Chris Mathias to discuss porting the Crank CRUD portion to Spring
MVC.
You can download Crank or get from SVN . More to come.... There have been
1,000 downloads of Crank so far.
Why the name Crank?
I get asked this a lot. I picked the name Crank as in "Crank it out" and the
name has nothing to do with drugs. I get asked about this a lot. To be clear:
The framework is named Crank as in: "crank out, to make or produce in a
mass-production, effortless, or mechanical way: She's able to crank out one
(CRUD listing) after another" and "crank up: to get started or ready", "to
stimulate, activate, or produce", and most importantly "to increase one's
efforts, output, etc.: Industry began to crank up after the new (CRUD framework
became our corporate standard)." http://www.dictionary.com
Also, I thought it was cool that Crank, Struts and Spring was something you
find in a Ford Model T. Crank is the production line way to create CRUD
listings.