I'm new to Java EE so please bear with me. I am trying to write a server that will listen for connections. When one arrives, it will hand off the connection (server socket) to a stateful bean which will service it and then be destroyed when the connection terminates. The stateful bean will use various JPA entities.
I am trying to do this with Netbeans. I created a new project of type "enterprise application". I then told it to make an EJB module and an application client module, but not a web application module. I created the main server listener loop in the main method of the application client's main class. The plan was to hand off to the stateful EJB within this loop, eg
clientSocket = ss.accept();
@EJB MainCommLoop mainCommLoop;
so the stateful bean would be used without an interface. I have created all of my entity classes and the stateful bean (MainCommLoop) in a package I created in the ejb module.
However, I have two problems:
1. I can't seem to inject the stateful bean in the application client's main class. The line @EJB MainCommLoop mainCommLoop produces the error: "annotation type not applicable to this kind of declaration".
2. I can't move the main class for the application client to my own package. If I move it from the default (no) package to my own package, it builds, but then when I try to run the application client I get an error that the module was not deployed.
Tim Holloway wrote:You have a bigger problem than that.
EJBs are forbidden (per the EJB spec) to listen on socket connections.
You need to hand off the listening function to a service that isn't part of an EJB.
The EJB isn't listening. The application client is listening. After the application client accepts a connection, it hands off the socket produced by ServerSocket.accept() to the EJB.
Well, actually, I think you'll find that the constraint also applies to receiving network traffic as well.
Joined: Oct 29, 2009
Here is what sunacle has to say on the subject:
Why can an enterprise bean not listen to or accept connections on a socket?
Because if an enterprise bean is listening on a socket, it can't be passivated -- it must always be available. Enterprise beans can be network socket clients, and so they can use other network resources (including other enterprise bean servers) to do their jobs. Just as with a database connection, don't hang on to open client sockets across method calls; instead, open them, communicate through the socket, and close it before returning from the method.
So maybe I should rethink the design, but its not prohibited by the specification.
I hadn't thought about passivation, but it's generally accepted that if you start playing games with networking on objects who are depending on on a network-based infrastructure that you're risking corruption of the container's network state.
An equally important reason is that EJBs are not processes, and therefore shouldn't be sitting around waiting for things to happen. In the original strict default implementation, an EJB method would block other accesses to the EJB while an EJB method call was being handled.
There is, however, a fine old tradition of using EJBs for message processing. Web services, JMS, etc. The key is that the listening, receiving and dispatching are done by some sort of process that isn't subject to EJB constraints. The control process then invokes EJBs to do the backend work.
Joined: Oct 29, 2009
Thanks very much for this discussion -- I have a better understanding now of how to do this. But I'll still want to use EJB's from my application client, so my original problem will still need to be solved. Anyone?