|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 6 of 6
The EJB 1.1 specification also supports the use of the JNDI ENC to access factories for other resources like the Java Messaging
Service (JMS), Java Mail, and URL with appropriate JNDI names (for example, java:comp/env/jms for the JMS). You can enhance PortableContext to support the use of these resources as well -- an exercise I will leave up to you.
PortableContext, as illustrated below.
import javax.ejb.EJBContext;
import java.util.Properties;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.naming.InitialContext;
import javax.naming.Context;
public class PortableContext1_0 extends PortableContext {
public Object lookup(String name, Class type)
throws PortableContextException {
try {
Properties props = ejbContext.getEnvironment();
String value = props.getProperty(name);
if (value == null)
return null;
if (name.startsWith("java:comp/env/jdbc"))
return DriverManager.getConnection(value); else if (name.startsWith("java:comp/env/ejb")) {
InitialContext jndiContext = getInitialContext();
return jndiContext.lookup(value);
}
else {
if (type == String.class)
return value;
else
return primitiveWrapper(value, type);
}
} catch(Exception e) {
throw new PortableContextException(e);
}
}
private InitialContext getInitialContext() throws Exception {
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.T3InitialContextFactory");
p.put(Context.PROVIDER_URL, "t3://localhost:7001");
return new InitialContext(p);
}
private Object primitiveWrapper(String value, Class type)
throws PortableContextException {
if (type == Double.class)
return new Double(value);
if (type == Integer.class)
return new Integer(value);
if (type == Boolean.class)
return new Boolean(value);
if (type == Long.class)
return new Long(value);
if (type == Byte.class)
return new Byte(value);
if (type == Short.class)
return new Short(value);
if (type == Float.class)
return new Float(value);
else
throw new PortableContextException();
}
}
|
import javax.ejb.EJBContext;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.SQLException;
import javax.rmi.PortableRemoteObject;
public class PortableContext1_1 extends PortableContext {
InitialContext jndiContext;
public Object lookup(String name, Class type){
throws PortableContextException
try {
jndiContext = new InitialContext();
Object value = jndiContext.lookup(name);
if (name.startsWith("java:comp/env/jdbc")){
DataSource ds = (DataSource)value;
return ds.getConnection();
} else if (name.startsWith("java:comp/env/ejb")) {
return PortableRemoteObject.narrow(value, type);
} else
return value;
} catch(NamingException ne) {
throw new PortableContextException(ne);
} catch(SQLException se) {
throw new PortableContextException(se);
}
}
}
|
With the EJB 1.0 implementation (PortableContext1_0), the bean home is obtained using conventional JNDI access with security authentication and loading of the JNDI service provider.
This example uses BEA WebLogic 3.x conventions. If you use a different EJB server, substitute the appropriate properties for
that platform.
In EJB 1.1, you can obtain the bean home from the JNDI environment context without having to authenticate or load the service
provider. EJB 1.1 requires that the javax.rmi.PortableRemoteObject.narrow() method be used to explicitly cast the home's remote reference to its appropriate type. The use of PortableRemoteObject is required to support Java RMI-IIOP (Remote Method Invocation over Internet Inter-ORB Protocol), which is based on CORBA
reference types that do not support native casting. You can take advantage of the Class type variable used in the lookup() method to specify the target interface in the PortableRemoteObject.narrow() method.
List 10 shows how the remote reference to a bean's EJB home is obtained in a forward-portable bean.
import javax.ejb.SessionContext;
public class TellerBean implements javax.ejb.SessionBean {
SessionContext ejbContext;
PortableContext portableContext = null;
public void setSessionContext(SessionContext ctx) {
ejbContext = ctx;
setPortableContext();
}
public void transfer(int accountSource, int accountTarget, amount)
throws TransferException {
try {
AccountHome accountHome = (AccountHome)
portableContext.lookup("java:comp/env/ejb/AccountHome", AccountHome.class);
Account as = accountHome.findByPrimaryKey(new AccountPK(accountSource));
Account at = accountHome.findByPrimaryKey(new AccountPK(accountTarget));
as.withdraw(amount);
at.deposit(amount);
...
}
}
|
PortableContext and its implementations are available at my Web site (see EJBNow in Resources).The next and final installment in this series will continue to enhance the PortableContext to encapsulate differences in security. The next installment will also explore the application of the PortableContext to make beans portable between brands of EJB servers. In addition, it will cover issues specific to entity bean forward compatibility
and deployment descriptors (*.ser to xml).
Read more about Enterprise Java in JavaWorld's Enterprise Java section.