Monday, March 16, 2009

EntityManager.persist: ¿What does/should it mean?

Lets say you are presented with the following JPA @Entity:

@Entity
public class Customer {

private Long id;
private String name;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

@Column(nullable=false)
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}



And then the following test



@Test
public void persistCustomerInTransaction() throws Exception {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);

EntityManager em = factory.createEntityManager();

em.getTransaction().begin();

Customer customer = new Customer();

em.persist(customer);em.getTransaction().commit();

em.close();

}



And the following question: Where does it crash?:




  1. At the line em.persist(customer); because the name is configured as nullable=false, and we are trying to persist the Customer instance with a null value in the name property


  2. em.getTransaction().commit(); because the name is configured as nullable=false, and we are trying to commit the transaction with a null value in the name property



Turns out… that the answer depends on the JPA provider you are using!!!! If using Hibernate, it crashes at em.persist, but if using EclipseLink, it crashes at em.getTransaction().commit.



Now, this might seem irrelevant, but it is in fact very important, because EclipseLink behavior means that constraint validations are deferred until the point where the transaction is committed, and that means that the developer has a lot more freedom to manipulate its persistent objects: they can be in any (possibly invalid) state while they are being manipulated by the business logic of the application, and they only have to be “right” the moment one needs to commit them to the database (not before), this is specially useful, for example, when building a wizard like UI (or a plain simple CRUD UI with support for full object graphs) with EclipseLink, I can persist my objects as soon as I want, and if want to, for example, run some validation logic at the end, all I have to do is ask the EclipseLink to give a list of all the objects that are going to be written in to the database, with Hibernate, the entityManager does not help me manage new object instances, I have to manage them myself.



What I find really surprising is that AFAIK there should be some kind of test to ensure that all JPA are compatible (something called the TCK?), and I think that this kind of discrepancy should be detected by those tests... shouldn't it?


I think this support for deferred validation, and an API to get will be inserted, will be updated or will be deleted, will be very important to really integrate JPA with something like JSR 330, so that validation can really integrate with the lifecycle of a persistent POJO.

Saturday, March 14, 2009

JPA/Hibernate (subjective?) weaknesses

I have had to work with JPA/Hibernate for a few years now... and I feel it has some weaknesses I really do not like (when compared with the first ORM I ever used, NextStep EOF), I am thinking about "switching to something else" but first i would like to be sure that the ORM I switch to does not have this weaknesses too.
List of (subjective? perhaps I only perceive them because I was exposed to EOF first?) weaknesses in JPA/Hibernate:

  • No way to manage an object that "will be persisted", in JPA/Hibernate if you call entityManager.persist(object) and the database does not support sequences (like MS-Sql) an insert will be triggered, and if any of the non nullable fields of the objects is null, it will crash. If your object has a compound primary key, things get worse, because the entityManager can not deal with it until the compound primary key is set, and if your compound primary key is formed by foreign keys pointing to objects that are new too, that means you will not be able to save stuff with with a simple single call to entityManager.persist to one of the objects, cascading will not help you (I really miss something "magic" like the single shot EditingContext.saveAllChanges() in EOF)
  • No easy way to know if "an object is dirty" (if it has changed/deleted since it was read from the database, there is just no API for that), and since you can not know what objects will be persisted, and what object have changed, and what objects will be deleted from database, that means you can not easily create an unified API for centralized polymorphic validation (that is no easy way to create validateForSave, or validateForDelete methods in your persistent entity classes)
  • No real equivalent for validateForXXX, JPA lifecycle callbacks are not match for validateForXXX because you can not query the database during the lifecycle callbacks, and if you throw an exception inside a lifecycle callback, the JPA/Hibernate entityManager enters an invalid state, and after that you can not continue to use your POJOs, you have to start over with a fresh entityManager... and without you modifications to the POJOs. Note that Hibernate new validation framework does not offer a real solution for this problem... and AFAIK JSR-000303 will not help with this either.
  • No support for some kind of temporary id: In JPA/Hibernate, the id for an object is "null" until you flush it to the database, so if you need to reference a particular object instance from the user interface... there is plain no way to do it, you have to "save it first" to get a primary key.
  • No support for Nested Contexts... ( I think they would be a perfect fit for conversational frameworks like Seam or Shale). One of the goals of the ObjectContext is to provide an isolated area where local object changes can be performed without affecting other similar areas or the underlying storage. Nested Context changes can be saved to the parent Context without saving them to the database. Such child context is often called "nested". Nested contexts are useful in many situations, such as nested UI dialogs, complicated workflows, etc.

Those are my main disagreements with the way I have to work with JPA/Hibernate... will switching to JPA/EclipseLink, JPA/OpenJPA or the still not fully JPA compliant Apache Cayenne help me with those? I will be writing about my findings on this in my following posts

Wednesday, February 25, 2009

AribaWeb: The framework of my dreams?

Could AribaWeb, finally be the framework of my dreams? that for which I have longed for ever since I stopped using WebObjects? The one to finally demonstrate those Ruby guys that what makes Ruby so great is Rails, and what made Java inferior (until before AribaWeb) was its framework, but not the language itself?

So far, it seems that, while not perfect (no client side caching, some Hibernate inherited validation limitations), AribaWeb gets many basics concept right (like programmatic navigation, UI meta generation, runtime UI customization, MVC separation…)

I am simply amazed….

Now someone just needs to integrate AribaWeb with Capuccino, and total world domination would be in their hands.

Wednesday, February 18, 2009

Functionally Complete Crud Generator

In my previous post I wrote about the Irreducible Complexity Model ….now why is that model so important?

Well, for a Crud Generator to be functionally complete it has to fulfill the following requirements:

  1. Be able to generated the Crud Screens for the Irreducible Complexity Model
  2. It should be possible to “capture” the entire “model graph” as a single transaction starting from any node in the graph
  3. It should be possible to “skip” validation until the “save” button of the screen to save the node where we started is clicked, and, it should be easy to go from there to any of the screens used to edit the other nodes to fix any validation error.
  4. It should be possible to search for instances (rows?) of the entity (class, table?) by using a “query by example” node graph that can be built using one or all of the nodes of the model with any arbitrary depth.

With this rules, I realize that the only functionally complete crud generator that I have seen was Apple WebObjects Direct2Web… All others (JBoss SeamGen for example) are unable to deal with all the kinds of relationships in the Irreducible Complexity Model and, even without that limitation, are just unable to deal with requirements 2,3, and 4. because all of them force you to either violate transactionality by forcing you to save before navigation to the next node, or force you to pass all validation rules at a particular node before going to the next, or, have a really simple and powerless query by example UI.

Irreducible (Minimal?) Complexity: EntityModel (RelationalModel? DatabaseModel?)

I am not sure that the name Irreducible Complexity Entity Model actually fits what I am about to describe, but I was the best I can think of:

Lets think of an Entity Model (Database Model?, Relational Model?) that has at least one instance of each kind of entity relationship, so that it becomes representative of pretty much anything that can happen at any database:

  • A One To One relationship
  • A One To Many relationship

So we would have:

  • TableA One To One TableB
    TableB One To Many TableC

But then, we remember that there are recursive relationships so the list now is:

  • A One To One relationship to the same table
  • A One To One relationship to another table
  • A One To Many relationship to the same table
  • A One To Many relationship to another table

So now we have:

  • TableA One To One TableA
  • TableA One To One TableB
  • TableB One To Many TableB
  • TableB One To Many TableC

But then we realize that there is si not representative of any case, because there is another kind of relationship, one that is “complex” (formed by 2 of the “simple” ones described before: Many To Many) so:

  • A One To One relationship to the same table
  • A One To One relationship to another table
  • A One To Many relationship to the same table
  • A One To Many relationship to another table
  • A Many To Many relationship to the same table
  • A Many To Many relationship to another table

So we have:

  • TableA One To One TableA
  • TableA One To One TableB
  • TableB One To Many TableB
  • TableB One To Many TableC
  • TableC Many To Many to TableC (using TableCC as intermediate)
  • TableC Many To Many to TableD (using TableCD as intermediate)

Now, with this one would think we have a representative case for each “conceptual” kind of entity relationship. Am I right? (For example Object Relational Mappers? offer a way to map relationships for their Object Oriented counterparts, and the only kinds of relationships that are supported by them (when going from the database to the object model) are: One To One, One To Many? and Many To Many?. (If going from the Object Model to the database, then "Inheritance" enters the game, so I guess the Irreducible Complexity Entity Model would have to include "Inherits From?" as a relationship type (note that Inherits From? is the only kind of relationship that can not be used in "reflective" way):

* A One To One relationship to the same class
* A One To One relationship to another class
* A One To Many? relationship to the same class
* A One To Many? relationship to another class
* A Many To Many? relationship to the same class
* A Many To Many? relationship to another class
* A Inherits From? relationship to another class

And so we get:

* Class A One To One Class A
* Class A One To One Class B
* Class B One To Many Class B
* Class B One To Many Class C
* Class C Many To Many to Class C
* Class C Many To Many to Class D
* Class D Inherits From Class E

But, then we realize there is another case, what if the relation is not to a concrete but to an abstract class?

  • Composition
    • A One To One relationship to the same class
    • A One To One relationship to another class
    • A One To Many relationship to the same class
    • A One To Many relationship to another class
    • A Many To Many relationship to the same class
    • A Many To Many relationship to another class
  • Inheritance
    • A Inherits From relationship to another Concrete Class?
    • A Inherits From relationship to an Abstract Class

And then (finally?) we realize that this "Concrete/Abstract" separation also applies to the Composition relationships:

  • Composition
    • A One To One relationship to the same abstract class
    • A One To One relationship to the same concrete class
    • A One To One relationship to another abstract class
    • A One To One relationship to another concrete class
    • A One To Many relationship to the same abstract class
    • A One To Many relationship to the same concrete class
    • A One To Many relationship to another abstract class
    • A One To Many relationship to another concrete class
    • A Many To Many relationship to the same abstract class
    • A Many To Many relationship to the same concrete class
    • A Many To Many relationship to another abstract class
    • A Many To Many relationship to another concrete class
  • Inheritance
    • A Inherits From relationship to another Concrete Class?
    • A Inherits From relationship to an Abstract Class

I wonder if I am missing a particular combination/ relationship kind… (or if there is a simpler way to express this…)

Friday, October 31, 2008

Conceptual Queries extension for JPAQL: JPAQL queries are too sensitive to model changes

When a query is written in JPAQL, it still depends to much on the domain model (I think JPAQL could be extended to support Conceptual Queries).

For example, lets say you want to:

Find each white cat that lives in a house with doors made of wood

A cat is of one color, it lives in one house, a house can have 1 door and the door can be made of 1 material

So, the query in JPAQL looks like this:

select c from Cat c where c.color=”white” and c.house.door.material.name = "wood"

But then, lets say our customer changes the requirements:

Find each white cat that lives in a house with doors made of wood

A cat is of one color, it lives in many houses, a each house has many doors and the door is made of one or more materials (for example half glass, half wood)

Since our relationships are now @OneToMany so we write their names in plural, and we are newbies in JPAQL we try doing this (and it, of course does not work):

select c from Cat c Cat c where c.color=”white” and c.houses.doors.materials.name = "wood"

Now, we can of course solve this problem using subqueries and the exists keyword, but that makes the resulting query way more complex, and even if the above worked, it still is a different query, but, in our english example, the query didn’t change:

Find each white cat that lives in a house with doors made of wood

So, why we can not write in JPAQL something like:

select c from Cat c where c with color= “white” and lives in House has Doors made of Material with name = "wood"

That way the query wouldn’t have to change even if the multiplicity of the relationships changed. Of course now the question is, from where do I get the “with”,“lives in”, “has”, “made of” and “with” well, simple:

  • The with operator is available for each non @Entity member of the class (for strings, integers, etc).
  • For relationships with other entities we just add the conceptual name of the relationship name as an attribute in the @OneToMany or @ManyToOne annotations:

Example:

Before:

public class Cat{

@Column

private String color;

@ManyToOne(conceptualName=”lives in ”)

private House houses;

}

After:

public class Cat{

@Column

private String color;

@OneToMany(mappedBy=”cat”, conceptualName=”lives in ”)

private Set<House> houses;

}

This way changes in the object model do not necessarily affect our queries. What do you think? Is this a good solution?

Tuesday, October 21, 2008

Process Isolation: JavaScript is getting it before Java!

So, with Google Chrome, JavaScript is finally getting process isolation (even IE 8 will work in a Loosely Coupled Internet Explorer (LCIE) mode that will give the JavaScript applications running there real OS level process isolation) and Java? well, Java still does not have a anything like that.

Requirements Analysis: Negative Space

A while ago, I was part of a team working on a crucial project. We were confident, relying heavily on our detailed plans and clear-cut requi...