views:

1008

answers:

4
+1  Q: 

JSF: navigation

I have to warn you: the question may be rather silly, but I can't seem to wrap my head around it right now.

I have two managed beans, let's say A and B:

class A
{
    private Date d8; // ...getters & setters
    public String search()
    {
        // search by d8
    }
}

class B
{
    private Date d9; //...getters & setters
    public String insert()
    {
         // insert a  new item for date d9
    }    
}

and then I have two JSP pages, pageA.jsp (the search page) and pageB.jsp (the input page). What I would like to do is placing a commandbutton in pageB so to open the search page pageA passing the parameter d9 somehow, or navigating to pageA directly after b.insert(). What I would like to do is showing the search result after the insertion.

Maybe it's just that I can't see the clear, simple solution, but I'd like to know what the best practice might be here, also...

I though of these possible solutions:

  1. including **A** in **B** and linking the command button with **b.a.search**
  2. passing **d9** as a **hiddenInput** and adding a new method **searchFromB** in **A** (ugly!)
  3. collapsing the two beans into one
+1  A: 

You should configure the navigation flow in faces-config.xml. In ideal scenario you would return a "status" message which would decide the flow. Read more at following link: http://www.horstmann.com/corejsf/faces-config.html http://publib.boulder.ibm.com/infocenter/rtnlhelp/v6r0m0/index.jsp?topic=/com.businessobjects.integration.eclipse.doc.devtools/developer/JSF_Walkthrough8.html

As far as passing the values from one page to another is concerned you can use backing beans. More about backing beans here: http://www.netbeans.org/kb/articles/jAstrologer-intro.html http://www.coderanch.com/t/214065/JSF/java/backing-beans-vs-managed-beans

Hope i have understood and answered correctly to your question

Way to share values between beans

FacesContext facesContext = FacesContext.getCurrentInstance();
Application app = facesContext.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ELContext elContext = facesContext.getELContext();
ValueExpression valueExp = elFactory.createValueExpression(elContext, expression, Object.class);
return valueExp.getValue(elContext);

In above code "expression" would be something like #{xyzBean.beanProperty} Since JSF uses singleton instances, you should be able to access the values from other beans. If you find more details on this technique, I am sure you'll get what you are looking for.

Priyank
Well, I got the general idea behind JSF. This is a special case, though: I want two beans to exchange parameters, not the plain vanilla usual flow.
Manrico Corazzi
I have edited my post to reflect one aspect with which you can atleast figure out attribute values between beans. Hope it helps.
Priyank
+1  A: 
  1. Add commandButton action attribute referencing to B'insert method

<h:commandLink action="#{b.insert}" value="insert"/>

  1. In B'insert method,add d9 parameter as request parameter. Then return an arbitrary string from insert method.

FacesContext fc = FacesContext.getCurrentInstance();
fc.getExternalContext().getRequestMap().put("d9", d9);

  1. Then go to faces context and add navigation from B to A with "from-outcome" as the arbitrary String you returned from insert method. But don't add redirect tag to navigation tags as it will destroy the request coming from B and the parameter you added (d9) will be cleared.

<from-outcome>return string of insert method</from-outcome>
<to-view-id>address of A</to-view-id>

  1. Then you might get the "d9" in A class by fetching it from request map at its constructor or in a place where its more appropriate (getters). You might add it into a session scope or place it to a hidden variable if you want to keep track of it later.

in class A, when page is navigated, A should be initialized as it will be referenced.

FacesContext fc = FacesContext.getCurrentInstance();
fc.getExternalContext().getRequestMap().get("d9", d9);

Sorry i cant give full code, as i have no ide at here, its internet machine at work. I could not give details therefore.

erdemoo
I will try this. Though I don't like the idea of working around the JSF mechanics, I think that just may be the only way.
Manrico Corazzi
A: 

In my opinion, the simplest way is 3-rd option - have both query and insert methods in same class. And you can do something like that:

public String query () {
//... 
}

public String Insert() {  
 //insert
return Query(); }

If your classes are managed Beans you can load class A from class B and call A.query() in your insert method at the end. Also class A can have

<managed-bean-scope>session</managed-bean-scope>

parameter in faces-config.xml and it wouldn't be instantiated again when loaded.

Vanger
Session scoping the beans is fine, but just be careful about getting rid of them otherwise your memory can get eaten pretty quick for large numbers of users.
Drew
+2  A: 

JSF 1.1/1.2 raw doesn't provide an easy way to do this. Seam/Spring both have ways around this and there are a couple of things you can do. JSF 2 should also have solutions to this once it is released.

Probably the easiest and most expedient would be to collapse the two beans into one and make it session scoped. The worry, of course, is that this bean will not get removed and stay in session until the session times out. Yay Memory leaks!

The other solution would be to pass the date on as a GET parameter. For instance, you action method could call the

FacesContext.getCurrentInstance().getExternalContext().redirect("pageB?d9=" + convertDateToLong(d9));

and then get the parameter on the other side.

Drew
Well, I guess I should've planned the coding better in advance, but I will try this "passing the parameters" workaround and see if it just keeps the application working. I still don't get (and don't like) JSF... :(
Manrico Corazzi
JSF raw, in its current incarnation, has its share of faults. Definitely true. The Navigation model being one of the biggest ones. However, the component based concept is really good IMO and the frameworks I play with (Seam, Facelets, IceFaces and sometimes RichFaces) allow me to get around the issues with JSF. Seam, IMO, is a killer app for JSF. If you're going to do prolonged JSF development, I highly recommend you take a look at seam.
Drew