Problems migrate from Seam3 to DeltaSpike - seam3

I'm just testing to migrate from Seam3 to DeltaSpike, everything is ok if there is only one EntityManager in a bean, but there will be a error if add other EntityManager(other datasource):
JBAS010152: APPLICATION ERROR: transaction still active in request with status 0
the error project:
https://github.com/yuanqixun/hellodeltaspike
run this project environment:
wildfly 8.2.0.Final
H2 datasource
MySql datasource
The EntityManagerProducer code:
#ApplicationScoped
public class EntityManagerProducer {
#PersistenceUnit(unitName = "hellodeltaspike")
EntityManagerFactory emf;
#PersistenceUnit(unitName = "hellodeltaspike2")
EntityManagerFactory mysqlemf;
#Produces
#ConversationScoped
EntityManager createEntityManager(){
return this.emf.createEntityManager();
}
#Produces
#MySqlEm
#ConversationScoped
EntityManager createMysqlEntityManager(){
return this.mysqlemf.createEntityManager();
}
}
The Action code:
#ConversationScoped
#Named
public class PersonAction implements Serializable{
#Inject
EntityManager em;
#Inject
#MySqlEm
EntityManager mysqlEm;
Person person;
List<Person> personList;
#PostConstruct
void afterCreate(){
person = new Person();
personList = queryPersonList();
}
private List<Person> queryPersonList() {
String jql = "select o from Person o ";
List<Person> result = em.createQuery(jql,Person.class).getResultList();
if(result == null)
return new ArrayList<Person>();
return result;
}
#Transactional
public void btnDoSave(ActionEvent event){
try {
if(StringUtils.isEmpty(person.getUuid())){
em.persist(person);
}else{
em.merge(person);
}
em.flush();
String msg = "Saved:"+person.getName();
FacesContext.getCurrentInstance().addMessage(null,new FacesMessage(FacesMessage.SEVERITY_INFO,msg,null));
person = new Person();
personList = queryPersonList();
} catch (Exception e) {
e.printStackTrace();
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), null));
}
}
...getter and setter
}
and there will be error:
ERROR [org.jboss.as.txn] (default task-6) JBAS010152: APPLICATION ERROR: transaction still active in request with status 0

Modify the method's annotation,add the special qualifier of the right EntityManager, so the problem will be solved. But also has another problem, how to support multiple entityManager's transaction in one method?
#Transactional(qualifier = {H2Em.class})

Related

Set value to ManagedProperty

I'm trying to set a value to my ManagedProperty but I'm getting the null result when I try to print this.
I'd like to set the Bean Class to use it in my query.
I've been tryin' set String, Class, but all the times it returned a null value.
Can anyone help me?
#ManagedBean
public class FilialBean extends BaseBean implements Serializable{
private Filial filial;
private List<Filial> filiais;
#ManagedProperty("#{entidadeService}")
private EntidadeService service;
#PostConstruct
public void init(){
service.setFaces(Filial.class);
filial = new Filial();
filiais = (List<Filial>) (List) service.getbasesEntidades();
}
//GETTERS AND SETTERS
}
#ManagedBean(name="entidadeService", eager=true)
#ApplicationScoped
public class EntidadeService implements Serializable{
private List<EntidadeBase> basesEntidades;
private Class faces;
#PostConstruct
public void init(){
System.out.println(faces.getSimpleName());
try{
EntityManager manager = JPAUtil.getEntityManager();
Query query = manager.createQuery("SELECT e FROM Filial e WHERE e.ativo = :ativo");
query.setParameter("ativo", true);
this.basesEntidades = query.getResultList();
}
catch(Exception e){
e.printStackTrace();
}
}
public List<EntidadeBase> getbasesEntidades() {
return basesEntidades;
}
public Class getFaces() {
return faces;
}
public void setFaces(Class faces) {
this.faces = faces;
}
}
Have you check that #ManagedBean has same package in both classes?
I ran into same problem, a property with null value executing Post Construct method and this is the problem, one class had javax.annotation.ManagedBean (CDI) annotation and the other had javax.faces.bean.ManagedBean (JSF) annotation.
In my case I needed both classes with JSF annotations...

JPA invalid user/password inside multithreads

I'm having an issue with JPA in multithreads application. I'm using JPA proxy authentication to access the database. Everything runs fine in session beans but when in java thread run() method, I cannot use #EJB so I use Initialcontext to look up the bean. When the program executes, I'm getting invalid username/password; logon denied.
#Stateless
public class MyDAO{
#PersistenceContext(name="myPU")
private EntityManager em;
public MyEntity getData(String id){
return em.find(MyEntity.class, id);
}
#AroundInvoke
public Object setSessionUser(InvocationContext ctx){
if(ctx.getTarget() instanceof MyDAO){
Map properties = new HasMap();
properties.put("eclipselink.oracle.proxy-type", OracleConnection.PROXYTYPE_USER_NAME);
properties.put(OracleConnection.PROXY_USER_NAME, "myusername");
properties.put("eclipselink.jdbc.exclusive-connection.mode", "Always");
properties.put("eclipselink.jdbc.exclusive-connection.is-lazy", "false");
((org.eclipse.persistence.internal.jpa.EntityManagerImpl)em.getDelegate()).setProperties(properties);
}
return ctx.proceed();
}
}
inside run();
#Override
public void run(){
...
MyDAO dao = (MyDAO) new InitialContext().lookup("java:module/...");
EntityObject obj = dao.getData("123456");
...
}

Injecting DAO give NullPointerException

Using the following Bean, I fill a form with countries:
#ManagedBean
#RequestScoped
public class CreateUser {
#EJB
private ParticipantDAO participantDAO;
#EJB
private CountryDAO countryDAO;
private List<Country> countries = new ArrayList<Country>();
. . .
. . .
. . .
#PostConstruct
public void init() {
countries = countryDAO.getAllCountries();
}
In the form I've to use a Converter:
<h:selectOneMenu id="country" value="#{createUser.user.country}" required="true" requiredMessage="Please select a country." converter="#{countryConverter}" >
<f:selectItem itemValue="#{null}" itemLabel="-- select one --" />
<f:selectItems value="#{createUser.countries}" var="country" itemValue="#{country}" itemLabel="#{country.country}" />
</h:selectOneMenu>
The Converter give a NullPointerException seems because it's unable to inject CountryDAO:
#ManagedBean
#RequestScoped
#FacesConverter(forClass = Country.class)
public class CountryConverter implements Converter {
#EJB
private CountryDAO countryDAO;
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (!(value instanceof Country)) {
return null;
}
return String.valueOf(((Country) value).getId());
}
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value == null || value.isEmpty()) {
return null;
}
try {
System.out.println("Converter Value: " + value);
Country c = countryDAO.find(Long.valueOf(value));
System.out.println("Converter: " + c.getCountry());
return c;
} catch (Exception e) {
throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to Country %s %d", value, e.toString(), Long.valueOf((value)))), e);
}
}
}
In the console I see the "Converted Value" message but not the "CountryDAO find" that should be printed by createDAO.find method.
#Stateless
#LocalBean
public class CountryDAO {
public CountryDAO() {
}
#PersistenceContext
private EntityManager em;
#Resource
SessionContext context;
public List<Country> getAllCountries() {
TypedQuery<Country> query = em.createNamedQuery(Country.FIND_ALL, Country.class);
return query.getResultList();
}
public Country find(Long id) {
System.out.println("CountryDAO find");
Country c = em.find(Country.class, id);
System.out.println(c.getCountry());
return c;
}
I tried the solution reported to Inject a EJB into a JSF converter with JEE6 (I don't know if I put the code in the correct location). I put it in the converter (and I obtain the NullPointerException):
#ManagedBean
#FacesConverter(forClass = Country.class)
public class CountryConverter implements Converter {
// #EJB
// private CountryDAO countryDAO;
private InitialContext ic;
private CountryDAO countryDAO;
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (!(value instanceof Country)) {
return null;
}
return String.valueOf(((Country) value).getId());
}
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value == null || value.isEmpty()) {
return null;
}
System.out.println("Converter Value: " + value);
try {
try {
ic = new InitialContext();
countryDAO = (CountryDAO) ic.lookup("java:global/DAO/CountryDAO");
} catch (NamingException e) {
}
Country c = countryDAO.find(Long.valueOf(value));
System.out.println("Converter: " + c.getCountry());
return c;
} catch (Exception e) {
throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to Country %s %d", value, e.toString(), Long.valueOf((value)))), e);
}
}
I was having the same problem in the some other project, where I was using a converter for some primefaces component. I solved the problem the CDI way.
All you have to do is annotate your converter class with #Named (and inject the DAO class via #Inject (JEE6), and not with JEE5 - #EJB).
You reference your converter with binding attribute like:
<f:converter binding="#{countryConverter}" />

JPA EclipseLink entities not refreshing

I have a problem with entities not being refreshed when values in the database are changed from outside the JPA session. For instance, I have a user entity:
#Entity
#Cacheable(false)
public class UserBean implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#OneToMany(mappedBy = "receiver")
#JoinTable(name = "NOTIFICATIONS_RECEIVED")
private List<NotificationBean> notificationsReceived;
...
}
And notifications entity:
#Entity
#Cacheable(false)
public class NotificationBean implements Serializable{
#Id
#GeneratedValue
private Long id;
#ManyToOne
private UserBean receiver;
...
}
I use this inside a JSF application and have a SessionScoped bean, which loads the user after login and stores it:
#Named("sessionManager")
#SessionScoped
public class SessionManagerBean implements Serializable {
#PersistenceUnit(unitName = "PU")
private EntityManagerFactory emf;
private UserBean user;
public UserBean getUser() throws Exception {
if (user == null) {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
String username = request.getRemoteUser();
if (username != null) {
EntityManager em = null;
try {
utx.begin();
em = emf.createEntityManager();
Query query = em.createQuery("SELECT u from UserBean u WHERE u.username = ?1");
query.setParameter(1, username);
user = (UserBean) query.getSingleResult();
}
catch (Exception e) {
try {
utx.rollback();
} catch (Exception e) {
} finally {
utx.commit();
em.close();
}
}
return user;
}
}
}
public void refreshUser() {
EnitytManager em = emf.createEntityManager();
// similar code as above to retrieve the user from the database
em.refresh(user);
}
}
The page which displays the notifications calls refreshUser() when it loads:
<f:metadata>
<f:event type="preRenderView" listener="#{sessionManager.refreshUser()}" />
</f:metadata>
The user data is not refreshed though and notifications which are displayed on the page are not updated when I refresh the page.
However, if I change refreshUser() to:
public void refreshUser() {
EntityManager em = emf.createEntityManager();
List<NotificationBean> notifications = em.createNativeQuery("SELECT * FROM NOTIFICATIONBEAN WHERE RECEIVER_ID = " +
user.getId() + ";").getResultList();
user.setMatchChallengesReceived(notifications);
}
the notifications are updated.
I have more variable than notifications that I need to refresh from the database and it would be a lot of code to do the same for each one. I thought em.refresh(user) should reload all variables that have changed from the database for me. I thought it is a caching issue, so I added #Cacheable(false) to UserBean and NotificationBean, but it has no effect.
What am I doing wrong?
If the problem is with notifications, then itis because refreshing user is not set to cascade the refresh. Set the CascadeType.REFRESH on the notificationsReceived mapping.

Accessing ManagedBean method from EJB

I have an EJB that handles creation of customer user accounts that needs access to a managed bean (account scoped) which manages user verification keys for user accounts (the keys are transient, so they don't need to be handled by database calls). However, I can't figure out a way to send the verification key to the EJB (which generates the verification email that is send to a user).
AccountVerifierBean.java
#ManagedBean(name = "accountVerifierBean", eager = true)
#ApplicationScoped
public class AccountVerifierBean implements Serializable {
private HashMap<String, String> verificationKeyMapping;
public AccountVerifierBean() {}
public boolean verifyKey(String username, String key) {
return key.equals(verificationKeyMapping.get(username));
}
public String generateKey(String username) {
Date time = new Date();
String key = username + time.toString();
key = Encryption.hashSHA(key);
verificationKeyMapping.put(username, key);
return key;
}
}
CustomerService.java
#Named
#Stateless
#LocalBean
public class CustomerService {
#PersistenceContext(unitName = "MovieProject-ejbPU")
private EntityManager em;
private String username;
private String password;
//getters and setters
public void validateEmail() {
Properties serverConfig = new Properties();
serverConfig.put("mail.smtp.host", "localhost");
serverConfig.put("mail.smtp.auth", "true");
serverConfig.put("mail.smtp.port", "25");
try {
Session session = Session.getInstance(serverConfig, new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("<ACCOUNT>","<PASSWORD>");
}
});
MimeMessage message = new MimeMessage( session );
message.setFrom(new InternetAddress("accounts#minimalcomputers.com","VideoPile"));
message.addRecipient(
Message.RecipientType.TO, new InternetAddress(username)
);
message.setSubject("Welcome to VideoPile!");
message.setContent("<p>Welcome to VideoPile, Please verify your email.</p><p>" + verifierKey + "</p>", "text/html; charset=utf-8"); //verifierKey is what I'm trying to get from AccountVerifierBean.
Transport.send( message );
}
catch (MessagingException ex){
Logger.getLogger(CustomerService.class.getName()).log(Level.SEVERE, null, ex);
}
catch (Exception e) {
Logger.getLogger(CustomerService.class.getName()).log(Level.SEVERE, null, e);
}
}
public String encrypt(String password) {
try {
return new String(Base64.encode(MessageDigest.getInstance("SHA").digest(password.getBytes())));
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(CustomerService.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
}
I've tried #Inject, #ManagedProperty, using the Application map, and using the ELContext. Nothing seems to work.
EDIT:
I think there is something wrong with the bean. Any methods called from bean don't seem to do anything (EL is resolved, no bean method calls though).
I've tested the annotations that it uses (both are javax.faces.bean.*)
So, the issue was in the AccountVerifierBean.
I added the following lines to faces-config.xml and it is now working.
<managed-bean eager="true">
<managed-bean-name>accountVerifierBean</managed-bean-name>
<managed-bean-class>org.Videotheque.beans.AccountVerifierBean</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
I'm fairly certain that the problem was because my bean needed to be in the EJB package instead of the WAR so that the EJBs can access it, but because of that, the WAR didn't know that the bean existed.

Resources