Monday, June 19, 2006

On EJB Restrictions - Can You Open a Socket?

During job interviews, one of the frequent questions is "What restrictions are imposed on EJBs?". I had a chat recently with someone about it, and we still don't agree on the answer.

He believes we can't open sockets, while I believe it is perfectly allowed, if you don't retain the socket connection between method calls.

His arguments are based on an analogy with files. After all in Linux, files are sockets. Here are his interpretations on a document about EJB restrictions on java.sun.com:
  1. Passivation affects server sockets. Why client sockets are not affected by passivation is not mentioned. I suspect that given that the socket mechanism is the same in both cases (IP packets), there should be no difference.
  2. EJBs are not allowed to access files because files are not transactional. Well, it is my understanding that sockets are neither.
  3. Deployability. The file open in one JVM will not necessarily be open in another JVM. It is my understanding that the same will happen on sockets.
Now here is my reply:

The reference I mentioned says you can not open server sockets, because to use them, you would have to let them open between methods calls, otherwise you can't do anything with your server socket.
  1. Passivation will only happen after or before a method call, not in the middle.
  2. Good point, rollback seems hard with sockets.
  3. The real problem with files and deployability is about clustering. I quote the same source: "if an enterprise bean running in a JVM on a particular machine is using or holding an open file descriptor to a file in the filesystem, that enterprise bean cannot easily be moved from one JVM or machine to another, without losing its reference to the file." Basically it says what's bad with files is if you use them to store some kind of state, because then this state will be different on different servers. This issue does not exist with sockets. What you mention is simply a configuration issue. Your datasources will vary as well from one JVM to another (on different servers).
I have the advantage that my interpretation is more common. But his arguments are still clever and EJBs specs could have been a bit more explicit about the use of java.io.Socket. Here is the line about it in the specs:
"The EJB architecture allows an enterprise bean instance to be a network socket client, but it does not allow it to be a network server. Allowing the instance to become a network server would conflict with the basic function of the enterprise bean-- to serve the EJB clients"

Our disagreement shows how such a simple subject, what you can and can't do in EJBs, is most of the time badly understood.


7 comments :

  1. I think a lot of constrains have the orgin in the opportunity of the ejb container to cluster the Beans. Because the container must replicate the state it is difficult with thinks like files, sockets, ...

    Christian

    ReplyDelete
  2. I can't give a totally authorative answer on this, but when it has come up in the EJB3 expert group, the conclusion has always been that EJBs definitely are allowed to open sockets.

    -- Gavin

    ReplyDelete
  3. [References to the EJB 2.1 specification appear in parentheses]

    The most obvious question is: are we talking about an outbound connection socket, or are we talking about listening on a socket?

    Listening on a socket is not allowed (25.1.2).

    Making outbound socket connections is allowed (25.2.1, table 23). The EJB should make outbound connections through a java.net.URL. It's not clear to me if it's legitimate for an EJB to make a non-URL socket connection; my guess is that it's not although you'd probably get away with it.

    The EJB must obtain the URL through a URL connection factory (20.5.1.3).

    The EJB obtains the URL connection factory via a resource-ref entry in the bean's deployment descriptor (B.5).

    The factory itself is defined in a container-specific way, and it is recommended but not required that the URL connection factory be placed in the java:comp/env/url subcontext (20.5.1.1).

    Custom socket factories are not allowed (25.1.2).

    Socket connections must be closed if a stateful bean is passivated (7.4). Interestingly, this requirement only appears under stateful session beans but I don't see why it wouldn't apply to entity beans as well.

    ReplyDelete
  4. My guess is that if you want to _listen_ on a socket, you need to create a JCA connector (a RAR), and wire it up to an MDB.

    -- Gavin

    ReplyDelete
  5. With an EJB3 Entity Bean you can define attributes/fields as transient... This way i don't see a reason why it can't be done..

    I don't see a reason to keep all these filehandles open when the entity itself is persisted though.. So i would probably use EntityCallBackHandlers in order to reestablish the conenctions when the objects are loaded again...

    ReplyDelete
  6. Is there any solution to this problem? Not ONE place on the entire internet is a real tutorial for doing this. It's all assumptions and maybe this and maybe that. Many say that you should use JCA, but that seems a minor (UNDERSTATEMENT) overkill if you only would like to communicate back and forth with a homebrew c++ application?

    ReplyDelete
  7. I think you can trust Gavin's answer as he was part of the EJB3 expert group.

    ReplyDelete