Showing posts with label Design Patterns. Show all posts
Showing posts with label Design Patterns. Show all posts

Saturday, September 12, 2009

Saving (detached) entities

Saving an entity in JPA is simple, right? We just pass the object we want to persist to EntityManager.persist. It all seems to work quite well until we run into the dreaded "detached entity passed to persist" message. Or a similar message when we use a different JPA provider than the Hibernate EntityManager.

So what is that detached entity the message talks about? A detached entity (a.k.a. a detached object) is an object that has the same ID as an entity in the persistence store but that is no longer part of a persistence context (the scope of an EntityManager session). The two most common causes for this are:

  • The EntityManager from which the object was retrieved has been closed.
  • The object was received from outside of our application, e.g. as part of a form submission, a remoting protocol such as Hessian, or through a BlazeDS AMF Channel from a Flex client.

The contract for persist (see section 3.2.1 of the JPA 1.0 spec) explicitly states that an EntityExistsException is thrown by the persist method when the object passed in is a detached entity. Or any other PersistenceException when the persistence context is flushed or the transaction is committed. Note that it is not a problem to persist the same object twice within one transaction. The second invocation will just be ignored, although the persist operation might be cascaded to any associations of the entity that were added since the first invocation. Apart from that latter consideration there is no need to invoke EntityManager.persist on an already persisted entity because any changes will automatically be saved at flush or commit time.

saveOrUpdate vs. merge

Those of you that have worked with plain Hibernate will probably have grown quite accustomed to using the Session.saveOrUpdate method to save entities. The saveOrUpdate method figures out whether the object is new or has already been saved before. In the first case the entity is saved, in the latter case it is updated.

When switching from Hibernate to JPA a lot of people are dismayed to find that method missing. The closest alternative seems to be the EntityManager.merge method, but there is a big difference that has important implications. The Session.saveOrUpdate method, and its cousin Session.update, attach the passed entity to the persistence context while EntityManager.merge method copies the state of the passed object to the persistent entity with the same identifier and then return a reference to that persistent entity. The object passed is not attached to the persistence context.

That means that after invoking EntityManager.merge, we have to use the entity reference returned from that method in place of the original object passed in. This is unlike the the way one can simply invoke EntityManager.persist on an object (even multiple times as mentioned above!) to save it and continue to use the original object. Hibernate's Session.saveOrUpdate does share that nice behaviour with EntityManager.persist (or rather Session.save) even when updating, but it has one big drawback; if an entity with the same ID as the one we are trying to update, i.e. reattach, is already part of the persistence context, a NonUniqueObjectException is thrown. And figuring out what piece of code persisted (or merged or retrieved) that other entity is harder than figuring out why we get a "detached entity passed to persist" message.

Putting it all together

So let's examine the three possible cases and what the different methods do:

Scenario EntityManager.persist EntityManager.merge SessionManager.saveOrUpdate
Object passed was never persisted 1. Object added to persistence context as new entity
2. New entity inserted into database at flush/commit
1. State copied to new entity.
2. New entity added to persistence context
3. New entity inserted into database at flush/commit
4. New entity returned
1. Object added to persistence context as new entity
2. New entity inserted into database at flush/commit
Object was previously persisted, but not loaded in this persistence context 1. EntityExistsException thrown (or a PersistenceException at flush/commit) 2. Existing entity loaded.
2. State copied from object to loaded entity
3. Loaded entity updated in database at flush/commit
4. Loaded entity returned
1. Object added to persistence context
2. Loaded entity updated in database at flush/commit
Object was previously persisted and already loaded in this persistence context 1. EntityExistsException thrown (or a PersistenceException at flush or commit time) 1. State from object copied to loaded entity
2. Loaded entity updated in database at flush/commit
3. Loaded entity returned
1. NonUniqueObjectException thrown

Looking at that table one may begin to understand why the saveOrUpdate method never became a part of the JPA specification and why the JSR members instead choose to go with the merge method. BTW, you can find a different angle on the saveOrUpdate vs. merge problem in Stevi Deter's blog about the subject.

The problem with merge

Before we continue, we need to discuss one disadvantage of the way EntityManager.merge works; it can easily break bidirectional associations. Consider the example with the Order and OrderLine classes from the previous blog in this series. If an updated OrderLine object is received from a web front end (or from a Hessian client, or a Flex application, etc.) the order field might be set to null. If that object is then merged with an already loaded entity, the order field of that entity is set to null. But it won't be removed from the orderLines set of the Order it used to refer to, thereby breaking the invariant that every element in an Order's orderLines set has its order field set to point back at that Order.

In this case, or other cases where the simplistic way EntityManager.merge copies the object state into the loaded entity causes problems, we can fall back to the DIY merge pattern. Instead of invoking EntityManager.merge we invoke EntityManager.find to find the existing entity and copy over the state ourselves. If EntityManager.find returns null we can decide whether to persist the received object or throw an exception. Applied to the Order class this pattern could be implemented like this:


Order existingOrder = dao.findById(receivedOrder.getId());
if(existingOrder == null) {
dao.persist(receivedOrder);
} else {
existingOrder.setCustomerName(receivedOrder.getCustomerName());
existingOrder.setDate(receivedOrder.getDate());
}

The pattern

So where does all this leave us? The rule of thumb I stick to is this:

  • When and only when (and preferably where) we create a new entity, invoke EntityManager.persist to save it. This makes perfect sense when we view our domain access objects as collections. I call this the persist-on-new pattern.
  • When updating an existing entity, we do not invoke any EntityManager method; the JPA provider will automatically update the database at flush or commit time.
  • When we receive an updated version of an existing simple entity (an entity with no references to other entities) from outside of our application and want to save the new state, we invoke EntityManager.merge to copy that state into the persistence context. Because of the way merging works, we can also do this if we are unsure whether the object has been already persisted.
  • When we need more control over the merging process, we use the DIY merge pattern.

I hope this blog gives you some pointers on how to save entities and how to work with detached entities. We'll get back to detached entities when we discuss Data Transfer Objects in a later blog. But next week we'll handle a number of common entity retrieval pattern first. In the meantime your feedback is welcome. What are your JPA patterns?


Original Source

Bidirectional assocations

JPA offers the @OneToMany, @ManyToOne, @OneToOne, and @ManyToMany annotations to map associations between objects. While EJB 2.x offered container managed relationships to manage these associations, and especially to keep bidirectional associations in sync, JPA leaves more up to the developer.

The setup

Let's start by expanding the Order example from the previous blog with an OrderLine object. It has an id, a description, a price, and a reference to the order that contains it:

@Entity
public class OrderLine {
@Id
@GeneratedValue
private int id;

private String description;

private int price;

@ManyToOne
private Order order;

public int getId() { return id; }
public void setId(int id) { this.id = id; }

public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }

public int getPrice() { return price; }
public void setPrice(int price) { this.price = price; }

public Order getOrder() { return order; }
public void setOrder(Order order) { this.order = order; }
}

Using the generic DAO pattern, we quickly get ourselves a very basic OrderLineDao interface and an implementation:

public interface OrderLineDao extends Dao<Integer, OrderLine> {
public List<OrderLine> findOrderLinesByOrder(Order o);
}

public class JpaOrderLineDao extends JpaDao<Integer, OrderLine> implements
OrderLineDao {

public List<OrderLine> findOrderLinesByOrder(Order o) {
Query q = entityManager.createQuery("SELECT e FROM "
+ entityClass.getName() + " e WHERE order = :o ");
q.setParameter("o", o);
return (List<OrderLine>) q.getResultList();
}
}

We can use this DAO to add a orderline to an order, or to find all the order lines for an order:

 OrderLine line = new OrderLine();
line.setDescription("Java Persistence with Hibernate");
line.setPrice(5999);
line.setOrder(o);
orderLineDao.persist(line);

Collection<OrderLine> lines = orderLineDao.findOrderLinesByOrder(o);

Mo associations, mo problems

All this is pretty straight forward, but it gets interesting when we make this association bidirectional. Let's add an orderLines field to our Order object and include a naïve implementation of the getter/setter pair:

 @OneToMany(mappedBy = "order")
private Set<OrderLine> orderLines = new HashSet<OrderLine>();

public Set<OrderLine> getOrderLines() { return orderLines; }
public void setOrderLines(Set<
OrderLine> orderLines) { this.orderLines = orderLines; }

The mappedBy field on the @OneToMany annotation tells JPA that this is the reverse side of an association and, instead of mapping this field directly to a database column, it can look at order field of a OrderLine object to know with which Order object it goes.

So without changing the underlying database we can now retrieve the orderlines for an order like this:

 Collection<
OrderLine> lines = o.getOrderLines();

No more need to access the OrderLineDao. :-)

But there is a catch! While container managed relationships (CMR) as defined by EJB 2.x made sure that adding an OrderLine object to the orderLines property of an Order also sets the order property on that OrderLine (and vice versa), JPA (being a POJO framework) performs no such magic. This is actually a good thing because it makes our domain objects usable outside of a JPA container, which means you can test them more easily and use them when they have not been persisted (yet). But it can also be confusing for people that were used to EJB 2.x CMR behaviour.

If you run the examples above in separate transactions, you will find that they run correctly. But if you run them within one transaction like the code below does, you will find that the item list while be empty:

 Order o = new Order();
o.setCustomerName("Mary Jackson");
o.setDate(new Date());

OrderLine line = new OrderLine();
line.setDescription("Java Persistence with Hibernate");
line.setPrice(5999);
line.setOrder(o);

System.out.println("Items ordered by " + o.getCustomerName() + ": ");
Collection<OrderLine> lines = o.getOrderLines();
for (OrderLine each : lines) {
System.out.println(each.getId() + ": " + each.getDescription()
+ " at $" + each.getPrice());
}

This can be fixed by adding the following line before the first System.out.println statement:

 o.getOrderLines().add(line);

Fixing and fixing...

It works, but it's not very pretty. It breaks the abstraction and it's brittle as it depends on the user of our domain objects to correctly invoke these setters and adders. We can fix this by moving that invocation into the definition of OrderLine.setOrder(Order):

 public void setOrder(Order order) {
this.order = order;
order.getOrderLines().add(this);
}

When can do even better by encapsulating the orderLines property of the Order object in a better manner:

 public Set<OrderLine> getOrderLines() { return orderLines; }
public void addOrderLine(OrderLine line) { orderLines.add(line); }

And then we can redefine OrderLine.setOrder(Order) as follows:

 public void setOrder(Order order) {
this.order = order;
order.addOrderLine(this);
}

Still with me? I hope so, but if you're not, please try it out and see for yourself.

Now another problem pops up. What if someone directly invokes the Order.addOrderLine(OrderLine) method? The OrderLine will be added to the orderLines collection, but its order property will not point to the order it belongs. Modifying Order.addOrderLine(OrderLine) like below will not work because it will cause an infinite loop with addOrderLine invoking setOrder invoking addOrderLine invoking setOrder etc.:

 public void addOrderLine(OrderLine line) {
orderLines.add(line);
line.setOrder(this);
}

This problem can be solved by introducing an Order.internalAddOrderLine(OrderLine) method that only adds the line to the collection, but does not invoke line.setOrder(this). This method will then be invoked from OrderLine.setOrder(Order) and not cause an infinite loop. Users of the Order class should invoke Order.addOrderLine(OrderLine).


The pattern

Taking this idea to its logical conclusion we end up with these methods for the OrderLine class:

 public Order getOrder() { return order; }

public void setOrder(Order order) {
if (this.order != null) { this.order.internalRemoveOrderLine(this); }
this.order = order;
if (order != null) { order.internalAddOrderLine(this); }
}

And these methods for the Order class:

 public Set<OrderLine> getOrderLines() { return Collections.unmodifiableSet(orderLines); }

public void addOrderLine(OrderLine line) { line.setOrder(this); }
public void removeOrderLine(OrderLine line) { line.setOrder(null); }

public void internalAddOrderLine(OrderLine line) { orderLines.add(line); }
public void internalRemoveOrderLine(OrderLine line) { orderLines.remove(line); }

These methods provide a POJO-based implementation of the CMR logic that was built into EJB 2.x. With the typical POJOish advantages of being easier to understand, test, and maintain.

Of course there are a number of variations on this theme:

  • If Order and OrderLine are in the same package, you can give the internal... methods package scope to prevent them from being invoked by accident. (This is where C++'s friend class concept would come in handy. Then again, let's not go there. ;-) ).
  • You can do away with the removeOrderLine and internalRemoveOrderLine methods if order lines will never be removed from an order.
  • You can move the responsibility for managing the bidirectional association from the OrderLine.setOrder(Order) method to the Order class, basically flipping the idea around. But that would mean spreading the logic over the addOrderLine and removeOrderLine methods.
  • Instead of, or in addition to, using Collections.singletonSet to make the orderLine set read-only at run-time, you can also use generic types to make it read-only at compile-time:
    public Set<
    ? extends OrderLine> getOrderLines() { return Collections.unmodifiableSet(orderLines); }

    But this makes it harder to mock these objects with a mocking framework such as EasyMock.

There are also some things to consider when using this pattern:

  • Adding an OrderLine to an Order does not automatically persist it. You'll need to also invoke the persist method on its DAO (or the EntityManager) to do that. Or you can set the cascade property of the @OneToMany annotation on the Order.orderLines property to CascadeType.PERSIST (at least) to achieve that. More on this when we discuss the EntityManager.persist method.
  • Bidirectional associations do not play well with the EntityManager.merge method. We will discuss this when we get to the subject of detached objects.
  • When an entity that is part of a bidirectional associated is (about to be) removed, it should also be removed from the other end of the association. This will also come up when we talk about the EntityManager.remove method.
  • The pattern above only works when using field access (instead of property/method access) to let your JPA provider populate your entities. Field access is used when the @Id annotation of your entity is placed on the corresponding field as opposed of the corresponding getter. Whether to prefer field access or property/method access is a contentious issue to which I will return in a later blog.
  • And last but not least; while this pattern may be a technically sound POJO-based implementation of managed associations, you can argue why you need all those getters and setters. Why would you need to be able to use both Order.addOrderLine(OrderLine) and OrderLine.setOrder(Order) to achieve the same result? Doing away with one of these could make our code simpler. See for example James Holub's article on getters and setters. Then again, we've found that this pattern gives developers that use these domain objects the flexibility to associate them as they wish.
Original Source

Saturday, August 29, 2009

Summary of Business Tier Patterns




The Presentation Tier will access the Business Tier via Business Delegate .
Business Delegate inturn access EJB by looking up using Service Locator.
The EJB [Session Facade] or the WebService End Point representing the Deployment Layer communicates to Application Service Layer [Algorithms, Main Logic].
Application Service Layer access Entities [Business Objects].

The communication between Tiers happen using Transfer Objects [not shown in the figure].
The Deployment Layer can also communicate to Business Objects directly and not via Application Service Layer depending on the Transaction Design.

Sunday, August 23, 2009

Summary of Presentation Tier Patterns

1) Intercepting Filters

You want to intercept and manipulate a request and a response before and after the request is processed.

When:

a) Does the client have a valid session?

b) Does the request path violate any constraints?

c) Do you support the browser type of the client?

d) What encoding does the client use to send the data?

e) Is the request stream encrypted or compressed?

Actors:

a) Filter Manager

Filter Manager manages Filter Processing. It creates the FilterChain with the appropriate filters, in the correct order, and initiates processing.

b) Filter Chain

The FilterChain is an ordered collection of independent filters.

c) Filter

Filter represents individual filters.

d) Target

The Target is the resource requested by the client. Target here can be a Front Controller.

2) Front Controller

You want a centralized access point for presentation-tier request handling

When:

a) You want to avoid duplicate control logic

b) You want to apply common logic to multiple requests.

c) You want to separate system processing logic from the view.

d) You want to centralize controlled access points into your system.

Does:

a) Converts the protocol specific requests into a more general form with the help of Context Object. An example of this is retrieving parameters from an HttpServletRequest instance and populating a MyRequest object that can be used independent of any servlet-related artifacts.

b) Validates the ContextObject for FormBased and Business Validation using the Validator provided by the ContextObject.

c) Delegates request to Application Controller.

3) Context Object

You want to avoid using protocol-specific system information outside of its relevant context. An example of this is retrieving parameters from an HttpServletRequest instance and populating a MyRequest object that can be used independent of any servlet-related artifacts. Context Object also provides a framework to validate the user data.

Actors:

a) ProtocolInterface [HttpServletRequest, HttpServletResponse]

An object that exposes protocol or tier-specific details.

b) ContextFactory [RequestContextFactory, ResponseContextFactory]

A ContextFactory creates a protocol and tier independent ContextObject.

c) ContextObject [RequestContextObject, ResponseContextObject]

ContextObject is a generic object used to share domain-neutral state throughout an application. Per Form a separate ContextObject can be created like for example StudentAdmission form can have its own ContextObject called StudentAdmissionContextObject which has its own logic for validating form.

4) Application Controller

You want to centralize and modularize action and view management.

Does:

a) First, the incoming request must be resolved to an action that services the request. This is called action management.

b) Second, the appropriate view is located and dispatched. This is called view management.

Actors:

a) Client

Client invokes the application controller. In the presentation tier, a FrontController or an InterceptingFilter typically fulfill this role.

b) ApplicationController

Uses Mapper to resolve an incoming request to the appropriate action and view, to which it delegates or dispatches.

c) Mapper

Uses a Map to translate an incoming request into the appropriate action [Command] and view [ViewFactory].

d) Map

Holds references to handles that represent target resources [Command or ViewFactory]

e) Target

A resource that helps fulfill a particular request, including commands, views and style sheets.

5) CommandProcessing

You want to perform core request handling and invoke business logic before control is passed to the view.

Actors:

a) ApplicationController

Manages choosing the appropriate action [Command] to fulfill the request.

b) CommandProcessor

Helps in processing the Command.

c) Command

Command performs an action for a request. It invokes the business method on the BusinessDelegate.

d) BusinessDelegate

BusinessDelegate acts as the façade which hides the details of invoking the BusinessService.

e) BusinessService

BusinessService is the Enterprise Beans normally Session Beans which does our task and returns the data in the form of the PresentationModel used by the view to render.

f) PresentationModel

PresentationModel is the data returned by the BusinessService for the use by the view.

6) ViewFactory

Helps in creating View

Does:

a) View Preparation

The view preparation phase involves request handling, action management, and view management. A request is resolved to a specific action, that action is invoked and the appropriate view is identified, with the request then being dispatched to that view.

b) View Creation

Subsequently, during view creation, the view retrieves content from its model, using helpers to retrieve and adapt the model state. Often extracted and adapted from TransferObject, this content is inserted, formatted, and converted into the static template text of the view to generate a dynamic response.

Actors:

a) ViewHelper

It helps in separating a view from its processing logic. This can be in the form of JSPTags, Helper Pojos etc.

b) ViewTemplate

Template used in creating view.

c) CompositeView

You want to build a view from modular, atomic component parts that are combined to create a composite whole, while managing the content and the layout independently.

d) PresentationModel

Presentation Model is the data used by the view.