[jboss-user] [JBoss Seam] - Getting objects from conversation in a custom PhaseListener
JakeC
do-not-reply at jboss.com
Thu Jul 5 19:24:14 EDT 2007
I need to make a URL that can download a binary file based on information stored in a long running conversation. I can get it to work fine once from a page, but the second time, it fails with:
ERROR [PhaseListenerManager] Exception in PhaseListener RESTORE_VIEW(1) afterPhase
| java.lang.IllegalStateException: No active event context
| at org.jboss.seam.core.Manager.instance(Manager.java:267)
I'm pretty sure something I'm doing is ending the long running conversation, because if I just download a document once, then try to continue with my workflow by going to the next page, or even just refresh the current page, I get a similar error:
org.jboss.seam.NoConversationException: no long-running conversation for @Conversational bean
I'm pretty new at Seam, so if I'm making a colossal blunder, please be kind... :-) I've searched all over trying to figure out what is going on, but I just can't seem to find anything relevant.
Here is my PhaseListener:
package com.myco.myproj;
|
| import java.util.Set;
|
| import javax.faces.context.FacesContext;
| import javax.faces.el.ValueBinding;
| import javax.faces.event.PhaseEvent;
| import javax.faces.event.PhaseId;
| import javax.servlet.http.HttpServletResponse;
|
| import org.jboss.seam.annotations.Name;
| import org.jboss.seam.annotations.security.Restrict;
| import org.jboss.seam.contexts.EntityBean;
| import org.jboss.seam.core.Manager;
| import org.jboss.seam.jsf.TransactionalSeamPhaseListener;
| import org.jboss.seam.log.Log;
|
| @Name("docPhaseListener")
| @Restrict("#{identity.loggedIn}")
| @SuppressWarnings("serial")
| public class DocPhaseListener extends TransactionalSeamPhaseListener {
| public final static int BUF_SIZE = 16384;
| public final static String DOC_VIEW_ID = "/document/";
|
| private static Log log = (Log) org.jboss.seam.log.Logging.getLog(DocPhaseListener.class);
|
| private MyObject getMyObject(FacesContext context) {
| MyObject myObject = null;
| log.info("Manager.instance().getCurrentConversationId()="+Manager.instance().getCurrentConversationId());
| ValueBinding vb = context.getApplication().createValueBinding("#{myObject}");
| if(vb == null) {
| log.info("vb is null!");
| } else {
| Object o = null;
| log.info("vb type="+vb.getType(context)+", vb value="+(o=vb.getValue(context)));
| if(o instanceof MyObject)
| myObject = (MyObject) o;
| else
| log.info("Not MyObject!");
| }
|
| return myObject;
| }
|
| public void afterPhase(PhaseEvent event) {
| super.afterPhase(event);
| FacesContext context = event.getFacesContext();
| String viewId = context.getViewRoot().getViewId();
| int index = viewId.indexOf(DOC_VIEW_ID);
| if (PhaseId.RESTORE_VIEW.equals(event.getPhaseId()) && index != -1 && viewId.endsWith(".xhtml")) {
| MyObject myObject = getMyObject(context);
| if(myObject != null)
| Util.handleDocumentRequest(context, myObject);
| else {
| // TODO: Handle bad requests better
| ((HttpServletResponse)context.getExternalContext().getResponse()).setContentType("application/octet-stream");
| context.responseComplete();
| }
| }
| }
| }
|
Since I'm extending TransactionalSeamPhaseListener (it seems necessary to get into the conversation the first time), and you can't have more than one SeamPhaseListener, I had to replace the existing one with mine, so my faces-config.xml looks like this:
<lifecycle>
| <!--phase-listener>org.jboss.seam.jsf.TransactionalSeamPhaseListener</phase-listener-->
| <phase-listener>com.medorder.mazama.DocumentPhaseListener</phase-listener>
| </lifecycle>
|
My UI is part of a rich:dataTable, and the column looks like this:
<h:column>
| <f:facet name="header">Download</f:facet>
| <h:outputLink value="document/download.seam?cid=#{conversation.id}&clr=true">
| <f:verbatim>Download</f:verbatim>
| </h:outputLink>
| </h:column>
|
Eventually, this URL will be called from an embedded Flash object, so I really need to use a PhaseListener. Can anyone tell me what I'm doing wrong to end the conversation?
I have also tried just implementing PhaseListener, and pulling the object from the SessionMap directly using the key "org.jboss.seam.CONVERSATION#xx$myObject", but I get the same kind of problem. The second time I access the EntityBean that is returned, the instance it points to is null.
Also, can someone confirm my suspicion that @Name and @Restrict are pointless to use on a PhaseListener? I don't think any injection has worked on it, and I'm pretty sure that it is not possible to use those on something that pretty much by definition lives outside the life-cycle.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4061067#4061067
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4061067
More information about the jboss-user
mailing list