jueves, 13 de junio de 2013

Un proyecto en NetBeans de principio a fin (VI). Clases de entidad y beans de sesión

En esta parte del tutorial se presentan las tecnologías Enterprise JavaBeans y Java Persistence. Vamos a conocer a dos asistentes que nos facilitarán bastante la vida a la hora de desarrollar para Java EE:
  • El Asistente para Clases de Entidad de Base de Datos, crea una clase de entidad de la API de persistencia de Java completa para cada tabla seleccionada de la base de datos; con anotaciones de consultas con nombre, campos representando columnas y relaciones representado claves externas.
  • El Asistente de Beans de Sesión para Clases de Entidad crea una fachada EJB de sesión para cada clase de entidad, con métodos básicos de acceso. 


Si recordamos en diagrama MVC de la primera entrega, podemos ver como los Session Beans (EJB) y las Entity Classes (JPA) forman parte de Modelo. 

En esta ocasión, las clases de entidad que crearemos, forman una representación, basada en Java, de la base de datos affablebean. Mientras cada clase de entidad representa a una tabla de la base de datos, las instancias de estas clases corresponderán a registros que pueden ser salvados (persistentes) en la base de datos. La lógica de negocio de la aplicación está encapsulada en beans de sesión, que pueden ser usados bien como clases fachada que usan CRUD (Create-Read-Update_Delete) para acceder a las entidades, o bien pueden contener código que implemente acciones específicas de nuestra aplicación.

¿QUÉ SON LAS TECNOLOGÍAS EJB Y JPA?

Hasta el momento el proyecto que estamos desarrollando en este tutorial podría ser ejecutado en un servidor web con un contenedor de servlets, como Apache Tomcat (o Glassfish como es en caso). Después de todo sólo estamos utilizando JSTL y tecnologías de servlet, y conectándonos a la base de datos usando directamente JDBC. Realmente sería posible continuar el desarrollo usando únicamente estas tecnologías, mientras codificamos a mano otros aspectos de la aplicación, como hilos de forma segura, transacciones y seguridad. Sin embargo, usando Enterprise Beans y clases de entidades persistentes (JPA) podremos centrarnos en la lógica de negocio, confiando en soluciones que ya han sido sobradamente probadas y testadas. En los siguiente apartados haremos una breve introducción de las dos tecnologías y del lugar que ocupan en el desarrollo EE.

Enterprise JavaBeans

La descripción oficial de esta tecnología es que es una arquitectura del lado del servidor que permite un desarrollo simple y rápido de aplicaciones distribuidas, transaccionales, seguras y portables. Así, es posible aplicar EJBs a nuestros proyectos, de modo que los servicios proporcionados por la tecnología son transparentes para nosotros como desarrolladores. Esto elimina la tediosa -y frecuentemente propensa a errores- tarea de teclear un montón de código que sería necesario de otro modo, y que es común a la mayoría de las aplicaciones del lado del servidor. Básicamente se trata de no reinventar la rueda una y otra vez.

Podemos pensar en EJB como en componentes -o clases Java- que pueden ser incorporadas en nuestro proyecto, o bien podemos concebirlo como un framework que proporciona numerosos servicios relacionados con los objetivos de nuestro desarrollo. Algunos de los servicios de los que sacaremos partido en este tutorial son:
  • Pooling: Para cada componente EJB, la plataforma crea un pool de instancias del componente que son compartidas por los clientes. En cualquier momento, cada instancia del pool sólo puede ser usada por un cliente, y tan pronto como ésta deja de prestar servicio al cliente vuelve al pool (en lugar de ser frívolamente despreciada por el recolector de basura...).
  • Hilos seguros: EJB crea hilos de ejecución seguros y eficientes para todos los componentes de forma completamente transparente, lo que significa que podemos escribir nuestros componentes de servidor como si estuviéramos desarrollando una aplicación con un único hilo de ejecución, sin las preocupaciones de la programación multi-hilo.
  • Transacciones: EJB soporta la gestión declarativa de transacciones. Esto ayuda a añadir comportamiento transaccional a los componentes simplemente usando configuración en lugar de código. Se puede designar a cualquier método de componente para ser transaccional. Si el método se completa normalmente, EJB confirma la transacción y hace que el intercambio de datos sea permanente. De lo contrario se deshace la transacción.
  • Seguridad: EJB se integra con la API del Servicio de Autenticación y Autorización de Java (JAAS), por lo que es posible externalizar completamente la seguridad y asegurar una aplicación usando configuración en lugar de enfrentarse a los problemas de implementar el código que esto supone.

Persistencia Java

En el contexto de Java Enterprise, la persistencia hace referencia al acto de almacenar datos -contenidos en objetos Java- en una base de datos relacional, de forma automática. JPA usa una tecnología de mapeo de objetos relacionales, que permite a las aplicaciones gestionar datos entre objetos Java y una base de datos relacional, de forma transparente para el desarrollador. Esto quiere decir, que aplicando JPA a nuestros proyectos, podemos crear y configurar conjuntos de clases Java que reflejan el modelo de datos. Así, nuestra aplicación puede acceder a esas entidades como si accediese directamente a la base de datos.

Usar JPA en nuestros proyectos proporciona varios beneficios:
  • JPA tiene su propio -y poderoso- lenguaje de consulta, similar a SQL, para consultas estáticas y dinámicas.
  • Se puede evitar la tarea de escribir a bajo nivel, código JDBC/SQL, más complejo y propenso a errores.
  • JPA proporciona, de forma transparente, servicios para captura de datos y optimización de rendimiento.

¿QUÉ SON LOS BEANS DE SESIÓN?

Los beans de sesión de Java Enterprise son invocados por un cliente para llevar a cabo una tarea específica del Negocio. Un objeto típico de sesión tiene las siguientes características:
  • Se ejecuta en favor de un cliente simple.
  • Puede ser preparado para transacciones.
  • Actualiza datos compartidos en una base de datos subyacente. 
  • No representa datos compartidos directamente en base de datos, aunque podría acceder y actualizar dichos datos. 
  • Tiene una vida relativamente corta. 
  • Se borra cuando en contenedor EJB se cae. El cliente puede restablecer un nuevo objeto de sesión para continuar trabajando.
Los EJB proporcionan tres tipos de beans de sesión:
  • Stateful (con estado): El estado del bean se mantiene a través de múltiples llamadas a métodos. El "estado" se refiere a los valores de sus variables de instancia. Dado que el cliente interactúa con el bean, a menudo a este estado se le denomina estado conversacional.
  • Stateless (sin estado): Este tipo de beans se usa para operaciones que pueden ocurrir en una llamada de método simple. Cuando el método finaliza su ejecución, el estado específico del cliente del bean no se conserva. Estos beans de sesión no permiten mantener un estado conversacional con el cliente. 
  • Singleton: Un bean de sesión de este tipo se instancia una vez por aplicación, y existe durante todo el ciclo de vida de la aplicación. Los beans de sesión singleton se diseñan para circunstancias en las que una única instancia de Enterprise Bean es compartida y accedida concurrentemente por los clientes.

En el caso del tutorial que nos ocupa sólo vamos a trabajar con beans de sesión sin estado (stateless).

A CERCA DE ESPECIFICACIONES E IMPLEMENTACIONES

Las tecnologías EJB y JPA están definidas por las siguientes especificaciones:
Estas especificaciones definen las tecnologías. Sin embargo, para aplicar la tecnología a un proyecto, se debe usar una implementación de la especificación. Cuando una especificación es finalizada, suele incluir una implementación libre de la tecnología, que sirve de referencia. Haciendo uso de una analogía: una composición musical (en forma de notas en unas páginas) describe la pieza musical, la define, es la definición. Cuando los músicos aprenden la composición y la graban, la interpretan -o implementan-. Esta grabación es la implementación de la pieza.

Si examinamos las páginas de descarga de las revisiones finales de las especificaciones de EJB y JPA, encontraremos enlaces a las siguientes implementaciones de referencia:
Las implementaciones de la especificación de JPA se llaman proveedores de persistencia. En este caso, la implementación del proveedor de persistencia de referencia es EclipseLink.

Si examinamos el enlace para la implementación de referencia de EJB, vemos que la implementación no es sólo para EJB, sino que incluye todas las implementaciones de referencia proporcionadas por el proyecto GlassFish (anda, justo nuestro servidor de aplicaciones...). La razón para esto es que el proyecto GlassFish conforma la implementación de referencia de la plataforma Java EE 6 (JSR 316). El servidor de aplicaciones GlassFish v3 contiene todas las implementaciones de referencia de todas las tecnologías desarrolladas bajo el proyecto GlassFish, tal cosa se conoce como contenedor Java EE 6.

Un contenedor Java EE tiene tres componentes esenciales: un contenedor web, un contenedor EJB, y un proveedor de persistencia. Así, las clases de entidad que crearemos en esta unidad serán gestionadas por el proveedor de persistencia; los beans de sesión que implementemos serán gestionados por el contenedor EJB; y las vistas serán renderizadas en páginas JSP, que serán gestionadas por el contenedor web.

AÑADIENDO CLASES DE ENTIDAD

El asistente de bases de datos nos permite generar clases de entidad basada en el esquema de affablebean. El asistente depende del proveedor de persistencia subyacente para acometer esta tarea.  
  1. En el asistente de de archivos, buscamos la carpeta de Persistencia, y seleccionamos "Clases de entidad de Base de Datos" (Entity Classes from Database). Continuamos...

  2. En el siguiente paso: Tablas de Base de Datos, elegimos jdbc/affablebean como origen de datos. Al elegir el origen de datos, el IDE escanea la base de datos y lista la tablas disponibles. Las seleccionamos todas y continuamos.

  3. Aquí podemos cambiar el nombre del empaquetado (Package) y poner "entity". Nótese que los nombres de las clases para las entidades están basados en las tablas de la base de datos, por ejemplo, la entidad CustomerOrder hace referencia a la tabla customer_order.

    Además aparecen activos por defecto una serie de checkbox. Estos sirven para generar anotaciones a consultas con nombre para los campos de persistencia, y crear una unidad de persistencia -lo que no es ni más ni menos que una colección de clases de entidades que existen en la aplicación-. La unidad de persistencia se define en el fichero de configuración "persistence.xml", que posteriormente es leído por el proveedor de persistencia.

  4. Al finalizar, las clases de entidad JPA -basadas en las tablas de la base de datos affablebean- serán generadas. Ahora podemos ver, en la ventana de proyecto, que tenemos un nuevo paquete llamado "entity", y que la unidad de persistencia aparece colgando del nodo de Ficheros de Configuración.

Puede observarse que el asistente ha generado una clase de entidad adicional, "OrdererProductPK.java". Recordemos que en el modelo de datos, la tabla ordered_product usaba una clave primaria compuesta que comprendía las claves primarias de las tablas customer_order y product. Por esta razón, en proveedor de persistencia crea una clase de entidad separada para la clave compuesta, y la incrusta dentro de la entidad OrderedProduct (abriendo la entidad podemos ver que JPA usa la anotación @EmbeddedId, lo que indica que la clase incrustada es una clave primaria compuesta).

Podemos también echarle un vistazo al XML de la unidad de persistencia abriéndola en el editor. Vamos a ir a la pestaña del código XML y a añadir la siguiente propiedad:

<persistence-unit name="AffableBeanPU" transaction-type="JTA">
  <jta-data-source>jdbc/affablebean</jta-data-source>

  <properties>
    <property name="eclipselink.logging.level" value="FINEST"/>
  </properties>

</persistence-unit>

Estableciendo esta propiedad como "FINEST", podemos ver todas las salidas posibles del proveedor de persistencia cuando se ejecuta la aplicación. Esto nos permite ver el código SQL usado por el proveedor de persistencia en la base de datos, lo que facilita las tareas de depuración.

AÑADIENDO BEANS DE SESIÓN

El asistente para beans de sesión de clases de entidades, permite generar una fachada EJB de sesión para cada una de las clases de entidad que hemos creado. Cada bean de sesión contendrá los métodos básicos de acceso para su respectiva clase de entidad.

Una fachada de sesión es un patrón de diseño que pretende resolver problemas comunes que surgen en el entorno de una aplicación multinivel, tales como:
  • Fuerte acoplamiento, lo que se traduce en una dependencia directa entre clientes y objetos de negocio.
  • Demasiada invocación de métodos entre cliente y servidor, lo que da lugar a problemas en en rendimiento de la red. 
  • Falta de una estrategia uniforme de acceso de clientes, exponiendo a los objetos de negocio a un mal uso.

Una fachada de sesión abstrae las interacciones entre los objetos de negocio subyacentes, y proporciona una capa de servicio que expone sólo las funcionalidades necesarias. De esta forma se oculta de la vista del cliente la complejidad de las interacciones entre los participantes. El bean de sesión (representando la fachada de sesión) gestiona las relaciones entre los objetos de negocio, así como el ciclo de vida de éstos, creándolos, localizándolos, modificándolos y borrándolos según lo requiera el flujo de trabajo. 
  1. En el asistente de de archivos, buscamos la carpeta de Persistencia, y seleccionamos "Beans de Sesión para Clases de Entidad" (Session Beans For Entity Classes). Continuamos...

  2. En el siguiente paso: Clases de Entidad, vemos que se muestran como disponibles todas las clases de entidad de nuestro proyecto. Las añadimos todas a la lista de Clases de Entidad Seleccionadas

  3. En el siguiente paso, Beans de Sesion Generados, pondremos el nombre "session" al empaquetado (Package).

    Se puede ver que es posible usar el asistente para generar interfaces locales y remotos para los beans de sesión. El uso de interfaces al programar beans de sesión puede ser muy beneficioso (permitiendo, por ejemplo, ocultar interacciones de objetos detrás de una interface, lo que permite desvincular todavía más al cliente de la lógica de negocio. O implementar varias interfaces de la aplicación de ser necesario...), pero eso escapa al objetivo de este tutorial, y lo aparcaremos por el momento.

Al finalizar, el IDE habrá generado los beans de sesión para cada una de las clases de entidad contenidas en el proyecto, y podremos ver el nuevo paquete "session" en la ventana de Proyectos.

Puede observarse que además de los beans de las clases de entidad, se crea otra clase llamada AbstractFacade. Esto es porque el IDE de NetBeans (a partir de la versión 6.9) extrae todo el código repetitivo común a todas las clases generadas a una clase abstracta de las que heredan las demás.

Si abrimos cualquiera de las fachadas de sesión, por ejemplo ProductFacade, veremos que todas instancian un EntityManager usando la anotación @PersistanceContext.

@PersistanceContext(unitName = “AffableBeanPU”)
private EntityManager em;

Esta anotación es utilizada para inyectar una EntityManager gestionada por contenedor en una clase. Dicho de otra forma, confiaremos en el contenedor EJB de GlassFish para abrir EntityManager's como y cuando sea necesario. El nombre de la unidad especifica la unidad de persistencia AffableBeanPU que definimos en el fichero persistence.xml.

El EntityManager es un componente integrado de la API de persistencia de Java, que se encarga de implementar acciones de persistencia en la base de datos.

Desde este momento, nuestra aplicación contiene un modelo persistente de la base de datos affablebean en forma de entidades de clase JPA. También contiene una fachada de sesión consistente en Enterprise Beans que pueden ser usados para acceder a las clases de entidad. Ahora vamos a ver como se usa esto...

ACCEDIENDO DATOS CON EJB'S

En una unidad previa del tutorial aprendimos cómo acceder a la base de datos desde la aplicación configurando un origen de datos en GlassFish, añadiendo referencias de recurso en el descriptor de despliegue, y usando etiquetas <sql> de JSTL en las páginas JSP. Esto es una valiosa técnica que permite configurar, de forma rápida, prototipos que incluyan datos de base de datos. Sin embargo no es un escenario realista en aplicaciones de cierto tamaño, o gestionadas por un equipo de desarrolladores, dado que da lugar a problemas de mantenimiento y escalabilidad. Es más, si estamos desarrollando una aplicación en múltiples niveles, o simplemente queremos adherirnos al patrón MVC, no querremos tener código de acceso a datos en nuestro front-end. Usando EJB y modelos de persistencia conseguiremos ajustarnos con más rigor a la definición de MVC mediante un desacoplamiento efectivo entre presentación y componentes del modelo.

En las siguientes líneas comenzaremos a usar los beans de sesión y de entidad en el proyecto AffableBean. Vamos a empezar por cargarnos la lógica de acceso a datos JSTL que habíamos puesto en las páginas index y category, y en su lugar usaremos métodos de acceso a datos proporcionados por los beans de sesión, y almacenaremos datos en variables de entorno, de forma que puedan ser recuperadas en las vistas de página del front-end. Vamos a empezar con la página index, y luego nos meteremos con la página category, más complicada.

Página index

La página index requiere datos para las cuatro categorías de producto. En la configuración actual, las etiquetas <sql> de JSTL consultan la base de datos cada vez que se carga la página index. Sin embargo esta información es raramente modificada, así que tiene más sentido, desde el punto de vista del rendimiento, realizar la consulta una única vez al desplegar la aplicación, y almacenar la información en atributos cuyo ámbito sea la aplicación. Lograremos esto añadiendo el siguiente código en el método init en el servlet del controlador:
  1. Abrimos el ControlerServlet.java (Source Package > controller), y declaramos una instancia de CategoryFacade y una a anotación @EJB, de la siguiente manera:

    public class ControlerServlet extends HttpServlet {
       
       @EJB
       private CategoryFacade categoryFacade;
       ...
    } 

  2. Usando las sugerencias del IDE, añadimos las líneas para la importación de las librerías javax.ejb.EJB y session.CategoryFacade.

  3. Ahora añadiremos el siguiente método init a la clase. El contenedor web inicia el servlet llamando a su método init. Esto ocurre una sola vez, después de la carga del servlet y antes de comenzar a atender peticiones:

    public class ControllerServlet extends HttpServlet {
       
       @EJB
       private CategoryFacade categoryFacade;
     
       public void init() throws ServletException {
          //store category list in servlet context
          getServletContext().setAttribute(“categories”, categoryFacade.finAll());
       } 
       ...
    }
    

    El método findAll obtiene todos los registros de Category de la base de datos. De esta forma obtenemos una lista de objetos Category como un atributo que puede ser referenciado mediante la cadena "categories". Colocar la referencia en el ServletContext significa que la referencia existe en el ámbito de toda la aplicación.

  4. Usando nuevamente las sugerencias del IDE, podemos añadir las anotaciones @overrides. El método init está definido en la superclase de HttpServlet, GenericServlet. Añadir la anotación no es realmente necesario, sin embargo proporciona, entre otras ventajas, legibilidad, puesto que deja claro que métodos están sobrecargados en nuestro código.

  5. Ahora que ya hemos configurado un atributo en el ámbito de la aplicación para contener una lista de categorías, vamos a modificar la página index para acceder al nuevo atributo creado. Para ello vamos a borrar -o comentar- las instrucciones <sql:query> y a modificar la etiqueta <c:forEach> de forma que su atributo items referencie el nuevo atributo de entorno de la aplicación, categories:
       
       <c:foreach items="”${categories}”" var="”category”">
    

  6. Ahora vamos a editar también el descriptor de despliegue, web.xml, donde vamos a borrar -o comentar- la entrada <resource-ref>. Esta entrada era necesaria para las etiquetas <sql> de forma que pudiera identificarse el origen de datos registrado en el servidor; pero ahora usaremos JPA para acceder a la base de datos, y el origen de datos jdbc/affablebean es especificado en la unidad de persistencia.

Podemos ahora ejecutar la aplicación para comprobar que lo que hemos hecho no ha sido estropearlo todo... 

Página category

La página de categorías se basa en tres piezas para funcionar adecuadamente: Los datos de categorías, la categoría seleccionada y los datos de productos en la categoría seleccionada.

Datos de categorías
Podemos reutilizar el atributo de ámbito de la aplicación, categories, que creamos en la página index.
  1. Abrimos el archivo category.jsp y comentamos las líneas correspondientes a las etiquetas <sql:query>. Luego modificamos la apertura de la etiqueta <c:forEach> de forma análoga a como hicimos en la página index.
       
       <c:forEach var=”category” items=”${categories}”>
    

  2. Si ejecutamos el proyecto, veremos que el botón de la categoría seleccionada se comporta como debe.

Categoría seleccionada
Para recuperar la categoría seleccionada, vamos a usar la clase categoryFacade que creamos para localizar la categoría cuyo ID coincidiese con la cadena de consulta.
  1. Vamos a editar el servlet del controlador (ControllerServlet.java) y vamos a implementar una funcionalidad para obtener la categoría seleccionada. Localizamos el comentario en el que pusimos: //TODO: Implement category request, lo borramos y añadimos en siguiente código:
       
    // if category page is requested
    if (userPath.equals("/category")) {
    
       // get categoryId from request
       String categoryId = request.getQueryString();
    
       if (categoryId != null) {
          // get selected category
          selectedCategory = categoryFacade.find(Integer.parseInt(categoryId));
      
          // place selected category in request scope
          request.setAttribute("selectedCategory", selectedCategory);
       }
    ...
    

    Hasta ahora, hemos recuperado el ID de la categoría llamando a getQueryString() en la petición; hemos usado el método find de CategoryFacade para recuperar el objeto Category basado en el ID de la categoría solicitada, y hemos colocado el objeto Category recuperado en el alcance de la petición.

    Utilizando el icono de sugerencias del editor, declararemos selectedCategory como variable local dentro del método doGet. Adicionalmente, como el tipo Category todavía no se ha importado en la clase, el IDE añade automáticamente la fila "import entity.Category" al principio del archivo.

    Obsérvese que hay que convertir categoryId a Integer, puesto que este es el tipo usado en el campo Id de la clase de entidad Category.

    Nota: La lógica para determinar la categoría seleccionada dentro de la columna izquierda ya está implementada en "category.jsp" mediante la expresión EL "pageContext.request.queryString", lo que es comparable a llamar a "getQueryString" en el servlet.

  2. Ahora volvemos a editar la página category.jsp para hacer los siguientes cambios en la etiqueta <p id="categoryTitle">:
       
    <p id=”categoryId”>
       <span style=”background-color: #f5eabe; padding: 7px;”>${selectedCategory.name}</span>
    </p>
    

Ahora ya estamos usando el atributo selectedCategory que acabamos de colocar en el alcance de la petición a través del ControllerServlet. Usando ".name" en la expresión EL se llama al método getName en el objeto Category dado.

Datos de productos en la categoría seleccionada  
Con el fin de recuperar todos los productos de la categoría seleccionada, vamos a usar el método getProductCollection(). Empezaremos llamando a este método en selectedCategory para obtener todos los productos asociados con la categoría. Luego almacenaremos la colección de productos en un atributo en el ámbito de la petición, y finalmente haremos referencia al atributo desde la vista de la página category.jsp.
  1. Primero vamos a editar el servlet del controlador, añadiendo las siguientes nuevas líneas al código que gestiona la petición de categorías; y colocaremos la colección de productos en el alcance de la petición, de forma que puede ser recuperada desde el front-end de la aplicación.
       
    // if category page is requested
    if (userPath.equals("/category")) {
    
       // get categoryId from request
       String categoryId = request.getQueryString();
    
       if (categoryId != null) {
    
          // get selected category
          selectedCategory = categoryFacade.find(Short.parseShort(categoryId));
    
          // place selected category in request scope
          request.setAttribute("selectedCategory", selectedCategory);
    
    -->   // get all products for selected category
          categoryProducts = selectedCategory.getProductCollection();
    
    -->   // place category products in request scope
          request.setAttribute("categoryProducts", categoryProducts);
       }
    

    Nuevamente usaremos el icono de sugerencias del IDE para definir categoryProducts como una variable local del método doGet.

  2. Finalmente editaremos la página category.jsp para hacer los siguientes cambios en la tabla de productos:
       
    <table id=”productTable”>
    <c:forEach var=”product” items=”${categoryProducts}” varStatus=”iter”>
    

La etiqueta <c:forEach> apunta ahora a la colección categoryProducts. El bucle ahora iterará sobre cada objeto Product contenido en la colección y extraerá los datos acorde a ello.

En esta parte del tutorial hemos visto una breve introducción a las tecnologías JPA y EJB. Ahora sabemos como crear un conjunto de clases de entidad que proporcionen una implementación Java para la base de datos del proyecto. También sabemos implementar un conjunto de beans EJB de sesión que estén por encima de las clases de entidad y proporcionen el acceso adecuado a éstas. Finalmente hemos modificado nuestro proyecto AffableBean para utilizar beans de sesión y entidades de acceso a base de datos para las páginas index y category.

Y por ahora creo que es suficiente. El el próximo capítulo exploraremos la gestión de sesiones, y cómo preparar a la aplicación para recordar acciones del usuario -como por ejemplo los clicks- a través del website. Esta es la clave para implementar el mecanismo de carrito de la compra en una aplicación de comercio electrónico.

4 comentarios:

  1. Como puedo hacer funcional algo como esto:
    @EJB
    TblServiciosFacade miServicioSession;
    TblUsuarioFacade miUsuarioSession;

    Si trato de realizar la inserción en el primero ya no me tiene en cuenta el segundo, cuando quiero hacer un:
    miServicioSession.crear(servicio);

    De antemano gracias por la ayuda.

    ResponderEliminar
  2. No estoy demasiado seguro de lo que estás preguntando; además, como ya he mencionado en alguna ocasión soy novel con NetBeans y estoy desarrollando este tutorial usando como fuente uno que está en inglés, con la sana intención de aprender algo (aunque más lentamente de lo que me gustaría)... Sin embargo, por el pequeño fragmento que escribes, me atrevería a decir que, como poco, te falta una anotación @EJB por cada propiedad que declaras.

    Un saludo y gracias por leernos.

    ResponderEliminar
  3. Te comento: He armado un proyecto en base a tablas y vistas de MySQL.
    Estoy tratando de armar un jpg a partir de un query que figura en la entidad (@NamedQuery(name = "NombCient.findByLetraCient", query = "SELECT n FROM NombCient n WHERE n.letraCient = :letraCient")}) pero el ControllerServlet desconoce esa propiedad en el Facade.
    Podrías aconsejarme cómo es que debo hacerlo.
    Muchísimas gracias

    ResponderEliminar
    Respuestas
    1. Hola. Este tipo de cuestiones tan concretas y alejadas de la intencion educativa de la entrada seria mejor que las pusieses en una plataforma mejor preparada para ello como http://es.stackoverflow.com/ o su version original en ingles http://stackoverflow.com/.

      Eliminar