Lets start by assuming that the Servlets and Session Beans are running on
separate machines (ie. a 'web' cluster and an 'object' cluster).

What do the Session Beans return to the Servlets?

My initial thought is to return the Business Data Objects directly. On the
object cluster, the Business Data Objects will be JDO enhanced, on the web
cluster they won't be - but it will be the same code.

But perhaps there need to be Value Objects that are created from Business
Data Objects. The problem is, writing a set of classes that just act as
containers for
all of the Business Data Objects seems to be a little wasteful. But I guess
generic solutions are possible...

I've seen a lot of discussion on value objects, and I agree with you, having value objects along with your persistence capable objects seems to be a duplication of a lot of stuff.

Since I see session beans as usually representing a request-response paradigm, I define XML Schemas for requests and responses, then use an XML Schema-to-Java code generator (until JAXB implementations become available) to create serializable Java request and response objects. You could define one request and response object per session bean method, or you could consolidate the request & response objects as you see fit. This way, you achieve several benefits:

1. You can support clients that can speak XML (over RMI, RMI-IIOP, COM via JIntegra, etc)
2. You are not returning more data than the client needs. For example, if a session bean client only needs two properties of a persistence capable business object, your response object can be defined to hold only those two values, whereas a value object would probably return all of the business object's properties, sucking up more bandwidth than really is necessary. The tradeoff? More classes, of course, but when they're generated code, the impact is not quite as severe as hand coding request and response classes.

It is important to note that I let the problem domain drive the discovery of our persistence capable business objects, and let use cases drive the discovery of the coarse-grained session bean methods, as well as temper how far you go during the analysis of the problem domain.

For example, if you had a persistence capable business object called com.yourcompany.Corporation, there might be session bean methods to perform operations on Corporation objects, like:

The "String execute(String request)" method would take an XML request, parse it enough to know which method to call, marshal the XML's request part into the appropriate Java request object, call the appropriate method, capture the return value of the method in the appropriate Java response object, marshall the response object back into the XML response, and return the response to the client.

The other methods could also be called directly from Java clients -- the String-based methods are there to help with non-Java clients. Since the Java request and response objects are serializable, Java clients could bypass the overhead of XML marshalling.

In this example, you can see an explosion in the number of *Request & *Response objects. Since they're generated, there's not much to worry about on that front, but you do have to be careful of the code that uses these generated classes -- changes may have a ripple effect.

This reply was originally sent to jdo-listserve at techtrader dot com, so please excuse some of the TechTrader-specific hype :)

-----------------------
>What do the Session Beans return to the Servlets?
>My initial thought is to return the Business Data Objects
>directly.

This is a great question. If your data objects are serializable, they can certainly be returned directly from the session beans. There is one gotcha when doing this, though: when a JDO instance is serialized, the entire object graph of related instances is serialized as well. While this is exactly how 'normal' java objects act when serialized, some people are surprised when serializing one JDO object that happens to have a lot of persistent relations ends up sucking in almost the entire DB! This problem is easily surmountable by either:
a) Making sure to only return instances with few relations (it's generally good to minimize inter-object dependencies anyway).
b) Making instances 'transient' before returning them and nulling relations that aren't needed by the web tier. (pm.makeTransient (obj))

Of course, one doesn't have to return jdo instances at all. Other options include packing only the needed data into special containers (tedious, but possibly automated in some generic way through reflection or otherwise), or simply using the session tier to perform transactional operations only.

In this latter case, very little data would have to be returned from EJBs (only the result of the update/insert/whatever or the calculation made). The web tier could use a PersistenceManager with 'nontransactionalRead' set to true to gather the data it needs itself, without the overhead of EJBs. If you're concerned that the business logic -- including how to find the right instances -- should all be performed in Session Beans, have them return one or more Query instances (which are serializable and can be re-constituted through the PersistenceManager.newQuery (Object otherQuery) method) that the web tier can then execute to get the data it needs. Either way, having the web tier do the work in 'read-only' situations and having Session Beans perform transactions gives you the best of both worlds and is amazingly efficient.

A final option is to use JDO and entity beans together, where any JDO instance that is to be returned to the client is first proxied with an entity bean wrapper. TechTrader has plans to work on this in the future, but not in the near term.

>On the
>object cluster, the Business Data Objects will be JDO
>enhanced, on the web
>cluster they won't be - but it will be the same code.

This doesn't matter. The deserialized instances -- even if enhanced -- will lose their association with the PersistenceManager during the transfer process and will therefore act exactly like 'normal' object instances.

If anyone else has some ideas on possible usage patters, please speak up! JDO is a new technology to all of us.

-- Abe White
TechTrader

p.s. Plug for new and somewhat relevant product: Within 2 weeks, TechTrader is going to release a new product that uses bytecode enhancement to transform normal java classes into stateful/stateless Session EJBs, with no change to either the class code or any code that used the original class. So using the above Session Bean patterns will get a whole lot easier.

If the servlet needs the Customer's name and address, then it would
make sense to return a Customer (business data object, I'm assuming)
directly to the servlet. The servlet could deserialize into a
non-enhanced class providing that care is taken to maintain the
serialization ID between the two versions. However, the enhance class
could also be used on the servlet as well, if you don't mind the code
bloat, although none of the PM stuff is available since JDO is not on
the web cluster. The deserialized business object is non-transactional
and non-persistent -- in other words, a JDO transient object, and by
definition it should act just like an object of the unenhanced class.
So yes, as I see it, value objects will be returned to the client of the
remote service that itself uses JDO.

On the other hand, if the servlet needs to verify that the client has
at least a net wealth of 100K in all brokerage accounts before serving
them up the page that allows them to apply for options trading, then
this would be just another service that the business service offers with
no business objects being returned.

The return trip from the first case is interesting as well. The
servlet may accept changes from the client to the name and address, and
now wants to send the modified Customer object back to the business
service to be validated and persisted. The business service like the
servlet receives a JDO transient object upon deserialization. It must
now find the JDO persistent object that matches. If primary key JDO
identity is being used, this is straightforward, since the application
can construct the JDO identity from the transient instance. If
datastore JDO identity is being used, then its a bit trickier. Last I
heard, Draft Two of the Proposed Final Draft which hasn't yet been
released will allow extracting a text key from the toString method
of JDO identity object, which can then be used with a TBD factory method
to recreate the key. So this text key could be sent down with the
Customer object and then, when it's sent back, used to recreate the
datastore JDO identity and find the persistent object. Having found the
matching persistent object, the class should probably have a utility
method to update the persistent object with the value object.
Thereafter, the code performs validation and either commit or rollback.

It is required to match the returned value object to the persistent
object on the return trip, since just calling makePersistent() on the
returned value objects will either lead to another distinct object in
the datastore or a duplicate primary key exception.

I don't think there is any general purpose need to write wrapper or
container classes.

TechTarget provides technology professionals with the information they need to perform their jobs - from developing strategy, to making cost-effective purchase decisions and managing their organizations technology projects - with its network of technology-specific websites, events and online magazines.