You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@turbine.apache.org by Chris Shenton <Ch...@hq.nasa.gov> on 2002/02/09 00:42:39 UTC

Client ServletInputStream already closed, can't read in my Action

I'm working on a proxy which has to be able to read GET/PUT/POST forms
from a client, then send stuff back.  It doesn't want or need Velocity for
this function -- I'm reading from the client with data.getRequest() as
an HttpServletRequest directly.

I can read the meta-data and headers OK, but when I go to read the
client input stream, it throws an exception saying:

  java.io.IOException: This input stream has been closed


The code bombs in the clientIn.read():

    public HTTPRequest( HttpServletRequest client )
        throws MalformedURLException, IOException
    {
        method   = client.getMethod().toUpperCase();
        length   = client.getContentLength();
        clientIn = client.getInputStream();

        if (length > 0) {
            log.debug("Read input length=" + length);
            int c;
            while ((c = clientIn.read()) != -1) {
                log.debug(" char=" + c);
            }
        }

I've tried using getReader() instead of getInputStream() and it says:

  java.lang.IllegalStateException:
  getInputStream() has already been called for this request

The only think I can think is that Turbine or Velocity have already
opened the stream as a ServletInputStream() then closed it. 

Is there a way around this, to read the client stream for PUT and POST
HTTP methods? What's opening then closing the InputStream?


For this portion of the project I don't need Velocity at all, since
I'm bypassing it.  But my proxy is implemented as a VelocityAction.
Is there some lighter Action I can use which doesn't close the input
or generate output pages, leaving the client connections for me?
I still need to use Turbine's authentication facilities to make sure
only logged in folks use this, else I could go with bare servlets.

Thanks.

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Client ServletInputStream already closed, can't read in my Action

Posted by Chris Shenton <Ch...@hq.nasa.gov>.
Daniel Rall <dl...@finemaltcoding.com> writes:

> Turbine's use of ParameterParser may be doing this.

That recently occurred to me too, or perhaps it's the mechanism that
parses incoming forms to determine which ActionEvent method to
dispatch.  (perhaps PP *is* what determines the method, I don't know)

The Turbine class hierarchy indicates:

java.lang.Object
  |
  +--org.apache.turbine.modules.Assembler
        |
        +--org.apache.turbine.modules.Action
              |
              +--org.apache.turbine.modules.ActionEvent
                    |
                    +--org.apache.turbine.util.velocity.VelocityActionEvent
                          |
                          +--org.apache.turbine.modules.actions.VelocityAction

So I'm guessing the last three, from ActionEvent on down, implement
the ActionEvent form parser, in order to decide what method to invoke
from an incoming form and buttons. 

Should I be able to bypass this by using the simple Action? My initial
tests indicate not,  my HTTP Request's ServletInputStream is still 
                
  java.io.IOException: This input stream has been closed


> In 2.1, you may want to write another servlet for this (i.e. other
> than the Turbine servlet).

Seems there's gotta be a way to get into the Turbine infrastructure
(so I can require authenticated sessions, and cookie/url session
tracking), but before ParameterParser and its friends muck with the
client's POST content. Still looking...

Thanks.

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: config layers

Posted by Jason van Zyl <jv...@zenplex.com>.
On Tue, 2002-03-26 at 10:15, Chris Shenton wrote:
> "Gareth Coltman" <ga...@majorband.co.uk> writes:
> 
> > Alternatively a method we used was to use tokens  like
> > 
> > @dbdriver@
> > 
> > in the tr.props file and have a seperate build.properties file outside of
> > cvs, e.g.
> > 
> > dbdriver=Oracle
> > 
> > Then use ant to filter the tr.props fill and fill in the tokens from the
> > build.props at build time.
> 
> Is it possible to make a decision on how to populate this at run-time,
> like based on the hostname? That way I wouldn't have to  have a
> separate mini-config file for each host.

I do have something for this but I have to dig it out. I made an sample
installer for Tambora that used a small configuration file to generate
the target db stuff. I'm planning on integrating it into the TDK, but no
time as yet. This is definitely possible, actually creating the db on
the client machine automatically.
 
> We take our source from CVS then wipe-and-install on the target QA
> systems where our DB also has different configs. After that, we
> wipe-and-install into our Production systems, where there's yet
> another config.  It would be real nice if we didn't have to tweak
> these DB-config files each time but could let Ant make a decision
> based on hostname or something else machine-specific.
> 
> Thanks.
> 
> --
> To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@jakarta.apache.org>
-- 
jvz.

Jason van Zyl
jvanzyl@apache.org

http://tambora.zenplex.org


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: config layers

Posted by Chris Shenton <Ch...@hq.nasa.gov>.
"Gareth Coltman" <ga...@majorband.co.uk> writes:

> Alternatively a method we used was to use tokens  like
> 
> @dbdriver@
> 
> in the tr.props file and have a seperate build.properties file outside of
> cvs, e.g.
> 
> dbdriver=Oracle
> 
> Then use ant to filter the tr.props fill and fill in the tokens from the
> build.props at build time.

Is it possible to make a decision on how to populate this at run-time,
like based on the hostname? That way I wouldn't have to  have a
separate mini-config file for each host.

We take our source from CVS then wipe-and-install on the target QA
systems where our DB also has different configs. After that, we
wipe-and-install into our Production systems, where there's yet
another config.  It would be real nice if we didn't have to tweak
these DB-config files each time but could let Ant make a decision
based on hostname or something else machine-specific.

Thanks.

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: config layers

Posted by Gareth Coltman <ga...@majorband.co.uk>.
Alternatively a method we used was to use tokens  like

@dbdriver@

in the tr.props file and have a seperate build.properties file outside of
cvs, e.g.

dbdriver=Oracle

Then use ant to filter the tr.props fill and fill in the tokens from the
build.props at build time.

This is also useful for different development/live builds.

Gareth

> -----Original Message-----
> From: Skip Walker [mailto:skipwork@skipwalker.com]
> Sent: 26 March 2002 03:19
> To: 'Turbine Users List'
> Subject: RE: config layers
>
>
>
> Simple!
>
> Cut the relevant database properties out of TR.props and put them into
> another file, say DB.properties.
>
> Add the following line to the TR.props file:
>
> include=DB.properties
>
>
> Use a different DB.properties file depending on your needed configuration.
>
> Skip
>
>
> > -----Original Message-----
> > From: Jesse Chen [mailto:jesse@jalvamedia.com]
> > Sent: Monday, March 25, 2002 9:03 PM
> > To: Turbine Users List
> > Subject: config layers
> >
> >
> > Hi,
> >
> > We have 2 teams that are currently developing on a shared
> > codebase using
> > Turbine2.1 in CVS in opposite parts of the world.
> > Unfortunately, the DB
> > settings need to be different for each team due to network
> > infrastructure
> > issues.
> >
> > I was wondering if there was an elegant way to point the
> > Database Settings
> > properties in TurbineResources.properties to an alternate
> > properties file
> > (ie: conf/localDev.properties) without having to extend the
> > TurbineResource
> > classes? This way, we can share config settings on everything
> > else except
> > the DB settings, which can be managed locally.
> >
> > thx,
> >
> > J
> >
> >
> >
> > --
> > To unsubscribe, e-mail:
> <ma...@jakarta.apache.org>
> For additional commands, e-mail:
> <ma...@jakarta.apache.org>
>
>
> --
> To unsubscribe, e-mail:
> <ma...@jakarta.apache.org>
> For additional commands, e-mail:
> <ma...@jakarta.apache.org>
>
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: config layers

Posted by Skip Walker <sk...@skipwalker.com>.
Simple!

Cut the relevant database properties out of TR.props and put them into
another file, say DB.properties.

Add the following line to the TR.props file:

include=DB.properties


Use a different DB.properties file depending on your needed configuration.

Skip


> -----Original Message-----
> From: Jesse Chen [mailto:jesse@jalvamedia.com]
> Sent: Monday, March 25, 2002 9:03 PM
> To: Turbine Users List
> Subject: config layers
>
>
> Hi,
>
> We have 2 teams that are currently developing on a shared
> codebase using
> Turbine2.1 in CVS in opposite parts of the world.
> Unfortunately, the DB
> settings need to be different for each team due to network
> infrastructure
> issues.
>
> I was wondering if there was an elegant way to point the
> Database Settings
> properties in TurbineResources.properties to an alternate
> properties file
> (ie: conf/localDev.properties) without having to extend the
> TurbineResource
> classes? This way, we can share config settings on everything
> else except
> the DB settings, which can be managed locally.
>
> thx,
>
> J
>
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
For additional commands, e-mail:
<ma...@jakarta.apache.org>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


config layers

Posted by Jesse Chen <je...@jalvamedia.com>.
Hi,

We have 2 teams that are currently developing on a shared codebase using
Turbine2.1 in CVS in opposite parts of the world. Unfortunately, the DB
settings need to be different for each team due to network infrastructure
issues.

I was wondering if there was an elegant way to point the Database Settings
properties in TurbineResources.properties to an alternate properties file
(ie: conf/localDev.properties) without having to extend the TurbineResource
classes? This way, we can share config settings on everything else except
the DB settings, which can be managed locally.

thx,

J



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


AW: link to a RawScreen

Posted by Gunter Miessbrandt <mi...@ixtern.de>.
Thanks for your reply!

It works now.
The package was correct, but the class was defined abstract and so
turbine couldn't take an instance of it.
A little cut and paste fault!


Gunter M.

> -----Ursprungliche Nachricht-----
> Von: Steve [mailto:turbine_user@knology.net]
> Gesendet: Dienstag, 26. Marz 2002 03:20
> An: Turbine Users List
> Betreff: RE: link to a RawScreen
> 
> 
> I use a class that extends RawScreen to output PDF and I call it (from a
> template) like your #3 & it works for me...
> 
> <a href="$link.setScreen("Reports.Billing.DailyStaffBillsScreen")">Daily
> Staff Bills</a>
> 
> and of course my screen is in screens/Reports/Billing
> 
> Maybe a typo on your part somewhere?
> 
> Usually when I have a class not found error, it's because I 
> forgot to change
> the package name, so the class file ends up in the wrong directory...
> 
> HTH,
> Steve
> 
> 
> -----Original Message-----
> From: Gunter Miessbrandt [mailto:miessbrandt@ixtern.de]
> Sent: Thursday, March 21, 2002 8:04 AM
> To: Turbine Users List
> Subject: link to a RawScreen
> 
> 
> Hi List!
> 
> We have a RawScreen which should create a PDF-OutputStream.
> Our Problem: How to point to this Screen from a Velocity-Template?
> We have tried:
> $link.setPage("admin.PDFRawScreen")
> $link.setPage("admin,PDFRawScreen")
> $link.setScreen("admin.PDFRawScreen")
> 
> We always get an class not found Exception.
> What should we do?
> 
> Gunter M.
> 
> --
> To unsubscribe, e-mail:
> <ma...@jakarta.apache.org>
> For additional commands, e-mail:
> <ma...@jakarta.apache.org>
> 
> 
> 
> --
> To unsubscribe, e-mail:   
> <ma...@jakarta.apache.org>
> For additional commands, e-mail: 
> <ma...@jakarta.apache.org>
> 

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: link to a RawScreen

Posted by Steve <tu...@knology.net>.
I use a class that extends RawScreen to output PDF and I call it (from a
template) like your #3 & it works for me...

<a href="$link.setScreen("Reports.Billing.DailyStaffBillsScreen")">Daily
Staff Bills</a>

and of course my screen is in screens/Reports/Billing

Maybe a typo on your part somewhere?

Usually when I have a class not found error, it's because I forgot to change
the package name, so the class file ends up in the wrong directory...

HTH,
Steve


-----Original Message-----
From: Gunter Miessbrandt [mailto:miessbrandt@ixtern.de]
Sent: Thursday, March 21, 2002 8:04 AM
To: Turbine Users List
Subject: link to a RawScreen


Hi List!

We have a RawScreen which should create a PDF-OutputStream.
Our Problem: How to point to this Screen from a Velocity-Template?
We have tried:
$link.setPage("admin.PDFRawScreen")
$link.setPage("admin,PDFRawScreen")
$link.setScreen("admin.PDFRawScreen")

We always get an class not found Exception.
What should we do?

Gunter M.

--
To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
For additional commands, e-mail:
<ma...@jakarta.apache.org>



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


link to a RawScreen

Posted by Gunter Miessbrandt <mi...@ixtern.de>.
Hi List!

We have a RawScreen which should create a PDF-OutputStream.
Our Problem: How to point to this Screen from a Velocity-Template?
We have tried:
$link.setPage("admin.PDFRawScreen")
$link.setPage("admin,PDFRawScreen")
$link.setScreen("admin.PDFRawScreen")

We always get an class not found Exception.
What should we do?

Gunter M.

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Client ServletInputStream already closed, can't read in my Action

Posted by Daniel Rall <dl...@finemaltcoding.com>.
Chris Shenton <Ch...@hq.nasa.gov> writes:

> Daniel Rall <dl...@finemaltcoding.com> writes:
>
>> Turbine's use of ParameterParser may be doing this.
>
> I think you're right, PP and other routines. In the API docs for
> javax.servlet.ServletRequest.getParameter() I noticed:
>
>   If the parameter data was sent in the request body, such as occurs
>   with an HTTP POST request, then reading the body directly via
>   getInputStream() or getReader() can interfere with the execution of
>   this method.
>
> So if *anything* in Turbine calls getParameter() on a servlet's
> request, and the request had content in the body of a PUT or POST,
> then the body content will likely be trashed. This jives with what I'm
> seeing when I try to read a POST request body: stream already closed.
>
> There are related servlet methods which don't have such explicit
> warnings in the docs, but I expect must also trash the body content
> since they effectively do the same thing:
>
>   getParameterNames()
>   getParameterValues()
>   getParameterMap()
>
> The last one at least mentions "parameters are contained in the query
> string or posted form data" but neglects to mention any warning about
> trashed POST body content.
>
> I did a grep on the Turbine source and found 58 instances of
> "getParameter".  getParameters() is a method on the RunData, which
> appears central to Turbine, to do all kinds of stuff like check for
> valid sessions, redirects, and other stuff.
>
> Is it possible to turn off PP?  Or have PP (and any other
> parameter-reading calls) examine only the HTTP Request itself (URI +
> PATH_INFO + QUERY_STRING) and leave a HTTP POST body alone, like it
> would for a GET request?  Is it possible for me to read the body
> before Turbine tries to use getParameters() anywhere for anything?  Is
> there a request-processor for naked requests, much like there's a
> RawScreen for responses?
>
> (If I go with a Turbine-free servlet -- and avoid calls to
> getParameter*() -- I lose authentication and session tracking, among
> other Turbine benefits).

Not sure if this will help or not, but you could try this in your
TR.props:

  # Whether the files should be automatically picked up by
  # ParameterParser.

  services.UploadService.automatic=false

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Client ServletInputStream already closed, can't read in my Action

Posted by Chris Shenton <Ch...@hq.nasa.gov>.
Daniel Rall <dl...@finemaltcoding.com> writes:

> Turbine's use of ParameterParser may be doing this.

I think you're right, PP and other routines. In the API docs for
javax.servlet.ServletRequest.getParameter() I noticed:

  If the parameter data was sent in the request body, such as occurs
  with an HTTP POST request, then reading the body directly via
  getInputStream() or getReader() can interfere with the execution of
  this method.

So if *anything* in Turbine calls getParameter() on a servlet's
request, and the request had content in the body of a PUT or POST,
then the body content will likely be trashed. This jives with what I'm
seeing when I try to read a POST request body: stream already closed.

There are related servlet methods which don't have such explicit
warnings in the docs, but I expect must also trash the body content
since they effectively do the same thing:

  getParameterNames()
  getParameterValues()
  getParameterMap()

The last one at least mentions "parameters are contained in the query
string or posted form data" but neglects to mention any warning about
trashed POST body content.

I did a grep on the Turbine source and found 58 instances of
"getParameter".  getParameters() is a method on the RunData, which
appears central to Turbine, to do all kinds of stuff like check for
valid sessions, redirects, and other stuff.

Is it possible to turn off PP?  Or have PP (and any other
parameter-reading calls) examine only the HTTP Request itself (URI +
PATH_INFO + QUERY_STRING) and leave a HTTP POST body alone, like it
would for a GET request?  Is it possible for me to read the body
before Turbine tries to use getParameters() anywhere for anything?  Is
there a request-processor for naked requests, much like there's a
RawScreen for responses?

(If I go with a Turbine-free servlet -- and avoid calls to
getParameter*() -- I lose authentication and session tracking, among
other Turbine benefits).

Thanks.

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Client ServletInputStream already closed, can't read in my Action

Posted by Daniel Rall <dl...@finemaltcoding.com>.
Chris Shenton <Ch...@hq.nasa.gov> writes:

> I'm working on a proxy which has to be able to read GET/PUT/POST forms
> from a client, then send stuff back.  It doesn't want or need Velocity for
> this function -- I'm reading from the client with data.getRequest() as
> an HttpServletRequest directly.
>
> I can read the meta-data and headers OK, but when I go to read the
> client input stream, it throws an exception saying:
>
>   java.io.IOException: This input stream has been closed
>
>
> The code bombs in the clientIn.read():
>
>     public HTTPRequest( HttpServletRequest client )
>         throws MalformedURLException, IOException
>     {
>         method   = client.getMethod().toUpperCase();
>         length   = client.getContentLength();
>         clientIn = client.getInputStream();
>
>         if (length > 0) {
>             log.debug("Read input length=" + length);
>             int c;
>             while ((c = clientIn.read()) != -1) {
>                 log.debug(" char=" + c);
>             }
>         }
>
> I've tried using getReader() instead of getInputStream() and it says:
>
>   java.lang.IllegalStateException:
>   getInputStream() has already been called for this request
>
> The only think I can think is that Turbine or Velocity have already
> opened the stream as a ServletInputStream() then closed it. 

Turbine's use of ParameterParser may be doing this.

> Is there a way around this, to read the client stream for PUT and POST
> HTTP methods? What's opening then closing the InputStream?

In 2.1, you may want to write another servlet for this (i.e. other
than the Turbine servlet).

> For this portion of the project I don't need Velocity at all, since
> I'm bypassing it.  But my proxy is implemented as a VelocityAction.
> Is there some lighter Action I can use which doesn't close the input
> or generate output pages, leaving the client connections for me?
> I still need to use Turbine's authentication facilities to make sure
> only logged in folks use this, else I could go with bare servlets.

Don't know the answer to the action question, but I'm pretty sure you
can do the authentication from outside of Turbine -- just find the
code it uses for auth and use that yourself.

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>