This chapter deals with different views which which EJBs can expose to their prospective clients. These are as follows
Local
Remote
No-interface
Web service
What are its benefits ?
Flexibility: Gives you the ability to choose the appropriate view for your business requirements. You can also mix and match views (subject to rules) if need be
Ease of use: View management is declarative in nature (annotation driven) and hence it is naturally easy to adopt
Interoperability: Helps business logic written using EJB 2.x specification adapt to the its modern (3.x) counterpart. Again, this adaptability is managed via annotations
Web Service
This is typically in the form of a SOAP or REST web service. For further details, please refer to the Web Services support chapter
@Local
This annotation can be used on a session bean interface or the bean implementation class itself - either ways, it makes the session bean available to clients in the same JVM.
The container exchanges instances of these beans by reference (within the same JVM). Hence Local session bean interfaces tend to be more efficient when compared to their remote (@Remote) counterparts (discussed soon)
There are multiple ways in which it can be used
Default
EJB implements an interface (without using @Local). The container applies local bean semantics by default
package ejbap.views.local.interfaces;
import java.util.Date;
public interface GithubAPIInterface {
public Date getLastUpdated(String repoID);
public int getStars(String repoID);
public int getForks(String repoID);
}
The implementation
package ejbap.views.local;
import ejbap.views.local.interfaces.GithubAPIInterface;
import java.util.Date;
import javax.ejb.Stateless;
@Stateless
//Local view assumed by default
public class GithubRestAPIImpl implements GithubAPIInterface {
@Override
public Date getLastUpdated(String repoID) {
return new Date(); //updated today !
}
@Override
public int getStars(String repoID) {
return 42;
}
@Override
public int getForks(String repoID) {
return 42;
}
}
EJB implements an interface which is annotated with @Local
package ejbap.views.local.interfaces;
import javax.ejb.Local;
@Local
public interface TimerServiceInterface {
public String getTime();
}
package ejbap.views.local;
import ejbap.views.local.interfaces.TimerServiceInterface;
import java.util.Date;
import javax.ejb.Stateless;
@Stateless
public class TimerServiceBean implements TimerServiceInterface {
@Override
public String getTime() {
return new Date().toString();
}
}
EJB implements an interface which is not annotated with @Local
package ejbap.views.local.interfaces;
public interface UserRepositoryInterface {
public String getUserFirstName(String id);
public String getUserEmail(String id);
}
package ejbap.views.local;
import ejbap.views.local.interfaces.UserRepositoryInterface;
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Stateless
@Local(UserRepositoryInterface.class)
public class DBUserRepository implements UserRepositoryInterface {
@PersistenceContext
private EntityManager em;
@Override
public String getUserFirstName(String id) {
//use EM
return "";
}
@Override
public String getUserEmail(String id) {
//use EM
return "";
}
}
EJB does not implement the interface but designates it as its local view
package ejbap.views.local.interfaces;
public interface TweeterInterface {
public void authenticate(String tweeterID, String pswd);
public int getRetweets(String tweetID);
public int getLikes(String tweetID);
}
package ejbap.views.local;
import ejbap.views.local.interfaces.TweeterInterface;
import javax.ejb.Local;
import javax.ejb.Stateless;
@Stateless
@Local(TweeterInterface.class)
public class TwitterJavaAPIBasedImpl {
public void authenticate(String tweeterID, String pswd) {
//logic
}
public int getRetweets(String tweetID) {
return 42;
}
public int getLikes(String tweetID) {
return 42;
}
}
@Remote
This annotation is also applicable for a session bean interface or the bean implementation class itself. It makes the session bean available to clients outside the JVM in which it is deployed
The container exchanges instances of these beans by value i.e. communication using remote EJB views requires serialization (of method parameters and return types)
Possible usage combinations (similar to @Local)
EJB implements an interface which is annotated with @Remote
EJB implements an interface which is not annotated with @Remote
EJB does not implement the interface but designates it as its remote view
@LocalBean
The usage of the @LocalBean annotation is synonymous with the no-interface view which means that the EJB does not implement any interfaces.
package ejbap.views.nointerface;
import java.util.Date;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Stateless
@LocalBean //does not make a difference
public class AttachmentManagerBean {
@PersistenceContext
private EntityManager em;
public void createAttachment(){
//use EM
}
public Date getAttachmentCreateDate(){
//use EM
return new Date(); //created just now!
}
}
Why is this even required ? Why not leave the bean alone (with just the @Stateless annotation) ?
Strictly speaking, @LocalBean is supposed to be used in scenarios where
the no-interface view needs to co-exist with other views which a session bean might expose
in case it implements another interface(s) which are not remote/local views
package ejbap.views.nointerface.interfaces;
public interface WorkflowManagementInterface {
public void trigger();
public String getCurrentAssigne(String workflowID);
public boolean isComplete(String workflowID);
public int getStatus(String workflowID);
}
package ejbap.views.nointerface;
import ejbap.views.nointerface.interfaces.WorkflowManagementInterface;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@Stateless
@LocalBean
public class WorkflowMangementSessionFacade implements WorkflowManagementInterface {
@Override
public void trigger() {
//logic...
}
@Override
public String getCurrentAssigne(String workflowID) {
return "42";
}
@Override
public boolean isComplete(String workflowID) {
return true;
}
@Override
public int getStatus(String workflowID) {
return 42;
}
}
@LocalHome
This annotation acts as a bridge b/w EJB 3.x and 2.x style session beans i.e. it can help 3.x session beans to be compatible with clients of EJB 2.1 (and before) session beans (since it was mandatory for beans to have home interfaces)
@RemoteHome
This is the remote equivalent of the @LocalHome annotation. It helps remote EJB 3.x beans adapt to EJB 2.1 style beans which previously required the existence of home interfaces
@Init
This annotation is applied on a method is only required for stateful session beans that provide an adapted remote/local home interface (using @RemoteHome or @LocalHome annotations discussed above)