One way is web services. I've written Java JAX-RPC clients which talk to a
J2EE Container's JSE (JAX-RPC service endpoint), and you can also have non-Java clients. The container vendor implements JAX-RPC
servlets for the JSE, so the JSE runs in a Servlet container.
Let's say you are invoking methods on generated stubs. Based on the contents of a WSDL description of a service, a
SOAP toolkit can be used to generate the stubs. (You'll have to do some research to establish what toolkits are available, I only know about how WebLogic Server generates the stubs.) These generated stubs are configured with all necessary information about the Web service and its endpoint. The client application uses the stubs to invoke remote methods available in the Web service endpoint.
The EJB 2.1 spec introduced another endpoint, the EJB endpoint. This endpoint is a stateless session bean which implements all the methods of the endpoint interface, which is a subinterface of either java.rmi.Remote or javax.ejb.EJBObject. You will still need a SOAP toolkit to generate the appropriate service interfaces to the Web service. The Web service client can then send a SOAP request to the EJB container which hosts the EJB endpoint.