I'm using JBoss6.1.Final, JSF 2.0 (Mojarra), Weld CDI, MyFaces CODI 1.0.5 (for view-access-scoped)
I'm using something like the Gateway Pattern from Real World Java EE Patterns Rethinking Best Practices (unfortunately I don't have it with me, so I may have screwed something up here). Basically, the application allows a user to go into "edit mode" and edit a List of people (create, edit, remove) maintained in a #ViewAccessScoped backing bean with an extended persistence context and then click a "save" command link that flushes all their changes to the database. At first I was having a problem with ViewExpiredExceptions (if the browser was idle past the session-timeout period and then further requests are performed), but I added some jQuery to make a get request to a servlet that keeps the session alive (called 10 seconds before session-timeout). This seems to be working but now I have another problem, the backing bean is also a SFSB and after some idle time, it is being removed resulting in the following error message being logged (and all ajax rendered data disappears) when I attempt to perform more edits ...
13:06:22,063 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] javax.el.ELException: /index.xhtml #27,81 rendered="#{!conversationBean.editMode}": javax.ejb.NoSuchEJBException: Could not find stateful bean: 43h1h2f-9c7qkb-h34t0f34-1-h34teo9p-de
Any ideas on how I could prevent SFSB removal or at least handle it more gracefully?
Here's my backing bean:
package com.ray.named;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJBTransactionRolledbackException;
import javax.ejb.Stateful;
import javax.ejb.TransactionAttribute;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.ViewAccessScoped;
import com.ray.model.Person;
#Named
#Stateful
#ViewAccessScoped
#TransactionAttribute(javax.ejb.TransactionAttributeType.NEVER)
public class ConversationBean implements Serializable {
private static final long serialVersionUID = 1L;
//properties
private List<Person> people;
private String name;
private Boolean editMode;
#PersistenceContext(type=PersistenceContextType.EXTENDED)
private EntityManager em;
#PostConstruct
public void init() {
people = em.createNamedQuery("Person.findAll", Person.class).getResultList();
setEditMode(false);
}
//event listeners
public void beginEdits() {
setEditMode(true);
}
public void addPerson() {
Person p = new Person(name);
em.persist(p);
people.add(p);
name = null;
}
public void removePerson(Person p) {
people.remove(people.indexOf(p));
em.remove(p);
}
//this method flushes the persistence context to the database
#TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
public void saveEdits() {
setEditMode(false);
}
//getters/setters
public List<Person> getPeople() {
return people;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getEditMode() {
return editMode;
}
public void setEditMode(Boolean editMode) {
this.editMode = editMode;
}
}
Here's the Person entity bean:
package com.ray.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Version;
#Entity
#NamedQueries({
#NamedQuery(name="Person.findAll",
query="SELECT p FROM Person p")
})
public class Person {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
private String name;
#Version
private int version;
public Person() { }
public Person(String name) {
setName(name);
}
public boolean equals(Object o) {
if (!(o instanceof Person)) {
return false;
}
return id == ((Person)o).id;
}
//getters/setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
}
Here's the view:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
$(document).ready(function() {
setInterval(function() {
$.get("#{request.contextPath}/poll");
}, #{(session.maxInactiveInterval - 10) * 1000});
});
</script>
<title>Conversation Test</title>
</h:head>
<h:body>
<h:form>
<h:commandLink value="Begin Edits" rendered="#{!conversationBean.editMode}">
<f:ajax render="#form" listener="#{conversationBean.beginEdits}"/>
</h:commandLink>
<h:commandLink value="Save" rendered="#{conversationBean.editMode}">
<f:ajax render="#form" listener="#{conversationBean.saveEdits}"/>
</h:commandLink>
<h:dataTable id="peopleTable" value="#{conversationBean.people}" var="person">
<h:column>
<f:facet name="header">Name</f:facet>
<h:panelGroup>
<h:inputText value="#{person.name}" disabled="#{!conversationBean.editMode}">
<f:ajax/>
</h:inputText>
<h:commandLink value="X" disabled="#{!conversationBean.editMode}">
<f:ajax render="#form" listener="#{conversationBean.removePerson(person)}"/>
</h:commandLink>
</h:panelGroup>
</h:column>
</h:dataTable>
<h:panelGrid columns="2">
<h:outputLabel for="name">Name:</h:outputLabel>
<h:inputText id="name" value="#{conversationBean.name}" disabled="#{!conversationBean.editMode}"/>
</h:panelGrid>
<h:commandButton value="Add" disabled="#{!conversationBean.editMode}">
<f:ajax execute="#form" render="#form" listener="#{conversationBean.addPerson}"/>
</h:commandButton>
</h:form>
</h:body>
</html>
Here's a servlet used to keep the session alive (called by jQuery ajax get request 10 seconds before session expires):
package com.ray.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class PollServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void init() throws ServletException {
}
public String getServletInfo() {
return null;
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
request.getSession(); //Keep session alive
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
}
public void destroy() {
}
}
Any ideas on how I could prevent SFSB removal or at least handle it
more gracefully?
To investigate further I would recommend to take a look at the EJB lifecycle hooks for passivation and add some debug output there.
Should that be the source of the problem you will be able to configure / deactivate passivation - but scalability might come up as an issue.
Honestly, this scenario seems quite uncommon to me. In general I would expect requests / conversations / sessions to be working more or less in the default boundaries - should you find yourself writing code that circumvents this can it be that you are better off with a RESTful / stateless approach...?
Please update the question with further information if available.
I suppose you have already solved your problem. Otherwise, this JBoss wiki page should be helpful (also for future readers...).
https://community.jboss.org/wiki/Ejb3DisableSfsbPassivation
Cheers,
Luigi
Related
After my post (Hibernate Primefaces AutoComplete text) I switched the implementation a little. But now I am facing a problem.
Even if I use an AJAX event I do not keep the selected value saved to populate a second drop down.
my CREATE.XHTML
<h:head></h:head>
<ui:debug rendered="true"/>
<body>
<h:form id="createAddressForm" prependId="true">
<!-- <p:messages autoUpdate="true" /> -->
<p:growl id="msgs" showDetail="true" />
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
<p:outputLabel for="countryDropDown" value="Country" />
<p:selectOneMenu id="countryDropDown" value="#{addressController.selectedIsoCountry}" >
<p:ajax listener="#{addressController.onCountryChange}" update="stateDropDown" />
<f:selectItem itemValue="" itemLabel="Select a country"/>
<f:selectItems value="#{addressController.countryMap}" />
</p:selectOneMenu>
<p:outputLabel for="stateDropDown" value="State" />
<p:selectOneMenu id="stateDropDown" value="#{addressController.state}" >
<f:selectItem itemValue="" itemLabel="Selecione a State" />
<f:selectItems value="#{addressController.stateMap}" />
</p:selectOneMenu>
</h:panelGrid>
</h:form>
</body>
</html>
And this is AddressController.java
import java.util.Map;
import java.util.TreeMap;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.SessionScoped;
import javax.inject.Named;
import br.com.azulseguros.ejb.CountryEJB;
import br.com.azulseguros.entity.Country;
import br.com.azulseguros.entity.State;
#SessionScoped
#Named
public class AddressController {
#EJB
private CountryEJB countryEJB;
private String selectedIsoCountry = null;
private State state = null;
private Map<String, String> countryMap = null;
private Map<String, String> stateMap = null;
#PostConstruct
private void init() {
Map<String, String> retorno = new TreeMap<String, String>();
for (Country _tmp : countryEJB.findAll()) {
retorno.put(_tmp.getName(), _tmp.getIso());
}
countryMap = retorno;
}
public Map<String, String> getCountryMap() {
return countryMap;
}
public Map<String, String> getStateMap() {
return stateMap;
}
public String getSelectedIsoCountry() {
return selectedIsoCountry;
}
public State getState() {
return state;
}
public void setSelectedIsoCountry(String selectedIsoCountry) {
this.selectedIsoCountry = selectedIsoCountry;
}
public void setState(State state) {
this.state = state;
}
public void setCountryMap(Map<String, String> countryMap) {
this.countryMap = countryMap;
}
public void setStateMap(Map<String, String> stateMap) {
this.stateMap = stateMap;
}
public void onCountryChange() {
setStateMap(getStatesFromSelectedCountry());
}
private Map<String, String> getStatesFromSelectedCountry() {
Map<String, String> retorno = new TreeMap<String, String>();
if (selectedIsoCountry != null && !selectedIsoCountry.equals("")) {
for (State _tmp : countryEJB.findByIso(selectedIsoCountry).getStates()) {
retorno.put(_tmp.getName(), _tmp.getFu());
}
}
return retorno;
}
}
The EJB responsibile for finding all countries and states is working fine. There is a lot of issues with that and I do not know what to do to fix it.
1 - After I invoke the page for the first time it calls the init method 10 times;
2 - After that it evoked the method getStatesFromSelectedCountry even not choosing any country from the 1st drop down and after that evokes the init method again;
3 - When i choose a country it evokes 7 times the init method and then the getStatesFromSelectedCountry() but the selectedIsoCountry is null.
The bean's init method is invoked many times because you have defined the bean both as a CDI bean using javax.inject.Named, without scope, and as a JSF Managed Bean using javax.faces.bean.SessionScoped; if you intended to use CDI beans, simply replace the latter annotation with javax.enterprise.context.SessionScoped. See Why are there different bean management annotations
From a CDI point of view, the bean is by default RequestScoped, this should explain also the second issue you are experiencing.
Concerning the third issue, see this Q/A:
Why is the getter called so many times by the rendered attribute?
Why JSF calls getters multiple times
I am try to develop a web application where I need the Conversation scope to carry on with the same String value in multiple xhtml pages with Primefaces 3.5.
When I begin the conversation with conversation.begin(), it throws null pointer exception with conversation being as null.
I know I can't create a instance of Conversation using 'new'. But I can't figure out where am I going wrong and why is it coming to be null.
Please guide.
Snippet of the xhtml where the bean method is called:
<p:column style="text-align: left" headerText="Deal ID"
width="30">
<p:commandLink value="#{selectedDealBean.getDealID()}"
action="#{SearchBean.action(selectedDealBean.getDealID())}"
process="#this" >
</p:commandLink>
</p:column>
Snippet of bean:
#Named()
#ManagedBean
#ConversationScoped
public class SearchBean implements Serializable {
#Inject
private Conversation conversation;
private DealBean selectedDealBean;
private String selectedID;
private SearchObject searchObj = new SearchObject();
public void start() {
this.conversation.begin();
}
public void end() {
conversation.end();
}
public void submit() {
System.out.println(selectedDealBean);
}
public String action(String selectedID) {
String actionstatus = null;
setSelectedID(selectedID);
actionstatus = "/common/dealDisplay.xhtml?faces-redirect=true" ;
start();
return actionstatus;
}
public String onFinish() {
end();
return "/common/create.xhtml";
}
}
You're mixing annotations. Since you're using CDI you should remove #ManagedBean annotation which is possibly the reason why your injection isn't working.
I'm trying to understand how to program composite components, and have followed the great example by balusc, and others, but I'm missing something.
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:cc="http://java.sun.com/jsf/composite">
<cc:interface componentType="simpleComponent">
<cc:attribute name="value" required="true" type="example.LanguageDefinition"/>
<cc:attribute name="possibilities" default="de_DE" type="java.lang.String"/>
</cc:interface>
<cc:implementation>
<p:selectOneMenu binding="#{cc.inputComponent}" converter="omnifaces.SelectItemsConverter" var="l"
value="#{cc.attrs.value}">
<p:ajax update="#form"/>
<f:selectItems value="#{cc.languages}" var="l" itemLabel="#{l.label}"
itemValue="#{l}" />
<p:column>#{l.label}</p:column>
<p:column>
<p:graphicImage name="#{l.imgPath}" />
</p:column>
</p:selectOneMenu>
</cc:implementation>
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.faces.component.FacesComponent;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIInput;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;
import example.LanguageDefinition;
#FacesComponent("simpleComponent")
public class SimpleComponent extends UIInput implements NamingContainer {
private UIInput inputComponent;
public UIInput getInputComponent() {
return inputComponent;
}
public void setInputComponent(UIInput inputComponent) {
this.inputComponent = inputComponent;
}
#Override
public Object getSubmittedValue() {
return inputComponent.getSubmittedValue();
}
#Override
protected Object getConvertedValue(FacesContext context, Object newSubmittedValue) {
return (String) newSubmittedValue;
}
#Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
#Override
public void encodeBegin(FacesContext context) throws IOException {
String possibilities = getAttributeValue("possibilities", "en_US");
// In theory, build based on incoming possibilities, now hard code
List<LanguageDefinition> languages = new ArrayList<LanguageDefinition>();
languages.add(new LanguageDefinition("pt_PT",
"images/flags/PT.gif", "Português (Portugal)"));
languages.add(new LanguageDefinition("cs_CZ",
"images/flags/CZ.gif", "Czech (Czech Republic)"));
getStateHelper().put("languages", languages);
super.encodeBegin(context);
}
#SuppressWarnings("unchecked")
public List<LanguageDefinition> getLanguages() {
return (List<LanguageDefinition>) getStateHelper().get("languages");
}
/**
* Return specified attribute value or otherwise the specified default if it's null.
*/
#SuppressWarnings("unchecked")
private <T> T getAttributeValue(String key, T defaultValue) {
T value = (T) getAttributes().get(key);
return (value != null) ? value : defaultValue;
}
}
This isn't working calling like this:
<ex:simpleComponent value="#{compBean.selected}"/>
Everything renders fine, but the submitted value is never passed back to my "compBean". However, if I set the selectItems "languages" in any other way other than doing it in encodeBegin it works... as a member variable with getters and setters, or using this code:
<c:set target="#{cc}" property="possibilities" value="#{cc.attrs.possibilities}"/>
In combination with this much simpler class:
import java.util.ArrayList;
import java.util.List;
import javax.faces.component.FacesComponent;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIInput;
import javax.faces.component.UINamingContainer;
import example.LanguageDefinition;
#FacesComponent("simpleComponent")
public class SimpleComponent extends UIInput implements NamingContainer {
#Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
public void setPossibilities(String possibilities) {
if (getStateHelper().get("possibilities") == null) {
List<LanguageDefinition> languages = new ArrayList<LanguageDefinition>();
languages.add(new LanguageDefinition("pt_PT",
"images/flags/PT.gif", "Português (Portugal)"));
languages.add(new LanguageDefinition("cs_CZ",
"images/flags/CZ.gif", "Czech (Czech Republic)"));
getStateHelper().put("languages", languages);
getStateHelper().put("possibilities", possibilities);
}
}
public String getPossibilities() {
return (String) getStateHelper().get("possibilities");
}
#SuppressWarnings("unchecked")
public List<LanguageDefinition> getLanguages() {
return (List<LanguageDefinition>) getStateHelper().get("languages");
}
}
But, it doesn't seem right to do it this way (wasn't the way balusc did it), so I'm just trying to understand. Which way is better? Assuming the first, why is mine not working?
Thanks!
So... the reason this wasn't working was because I forgot to implement Serializable on my custom drop down list value object "example.LanguageDefinition".
Hopefully the next person won't have to look for this needle in the haystack as long as I did :)
Hi I have experimented #Inject annotation with cdi bean. I have one variable in first bean which is injected into second bean. When I call method on second bean using variable in first bean, during that method call first bean's variable returns null.
Here is xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Experiments</title>
</h:head>
<h:body>
<h:form id="main_form">
<h:inputText id="nameInput" value="#{myBean.name}"></h:inputText>
<h:commandButton value ="ok" action="#{myBean2.print()}">
<f:ajax execute="nameInput" render="nameOutput"/>
</h:commandButton>
<h:outputText id ="nameOutput" value="#{myBean2.name}"/>
</h:form>
</h:body>
</html>
beans:
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable
#Named(value = "myBean")
#SessionScoped
public class MyBean implements Serializable {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* Creates a new instance of myBean
*/
public MyBean() {
}
}
second bean: when I call print method of mybean2, injected myBean's 'name' property returns null.
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named
#Named(value = "myBean2")
#SessionScoped
public class MyBean2 implements Serializable{
String name;
#Inject
MyBean myBean;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String print(){
this.name = this.myBean.name;
return null;
}
/**
* Creates a new instance of myBean2
*/
public MyBean2() {
}
}
Is that normal or something wrong with code or config?
I created an ejb
#Stateless
#LocalBean
public class BasitBean {
public String helloBasit() {
return "Basit";
} //end of helloBasit()
} //end of class BasitBean
I am calling it from JSF like
<h:body>
<h:outputLabel value="#{helloBasit.callBasit()}" />
</h:body>
#ManagedBean
#SessionScoped
public class HelloBasit {
#EJB
private BasitBean basitBean;
/** Creates a new instance of HelloBasit */
public HelloBasit() {
}
public String callBasit() {
return basitBean.helloBasit();
} //end of callBasit()
} //end of class HelloBasit
This code is working fine. But when i change the code like this
<h:body>
<h:outputLabel value="#{helloBasit.label}" />
</h:body>
#ManagedBean
#SessionScoped
public class HelloBasit {
#EJB
private BasitBean basitBean;
String label;
/** Creates a new instance of HelloBasit */
public HelloBasit() {
System.out.println();
String label = basitBean.helloBasit();
System.out.println(label);
}
public BasitBean getBasitBean() {
return basitBean;
}
public void setBasitBean(BasitBean basitBean) {
this.basitBean = basitBean;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
} //end of class HelloBasit
Then i get the exception
SEVERE: Error Rendering View[/index.xhtml]
com.sun.faces.mgbean.ManagedBeanCreationException: Cant instantiate class: pk.mazars.basitMahmood.HelloBasit.
at com.sun.faces.mgbean.BeanBuilder.newBeanInstance(BeanBuilder.java:193)
at com.sun.faces.mgbean.BeanBuilder.build(BeanBuilder.java:102)
......
Why i am getting this exception? The flow should be what i understand is when my page encounters #{helloBasit.label} then my constructor get call, instance variable get initialized, injected the bean instance into the basitBean, then the bean method should call. But i am getting null in the bean instance in this case why? Why previous code is working and it is not ? How can i call bean from the constructor ?
Thank you.
try to move your content of the constructor into a post constructor instead...
like this
#PostConstruct
private void init() {
System.out.println();
String label = basitBean.helloBasit();
System.out.println(label);
}
Cause the ejb bean should be injected only after the managed bean has been initiated
The #PostConstruct is being run after the constructor (after that the managed bean itself was created by the JSF) and only then the EJB is being injected into the bean and can be accessed...
Your idea is correct, but I see some things that may be fixed.
#LocalBean annotation is not required if your EJB is not directly implementing an interface. In this case, with or without the #LocalBean annotation you have the same effect. You may leave that if you want to make it explicit though. See this.
Make sure both #ManagedBean and #SessionScoped import from javax.faces.bean package.
Please, see this working sample:
EJB
import javax.ejb.Stateless;
#Stateless
public class PersonService {
public String getName() {
return "Cloud Strife";
}
}
Managed Bean
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class PersonBean {
#EJB
private PersonService ps;
private String name;
#PostConstruct
public void init() {
name = ps.getName();
}
public String getName() {
return name;
}
}
XHTML Page
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:view contentType="text/html">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<h1>Welcome, #{personBean.name}</h1>
</h:body>
</f:view>
</html>
If your value should be loaded only once, say at your bean construction, always prefer a method with #PostConstruct annotation instead of the constructor.
Also, in order to call bean methods before rendering a view you could use a f:event tag, for example:
<f:event type="preRenderView" listener="#{personBean.init}" />
I hope it helps!