Adam Bien's Weblog

Building Perfect Anti-Facades - Almost Without Layers, For Better Maintainability

Sometimes you own the database and the requirements are driven by the customer / sponsor and so mainly by the UI. Decoupling from your own database is, in such scenario, not beneficial. In contrary the decoupling would make your code more complex and harder to maintain. In the case of a feature enhancement, you will have to maintain / enhance the mapping logic and all indirections as well.

Instead of hiding your domain objects behind a Service Facade, you could directly derive the objects from the database (e.g. through generation) and expose them directly (=per reference) to the UI. The presentation tier (JSF, Wicket and other server-centric frameworks) could even bind the persistent objects declaratively to the UI-components.

A stateful session bean is perfectly suitable for this job. The EXTENDED EntityManager keeps all, already loaded, JPA-entities managed. This approach has a significant advantage - there is no synchronization and manual loading of lazy references needed. The EntityManager reacts to transactions and flushes all "dirty" entities into the database. The transaction is initiated the empty save method. The EJB 3.X gateway is simple. It exposes the root / aggregate entity and is very similar to a domain repository:


@Stateful
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class OrderGateway{

    @PersistenceContext(type=PersistenceContextType.EXTENDED)
    EntityManager em;

    private Load current;

    public Load find(long id){
       this.current = this.em.find(Load.class, id);
       return this.current;
    }

    public Load getCurrent() {
        return current;
    }

    public void create(Load load){
        this.em.persist(load);
        this.current = load;
    }

    public void remove(long id){
        Load ref = this.em.getReference(Load.class, id);
        this.em.remove(ref);
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void save(){
        //nothing to do
    }
}

The Gateway remembers the root entity and makes it accessible through a getter. This can be leveraged in declarative data binding (you could even navigate from the backing bean, through the Gateway into a JPA entity). A Gateway is very easy to test outside, as well as, inside the EJB-container.

The EJB 3.1 / JSF 2.0 project GatewayWarDeployment was tested with Glassfish v3 and NetBeans 6.8 / 6.7.1 and pushed into: http://kenai.com/projects/javaee-patterns/.

[See Gateway, page 101 in "Real World Java EE Patterns Rethinking Best Practices" book for more in-depth discussion]


NEW workshop: Microservices with Java EE 7 and Java 8, January 26th, 2015, Airport Munich

A book about rethinking Java EE Patterns

Comments:

Have you ever made any measurements on how large a footprint it leaves on a typical App Server to maintain this client/server-like scenario with the UI and RDMS linked directly with a Gateway?

I could easily see the memory footprint explode on an average WebSphere cluster ... :-) Or is there a trick to minimizing this impact or perhaps even building a better performing system compared to using Service Facades everywhere? I guess it very much depends on how containers optimizes handling of stateful session beans behind the scenes.

Posted by Martin K on September 23, 2009 at 01:40 PM CEST #

"(in such cases) decoupling would make your code more complex and harder to maintain. In the case of a feature enhancement, you will have to maintain / enhance the mapping logic and all indirections as well."

So true. Too often programmers blindly follow the "must decouple" mantra w/o realizing its downsides.

Posted by Itay Maman on September 23, 2009 at 02:31 PM CEST #

Sorry but I feel queasy with such an approach.

I can not imagine that all what we've learned in the past was wrong (the statelesser the better paradigm).

I aggree with the trend to slimming the excessive layering.

But when I have an application with a certain complexity, with business functionality which has to be used not only from one UI and so on it is really hard for me to believe that this is the right approach from an application designing point of view.

Also the resource consumption would be much more expensive...

Posted by Martin on September 23, 2009 at 03:29 PM CEST #

@Martin K

Gateway isn't viable for all scenarios - it is stateful and can consume a significant amount of memory. The newer versions for WebSphere are actually leaner than expected :-) The problem, however is the EntityManager - it will cache all managed entities for the length of the transaction...

I will cover that in some upcoming posts...

thanks!,

adam

Posted by Adam Bien on September 24, 2009 at 12:12 AM CEST #

@Martin,

you are right - Gateway is not suitable for all use cases. Stateless ServiceFacades are still viable - especially for more procedural (service oriented) use cases.

Gateway itself is simplistic - the exposes rich domain objects may be really complex.

In one of my past projects we had about 10-20 Gateways and several hundred entities. It was one of the most complex projects I worked on.

thanks for your feedback!

adam

Posted by Adam Bien on September 24, 2009 at 12:16 AM CEST #

Have a look at JBoss Seam. They propose the architecture with a Gateway. And there are - at least for web applications - some performance and memory problems. But they can be resolved if you understand the business and the frameworks. There is a very good article about JBoss Seam (http://www.jsfcentral.com/articles/speed_up_your_jsf_app_2.html) at JSFCentral from Dan Allen.

From my experience, you are really fast developing applications with this approach and if you have a good IDE(A) which supports declarative access to Domain Object - your done (Seam Support in IDEA). And this is what counts.

Posted by Cyrill on September 24, 2009 at 12:35 AM CEST #

Adam,

You can't imagine how am I with you on this one. Many developers still program the way they did in about 2004-2005 and still generate tons of layers, just because "it's decoupling". Sometimes I advise people to have a look at Ruby on Rails (as a kind of extreme opposition to excessive layering in web apps) just to see the difference.

I am also with Cyrill on Seam - it allows to expose session beans as managed beans in the view layer by thus eliminating yet another useless glue layer who's purpose is to bind ejb's with the jsf managed beans (if you want to use extended persistence context, for example). Even better- it provides functionality like you've given above but without single line of (java) code.

Regards,
Siarhei

Posted by Siarhei on September 25, 2009 at 04:58 PM CEST #

Unfortunally the approach ain't work in a clustered environment (with session replication enabled) without an EntityManager that is Serializable and replicates the changes to the entities to the other servers in the cluster. The container is also not able to passivate such SFSB without a Serializable EM. I may be wrong, but I'm not aware of a persistenceprovider that allready supports this? In other words: as long theres no such support in JPA you first have to decide against high availability of your application before going down this road.

Posted by ntruchsess on September 26, 2009 at 12:17 AM CEST #

How do you recommend to work with lists of objects (reports, tables of objects and so on)? Do you recommend to create both Facade (to get list of objects at the first step) and Gateway (to view and edit properties of one selected object)?

Regards,
Roman

Posted by Roman on September 28, 2009 at 06:02 PM CEST #

@Ntruchsess,

your question was too interesting too be answered here :-). I wrote a post about that: http://www.adam-bien.com/roller/abien/entry/does_httpsession_stateful_session_bean

regards!,

adam

Posted by Adam Bien on September 29, 2009 at 12:37 PM CEST #

Very interesting. But does the entities are shared across the sessions ?

If 100 clients access the same 100 entities, will we have 100 shared entities in memory or 100x100=10000 non-shared entities ?

Posted by Arnaud on September 29, 2009 at 06:11 PM CEST #

Hello Adam,

I am new in EJB technology and may be my questions are strange, but I cannot catch the idea how I can make full system with using your approach.

As I understand the layer of Facades is not only a way how to connect client layer with domain objects, but it also can be used for some 'common tasks' like logging, notifications and so on.

For example, I need to log all changes in domain objects. Do you recommend to do this from domain objects by self? In this variant domain objects will be clients by self, using other facades/gateways, processing events. What do you think about this?

I also need to notify set of listeners (modules-plugins) about changes in configuration (domain objects) through JMS. The problem is that if I do this from domain objects, JMS messages will be sent before transaction's commit, but this is too early. Is there a way to do that from gateway's 'save' method by getting the list of changed objects, for example?

Is it possible/convenient to use your approach in my situation or my examples are just not typical and in this particular case I should use classic approach with facades and interceptors?

Thank you in advance!
Roman

Posted by Roman on October 15, 2009 at 05:59 PM CEST #

Hi Adam,

on Websphere I only was able to update the database with this save-method:

public void save {
em.flush();
}

It seems like the commit of the transaction does not necessarily makes changes visible to other EntityManagers...

Dirk

Posted by Dirk on February 04, 2010 at 12:07 PM CET #

Hi! Can you help me pls.
I have two glassfishv3 servers and
statefull session bean.
public class TestSession implements TestSessionRemote, TestSessionLocal {
private
List<String> list;

public void add(String parameter) {
list.add(parameter);
}

I want to implement replication session copies of these objects between the two servers, but do not know how to do it. :(

Posted by Alex on March 22, 2010 at 01:15 PM CET #

What about the notion of conversations (single page in my case). Maybe a single stateful order gateway works just fine, but what if I need multiple coversations. Can I @ViewScoped a @Stateful bean?

Posted by Alex on August 27, 2010 at 01:57 AM CEST #

The is a feature that can make the Entitymanager survive after passivation in Jboss Seam 2 framework. I didn´t test this solution, because I have my eyes on Seam 3, not Seam 2.

http://docs.jboss.org/seam/2.2.0.GA/en-US/html/ClusteringAndEJBPassivation.html#d0e29958

Posted by Flávo Henrique on September 16, 2010 at 05:32 AM CEST #

Maybe I missed the Point, but how can I make a change undo.
I miss something like refresh all.

I have a save method but no cancle method.
Can anyone help me on that point.

Chris

Posted by Chris on September 03, 2011 at 01:08 AM CEST #

Hi Adam,
I can't catch one thing. Facade should be designed in a way where its methods should take as argument some primitive types, entity objects, transfer objects or mixed?
For example: is it better to create method:
1) addEntry(Entry e, List<Long> dictionaryIds),
2) addEntry(String name, String value, ..., List<Long> dictionaryIds)
3) addEntry(Entry e), where Entry e contains list of dictionary objects
4) addEntry(AddEntryTO e), where AddEntryTO is a specific transfer object containing name, value and list of dictionaries id.
(Let's define {Entry: String name, String value, List<Dictionary> dictionaries}, {Dictionary: String name, List<Entry> entries}

Taking into account your other posts and book about patterns I would follow the third option, but then there are two problems:
- I can pass some values which are not interesting for client (should I null them before returning? or create TO object which is an overkill..)
- client can send me the Entry object (as inpput argument for some method) containing some element which should affect changes to database - or example he pass Dictionary object which has the same id as an exisiting object in the database but has some other fields changed (name). In this case my method addEntry will persist entry object merging changes to existing dictionary object (that is lack of security). Shuld I then rewrite gathered object (treat it as TO) to newly created object coping only necessary information?

Thank you and I am waiting for your response!
wojciech

Posted by Wojciech on October 06, 2012 at 01:15 AM CEST #

Hi Adam,
Quick question concerning the gateway pattern. Even in your last book I don't see anything about "clearing" the entity manager. In fact, I'm trying to use this pattern for a ui screen with a table and a small editor corresponding to the current selected row in the table. So, I'm keeping the reference to the gateway and for each selection change event in the table, I'm setting the corresponding "entity" in my gateway. My main concern is that I'm having more and more objects in my first level cache (the entity manager). I'm wondering if it could be a good idea, in that case, to provide a function in my gateway allowing to clear the cache.

Thanks in advance for your valuable input.

Best regards

Steve

Posted by Steve on September 09, 2013 at 07:53 PM CEST #

@Steve

I'm using a CDI interceptor to clear the entity manager at some point. For example, if I have some pagination, changing of page would clear my persistence context to always keep a limited number of entities loaded at all time.

Posted by Xavier on August 28, 2014 at 10:30 AM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed
realworldpatterns.com
...the last 150 posts
...the last 10 comments
License