views:

41

answers:

2

I'm creating a stateless session bean (the façade) which will be used for "managing" a particular entity, let's call it Product. There will be methods to add a new product, update an existing product, get products, etc (I'm using Hibernate for persistence, so I have a "ProductDbManager" bean that the façade will use for DB access).

This bean will be exposed as a web service so it can be called from a web interface and a simple desktop app.

My question is, would it be best practice for a method such as AddProduct to accept an instance of Product, or the individual parameters such as "Name", "Description", "Price", etc?

It's possible for a Product to be created with just a "Name" initially, or perhaps "Name" and "Description", or with all attributes set, and so on. From that point of view it would be simpler (in terms of creating the façade) just to accept the Product instance so that the client can simply create a new Product, set whichever attributes are available, then pass it in.

With the alternative option, I will need to create quite a few overloads of AddProduct in order to accept the varying parameters. However, would this be preferable in order to be as flexible as possible and make life easier for the users of the façade? Should both options be availble?

+1  A: 

I’d prefer adding a Product instance directly. If you worry about client code creating Product instances, you can supply a ProductFactory that can then have all those overloaded methods for setting only parts of a Product.

Bombe
+1  A: 

I prefer web service methods to take in objects representing related data items.

Sometimes for non-trivial methods, to the point of having:

DoActionResponse doAction(DoActionRequest request);

as my web service method. The web service implementation will then do input validation (in the same way that a servlet would validate form input before passing it on to the core of your code) and necessary data mapping to what your core code expects. Why Data Mapping? I've found that having a web service data model that is separate from my internal core system data model allows me to update my internal model as required without changing the external model, and thus affecting clients.

For yours, I'd have

boolean addProduct(Product toAdd);

just in case you add more fields to Product, you don't need to change your web service interface, which will eventually lead to five people having to change their code three years down the line because their systems piggy-backed onto your web service.

I'd also consider some authentication, so that only admin users can manipulate the database. SOAP has stuff for this, or you could have:

boolean addProduct(Product toAdd, Authentication auth);

or

AuthToken login(String username, String password);
boolean addProduct(Product toAdd, AuthToken token); // token is a string really. like a session id

But what about returning errors to the client, not just true/false? Sure, there is SOAPFault but it's quite low level. That's why I sometimes have response objects, where one of the fields in the object is an array of error objects (error code, error message, etc).

JeeBee
Thanks for that. Interesting point about the seperate data model - as my internal entities are JPA annotated POJOs, it didn't seem right for the clients to use these directly (i.e. in the case of changing the DB structure, etc).
William
Yeah, we had a similar issue with database metadata in the object (ids and timestamps) we didn't want to expose. As time has gone by, we've found that separating models leads to better reliability (with multiple clients) and easier to maintain code. It's a pain with a complex model of course, especially when they're effectively the same structure.
JeeBee
My only concern would be possibly violating the DRY principle, though I suppose it would be possible to somehow auto-generate the exposed classes from the JPA entities, leaving out the internal attributes.
William
Better than violating the Don't Expose Yourself principle, where you expose too much of your innards to an external party. It does depend on your web service implementation of course. With Axis we had to also change to using plain arrays and so on, which made a different model a nicer option. The amount of incompatibility between different web service implementations is a real pain, and currently Axis doesn't even work with itself because it can't java2wsdl enums (a problem in the wsdl generator). No wonder people advocate WSDL-First.
JeeBee