Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Mastering Enterprise JavaBeans™ and the Java 2 Platform, Enterprise Edition - Roman E

..pdf
Скачиваний:
41
Добавлен:
24.05.2014
Размер:
6.28 Mб
Скачать

148 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!