Can't I access session scope variable using #ManagedProperty? - jsf

I know I can put/get session scope variables like this.
FacesContext.getCurrentInstance().getExternalContext()
.getSessionMap().put(SESSION_KEY_SOME, some);
Then can't I access the value like this?
#ManagedBean
#SessionScoped
public class SomeOtherBean {
#ManagedProperty("#{sessionScope.some}")
private Some some;
}
The value is null.

#ManagedProperty runs during creation/instantiation of the #ManagedBean.
So, when the #ManagedBean is created before the #{sessionScope.some} is set for first time, then it will still remain null in the #ManagedBean. It will only work when #ManagedBean is created after the #{sessionScope.some} is set for the first time.
There are basically three ways to achieve the desired behavior.
Replace private Some some by externalContext.getSessionMap().get("some").
#ManagedBean
#SessionScoped
public class SomeOtherBean {
public void someMethod() {
Some some = (Some) FacesContext.getCurrentInstance()
.getExternalContext().getSessionMap().get("some");
// ...
}
}
Replace #SessionScoped by #RequestScoped.
#ManagedBean
#RequestScoped
public class SomeOtherBean {
#ManagedProperty("#{sessionScope.some}")
private Some some;
// ...
}
Replace externalContext.getSessionMap().put("some", some) by directly setting it as bean property.
#ManagedBean
public class SomeBean {
#ManagedProperty("#{someOtherBean}")
private SomeOtherBean someOtherBean;
public void someMethod() {
// ...
someOtherBean.setSome(some);
}
// ...
}
See also:
How to choose the right bean scope?

Related

Passing value between JSF Forms. I can't get it to work

I read the other posts about this subject but I still can't get it to work
This are my beans:
Bean1:
#ManagedBean()
#SessionScoped
public class Bean1 implements Serializable {
//Here are some important Properties
public String buttonPressed() {
return "bean2.xhtml";
}
}
<h:form>
<p:commandButton action="#{Bean1.buttonPressed}" value="Do Work"/>
</h:form>
Bean2:
#ManagedBean()
#SessionScoped
public class Bean2 implements Serializable {
#ManagedProperty(value = "#{Bean1}")
private Bean1 b1;
//getter/setter is here
public String doWorkOnSubmit() {
//Access important Properties from bean1
b1.getFoo()
}
}
Now I have two Problems
1.) How to call "doWorkOnSubmit" if the button in Bean1 is pressed? I can't use the constructor because it's SessionScoped and I don't know how to call doWorkOnSubmit un submit
2.)The managed property "b1" is sometimes null
Since on clicking of Do Work button you are calling Bean1.buttonPressed() action method you can call Bean2s doWorkOnSubmit() by injecting Bean2 in Bean1.
Here is your code altered:
#ManagedBean()
#SessionScoped
public class Bean1 implements Serializable {
//Here are some important Properties
/*
* Inject Bean2 here. since both beans are session scoped,
* there ain't gonna be any problem in injection.
*/
#ManagedProperty(value = "#{Bean2}")
private Bean2 b2;
//GETTER SETTER for b2
public String buttonPressed() {
//Here you will be invoking injected managed beans method.
b2.doWorkOnSubmit();
return "bean2.xhtml";
}
}

getselectednode from another bean (primefaces)

I have a ManagedBean of a treeNode and other managed bean where i would like to get the selectedNode and from getType i would like to execute some code but the problem i can't get the selectedNode cause every time i get this:
java.lang.NullPointerException: javax.faces.FacesException: #{dimMan.makeDim()}: java.lang.NullPointerException
and this is my two Managed bean:
#ManagedBean
#ViewScoped
public class TreeBean implements Serializable {
private static final long serialVersionUID = 2417620239014385855L;
private TreeNode root;
private TreeNode selectedNode;
.....
and the other one where i would like to make a test of the type of selected node:
#ManagedBean(name = "dimMan")
#SessionScoped
public class DimenssionManaged {
#EJB
DimensionDaoRemote dimService;
#Inject
TreeBean treeSelected;
String select;
public TreeBean getTreeSelected() {
return treeSelected;
}
public void setTreeSelected(TreeBean treeSelected) {
this.treeSelected = treeSelected;
}
public void makeDim(){
System.out.println("adding dimen");
fkey=tTable.getSelectedFk();
dimUpdate.setFk_dimension(fkey);
dimUpdate.setType_dimension(selectedType);
select=treeSelected.getSelectedNode().getParent().getType();
System.out.println(select);
if (select=="cube"){
CubeBase cub=cubManged.getCubUpdate();
dimUpdate.setCube(cub);
dimService.creat_dimension(dimUpdate);
}
else {
SchemaBase sh=shmanged.getSchema();
dimUpdate.setSchema(sh);
dimService.creat_dimension(dimUpdate);
}
}
i try also to use this annotation #ManagedProperty(value =***) but it didn't work to so what should i do to get the selectedNode type from in other ManagedBean ?
DimenssionManaged ManagedBean associated with other page? If so once you navigate TreeBean will loose its data since its in #ViewScoped.
Change TreeBean to #SessionScoped to retain the the data even after navigation, but clearing/refreshing the data again is a concern.

How to get inputTextArea value into another bean?

I want to get the value with the getter method, but it doesn't work. I use SessionScoped into my two managed-beans.
<h:outputLabel for="commentInput" value="Comment:" />
<p:inputTextarea id="commentInput" value="#{dashboardBean.currentComment}" rows="6" cols="25" label="commentInput" required="true"/>
#ManagedBean
#SessionScoped
public class DashboardBean implements Serializable
{
private String _currentComment = null;
public String getCurrentComment() {
return this._currentComment;
}
public void setCurrentComment(String _currentComment) {
this._currentComment = _currentComment;
}
}
If i call getter in this class, it's works.
But in the other class:
#ManagedBean
#SessionScoped
public class PanelListener extends AjaxBehaviorListenerImpl
{
private DashboardBean _dashDashboardBean = null;
public void editMemo(ActionEvent actionEvent)
{
System.out.println("Statements ==== [ " + _dashDashboardBean.getCurrentComment() + " ]");
}
}
I have an NullPointerException.
You need to use #ManagedProperty annotation to inject one bean into another.
#ManagedProperty("#{dashboardBean}")
private DashboardBean bean;
public DashboardBean getBean(){
return this.bean;
}
public void setBean(DashboardBean bean){
this.bean = bean;
}
Make sure the scope of the ManagedProperty is greater than or equal to the scope of bean in which you are injecting.
so here, DashBoardBean should have scope greater than or equal to PanelListener
Please note that JSF needs public getters and setters to access the fields
You have to use #ManagedProperty annotation. So try this in PanelListener, note that you need a setter to perform the bean injection. You can also only inject beana with greater or same scope to the bean with lower scopes (so for example you can inject SessionScoped to the RequestScoped but not the other way around).
#ManagedProperty("#{dashboardBean}")
private DashboardBean bean;
private void setDashboardBean(DashboardBean bean) {
this.bean = bean;
}

How to replace #ManagedBean / #ViewScope by CDI in JSF 2.0/2.1

I'm currently evaluating Java EE 6 / JSF 2.1 with RichFaces.
A bean which is declared as
#ManagedBean
#ViewScoped
Gets an ID set (to prepare e.g. a delete operation).
Via JSF a confirmation popup is displayed.
If the user confirms, the delete method is invoked and removes the row for which the ID was stored in step 1.
Since CDI beans don't have a ViewScope I tried to declare the bean as:
#Named
#ConversationScoped
Now the processing fails in step 3. because the value that was set in step 1 (checked that) is no longer available.
Do I have to use Conversation.begin() and Conversation.end() methods?
If so, where would be good place to invoke them?
If you can upgrade to JSF 2.2, immediately do it. It offers a native #ViewScoped annotation for CDI.
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named
#ViewScoped
public class Bean implements Serializable {
// ...
}
Alternatively, install OmniFaces which brings its own CDI compatible #ViewScoped, including a working #PreDestroy (which is broken on JSF #ViewScoped).
import javax.inject.Named;
import org.omnifaces.cdi.ViewScoped;
#Named
#ViewScoped
public class Bean implements Serializable {
// ...
}
Another alternative is to install MyFaces CODI which transparently bridges JSF 2.0/2.1 #ViewScoped to CDI. This only adds an autogenerated request parameter to the URL (like #ConversationScoped would do).
import javax.faces.bean.ViewScoped;
import javax.inject.Named;
#Named
#ViewScoped
public class Bean implements Serializable {
// ...
}
If you really need to use #ConversationScoped, then you indeed need to manually begin and end it. You need to #Inject a Conversation and invoke begin() in the #PostConstruct and end() in the latest step of the conversation, usually an action method which redirects to a new view.
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Named;
#Named
#ConversationScoped
public class Bean implements Serializable {
#Inject
private Conversation conversation;
// ...
#PostConstruct
public void init() {
conversation.begin();
}
public String submit() {
// ...
conversation.end();
return "some.xhtml?faces-redirect=true";
}
}
See also:
How to choose the right bean scope?
I think you can benefit from CDI extension to create your own scope so you can implement the context and use the #NormalScope.
CDI fires an event AfterBeanDiscovery after each bean call
You can use CDI extension to #Observes this event and add your context implementation
In your scope implementation you can :
Use Contextual to get your bean by its name from FacesContext ViewRoot Map and return it after each ajax call back
Use CreationalContext if the bean name from first step is not found to create it in the FacesContext ViewRoot Map
For a more in-depth explanation, I recommend this link : http://www.verborgh.be/articles/2010/01/06/porting-the-viewscoped-jsf-annotation-to-cdi/
Inject the conversation into your bean and in the #PostConstructor method start the conversation if the conversation is transient.
And after deleting the record, end your conversation and navigate to your destination page. When beginning a conversation. Here is an example
public class BaseWebBean implements Serializable {
private final static Logger logger = LoggerFactory.getLogger(BaseWebBean.class);
#Inject
protected Conversation conversation;
#PostConstruct
protected void initBean(){
}
public void continueOrInitConversation() {
if (conversation.isTransient()) {
conversation.begin();
logger.trace("conversation with id {} has started by {}.", conversation.getId(), getClass().getName());
}
}
public void endConversationIfContinuing() {
if (!conversation.isTransient()) {
logger.trace("conversation with id {} has ended by {}.", conversation.getId(), getClass().getName());
conversation.end();
}
}
}
#ConversationScoped
#Named
public class yourBean extends BaseWebBean implements Serializable {
#PostConstruct
public void initBean() {
super.initBean();
continueOrInitConversation();
}
public String deleteRow(Row row)
{
/*delete your row here*/
endConversationIfContinuing();
return "yourDestinationPageAfter removal";
}
}
There is a project which holds an extentions to the Java EE stack features: DeltaSpike. It is a consolidation of Seam 3, Apache CODI. Above others, it includes the #ViewScoped into CDI. This is an old article and by now it has reached version 1.3.0
You can use:
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named
#ViewScoped
public class PageController implements Serializable {
private String value;
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void execute() {
setValue("value");
}
#PostConstruct
public void init() {
System.out.println("postcontructor");
}
}

Why is an exception thrown when an #ManagedProperty is referenced?

I have a JSF web application with a view-scoped bean and a session-scoped bean. I'd like to modify the session bean's members from the view bean, and I followed this guide from a certain well-known JSF guy, but I can't seem to get it to work without a runtime exception. The reference to the managed session bean, "home" is null when referenced, similar to this question except I've already followed the advice of the accepted answer.
package brian.canadaShipping;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
#ManagedBean(name= "requestBean")
#ViewScoped
public class CpstcRequestBean implements Serializable {
#ManagedProperty(value="#{home}")
private CpstcHomeBean homeBean;
public CpstcHomeBean getHomeBean() {
return homeBean;
}
public void setHomeBean(CpstcHomeBean homeBean) {
this.homeBean = homeBean;
}
private static final long serialVersionUID = -5066913533772933899L;
public String testVar = "hello world";
private boolean displayOutput = false;
public boolean isDisplayOutput() {
return displayOutput;
}
public void setDisplayOutput(boolean displayOutput) {
this.displayOutput = displayOutput;
}
public String getTestVar() {
return testVar;
}
public void setTestVar(String testVar) {
this.testVar = testVar;
}
public CpstcRequestBean()
{
System.out.println("TEST: " + homeBean.toString());
System.out.println("Hello, ResuestBean!");
}
}
The first bit of my "home" bean is as follows:
#ManagedBean(name= "home")
#SessionScoped
public class CpstcHomeBean implements Serializable {
...
UPDATE: I've followed Jordan's suggestions and I have the following in my view-scoped bean:
#ManagedBean(name= "requestBean")
#ViewScoped
public class CpstcRequestBean implements Serializable {
#Inject #Named("home") CpstcHomeBean homeBean;
public CpstcHomeBean getHomeBean() {
return homeBean;
}
public void setHomeBean(CpstcHomeBean homeBean) {
this.homeBean = homeBean;
}
public CpstcRequestBean()
{
System.out.println("TEST: " + homeBean.toString());
System.out.println("Hello, ResuestBean!");
}
...
as well as this in my session-scoped bean:
#Named("home")
#SessionScoped
public class CpstcHomeBean implements Serializable {
...
yet my "home" bean reference is still null. Any ideas?
UPDATE 2: It turns out that you must use #Named in both classes, not just the injected class. My web app now loads but some elements are blank. In my console log, I see, "Target Unreachable, identifier 'home' resolved to null." I'm running on Tomcat 7, if that affects things. Any ideas?
You can either change your session bean's #ManagedBean to #Named and then just inject it into your view scoped bean OR you can reference the session bean as is like this:
FacesContext fc = FacesContext.getCurrentInstance()
private CpstcHomeBean homeBean = (CpstcHomeBean) fc.getApplication().evaluateExpressionGet(fc, "#{home}", CpstcHomeBean.class);

Resources