I am trying to understand what the purpose and why we need the different client views in EJB. Could someone try to explain?
Remote client view
When your EJB and its clients will be in a distributed environment - meaning EJBs and clients will reside on separate Java virtual machines. Example : EJBs hosted on a WebSphere Application Server and Servlets that consume EJB APIs hosted on a Tomcat server.
Local client view
Only when it is guaranteed that other enterprise beans or clients will only address the bean within a single JVM. Example, EJBs as well as the Servlets deployed on the same WebSphere server.
No-Interface view
Is almost same as local client view, but there are differences. Your bean class is not required to implement client view interfaces in this case. All public methods of the bean class are automatically exposed to the caller. no-interface view always acquires an EJB reference - just like local or remote views - either through injection or JNDI lookup; but, Java type of the EJB reference is the bean class type rather than the type of a local interface. This is a convenience introduced as part of Java EE6.
Difference between local client view and no-interface view
In case of no-interface view, the client and the target bean must be packaged in the same application (EAR). In case of local view, client can be packaged in a separate application than the enterprise application. So, this gives more flexibility in terms of fine-graining your components.
You may use local client view vs no-interface view depending on your API usage scenario. It is very likely for no-interface view to receive flexible features in future specs.
Reason
Historically or otherwise, a client wishing to use EJB services was supposed to "look up" the bean on the container ( with certain initial contexts ). That was because all invocations are made through a special EJB reference(proxy) provided by the container. This allows the container to provide all the additional bean services such as pooling, container-managed transactions etc. So, a client can not explicitly instantiate an EJB with new operator. The client view is provided via certain interfaces that the client would have access to. The proxy realization at server side is done based on these interfaces. Different client views are defined to suite different deployment scenarios as mentioned above.
As per Section 3.2.2 of EJB 3.1 Specification:
Access to an enterprise bean through the local client view is only
required to be supported for local clients packaged within the same
application as the enterprise bean that provides the local client
view. Compliant implementations of this specification may optionally
support access to the local client view of an enterprise bean from a
local client packaged in a different application. The configuration
requirements for inter-application access to the local client view are
vendor-specific and are outside the scope of this specification.
Applications relying on inter-application access to the local client
view are non-portable.
No-interface view is just a convenience feature that allows a bean to
expose a local client view without having to declare a separate
interface.
Related
I'm new to Java EE and got confused about EJB.
As I understand #remote EJBs are using RMI and JNDI for communication.
Before EJB3.0 beans needed to implement Remote interface through EJBHome interface - that way I understand how RMI was used.
But now I only need to put #remote annotation, which can be substituted by properties in ejb-jar.xml.
So, the question is: how is it possible to use JNDI without Serializible interface and RMI without Remote interface?
Please correct me if some of my assumptions are wrong.
EJB3 still uses RMI underneath except the application container will take care of generating and using RMI stubs and remote interfaces automatically for you and map them to your EJB3 classes.
You are still required to use Serializible in certain cases. See this:
Clustered Session Beans (SLSB & SFSB)
First of all, clustered EJB3
SLSBs or SFSBs do not need to implement Serializable. In fact, it's
recommended that they don't. In the case of clustered SLSBs, no state
replication occurs, so their instance variables do not even need to be
Serializable. With clustered SFSBs though, the same serialization
rules used for SFSB passivation apply to SFSB state replication. In
other words, all non-transient instance variables that are not
references to beans, sessions contexts or user transactions must be
serializable, or null at replication time. For further information on
the SFSB passivation (and by extension replication because in both
cases the SFSB bean context needs to be serialized), please check
section 4.2.1 of the EJB3 core specification.
Clustered Entity Beans
These only need to be marked Serializable if
the clustered entity instances are to be passed by value as a detached
object (e.g., through a remote interface). Otherwise, there's no need
to mark them as Serializable.
EJB uses RMI, but it's not exactly equal to RMI. The container generates classes and interfaces at runtime that conform to the RMI spec, and hide them from you. This is why in a EJB project your remote client usually needs to include in its classpath a bunch of libraries specific to the container.
In this regard, EJB 2.0 was more transparent to the fact that it uses RMI under the hood, and thus, more complicated.
I'm using EJB 3.1. I need to get a references to one of the EJBs in a servlet and I'd rather not put an EJB interface jar on the class path to get the code to compile.
Is it possible to look an EJB via JNDI and find the method I want to invoke using reflection without ever strongly typing the object to an interface?
Yes, if you're looking up a local EJB interface, then you can look up and invoke a local EJB within the same application using reflection.
This should work if you're using a direct lookup or an EJB ref lookup because the Java EE spec requires the application server to make EJB module classes available to WARs within the same application. The EJB spec doesn't require support for local interfaces across applications, so if that's what you're doing, you'll have to check with your application server vendor.
This will not work in general for remote EJB interfaces because a client proxy needs to be created. If you're using RMI-IIOP (EJB 2.x remote or EJB 3 extending java.rmi.Remote), you might be able to cast the EJB lookup result to javax.rmi.CORBA.Stub and use the _servant_preinvoke or _invoke methods the same as a generated stub method would do.
(Ultimately, this is a lot of caveats just to avoid a compile-time dependency. It's probably not worth the fragility, so I would recommend finding a way to solve that and compile normally.)
Why only JNDI is used to access remote EJB (different JVM, differente host)? why not use the # EJB annotation?
In all EJB books mention that you can access remote EJB using #EJB annotation.
Example: http://docs.oracle.com/javaee/7/tutorial/doc/ejb-intro004.htm
32.4.4 Remote Clients
A remote client of an enterprise bean has the following traits.
It can run on a different machine and a different JVM from the enterprise bean it
accesses. (It is not required to run on a different JVM.)
It can be a web component, an application client, or another enterprise bean
It can be a web component, an application client, or another enterprise bean.
To a remote client, the location of the enterprise bean is transparent.
The enterprise bean must implement a business interface. That is, remote clients may not
access an enterprise bean through a no-interface view.
To create an enterprise bean that allows remote access, you must either:
Decorate the business interface of the enterprise bean with the #Remote annotation:
#Remote public interface InterfaceName { ... }
Or decorate the bean class with #Remote, specifying the business interface or
interfaces:
#Remote(InterfaceName.class)
public class BeanName implements InterfaceName { ... }
Client access to an enterprise bean that implements a remote business interface is
accomplished through either dependency injection or JNDI lookup.
To obtain a reference to the remote business interface of an enterprise bean through
dependency injection, use the javax.ejb.EJB annotation and specify the enterprise bean's
remote business interface name:
#EJB Example example;
To obtain a reference to a remote business interface of an enterprise bean through JNDI
lookup, use the javax.naming.InitialContext interface's lookup method:
ExampleRemote example = (ExampleRemote)
InitialContext.lookup("java:global/myApp/ExampleRemote");
The text above is incorrect? I have not seen any code that uses Dependency Injection (#EJB) to access a remote EJB. It is not possible?
Several post say it is not possible to use the # EJB annotation for calls to remote ejb:
https://stackoverflow.com/a/7842345/3167508
https://stackoverflow.com/a/16518704/3167508
PD: Excuse me. My English is basic.
I believe the main reason is that injection of remote (different JVM) EJB instances through
#EJB(lookup = "jndi_name")
is only supported by some Application Servers and only with specific configuration.
i.e. JBoss 7+ supports it only when you define the remote-outbound-connection in the standalone file (and add a jboss-ejb-jar.xml in the META-INF folder of deployed packages containing the reference to that connection).
Furthermore:
#EJB can only work in CDI managed beans
Using this approach forces you to define connection properties once per connection, while with the programmatic lookup you may vary them on every request (and you are free to handle contexts and connections manually, if needed).
I'm a newbie to EJB3. I want to know that how client know the EJB bean implementation is in remote or local. When i access the bean using InitialContext in client class i want to know wether that bean is local or remote? Sorry if I'm asking stupid question?
The type of interface is determined via annotations.
These can be put next to Interface class declaration:
#Local - declares a local business interface
#Remote - declares a remote business interface
Then when an EJB extends such interfaces, it uses the interface as a local/remote view. If it extends multiple interfaces, it has multiple views.
These can be put next to EJB class declaration:
#Local(com.example.LocalInterfaceClass) - declares a local business interface
#Remote(com.example.SomeRemoteInterfaceClass) - declares a remote business interface
#LocalBean - declares a no-interface view (the full bean definition used as an interface)
If multiple of above annotations are used in combination, the EJB has multiple interface views. If all are ommitted, the bean defaults to a no-interface view.
You can use JDK inbuilt annotation processing to process annotations during compile time (via javax.annotation.processing classes and javac commandline options). E.g. you could generate code or set options/switches.
You can use reflection to determine annotations at runtime.
Probably cleanest and simplest of all not to have dynamic lookup & behaviour, but just to commit to either Local or Remote for each client and hard-code the appropriate behaviour.
There are two different interfaces available when you are writing an EJB. One is remote and one is Local. Remote, as it name suggests is for remote client that want to remotely call (or fire) functions and get some results. On the other hand Local is designed to be used in a local environment, for example in a case if another EJB or even a POJO in your system is using that. The usage would be the same as when you want to use an EJB using its Remote interface. However, it has less headache for the server to handle that. That's the only reason you might want to use a Local interface instead of Remote interface. Local interface is not local to JVM but local like an other POJO class.
Local client view cannot be accessed:
When an EJB or web component is packaged in a different application's EAR packages.
When a web component is deployed in a web container, and EJBs are deployed in an EJB container, and these containers are separated (even if they are running on the same machine)
These are main factors in considering a Local or Remote interface:
Client: if your client is not a web component or another bean do not use Local
Beans & Beans: Are the beans loosely coupled? then it is a good idea to use Local
Scalability: Remote is always better for scalability
Local interfaces are recommended for entity beans, which helps with performance issue.
More to read:
http://onjava.com/pub/a/onjava/2004/11/03/localremote.html
http://www.conceptgo.com/gsejb/ov06.html
Using #Remote of your interface you can use as Remote interface
#Remote
public interface Cart {
}
Now, Implement this interface to EJB bean.
#Stateful
public class CartBean implements Cart {
}
Similarly using #Local annotation you can use as Local interface.
I have a #Stateless #Local Bean successfully deployed in an ear. I can see the new EJB 3.1 standard global JNDI name when I browse the JNDI tree. (java:global/product/product-ejb/ProductManagement)
I want to use this EJB in a different application on the same app server. Do I need to add a remote interface for this EJB?
Inter-application access to the local client view is not required by the specification but might be optionally supported by your container. If you want your application to be portable, you shouldn't rely on it and use a Remote interface (a decent container should optimize calls inside a same JVM anyway). From the EJB 3.1 specification:
3.2.2 Local Clients
Session beans may have local clients.
A local client is a client that is
collocated in the same JVM with the
session bean that provides the local
client view and which may be tightly
coupled to the bean. A local client of
a session bean may be another
enterprise bean or a web component.
Access to an enterprise bean through
the local client view requires the
collocation in the same JVM of both
the local client and the enterprise
bean that provides the local client
view. The local client view therefore
does not provide the location
transparency provided by the remote
client view.
Access to an enterprise bean through
the local client view is only required
to be supported for local clients
packaged within the same application
as the enterprise bean that provides
the local client view. Compliant
implementations of this specification
may optionally support access to the
local client view of an enterprise
bean from a local client packaged in a
different application. The
configuration requirements for
inter-application access to the local
client view are vendor-specific and
are outside the scope of this
specification. Applications relying on
inter-application access to the local
client view are non-portable.
...
References
EJB 3.1 Specification
Section 3.2.2 "Local Clients"