generic generics java-ee ejb-3.0 crud

generics - generic dao spring



Diseño Genérico CRUD Session Bean (2)

  1. El contenedor EJB realmente creará una implementación basada en proxy de la interfaz que envuelve a su bean y agrega cosas como transacciones y comprobaciones de seguridad. Este proxy se inyecta en el campo anotado, por lo que debe tener el tipo de interfaz. Creo que en EJB 3.1, puede omitir la interfaz y tener solo una clase de bean, y el contenedor creará una subclase para implementar su magia.
  2. javax.ejb.Remote es una anotación EJB 3.0, mientras que java.rmi.Remote es una interfaz sencilla desde antes de que existieran los EJB. No hay javax.rmi.Remote . Y tiene razón, si no usa la anotación Remote , entonces se considera que el EJB solo tiene una interfaz local.
  3. Del API doc de TransactionAttributeType.MANDATORY :

    Si un cliente invoca el método enterprise bean mientras el cliente está asociado con un contexto de transacción, el contenedor invoca el método enterprise bean en el contexto de transacción del cliente.

    Si no hay una transacción existente, se lanza una excepción.

    Probablemente desee utilizar TransactionAttributeType.REQUIRED , que inicia automáticamente una transacción si no está presente y también es la predeterminada si utiliza la anotación sin un parámetro.

Esta pregunta se hizo una vez aquí. EJB 3 Session Bean Design para CRUD simple , y solo quiero hacer más preguntas en profundidad sobre este diseño. Ya traté de hacer las preguntas en la publicación original, sin embargo, no vi ninguna respuesta, por lo que decido crear una nueva publicación. Así que la solución de Pascal para implementar el bean de sesión CRUD genérico es la siguiente

public interface GenericCrudService { public <T> T create(T t); public <T> T find(Class<T> type, Object id); public <T> void delete(T t); public <T> T update(T t); public List findWithNamedQuery(String queryName); public List findWithNamedQuery(String queryName, int resultLimit); public List findWithNamedQuery(String namedQueryName, Map<String, Object> parameters); public List findWithNamedQuery(String namedQueryName, Map<String, Object> parameters, int resultLimit); public <T> List<T> findWithNativeQuery(String sql, Class<T> type); }

Y

@Stateless @Remote(GenericCrudService.class) @TransactionAttribute(TransactionAttributeType.MANDATORY) public class GenericCrudServiceBean implements GenericCrudService { @PersistenceContext private EntityManager em; @Override public <T> T create(T t) { em.persist(t); return t; } @Override public <T> T find(Class<T> type, Object id) { return em.find(type, id); } @Override public <T> void delete(T t) { t = em.merge(t); em.remove(t); } @Override public <T> T update(T t) { return em.merge(t); } @Override public List findWithNamedQuery(String queryName) { return em.createNamedQuery(queryName).getResultList(); } @Override public List findWithNamedQuery(String queryName, int resultLimit) { return em.createNamedQuery(queryName).setMaxResults(resultLimit) .getResultList(); } @Override public List findWithNamedQuery(String namedQueryName, Map<String, Object> parameters) { return findWithNamedQuery(namedQueryName, parameters, 0); } @Override public List findWithNamedQuery(String namedQueryName, Map<String, Object> parameters, int resultLimit) { Query query = this.em.createNamedQuery(namedQueryName); if(resultLimit > 0) { query.setMaxResults(resultLimit); } for (Map.Entry<String, Object> entry : parameters.entrySet()) { query.setParameter(entry.getKey(), entry.getValue()); } return query.getResultList(); } @Override @SuppressWarnings("unchecked") public <T> List<T> findWithNativeQuery(String sql, Class<T> type) { return em.createNativeQuery(sql, type).getResultList(); } }

Preguntas:

1) Cuando intento hacer referencia a este bean EJB en mi bean administrado, tengo que hacer

@EJB private GenericCrudService myEJB;

en lugar de

@EJB private GenericCrudServiceBean myEJB;

Esto tiene poco sentido para mí ya que GenericCrudService es solo una interfaz, GenericCrudServiceBean es el Stateless Bean

Obtengo esta excepción cuando hago GenericCrudServiceBean ,

Caused by: javax.naming.NamingException: Lookup failed for ''java:comp/env/com.bridgeye.web.Profile/myEJB'' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NamingException: Exception resolving Ejb for ''Remote ejb-ref name=com.bridgeye.web.Profile/myEJB,Remote 3.x interface =com.bridgeye.ejb.GenericCRUDServiceBean,ejb-link=null,lookup=,mappedName=,jndi-name=com.bridgeye.ejb.GenericCRUDServiceBean,refType=Session'' . Actual (possibly internal) Remote JNDI name used for lookup is ''com.bridgeye.ejb.GenericCRUDServiceBean#com.bridgeye.ejb.GenericCRUDServiceBean'' [Root exception is javax.naming.NamingException: Lookup failed for ''com.bridgeye.ejb.GenericCRUDServiceBean#com.bridgeye.ejb.GenericCRUDServiceBean'' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: com.bridgeye.ejb.GenericCRUDServiceBean#com.bridgeye.ejb.GenericCRUDServiceBean not found]]] at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:518) at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455) at javax.naming.InitialContext.lookup(InitialContext.java:392) at javax.naming.InitialContext.lookup(InitialContext.java:392) at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:597)

2) ¿cuál es la diferencia entre javax.rmi.Remote y javax.ejb.Remote? Si eliminé la anotación Remoto, mi EJB se convierte en local o tengo que especificar con anotación Local

3) En mi bean gestionado, hago un simple myEJB.find(User.class, id) , pero si tengo @TransactionAttribute(TransactionAttributeType.MANDATORY) , entonces me encuentro con la excepción, funciona bien si saqué la declaración TransactionAttribute . ¿Alguna idea de por qué?


1.- Su bean sin estado está exponiendo la interfaz GenericCrudService (la vista es lo que registra el servidor de la aplicación), por esa razón usted usa

@EJB private GenericCrudService myEJB;

Si tiene varias implementaciones de esta interfaz, puede agregar el nombre ejb a la anotación para desambiguación:

@EJB(name="GenericCrudServiceBean") private GenericCrudService myEJB;

En EJB 3.1, Session Bean sin interfaz está exponiendo algo llamado Vista sin interfaz. Estos beans de sesión solo se pueden usar localmente.