Mastering Enterprise JavaBeans™ and the Java 2 Platform, Enterprise Edition - Roman E
..pdf148 M A S T E R I N G E N T E R P R I S E J A V A B E A N S
package com.wiley.compBooks.session.Fazuul;
import javax.ejb.*;
import java.rmi.RemoteException; import java.rmi.Remote;
/**
*These are the business logic methods exposed publicly
*byComponentBean.
*/
public interface Component extends EJBObject {
/**
*Attaches this component to another component. If
*attach is successful, the Bean will call remove()
*on the two EJB objects and generate a new,
*combined Component.
*
*@return newly formed Component if successful
*@exception ComponentException thrown if two
*Components can't fit together
*/
public Component attachTo(Component other) throws RemoteException, ComponentException;
/**
* Returns the short name of this component */
public String getName() throws RemoteException;
/**
* Returns the long description of this component */
public String getDescription() throws RemoteException;
}
Source 6.1 Component.java.
The Component Bean Implementation
The implementation of our component bean is in ComponentBean.java. Our ComponentBean is a stateful session bean. The conversational state consists of the name and description of the component. This state will be automatically saved if our component bean is passivated by the EJB container. The code is shown in Source 6.2.
Go back to the first page for a quick link to buy this book online!
Adding Functionality to Your Beans 149
package com.wiley.compBooks.session.Fazuul;
import javax.ejb.*; import java.util.*; import java.rmi.*;
/**
* Stateful Session Bean.
*/
public class ComponentBean implements SessionBean {
//Constants used for reading properties object public static final String ENV_MATCHES = "MATCHES";
public static final String ENV_DESCRIPTION = "DESCRIPTION_";
//Conversational state
public String name; public String description;
private SessionContext ctx;
public void ejbCreate(String name) { this.name = name;
/*
*Get the description of our Bean by querying
*the SessionContext and retrieving the
*application-specific properties.
*/
Properties props = ctx.getEnvironment();
description = (String) props.get(ENV_DESCRIPTION + name);
}
public void ejbRemove() {
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void setSessionContext(SessionContext ctx) { this.ctx = ctx;
}
Source 6.2 ComponentBean.java (continues).
Go back to the first page for a quick link to buy this book online!
150 M A S T E R I N G E N T E R P R I S E J A V A B E A N S
/**
*Attaches this component to another component. If
*attach is successful, the Bean will call remove()
*on the two EJB objects and generate a new,
*combined Component.
*
*@return newly formed Component if successful
*@exception ComponentException thrown if two
*Components can't fit together
*/
public Component attachTo(Component other) throws RemoteException, ComponentException {
/*
*Retrieve the application-specific environment
*properties from the current context.
*/
Properties props = ctx.getEnvironment();
/*
* Get the list of matching components from the properties */
String matchString = (String) props.get(ENV_MATCHES); Enumeration matches = new StringTokenizer(matchString, ",");
/*
*Loop through each match listing. Match listings
*are of the form x+y=z, such as Snarf+Vrommell=Subbert.
*Check to see if any of the matches involve our
*components.
*/
while (matches.hasMoreElements()) {
String equationString = (String) matches.nextElement();
Enumeration equation = new StringTokenizer(equationString, "+="); String nameA = (String) equation.nextElement();
String nameB = (String) equation.nextElement();
String result = (String) equation.nextElement();
/*
* If there's a match, make the new, combined component */
if (( nameA.equals(this.getName())
&&nameB.equals(other.getName()) ) || ( nameB.equals(this.getName())
&&nameA.equals(other.getName()) ) ) {
Source 6.2 ComponentBean.java (continues).
Go back to the first page for a quick link to buy this book online!
Adding Functionality to Your Beans 151
/*
* Get my Home Object from Session Context. */
ComponentHome home = (ComponentHome) ctx.getEJBHome();
/*
* Create a new Component, and return it */
try {
return home.create(result);
}
catch (Exception e) {
throw new ComponentException(e.toString());
}
}
}
/*
* Two components don't fit together, so throw an exception */
throw new ComponentException("Those components do not fit together!");
}
/**
* Returns the short name of this component */
public String getName() throws RemoteException { return name;
}
/**
* Returns the long description of this component */
public String getDescription() throws RemoteException { return description;
}
}
Source 6.2 ComponentBean.java (continued).
Notice our ejbCreate() method. It illustrates a session bean retrieving its environment properties from the session context. Our bean can access its environment during ejbCreate() because setSessionContext() is always called prior to ejbCreate(). In fact, you can access the session context any time between ejbCreate() and ejbRemove(), including within ejbCreate() and ejbRemove().
Now take a look at the following segment in the attachTo() method, which illustrates how to create an enterprise bean from another bean:
Go back to the first page for a quick link to buy this book online!
152 M A S T E R I N G E N T E R P R I S E J A V A B E A N S
ComponentHome home = (ComponentHome) ctx.getEJBHome();
...
return home.create(result);
When we call attachTo() on a component, the component combines itself with another component, making a new, combined component. In order to create a component, the bean needs to retrieve its own home object from the session context. The bean then can call create() on the home object, which generates a fresh component EJB object, and can return that to the client.
The Component Home Interface
Next, we have the home interface for our components, shown in Source 6.3.
The home interface has a create() method that initializes our component to a certain name, such as “Snarf.” This create() method gets called in two places:
■■When the Machine bean wants to make a component, it calls create() to generate a basic component.
■■When the Component bean merges two components, it calls create() to generate a new, merged component.
The Component Custom Exception Class
The final Java file for our component bean is the custom exception class that it throws, shown in Source 6.4.
package com.wiley.compBooks.session.Fazuul;
import javax.ejb.*;
import java.rmi.RemoteException;
/**
* This is the home interface for ComponentBean. */
public interface ComponentHome extends EJBHome {
/*
*This method creates the EJB object for a Component whose Name is name.
*@return The newly created EJB object.
*/
Component create(String name) throws RemoteException, CreateException;
}
Source 6.3 ComponentHome.java.
Go back to the first page for a quick link to buy this book online!
Adding Functionality to Your Beans 153
package com.wiley.compBooks.session.Fazuul;
/**
* Exceptions thrown by Components */
public class ComponentException extends Exception {
public ComponentException() { super();
}
public ComponentException(Exception e) { super(e.toString());
}
public ComponentException(String s) { super(s);
}
}
Source 6.4 ComponentException.java.
ComponentException simply delegates all method calls to its parent, java.lang
.Exception. It’s nice to have a custom Exception class as a way of distinguishing the nature of certain exceptions. For example, because we have a ComponentException, we can use it as a way of generating application-level exceptions, rather than using the stock java.rmi.RemoteException that all EJB objects throw—remote exceptions are intended for system-level problems, such as machines going down, application servers crashing, or networks failing.
The Component Deployment Descriptor
We now have our component’s deployment descriptor. It’s shown in Table 6.2.
The two important deployment descriptor settings to notice are the last two, which are related to security. We specify that the component’s ejbCreate() method may only be called by a client who is assuming the security role of creators. We define the creators role in the weblogic.properties file as follows:
weblogic.password.creator=foobarbaz
weblogic.security.group.creators=creator
This creates an identity creator with password foobarbaz, and creates a security role called creators which contains a single user, creator.
Go back to the first page for a quick link to buy this book online!
154 |
|
M A S T E R I N G |
E N T E R P R I S E J A V A B E A N S |
Table 6.2 Deployment Descriptor Settings for ComponentBean |
|||
|
|
||
DEPLOYMENT |
|
||
DESCRIPTOR SETTING |
VALUE |
||
Bean home name |
ComponentHome |
||
Enterprise bean class name |
com.wiley.compBooks.roman.session.fazuul |
||
|
|
|
.ComponentBean |
Home interface class name |
com.wiley.compBooks.roman.session.fazuul |
||
|
|
|
.ComponentHome |
Remote interface class name |
com.wiley.compBooks.roman.session.fazuul.Component |
||
Environment properties |
See Table 6.3 |
||
Re-entrant |
False |
||
Stateful or stateless |
STATEFUL_SESSION |
||
Session timeout |
10 seconds |
||
Declarative security on |
ejbCreate requires client to be in security role creators |
||
methods |
|
||
runAsMode |
SPECIFIED_IDENTITY |
||
runAsIdentity |
creator |
The runAsMode is set to SPECIFIED_IDENTITY, with a runAsIdentity equal to creator. This means all methods in our component bean run as the creator user. We need this access level because components can create other components, and thus need the creator level of authorization to create other components.
We also have a number of environment properties that we use for our component. They are shown in Table 6.3.
A component bean queries the DESCRIPTION properties to get its long description. The MATCHES property lists a set of equations, indicating which two components can be combined to form a new, combined component.
The Machine Remote Interface
Now let’s move on to our second bean—a Machine bean, used to generate components. We’ll start with our remote interface, shown in Machine.java in Source 6.5.
Our remote interface is very simple—it has one method, makeComponent(), that creates a random component.
Go back to the first page for a quick link to buy this book online!
|
Adding Functionality to Your Beans |
155 |
Table 6.3 Environment Properties for ComponentBean |
|
|
ENVIRONMENT |
|
|
PROPERTY SETTING |
VALUE |
|
DESCRIPTION_Snarf |
“This is a snarf. It came all the way from snarfland. It looks |
|
|
like a large peanut with a hole in the side of it. The hole |
|
|
looks big enough to fit a Vrommell inside.” |
|
DESCRIPTION_Vrommell |
“This Vrommell is a funny banana-shaped thing. It looks like |
|
|
it will fit snugly into a Snarf.” |
|
DESCRIPTION_Rector |
“Oh no, it’s Rector! Rectors are dangerous, disease-spreading |
|
|
devices. You don’t want to hold on to this one for very long. |
|
|
Perhaps if you fed the Rector a peanut or disc, it would be |
|
|
pacified.” |
|
|
. . . there are more descriptions as well . . . |
|
MATCHES |
Snarf+Vrommell=Subbert Snarf+Rector=Lucia |
|
|
. . . there are more matches as well . . . |
|
package com.wiley.compBooks.session.Fazuul;
import javax.ejb.*;
import java.rmi.RemoteException; import java.rmi.Remote;
/**
* These are the business logic methods exposed publicly by MachineBean. */
public interface Machine extends EJBObject {
/**
* Makes a new, random Component */
public Component makeComponent() throws RemoteException;
}
Source 6.5 Machine.java.
The Machine Bean Implementation
Next, we have our machine’s enterprise bean class implementation in MachineBean
.java, shown in Source 6.6. This is a stateless session bean, and thus it has blank ejbPassivate() and ejbActivate() methods. We also have a no-argument initializer, ejbCreate()—this is required for all stateless session beans.
Go back to the first page for a quick link to buy this book online!
156 M A S T E R I N G E N T E R P R I S E J A V A B E A N S
package com.wiley.compBooks.session.Fazuul;
import javax.ejb.*; import java.util.*; import javax.naming.*;
/**
* Stateless Session Bean. Simple factory for generating random Components. */
public class MachineBean implements SessionBean {
// Constants used for properties file reading
public static final String COMPONENT_LIST = "COMPONENT_LIST";
private SessionContext ctx;
//
// EJB-required methods
//
public void ejbCreate() {
}
public void ejbRemove() {
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void setSessionContext(SessionContext ctx) { this.ctx = ctx;
}
//
// Business methods
//
/**
* Makes a new, random component */
public Component makeComponent() throws MachineException { /*
*Get properties from Session Context, and retrieve
*app-specific property that lists the available
*components for creation.
*/
Source 6.6 MachineBean.java (continues).
Go back to the first page for a quick link to buy this book online!
Adding Functionality to Your Beans 157
Properties props = ctx.getEnvironment();
String componentString = (String) props.get(COMPONENT_LIST); StringTokenizer components = new StringTokenizer(componentString, ",");
/*
* Find a random component name */
int componentNumber = (new Random().nextInt() % components.countTokens()); if (componentNumber < 0) {
componentNumber *= -1;
}
String componentName = null;
for (int i=0; i <= componentNumber; i++) { componentName = (String) components.nextToken();
}
try { /*
*Get a reference to the ComponentHome Object
*via JNDI. We need the Component's Home Object
*to create Components.
*
*We rely on app-specific properties to define
*the Initial Context params which JNDI needs.
*/
Context ctx = new InitialContext(props);
ComponentHome home = (ComponentHome) ctx.lookup("ComponentHome");
/*
*Use the factory to create the new,
*merged component, and return it. */
return home.create(componentName);
}
catch (Exception e) {
throw new MachineException(e);
}
}
}
Source 6.6 MachineBean.java (continued).
Notice the makeComponent() method. Here we are using JNDI from within a bean. Specifically, we are looking up the bean’s home object using JNDI in order to create a new, random component EJB object.
Our approach first queries the session context to get the environment properties. These environment properties specify the necessary startup parameters
Go back to the first page for a quick link to buy this book online!