[EJB 3.0 Users] - Re: Design: When the line between domain objects and service
by ttarhan
Don't read too much into my specific example. I'm trying to illustrate a point. My point is that EJB and JPA force us into a model where our domain objects cannot rely on any container provided services. I fully understand the reasoning behind it.
However, I'm asking for ideas on elegant ways to deal with this issue. If certain subclasses of an Entity need to do things that weren't necessarily anticipated when the service layer was created, we have to make changes to the service layer to specifically support these things.
So each time I subclass Mailbox, I have to modify a service method somewhere to deal with that new type of Mailbox, if that new type has any different behavior which may need a container service. This means we completely miss-out on the polymorphism of the Mailbox object.
Seems to go against the whole notion of objects, which combine data and behavior, and more into a combination of data structures and procedural methods.
So, does anyone have any solutions?
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4257767#4257767
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4257767
14 years, 7 months
[EJB] - Loading classes from client for EJB 2 / RMI Class loading fr
by evgens
Imagine you have a SessionBean with the method:
| Object executeTask(Task t) throws RemoteException {
| return t.execute();
| }
|
where
| public interface Task {
| Object execute();
| }
|
This means, the client of this EJB can call the method executeTask with its own class, that implements Task interface:
| public class Pi implements Task, Serializable {
| ...
| /**
| * Compute the value of pi to the specified number of digits after the
| * decimal point. The value is computed using Machin's formula
| */
| public Object execute() {
| int digits = 45;
| int scale = digits + 5;
| BigDecimal arctan1_5 = arctan(5, scale);
| BigDecimal arctan1_239 = arctan(239, scale);
| BigDecimal pi = arctan1_5.multiply(FOUR).subtract(arctan1_239)
| .multiply(FOUR);
| return pi.setScale(digits, BigDecimal.ROUND_HALF_UP);
| }
|
Obviously, the server will not have this implementation class.
RMI has introduced special JVM Parameter for this: java.rmi.server.codebase
The client has to specify it while starting its jvm: -Djava.rmi.server.codebase=file:/Users/xxx/work/samples/compute-client-0.0.1-SNAPSHOT.jar
where the jar file compute-client-0.0.1-SNAPSHOT.jar contains the class PI.
This works perfectly in standard sun's RMI.
This also works fine in JBoss 4.2 and newer, but only if the SessionBean is implemented and deployed as EJB3.
Unfortunately I have failed trying to get it running in JBoss 4.2.2 for the SessionBean that was implemented and deployed as EJB2 with the following exception:
| Caused by: java.lang.ClassNotFoundException: No ClassLoaders found for: sample.remote.ejb2client.Pi
| at org.jboss.mx.loading.LoadMgr3.beginLoadTask(LoadMgr3.java:212)
| at org.jboss.mx.loading.RepositoryClassLoader.loadClassImpl(RepositoryClassLoader.java:521)
| at org.jboss.mx.loading.RepositoryClassLoader.loadClass(RepositoryClassLoader.java:415)
| at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
| at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:374)
| at java.lang.Class.forName0(Native Method)
| at java.lang.Class.forName(Class.java:242)
| at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:585)
| at org.jboss.invocation.MarshalledValueInputStream.resolveClass(MarshalledValueInputStream.java:109)
| at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1544)
| at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1466)
| at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1699)
| at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
| at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1634)
| at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299)
| at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
| at org.jboss.invocation.MarshalledValue.get(MarshalledValue.java:91)
| ...
|
Does anybody have an idea what can be wrong?
P.S. The security manager of both client and server were set to java.lang.SecuirtyManager. The corresponding policy file on both client and app. server allows everything:
| grant {
| permission java.security.AllPermission;
| };
|
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4257745#4257745
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4257745
14 years, 7 months
[EJB 3.0 Users] - Design: When the line between domain objects and service obj
by ttarhan
I have a design question in the fight about domain driven design, the anemic domain model, and the way EJB/JPA force us to do things.
Consider a web-mail application which is built using JPA for persistence and EJB for the services layer. Let's say we have a service method in our EJB like this:
| public void incomingMail(String destination, Message message) {
| Mailbox mb = findMailBox(destination); // who cares how this works
| mb.addMessage(message);
| }
|
This is seemingly a reasonable business method. Presumably, the Mailbox object will still be attached and it will seamlessly save the changes back to the database. After all, that is the promise of transparent persistence.
The Mailbox object would have this method:
| public void addMessage(Message message) {
| messages.add(message);
| }
|
Here's where it gets complicated -- assume we want to have other mailbox types. Say we have an AutoRespondingMailbox which automatically responds to the sender, and a HelpDeskMailbox which automatically opens a helpdesk ticket with each email received.
The natural thing to do would be to extend Mailbox, where AutoRespondingMailbox has this method:
| public void addMessage(Message message) {
| String response = getAutoResponse();
| // do something magic here to send the response automatically
| }
|
The problem is that our Maibox object and it's subclasses are "domain objects" (and in this example, also JPA entities). The Hibernate guys (and many others) preach a non-dependent domain model -- that is, a domain model that does not depend on container/runtime provided services. The issue with such a model is that the AutoRespndingMailbox.addMessage() method cannot send an email because it can't access, for example, JavaMail.
The exact same issue would occur with HelpDeskMailbox, as it could not access WebServices or JNDI injection to communicate with the HelpDesk system.
So you're forced to put this functionality in the service layer, like this:
| public void incomingMail(String destination, Message message) {
| Mailbox mb = findMailBox(destination); // who cares how this works
| if (mb instanceof AutoRespondingMailbox) {
| String response = ((AutoRespondingMailbox)mb).getAutoResponse();
| // now we can access the container services to send the mail
| } else if (mb instanceof HelpDeskMailbox) {
| // ...
| } else {
| mb.addMessage(message);
| }
| }
|
Having to use instanceof in that way is the first sign of a problem. Having to modify this service class each time you want to subclass Mailbox is another sign of a problem.
Does anyone have best practices for how these situations are handled? Some would say that the Mailbox object should have access to the container services, and this can be done with some fudging, but it's definitely fighting the intended usage of JPA to do that, as the container provides dependency injection everywhere except in Entities, clearly indicating that this isn't an expected use case.
So, what are we expected to do instead? Liter-up our service methods and give-up polymorphism? Our objects automatically become relegated to C-style structs and we lose most of the benefit of OO.
The Hibernate team would say that we should split our business logic between the domain layer and the service layer, putting all of the logic that's not dependent on the container into the domain entities, and putting all the logic that is dependent on the container into the services layer. I can accept that, if someone can give me an example of how to do that without having to completely give-up polymorphism and resorting to instanceof and other such nastiness.
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4257740#4257740
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4257740
14 years, 7 months