There's been some discussion of how to implement a service in J2EE: use a stateless session bean (SLSB), a plain old Java object (POJO), or a combination thereof.
Awhile back, I discussed How to Implement a Service in J2EE. (Where I abbreviated "stateless session bean" as "SSB". And the abbreviation for "stateful session bean" would be ...?! I meant to use the abbreviation SLSB (which is not a SFSB). Duh!) Synchronous clients could invoke the service by calling the method in the SLSB's local or remote interface. Asynchronous clients could use JMS messages; an MDB would receive the request, invoke the method in the SLSB's local interface, then return the result in a reply message. For HTTP clients (such as a Web service), the MDB would be a servlet. I go on to say that the object could be a POJO, but making it a SLSB adds the advantages of being an EJB.
Eugene Kuleshov has discussed this further on his blog on BEA's dev2dev. In Implementing J2EE-based services for a real world, Eugene shows a design whereby the service is implemented as a POJO, which can then be invoked by a SLSB or a MDB. He points out that this is more dependency injection (IoC) friendly. I agree.
My bias is that I use WAS and I don't use enterprise Java w/o EJBs frameworks like Spring (which also supports EJBs for good measure). So my first pass at an implementation is usually to go ahead and put the code in the EJB. Nevertheless, if I see or later discover the need to use code separately without going through an EJB (perhaps because I'm already going through another EJB), I would certainly refactor the code to move the logic into a separate POJO class. Whether that should always be done preemptively, just in case--I rarely (never?) do.
I will say that I believe it's a good practice to pretty much always have an MDB delegate to a SLSB, not directly to a POJO as Eugene shows. This way, synchronous and asynchronous clients will always experience the same QoS, whatever you configure in the SLSB--security, transactions, etc. An MDB or servlet calling the same access point that synchronous clients do--usually a SLSB--is the typical implementation of the Service Activator pattern (EIP, Core J2EE).
So, Eugene makes some good points. His approach and mine are pretty similar, but with a little difference that depends on one's desire to fit into frameworks like Spring. If you're interested in this stuff, check out what Eugene has to say.