Java Champion / JavaOne Rockstar Adam Bien (adam-bien.com) is a self-employed consultant, lecturer, software architect, developer, and author in the enterprise Java sector. He is also the author of several books and articles on Java and Java EE technology, as well as distributed Java programming. adam has posted 59 posts at DZone. View Full User Profile

Why Stateful and Local Anti-facades are KISS

08.03.2010
| 4107 views |
  • submit to reddit

The Gateway exposes rich and persistent domain objects directly to the presentation logic. Because the domain objects are well encapsulated already - it is rather an advantage, than a shortcoming. Because of simplicity and built-in aspects, an EJB 3.1 happens to be the simplest and leanest candidate for a Gateway implementation.

Why local (to JSF 2, Wicket or a Fat Client)?

  1. Rich domain objects (JPA 2) contain business logic per definition. A call to method can change the state not only of the target entity, but of the whole connected graph. In the local case the EntityManager will correctly recognize the changes and compute deltas (change sets) and persist all changes at the end of the transaction. In remote case you will have to implement the same functionality - what is actually duplication.
  2. In local case you don't have to care about lazy loading. The entities gets just loaded on demand.

Why stateful (means: keeping the entities attached between requests)?

  1. In complex scenarios the data synchronization between layers becomes a challenge. If you keep you entities managed between requests, there is nothing left to do. You can even bind them directly to the UI - and it will still work.
  2. For every request you will have to build the domain graph again and again. This is not only complex, but it does not necessarily scale better, than a stateful solution

Local, stateful facades are not necessary the silver bullet, but the resulting architecture is very lean. It mainly consists of only domain objects, with a few Gateways.

Before you start prematurely "improving" the scalability and start with bloated applications, it is more reasonable to concentrate on the core business logic and stress test continually the application. In some cases a stateful architecture wont't scale. In this case you will have to provide the synchronization, delta-computation afterwards - with demand documented with stress test results. [See Gateway, page 101 in "Real World Java EE Patterns Rethinking Best Practices" book for more in-depth discussion]

From http://www.adam-bien.com/roller/abien/entry/why_stateful_and_local_anti

Published at DZone with permission of its author, adam bien.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Andrea Mattioli replied on Tue, 2010/08/03 - 6:30am

My main customers are small-size enterprises (5-10 employees) so scalability usually is not a problem for me. The real problem is that they have only a few money to spend for software so I have to develop as quick as possible to maintain low costs.

I've found that using stateful services that keep entities attached between requests gave me a lot of speed. Using ZK that is stateful in nature allowed me to bind UI to business logic objects in a very simple way.

I collected my experience about the subject in the JavATE framework

Ronald Miura replied on Tue, 2010/08/03 - 7:08am

Applications have state, this is a fact. Where and how you hold this state is the problem.

If you try to make things completely 'stateless', you end up keeping state in hidden fields, which introduces all sorts of security problems.

If you just make everything stateful without much consideration, you make it hard to understand the code. Even if the code itself is clean (fewer lines), you can't know for sure what it does, because you can't make safe assumptions about the state (you introduce a 'time' variable into the equation). Contrast this with a (purely stateless) function, which takes some parameters, and return a value, and everything between is relative to the parameters passed. No concurrency, no stale state.

The combination I like most is, keeping the state within the UI (the state is always relative to the user interactions anyway), and keep my business code stateless. 'Rules' shouldn't have state, at least not user interaction-related state, only business-related state (which is held in the database, not in instance variables).

Simplicity is not about less code. Code that is easy to read is simple. Code that is easy to understand is simple. Simplicity is not necessarily in fewer lines of code, even if it looks simpler.

Andrea Mattioli replied on Tue, 2010/08/03 - 3:13pm

Ronald,
I once reasoned like you but experience changed my mind.

Consider this very simple example: I have a view of a person with birth-date and age, every time I change the birth-date the age has to change.

Maintining the state on the UI means that if the user change the birth-date I have to tell the field representing age to update.
So some event-processor has to take the value from the birth-date field, call the function that calculates age from birth-date and set the new value on the age field.

It seems simple. But if you try to test it you face a little problem. The event-processor needs to access both the birth-date and the age fields. And UI components not always can be mocked-up in a simple way. This could not be a problem in this very simple example but imagine you have to calculate a mortgage plan!

Compare it with the JavATE stateful approach: I have an object that represent the person (maybe an entity or some stateful service)  with a readable/writable birth-date property and a read-only age property
public class Person extends EntityImpl {
private Date birthDate;

public Date getBirthDate() {
return birthDate;
}

public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
firePropertyChange("birthDate");
}

@Derived(dependsOn="birthDate")
public int getAge() {
return calcAgeFromBirthDateInSomeWay(this.birthDate);
}

}

Every time the birth-date is set a property-change event is fired for the birth-date property and consequently a property-change event is fired for the age property (as it is annotated with @Derived).

The Person object is very simple to test because all the logic is encapsulated in one class.

Now you can bind your UI fields on this object. All the logic in these fields will be the binding one that is common to most fields and can be factored out. In JavATE it is part of the library and you don't have to write a line of code to do it. And  you don't need to test it (you have to test only your code, not library code).

Ronald Miura replied on Tue, 2010/08/03 - 8:20pm

I didn't say that the app should be stateless, I said that the state should be held in the UI layer.

With JSF/Seam, it would be in those Action/Home beans. With Wicket, it would be the Page class.

And this kind of simple value-binding between these two properties could be easily implemented (in either JSF or Wicket) like this:
public class Person {
  private Date birthDate;
  public Date getBirthDate() {
    return birthDate;
  }
  public void setBirthDate(Date birthDate) {
    this.birthDate = birthDate;
  }
  public int getAge() {
    return calcAgeFromBirthDateInSomeWay(this.birthDate);
  }
  ...
}
or
public class Person {
  private Date birthDate;
  private int age;
  public Date getBirthDate() {
    return birthDate;
  }
  public void setBirthDate(Date birthDate) {
    this.birthDate = birthDate;
    this.age = calcAgeFromBirthDateInSomeWay(this.birthDate);
  }
  public int getAge() {
    return age;
  }
  ...
}
They don't even need this event-dispatching stuff, since they store/retrieve values directly from properties, and their components don't need to be notified of changes.

About the state (which is what I'm talking about), here is the code in Wicket:
public class PersonPage extends WebPage {
  @SpringBean // using Spring to inject dependencies
  PersonDAO dao;
  public PersonPage(Person person) {
    Form form = new Form("form", new CompoundPropertyModel(person));
    form.add(new TextField("birthDate")); //editable
    form.add(new Label("age")); //read-only, since the age is derived from birthDate
    form.add(new Button("save") {
      public void onSubmit() {
        dao.save(person);
        info("Person saved");
        setResponsePage(HomePage.class);
      }
    });
  }
}
In this case, the Page is holding the state, the current person object. In Seam, it could be held in the Home bean and the interactions would happen within a conversation (which I really don't like, I prefer the simplicity of Wicket).

When I said that the state should be held in the UI, and not in the business layer, I meant that DAOs/Services/Façades should be stateless (unless you have a reeeeeaaaaally good reason not to), and the state should be as near the UI as possible.

But if you code your applications like the samples that come with Seam, with all the code in Action and Home beans, well, there are no layers, so the state must be there, mixed with the UI code. If so, then Adam is right, you simply can't make classes stateless, which is a quite hard thing to do with Seam.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.