cocoon-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Geoff Howard <>
Subject Re: File upload with flow (Wiki examples)
Date Sun, 14 Sep 2003 12:33:01 GMT
Stephen Ramsay wrote:

> On Thu, Sep 11, 2003 at 11:09:41PM -0400, Geoff Howard wrote:
>>>2.  It also says you can "Alternatively . . . write the following
>>>Java code in your sitemap components."  What does it mean to write
>>>Java code "in the sitemap components."  Does that mean use it as an
>>Yes, but not limited to Actions.  You can use that section to modify the 
>>portions of the upload action wiki page and be up and running sooner.
>>>I tried to do that and couldn't get it to work, but the
>>>language here makes me think I'm supposed to do something different.
>>>I'd actually rather do this without javascript, but at this point,
>>>I'll settle for anything that works.
>>Let us know exactly what you tried, and what went wrong.
> Okay, so let me pose the following scenario.  I'd like to do a file
> upload using a simple action (i.e. without using flows).  Here's
> some simple HTML for the upload
> <html>
>   <body>
>       <form action="upload" method="post" enctype="multipart/form-data">
> 	   File:  <input type="file" name="uploadfile" size="50">
> 	  <input type="submit"/>
> 	  </form>
> 	</body>
> </html>


> The wiki gives an example action, but it doesn't work because the
> API has changed for Cocoon 2.1.  So let's try this:
> package edu.uga.english.cantor;
> // Lots of imports  . . .
> public class SGUpload
>   extends AbstractLogEnabled
>       implements Action, ThreadSafe {
> 	      public Map act(Redirector redirector, SourceResolver resolver,
> 		  	Map objectModel, String source, Parameters par)
> 				throws Exception {
> 			Request request = ObjectModelHelper.getRequest(objectModel);
> 			PartOnDisk filePart = (PartOnDisk) request.get("uploadfile");
> 			if (filePart != null) {
> 				getLogger().debug("Uploaded file = " +
> 				filePart.getFileName());

				return new Map();

> 			} else {
> 				getLogger().debug("File not found");

				return null;

> 			}

  		//return null;

> 	}
> }

Aha!  That wiki example has a problem I just noticed -- you shouldn't 
return null here (I just corrected the wiki).  Use the corrected version 
above - I'll explain below.

As written your action (and the wiki example) always signals failure. 
This means that depending on how your pipeline is written you may be 
forcing a 404 because no complete pipeline is constructed.

> That compiles without incident, and I drop it (and its package tree)
> into WEB-INF/classes.  I need to add a line to the components
> section that tells Cocoon where it is, so I put:
> <map:actions>
>     <map:action name="sg-upload" src="edu.uga.english.cantor.SGFlow"/>
> </map:actions>


> I think I'm stuck trying to figure out what to put in the pipeline
> (the examples online and in the book I'm using aren't exactly on
> point).  I realize that I can trap on <map:match pattern="upload">,
> trigger the action with <map:act type="sg-upload">, and then do
> whatever (presumably something as simple as "<map:read
> src="static/success.html" mime-type="text/html"/>), but all I get is
> 404s and NullPointerExceptions.  
> What's the dumbest thing that can work in this situation?

I think what you outline above is about as simple as it can get.  I'd

<map:match pattern="upload">
   <map:act type="sg-upload">
     <map:read src="static/success.html" mime-type="text/html"/>
   </map:act> <!-- If act returns a map, processing stops here -->
   <map:read src="static/failure.html" mime-type="text/html"/>

> Oh, and here's a possibly dumb question: Where is this getting
> logged?  I understand that AbstractLogEnabled is an avalon facade
> for whatever logging system is in use, but I don't know where my
> calls to debug() are getting written (and in any event, they're not
> being written to any file in my tomcat tree).

All cocoon logging goes to WEB-INF/logs/*.log (in this case, should be

Note though that there is a logging config in WEB-INF/logkit.xconf which 
sets the threshhold for different log topics.  By default, this may not 
be getting your debugs.  (to really simplify this during "pull your hair 
out" phase, you can always just use System.out.println() which will go 
to the console.  Be sure to either get rid of that or turn it into 
proper logging statements after you've moved into some more sanity.

> I'm definitely a beginner with Cocoon (though not with Java and
> XML).  I have a complete site running on Cocoon that uses lots of
> conditional logic and whatnot, but I haven't tried to do anything
> fancy with it yet.  I'd really like to do all my computational logic
> without XSP, so if anyone knows of a lucid explanation of Actions,
> I'd be much obliged.  

I just looked again and could find no lucid explanation of Actions (and 
I can't remember where I read about them when I first started).  While 
simple, actions do have a dark side.  They can start to make a sitemap 
pretty convoluted as complexity grows.  Flow is seen as a much more 
advanced successor.  I believe that actions may always have their place 
for simple uses but I wouldn't build a whole application in 2.1+ without 
using flow.  I'd love to hear your thoughts in a separate thread after 
you've had a chance to take flow for a spin.

So, here's a starter at the basics of actions:

The basic contract:
1) Actions (like Matchers, and Selectors) are executed before pipeline 
setup, and so can affect which pipeline elements are executed.
2) Actions signal success or failure by returning a Map (success) or 
null (failure).
3) Sitemap elements nested inside <map:act></map:act> are only executed 
  if the action signals success.  Elements outside may or may not be
executed depending on whether a full pipeline (a reader, or up to a 
serializer) is found inside.
4) If desired, the map can be used to return values to the sitemap
which can be referenced by their key.

(action snippet)
   returnValue = new Map();
   return returnValue;

(sitemap snippet)
   <map:act type="myAction">
     <map:generate src="{someKey}.xml"/> <!-- "someValue.xml" -->
   <!-- {someKey} will not be defined here -->

Does that make things any clearer?  (Could someone wiki this?)

Now, you also need to check to make sure your web.xml settings for 
uploads are set to create a PartOnDisk (autosave-uploads -> true, 
allow-uploads -> true IIRC).


To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message