Client View of Bean  «Prev  Next»

Lesson 5 Creating a session EJB
Objective Write Java Code in Client to create Session EJBs

Write Java Code in Client to create Session EJBs

In Jakarta EE 10 (formerly known as Java EE), the approach to creating and accessing Session Enterprise JavaBeans (EJBs) varies based on the type of client interacting with them. Here's a detailed explanation:
1. Server-Side Clients (Within the Same Application Server):
  • Dependency Injection: Simplified Access: If the client is another component within the same Jakarta EE application (such as a servlet, another EJB, or a managed bean), you can leverage dependency injection to access Session EJBs. This mechanism eliminates the need to write explicit code to instantiate or look up EJBs.

Implementation Example:
import javax.ejb.EJB;
import javax.inject.Named;
import javax.enterprise.context.RequestScoped;

@Named
@RequestScoped
public class MyBean {

   @EJB
   private MySessionBeanLocal mySessionBean;

   public void performAction() {
	   mySessionBean.businessMethod();
   }
}

In this example, the `@EJB` annotation instructs the container to inject an instance of `MySessionBeanLocal` into `mySessionBean`. The developer doesn't need to write any additional code to create or locate the EJB.

2. Remote Java Clients (Standalone Java Applications):
JNDI Lookup:
  • Explicit Code Required: For clients running outside the application server, such as standalone Java applications, developers must write code to perform a Java Naming and Directory Interface (JNDI) lookup to obtain a reference to the Session EJB.

Implementation Example:
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class RemoteClient {
 public static void main(String[] args) {
  try {
   Context context = new InitialContext();
   MySessionBeanRemote mySessionBean = 
   (MySessionBeanRemote) context.lookup(
   "java:global/myApp/MySessionBean!com.example.MySessionBeanRemote");
    mySessionBean.businessMethod();
	} catch (NamingException e) {
    e.printStackTrace();
	}
  }
}

In this scenario, the client performs a JNDI lookup to retrieve the remote interface of the EJB and then invokes its methods.

3. Web Service Clients (RESTful or SOAP-based):
  • Exposing EJBs as Web Services:
    • No Direct EJB Code Required: If the Session EJBs are exposed as RESTful (using JAX-RS) or SOAP-based web services, clients can interact with them over HTTP. This approach abstracts the EJB layer from the client, allowing interactions without direct EJB-related code.
    • Implementation Example (Exposing EJB as RESTful Service):

import javax.ejb.Stateless;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Stateless
@Path("/myservice")
public class MySessionBean {

   @GET
   @Path("/business")
   @Produces(MediaType.TEXT_PLAIN)
   public String businessMethod() {
	   return "Business logic executed.";
   }
}

Clients can then make HTTP GET requests to the `/myservice/business` endpoint to invoke the `businessMethod`.
4. Non-Java Clients:
  • Interaction via Web Services: Language-Agnostic Access: By exposing EJBs as web services, clients written in other programming languages (like Python, JavaScript, or C#) can interact with them using standard HTTP protocols. This method eliminates the need for Java-specific code in the client.

Summary:
  • Within the Same Application Server: Developers do not need to write explicit Java code in the client to create or access Session EJBs. Dependency injection handles the instantiation and injection of EJBs seamlessly.
  • External Java Clients: Developers must write Java code to perform JNDI lookups to obtain references to Session EJBs.
  • Web Service Clients: By exposing EJBs as RESTful or SOAP-based services, clients can interact with them over HTTP without needing Java-specific code related to EJBs.
  • Non-Java Clients: These clients can utilize the web service endpoints to interact with the business logic encapsulated within EJBs, bypassing the need for Java code entirely.

Ultimately, the necessity for writing Java code in the client to create or access Session EJBs in Jakarta EE 10 hinges on the architecture of the application and the nature of the client interacting with the EJBs.

The Client's Remote References in legacy J2EE

Write the Java code in the client to create session EJBs. The client invokes the methods of the home interface to create its associated bean instance. There is a single home object for each session bean type and an EJBObject/ bean instance pair for each client.
The client's remote references
The client's remote references

On the creation of a new bean instance, the creation process will return a remote reference to the bean instance's EJBObject.
  • Home Interface Methods:
    ejb-exception
    1. interface HelloHome extends EJBHome - Home objects implement interfaces that always extend javax.ejb.EJBHome
    2. Hello create() - Creates the bean instance with a default state and returns a remote reference to the bean's EJBObject instance.
    3. Hello create(String arg1) - Creates a bean instance using the specified parameters to set the initial state rather than the default state.
    4. CreateException, RemoteException - The create methods must throw both these exceptions.
    5. All the EJB methods are in the "javax" package

EJB Home's create() methods in J2EE

EJB Home's create() methods
EJB Home's create() methods

  1. interface HelloHome extends EJBHome: Home objects implement interfaces that always extend javax.ejb.EJBHome.
  2. Hello create(): Creates the bean instance with a default state and returns a remote reference to the bean's EJBObject instance.
  3. Hello create(String arg1): Creates a bean instance using the specified parameters to set the initial state rather than the default state.
  4. CreateException, RemoteException: The create methods must throw both these exceptions.

Exceptions and EJB

Every networked object in EJB conforms to the RMI-IIOP standard and must throw a remote exception. Thus, every method in an EJB object and home object (such as our hello() method) must throw a remote exception. When such an exception is thrown, it indicates a special error condition such as a
  1. network failure,
  2. machine failure.
But how can your beans throw exceptions that indicate regular, run-of-the-mill problems, such as bad parameters passed to a business method? EJB comes with some built-in exceptions to handle this, and it also allows you to define your own exception types. More formally, EJB defines the following exception types:
  1. A system-level exception is a serious error that involves some critical failure, such as a database malfunction.
  2. An application-level exception is a more routine exception, such as an indication of bad parameters to a method or a warning of an insufficient bank account balance to make a withdrawal. For example, in our Hello, World! home interface, we throw a standard javax.ejb.CreateException from home interface’s create() method. This is an example of a required applicationlevel exception, indicating that some ordinary problem occurred during bean initialization.

Why must we separate the concepts of system-level and application-level exceptions? The chief reason is that system-level exceptions are handled quite differently from application-level exceptions.

Developing Middleware in Java EE 8

System-level Exceptions

For example, system-level exceptions are not necessarily thrown back to the client. Remember that EJB objects, the container-generated wrappers for beans, are middlemen between a bean’s client and the bean itself. EJB objects have the ability to intercept any exceptions that beans may throw. This allows EJB objects to pick and choose which exceptions the client should see. In some cases, if a bean fails, it may be possible to salvage the client's invocation and redirect it to another bean. This is known as transparent fail-over, a quality of service that some EJB container/server vendors provide. This is an easy service to provide for stateless beans because there is no lost state when a bean crashes. Some highend EJB products even provide transparent fail-over for stateful beans by routinely checkpointing the stateful bean's conversational state. In case of a critical, unrecoverable problem, your EJB container may support professional monitoring systems, alerting a system administrator if a catastrophic error occurs.
By way of comparison, application-level exceptions should always be thrown back to the client. Application-level exceptions indicate a routine problem, and the exception itself is valuable data that the client needs. For example, we could notify a client of insufficient funds in a bank account by throwing an applicationlevel exception. The client would always want to know about this because it is an application-level problem, not a system-level problem.
Besides correctly routing 1) system-level and 2) application-level exceptions, the EJB object is responsible for catching all unchecked exceptions that your bean may throw, i.e. NullPointer exception which are typically not caught by code. Exceptions that are unchecked in the bean could leave the bean in an abnormal state because the bean is not expecting to handle such an exception. In this scenario, the EJB container intercepts the exception and performs some action, such as throwing the exception back to the client as a remote exception. It also probably stops using that bean because the bean is in an undefined state.
The following two rules of thumb should help you with exceptions.
  1. Application-level exceptions are always thrown back to the client. This includes any exception the bean defines. It also includes the javax.ejb. CreateException for creating beans
  2. When system-level exceptions occur, the EJB container can do anything it wants to: page a system administrator with an alert, send an email to a third party, or throw the exception back to the client. Your bean can throw a system-level exception as either an RMI-IIOP remote exception or an unchecked RuntimeException. If the exception is thrown to the client, it is always thrown as a remote exception or a subclass of it.

Note that there must be, at least, a no-arg[1] create() method in the Home object.
The code in the client that creates the bean using the create(String) method will be as simple as:
Hello bean = home.create("Data");

During the evolution of the code, I will only show the important features. I will ignore exception handling, when not essential for understanding, as it adds clutter to the code samples. However, in all the complete examples, workshop solutions, etc., I will show full-strength code.
create() methods return remote references to the bean's EJBObject instance. If no exceptions are thrown, the bean instance will be created and is then ready to accept method calls.

Creating Session Bean - Quiz

Click the Quiz link below to test your understanding of session bean architecture and how to create session beans.
Creating Session Bean - Quiz
In the next lesson, you will be introduced to the code in the client to call the bean's methods.

[1]no-arg: A method that takes no arguments. For example create() in the home interface.

SEMrush Software