views:

1264

answers:

2

I'm in the process of developing a multi-tiered financial processing application in Java using EJB3 (Hibernate + Glassfish for the app and web services layer, Lift on Glassfish for the web UI) and I'm struggling with the question of where to put my business logic.

When this project started, our first notion was to put the bulk of our business logic into the stateless session beans. As time has gone on, though, we've found the dependency injection provided by the EJB framework too limiting, so a lot of our business logic has ended up in POJOs that are assembled by Guice in the @PostConstruct method of the stateless session beans. This progress has led to fragmentation of our business logic between the session beans and the POJOs, and I'm trying to figure out an approach for correcting this.

Initially, we tried to have our web tier use the remote interfaces of the session beans to perform some functions that are accessible both from the UI and from the web service layer, which is provided by @WebService-annotated stateless session beans. This turned out to be a nightmare from a persistence and performance perspective, because our entity graph can grow quite large and reattaching the detached entity graph to the persistence context turned out to be highly error-prone, so our solution was to start just passing object identifiers around and looking up the entities from the database wherever they were needed.

My basic question is this: what principles and guidelines can you suggest for deciding whether business logic should go in a session bean or a POJO? When does it make sense to pass entity beans around, given a complex object graph?

A: 

Whenever you need many "system" services (injections, etc) use stateless bean. Otherwise - POJOs. POJOs are much more flexible.

However simple (accessor?) methods (e.g. in webservices and beans) can just do some simple work and return the results.

G B
By "system" services, you're referring to such things as the persistence context, transactions, etc? I ask because my application uses a number of external services that require injected dependencies (connection configuration and stuff) that I'm handling with Guice.
Kris Nuttycombe
+1  A: 

I struggled with this while building a webapp using JPA, EJB3, and Wicket. Since hitting my database hard with repeated queries was more scalable than holding lots of large entities in memory, I decided to only pass around their ids and never the entity itself.

Wicket and its concept of models had a lot to do with this decision. Their loadableDetachableModel cleans up entities when they are not in use, while still holding on to the id. A load() method is implemented which knows how to get the entity when it is needed again, in my case by calling a stateless session bean; and a persist() method calls the stateless bean to persist changes. This model class is what I actually pass around. Wicket only handles logic pertaining to display and input validation, and I only need to inject the ejb into the model classes. Perhaps you could create something similar in your app (I've got no idea what lift has to offer...).

This has worked out nicely for me, but I don't have particularly complex business logic and can isolate any changes which need to be persisted into small units of logic and single pages.

perilandmishap