Aplicación J2EE (Web, Ejb, Datasource)

lesancor
31 de Mayo del 2006
Hola:

Estoy haciendo un programa en J2ee (soy un novato) y me tiraron a los leones de una...

Ahora estoy tratando de hacer una conexión a la Base de Datos mediante un DataSource (creo q ya lo tengo configurado en el servidor WAS de IBM, lo probé en el administrador de consola del servidor y me funciona).

La conexión tiene que ser desde la capa EJB, utilizando JNDI para obtener el data source... tengo el siguiente código, pero no tengo que ponerlo en el EJB mismo, sino que, se recomienda tenerlo centralizado, implementando el patrón Service Locator.

------------------------------------------------------------------------------------------------------------------------------------
Connection connection = null;
Properties prop = new Properties();
prop.put(Context.INITIAL_CONTEXT_FACTORY, \\\"com.ibm.websphere.naming.WsnInitialContextFactory\\\");

InitialContext contexto = new InitialContext(prop);

try {
// suponiendo que en ejb-jar.xml esta declarado el resource-ref con
// el nombre dataSOURCE
DataSource origenGo = (DataSource) contexto.lookup(\\\"java:comp/env/dataSOURCE\\\");
connection = origenGo.getConnection();
} finally {
contexto.close();
}
--------------------------------------------------------------------------------------------------------------------------------------


Al ser la conexión en la capa EJB... ¿que Beans se usa? y ¿como se hace la relación con el datasource?

Una vez hecha la conexión en la capa EJB, ¿como hago referencia a esa conección desde la capa de presentación (una JSP por ejemplo) ?

Y lo otro que se me queda en el tintero, ¿en que parte se deja el código del \\\"service locator\\\"?, lo tengo y lo entiendo.... pero el problema es que no se si va en el EJB o en el modulo Web.

Si hay alguien de buena voluntad que me pueda ayudar, se lo agradecería un montón.

neossoftware
31 de Mayo del 2006
Que tal:

Pues en efecto te tiraron a la jaula de los Leones jajajaja, pero bueno con estas ondas te aseguro que vas a aprender bastante.

En primer lugar debes de implementar Service Locator de la siguiente manera (una posible solucion)

public class ServiceLocator {
private static ServiceLocator me;
InitialContext context = null;

private ServiceLocator()
throws ServiceLocatorException {
try {
context = new InitialContext();
} catch(NamingException ne) {
throw new ServiceLocatorException(...);
}
}

// Returns the instance of ServiceLocator class
public static ServiceLocator getInstance()
throws ServiceLocatorException {
if (me == null) {
me = new ServiceLocator();
}
return me;
}

//returns Object from JnDI
public Object getObject(String jndi) throws NamingException{


Object objref = context.lookup(name);
return objref;

}

// Returns the EJBHome object for requested service
// name. Throws ServiceLocatorException If Any Error
// occurs in lookup
public EJBHome getHome(String name, Class clazz)
throws ServiceLocatorException {
try {
Object objref = context.lookup(name);
EJBHome home = (EJBHome)
PortableRemoteObject.narrow(objref, clazz);
return home;
} catch(NamingException ex) {
throw new ServiceLocatorException(...);
}
}

}


hay que recordar que este patron es utilizado para localizar servicios, para quitarle abstraccion al uso de JNDI, por lo que lo recomendable es que no pases nombres JNDI, si no que los tengas definidos en una clase de servicios


public class ServiceLocator {
// singleton's private instance
private static ServiceLocator me;

static {
me = new ServiceLocator();
}

private ServiceLocator() {}

// returns the Service Locator instance
static public ServiceLocator getInstance() {
return me;
}


// Services Constants Inner Class - service objects
public class Services {
final public static int PROJECT = 0;
final public static int RESOURCE = 1;
}

// Project EJB related constants
final static Class PROJECT_CLASS = ProjectHome.class;
final static String PROJECT_NAME = "Project";

// Resource EJB related constants

final static Class RESOURCE_CLASS = ResourceHome.class;
final static String RESOURCE_NAME = "Resource";

// Returns the Class for the required service
static private Class getServiceClass(int service){
switch( service ) {
case Services.PROJECT:
return PROJECT_CLASS;
case Services.RESOURCE:
return RESOURCE_CLASS;
}
return null;
}

// returns the JNDI name for the required service
static private String getServiceName(int service){
switch( service ) {
case Services.PROJECT:
return PROJECT_NAME;
case Services.RESOURCE:
return RESOURCE_NAME;
}
return null;
}

/* gets the EJBHome for the given service using the
** JNDI name and the Class for the EJBHome
*/
public EJBHome getHome( int s )
throws ServiceLocatorException {
EJBHome home = null;
try {
Context initial = new InitialContext();

// Look up using the service name from
// defined constant
Object objref =
initial.lookup(getServiceName(s));

// Narrow using the EJBHome Class from
// defined constant
Object obj = PortableRemoteObject.narrow(
objref, getServiceClass(s));
home = (EJBHome)obj;
}
catch( NamingException ex ) {
throw new ServiceLocatorException(...);
}
catch( Exception ex ) {
throw new ServiceLocatorException(...);
}
return home;
}
}


El código de cliente para utilizar el Service Locator mediante está estrategía, se podría parecer a esto:

public class ServiceLocatorTester {
public static void main( String[] args ) {
ServiceLocator serviceLocator =
ServiceLocator.getInstance();
try {
ProjectHome projectHome = (ProjectHome)
serviceLocator.getHome(
ServiceLocator.Services.PROJECT );
}
catch( ServiceException ex ) {
// client handles exception
System.out.println( ex.getMessage( ));
}
}
}

Ahora todas las conexiones a la base de datos, las debes de colocar en la capa de Negocios, nunca debes de utilizar estos objetos en la capa de presentacion ojo........

Despues de hacer esto te recomiendo que uses Business Delegate para quitar complejidad el uso de tus servicios, dentro de Business Delegate, vas a usar Service Locator para lozalizar tus servicios.

Ahora debemos tener en mente que la utilizacion de EJB 2.1 ya esta siendo sustituida por EJB 3.0 te pongo un ejemplo. de Bean de Session. con el cual creo servicios usando POJO's

//la interface remota
package com.sun.tutorial.javaee.ejb;

import java.math.BigDecimal;
import javax.ejb.Remote;

@Remote()
public interface Converter {
public BigDecimal dollarToYen(BigDecimal dollars);
public BigDecimal yenToEuro(BigDecimal yen);
}

//el bean de session
package com.sun.tutorial.javaee.ejb;

import java.math.BigDecimal;
import javax.ejb.*;

@Stateless()
public class ConverterBean implements Converter {
private BigDecimal yenRate = new BigDecimal("115.3100");
private BigDecimal euroRate = new BigDecimal("0.0071");

public BigDecimal dollarToYen(BigDecimal dollars) {
BigDecimal result = dollars.multiply(yenRate);
return result.setScale(2, BigDecimal.ROUND_UP);
}

public BigDecimal yenToEuro(BigDecimal yen) {
BigDecimal result = yen.multiply(euroRate);
return result.setScale(2, BigDecimal.ROUND_UP);
}
}

y la forma de usarlo

import java.math.BigDecimal;
import javax.ejb.EJB;

public class ConverterClient {

//con esto no es necesario una llamada usando
//JNDI
@EJB
private static Converter converter;

public ConverterClient(String[] args) {
}

public static void main(String[] args) {
ConverterClient client = new ConverterClient(args);
client.doConversion();
}

public void doConversion() {
try {
BigDecimal param = new BigDecimal("100.00");
BigDecimal yenAmount = converter.dollarToYen(param);

System.out.println("$" + param + " is " + yenAmount
+ " Yen.");
BigDecimal euroAmount = converter.yenToEuro(yenAmount);
System.out.println(yenAmount + " Yen is " + euroAmount
+ " Euro.");

System.exit(0);
} catch (Exception ex) {
System.err.println("Caught an unexpected exception!");
ex.printStackTrace();
}
}
}

Espero que te sirva la información, cualquier duda por aca andamos....

Saludos comunidad Open Source.

lesancor
31 de Mayo del 2006
Hola:

Agradezco mucho tu respuesta... voy a trabajar con lo que me has enviado mas lo que he encontrado por mi cuenta.

De una cosa estoy seguro... cuando tenga listo esto, lo publicaré con lujo y detalle para que lo ocupe alguien que lo pueda necesitar.

Agradecido y recordando que cualquier información extra es valiosa, se despide.

Leonardo Sandoval

Viva la comunidad Open Source

leo_gran
31 de Mayo del 2006
HOLA:

He avanzado bastante (a mi parecer)... voy a publicar lo que llevo a la fecha cuando tenga tiempo, pero si alguien necesita información me puede mandar un correo y ahí veré como me las arreglo para ayudar.

Nos vimos