JSF inyectado EJB inyectado
managed-bean (1)
Tengo un EJB (PersonManager) en el módulo de aplicación empresarial, que inyecta otro EJB (Persona):
@Stateful
public class PersonManager implements PersonManagerLocal {
@EJB
private PersonLocal person;
@Override
public void setPersonName(String name) {
person.setName(name);
}
@Override
public String getPersonName() {
return person.getName();
}
}
Quiero usar el EJB PersonManager en una aplicación web JSF. Lo defino en el rostro-config.xml:
<managed-bean>
<managed-bean-name>personManager</managed-bean-name>
<managed-bean-class>ejb.PersonManager</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
El problema es que, la inyección de PersonLocal EJB no ocurre. La propiedad de la persona es siempre NULA. ¿Qué me equivoqué?
Pero si inyecto el PersonManager en un bean administrado JSF como este:
@ManagedBean
@RequestScoped
public class Index {
@EJB
private PersonManagerLocal personManager;
....
FUNCIONA. Necesito el primer escenario, por favor ayúdame :-D
Está mezclando las responsabilidades de los EJB y los beans gestionados JSF. El faces-config.xml
registra solo artefactos JSF, como beans administrados y no EJBs. Su registro en faces-config.xml
<managed-bean>
<managed-bean-name>personManager</managed-bean-name>
<managed-bean-class>ejb.PersonManager</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
hace básicamente exactamente lo mismo que
@ManagedBean
@SessionScoped
public class PersonManager {
// ...
}
En otras palabras, está registrando la clase como un bean administrado JSF que está disponible en las vistas por #{personManager}
. Esto no representa la misma instancia que es administrada por el contenedor EJB. Puede y no debe usar faces-config.xml
para registrar EJBs. Allí se usan las anotaciones del paquete javax.ejb
, como @Stateless
y @Stateful
. Eso es todo lo que necesitas para registrar un EJB.
En realidad, el registro de beans administrados JSF en faces-config.xml
es una antigua forma JSF 1.x que en JSF 2.x ha sido reemplazada por la nueva anotación @ManagedBean
.
Actualizar el enfoque adecuado sería:
Ver (el archivo Facelets):
<h:form>
<h:inputText value="#{personManager.person.name}" />
...
<h:commandButton value="Save" action="#{personManager.save}" />
<h:messages />
</h:form>
Controlador (el bean gestionado JSF):
@ManagedBean
@ViewScoped
public class PersonManager implements Serializable {
private Person person;
@EJB
private PersonService personService;
@PostConstruct
public void init() {
person = new Person();
}
public void save() {
personService.create(person);
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("Person successfully created, new ID is " + person.getId()));
}
// ...
}
Modelo (la entidad JPA):
@Entity
public class Person implements Serializable {
@Id
private Long id;
private String name;
// ...
}
Servicio (el EJB sin estado):
@Stateless
public class PersonService {
@PersistenceContext
private EntityManager em;
public void create(Person person) {
em.persist(person);
}
// ...
}