Heterogeneous Interfaces

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)

Last updated