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
_______________________________________________
jboss-user mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/jboss-user

Reply via email to