You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Mick Wever <mi...@machina.no> on 2004/10/13 17:53:41 UTC

Cannot call more than once!

I think I've got a very annoying 
"Response has already been committed" problem narrowed down...

The follwing jsp code does not work for me:

<%@ taglib uri="c.tld" prefix="c" %>

<c:forEach items="${listOfNumbers}" var="number">
        <c:import url="/customAction.do?number=${number}"/>
        <br/>
</c:forEach>  

Because during the c:import the response is committed, and when the
second (or third) c:import executes it dumps "Response has already been
committed". So somewhere between 
org.apache.taglibs.standard.common.core.ImportSupport.doEndTag(:179) and
org.apache.struts.action.RequestProcessor.processActionPerform(:421)
my response is getting committed.
Does anyone know where this would be?
Or has anyone experienced this problem before?
Or even better, can someone give me a solution to get around this?

I'm using struts-1.2.4, and Oracle's OC4J (Orion).
The following stacktrace hints at the methods involved between the
c:import and customAction:

at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:421)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:226)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1164)
at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:397)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:740)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:765)
at com.evermind.server.http.ServletRequestDispatcher.include(ServletRequestDispatcher.java:121)
at com.evermind.server.http.GetParametersRequestDispatcher.newInclude(GetParametersRequestDispatcher.java:80)
at com.evermind.server.http.GetParametersRequestDispatcher.include(GetParametersRequestDispatcher.java:34)
at org.apache.taglibs.standard.tag.common.core.ImportSupport.acquireString(ImportSupport.java:314)
at org.apache.taglibs.standard.tag.common.core.ImportSupport.doEndTag(ImportSupport.java:179)

Mick.

-- 
---<BR/> "You must be the change you wish to see in the world." Gandhi
<BR/>
<a href=http://www.harryspractice.com.au>Harry's Practice</a>
<BR/>--- 



---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Cannot call more than once!

Posted by Mick Wever <ha...@netbeans.org>.
> > There is a simple solution. In the c:import specify an absolute URL.


> I am having the same issue as you were last month.  I am using OC4J (AS
> 10g) and can not <c:import> nor <tiles:insert> more than one Struts
>action
> on the same JSP.  I saw that you worked around the issue by using an
> absolute URL with <c:import>.  I tried this too and it does indeed work
> however this results in a distinct request scope such that the request
> scope of the calling JSP is not visible in the included Struts action
>(and
> vice versa).  Did you find this too?  Have you found any other
>workarounds
> to this issue?  Do you think this is an OC4J issue, a Struts issue, a
>JSTL
> issue?  Why do you suppose there is so little written about this problem
> considering that what we are doing seems like it would be an ideal
> architecture?


It does say in the jstl spec for import that if the url is within the same
application context then the environment variables will be pass on, ie
request, response, etc. Struts actions commit to the response so you
cannot use them to include additional data in this way. It worked out well
with an absolute url because we are using a webcache so that the import
was fast enough. I guess your options are to either change the struts
action into just including a jsp page or servlet, or importing an absolute
url and putting the required information in as request parameters to the
url. 
Mick.

ps. please post your question to the mailing list, and then, only if the
thread is old, email me a copy. 

-- 
"To be young, really young, takes a very long time." Picasso 
--- www.vetproducts.com.au --- 



---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Cannot call more than once!

Posted by Mick Wever <mi...@machina.no>.
On Thu, 14 Oct 2004 07:17:34 -0400, Kris Schneider wrote:

> It's got nothing to do with JSTL and everything to do with your Struts
> action. The Struts controller effectively performs the forward with the
> result of your action's execute method. Yes, <c:import> can work perfectly
> well when used multiple times in a page. For URLs that are within the same
> context (same app), the semantics are pretty much the same as
> RequestDispatcher.include.

Delving deeper into the JSTL defintion for c:import it does mentioned that
if the url is relative and within the same context then the
RequestProcessor.include is used, and the entire environment is available.

There is a simple solution. In the c:import specify an absolute URL.
So the code below works just fine:

<%@ taglib uri="c.tld" prefix="c" %>

<c:forEach items="${listOfNumbers}" var="number">
        <c:import url="http://myServer/myContext/myAction.do?number=${number}"/>
        <br/>
</c:forEach>


Mick.

ps Thanks for your explanation and reference to RequestProcessor.include, without 
this I would not have found the small print ;=)


-- 
---<BR/> "Great spirits have always encountered violent opposition from mediocre minds." 
Albert Einstein
<BR/>
<a href=http://www.harryspractice.com.au>Harry's Practice</a>
<BR/>--- 



---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Cannot call more than once!

Posted by Mick Wever <mi...@machina.no>.
> It's got nothing to do with JSTL and everything to do with your Struts
> action. The Struts controller effectively performs the forward with the
> result of your action's execute method. Yes, <c:import> can work perfectly
> well when used multiple times in a page. For URLs that are within the same
> context (same app), the semantics are pretty much the same as
> RequestDispatcher.include.

This is awkward. Is there no way that the Struts could avoid committing
the response when it is called from the import tag.
Simply avoiding the commit, or cloning the response so the original
response is not altered?
Mick



-- 
---<BR/> "The turtle only makes progress when it's neck is stuck out" Rollo May
<BR/>
<a href=http://www.harryspractice.com.au>Harry's Practice</a>
<BR/>--- 



---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Cannot call more than once!

Posted by Kris Schneider <kr...@dotech.com>.
It's got nothing to do with JSTL and everything to do with your Struts action.
The Struts controller effectively performs the forward with the result of your
action's execute method. Yes, <c:import> can work perfectly well when used
multiple times in a page. For URLs that are within the same context (same app),
the semantics are pretty much the same as RequestDispatcher.include.

Quoting Mick Wever <mi...@machina.no>:

> On Wed, 13 Oct 2004 13:59:32 -0400, Kris Schneider wrote:
> 
> > I'm not sure he actually intended to do multiple forwards, it seems like
> > he just wanted to reuse an action to generate some common output. The
> > fact that Struts is performing an implicit forward in response to each
> > of those imports can be easy to overlook.
> 
> 
> Well bugger.
> I would go so far as to say that struts is not honouring the contract of
> c:import. Nowhere (that I can find, and please quickly point it out if you
> can) in the JSTL documentation can I find spec or definition that c:import
> 'forwards'. It is clearly stated that it imports a URL and never mentions
> forwarding.
> Taking this further, examples in Sun's 'core JSTL' book actually use
> multiple c:import's! So there is the clear indication that the import does
> not forward, and struts is breaking this contract...
> 
> Should I enter a bug?
> 
> Mick.
> 
> 
> -- 
> ---<BR/> "Everything you can imagine is real." Pablo Picasso
> <BR/>
> <a href=http://www.harryspractice.com.au>Harry's Practice</a>
> <BR/>--- 

-- 
Kris Schneider <ma...@dotech.com>
D.O.Tech       <http://www.dotech.com/>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Cannot call more than once!

Posted by Mick Wever <mi...@machina.no>.
On Wed, 13 Oct 2004 13:59:32 -0400, Kris Schneider wrote:

> I'm not sure he actually intended to do multiple forwards, it seems like
> he just wanted to reuse an action to generate some common output. The
> fact that Struts is performing an implicit forward in response to each
> of those imports can be easy to overlook.


Well bugger.
I would go so far as to say that struts is not honouring the contract of
c:import. Nowhere (that I can find, and please quickly point it out if you
can) in the JSTL documentation can I find spec or definition that c:import
'forwards'. It is clearly stated that it imports a URL and never mentions
forwarding.
Taking this further, examples in Sun's 'core JSTL' book actually use
multiple c:import's! So there is the clear indication that the import does
not forward, and struts is breaking this contract...

Should I enter a bug?

Mick.


-- 
---<BR/> "Everything you can imagine is real." Pablo Picasso
<BR/>
<a href=http://www.harryspractice.com.au>Harry's Practice</a>
<BR/>--- 



---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Cannot call more than once!

Posted by Kris Schneider <kr...@dotech.com>.
I'm not sure he actually intended to do multiple forwards, it seems like he just
wanted to reuse an action to generate some common output. The fact that Struts
is performing an implicit forward in response to each of those imports can be
easy to overlook.

Mick, if you want a lower-level analogy, this is sort of equivalent to using
RequestDispatcher.include on a resource that performs a
RequestDispatcher.forward. If you check out the docs, you'll see that forward
should be called before the response is committed. If the response is already
committed, an exception will be thrown. Even if you had few enough numbers in
your list to avoid the exception (output still buffered), you probably won't
get the results you're looking for. As part of the processing of a forward, the
container will automatically discard any currently buffered output.

As Rick also points out, you'll have to rethink how you have things architected.
You may be able to get away with just including a JSP fragment to handle some
common formatting tasks:

<c:forEach var="number" items="${listOfNumbers}">
  <%-- static inclusion of a fragment, can access ${number} directly --%>
  <%@ include file="processNumber.jspf" %><br/>
</c:forEach>

Quoting Rick Reumann <st...@reumann.net>:

> Mick Wever wrote the following on 10/13/2004 11:53 AM:
> 
> >         <c:import url="/customAction.do?number=${number}"/>
> 
> I guess this would be like doing the equivalent of trying to do a 
> forward. On your second loop you'll have already wrote stuff out to the 
> JSP so I don't think you could then do any forwarding. Any reason why 
> you are trying to do fowards within a forEach loop? I can't imagine what 
> good that could accomplish? If there was a bunch of different processing 
> you needed to do, do that in one action business method (do the looping 
> there, not in the JSP).
> 
> -- 
> Rick

-- 
Kris Schneider <ma...@dotech.com>
D.O.Tech       <http://www.dotech.com/>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Cannot call more than once!

Posted by Rick Reumann <st...@reumann.net>.
Mick Wever wrote the following on 10/13/2004 11:53 AM:

>         <c:import url="/customAction.do?number=${number}"/>

I guess this would be like doing the equivalent of trying to do a 
forward. On your second loop you'll have already wrote stuff out to the 
JSP so I don't think you could then do any forwarding. Any reason why 
you are trying to do fowards within a forEach loop? I can't imagine what 
good that could accomplish? If there was a bunch of different processing 
you needed to do, do that in one action business method (do the looping 
there, not in the JSP).

-- 
Rick

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org