EJBs can be accessed from a number of different application clients. Here we will see how an EJB can be accessed from an Applet. Applets are still used extensively to provide a richer browser interface than that provided using standard HTML. This includes the use of graphics and animations. Knowing how to access an EJB from an applet gives the applet developer even more opportunities.
Accessing an EJB from an applet uses three steps:
The remote interface determines which methods are available to the Applet.
Create two different applications. The first application will be called CapitalApplication,
packaged as EJB-JAR, and contains an EJB called CapitalBean
. It possesses a method which, when passed the name of a country, returns its capital. The second is a stand-alone JApplet
application which uses the CapitalBean
.
For this recipe, we will create three classes:
EJBs used outside of a Java EE application normally need to implement a remote interface. This interface specifies the methods available to a client. The CapitalBean
EJB implements CapitalBeanRemote
interface. This interface has a single method called getCapital
.
package packt; import javax.ejb.Remote; @Remote public interface CapitalBeanRemote { public String getCapital(String state); }
The CapitalBean
implements the getCapital
method using a HashMap
initialized with countries and their capitals.
@Stateless public class CapitalBean implements CapitalBeanRemote { private HashMap<String, String> capitals = new HashMap<String, String>(); public CapitalBean() { capitals.put("United Kingdom", "London"); capitals.put("Japan", "Tokyo"); capitals.put("India", "New Delhi"); } @Override public String getCapital(String country) { return capitals.get(country); } }
Create a separate application called CapitalApplet.
Add a JApplet
called EJBApplet
. The applet includes a JButton
that when pressed will populate a JTextField
with the capital of Japan.
The applet as shown below includes the following methods:
public class EJBApplet extends JApplet { private JButton invokeButton = new JButton("Invoke EJB"); private JTextField messageTextField = new JTextField("Waiting for results"); public void init() { EJBaccessing, from applettry { java.awt.EventQueue.invokeAndWait(new Runnable() { public void run() { initComponents(); } }); } catch (Exception ex) { ex.printStackTrace(); } } private void initComponents() { Container container = this.getContentPane(); container.setLayout(new FlowLayout()); container.add(invokeButton); container.add(messageTextField); invokeButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event. ActionEvent evt) { invokeEJB(); } }); } public void invokeEJB() { try { InitialContext context =new InitialContext(); CapitalBeanRemote bean = (CapitalBeanRemote) context.lookup( "java:global/CapitalApplication/CapitalBean"); messageTextField.setText(bean.getCapital("Japan")); context.close(); } catch (Exception e) { e.printStackTrace(); } } }
When setting up the project add libraries for the CapitalApplication
(CapitalApplication.jar) and for the server (appserv-rt.jar). These files can be added using the properties tab of the CapitalApplet
.
Most IDEs provide a way of executing an applet without actually creating an HTML page for the applet. Use the IDE to execute the EJBApplet
. The applet will appear as shown in the following screenshot.
The CapitalBean
EJB used a HashMap
to maintain a list of countries and their capitals. This HashMap
was initialized in the constructor. The getCapital
method was passed the name of the country and returned the corresponding capital name.
In a HashMap
, the first string represents a key (which for us is the name of a country), and a value (which is the country's capital). The put
method adds the pair to the HashMap
. The get
method returns a value based on a key.
The applet InitialContext
object bears further explanation. When the applet is created there are at least two JAR files placed on the application's classpath: the CapitalBean
EJB JAR and an appserv-rt.jar
file.
The EJB JAR contains the class declarations needed for the references to the EJB to be used correctly within the applet. Without this file, the compiler will be unable to know whether we are using the CapitalBean
correctly.
The appserv-rt.jar
file contains a manifest.mf
file. This file contains the information needed to configure the client side of JNDI enabling it to successfully locate a resource and return a reference to it. In our case, the client side was our applet. Unless this JNDI information is configured properly, the InitialContext
object may not be constructed correctly. This often results in an annoying naming exception message.
The declarations for the JApplet
consisted of a JButton
and a JTextField
. The init
method used a standard Swing technique of creating a thread which works gracefully with the AWTEvent
thread to call the initComponents
method. The initComponents
method created a simple user interface. The invokeButton
used an anonymous inner class to call the invokeEJB
method when the button is selected.
The invokeEJB
method is the interesting part of the applet. An InitialContext
object was created and used with a global JNDI name to locate and return a reference to the CapitalBean
EJB.
It is sometimes useful to examine the applet JNDI context in more detail. The InitialContext
object's getEnvironment
method returns a Hashtable
we can use to list the environmental properties.
The Hashtable
consists of key/value pairs which we can iterate through using an Enumeration
object. The keys
method of the Hashtable
returns the Enumeration
.
Hashtable table = context.getEnvironment(); Enumeration<String> enumeration = table.keys(); while (enumeration.hasMoreElements()) { String key = enumeration.nextElement(); System.out.println(key + " - " + table.get(key)); }
One possible list may include the following properties and values:
java.naming.factory.initial - com.sun.enterprise.naming.impl.SerialInitContextFactory java.naming.factory.url.pkgs - com.sun.enterprise.naming java.naming.factory.state - com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl
3.145.97.170